Solved PHP inside jail and stderr

I have a strange issue with PHP running inside a jail when calling the php script using cron.

Code:
*/5 * * * * /usr/local/bin/php -d memory_limit=4096M /home/www/sites2/example.com/www/magento_softone/sync_images.php >> /home/www/sites2/out.txt

The output of the script is:

Code:
Warning: rename(/tmpfs/1040ca8.989258eea54e4c1301732ecbd23c2c4a.jpg,/home/www/sites2/example.com/www/pub/media/tmp/catalog/product/9/8/989258eea54e4c1301732ecbd23c2c4a.jpg): Operation not permitted in /home/www/sites2/example.com/www/lib/internal/Magento/Framework/File/Uploader.php on line 298

Fatal error: Uncaught Magento\Framework\Exception\StateException: The product can't be saved. in /home/www/sites2/example.com/www/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php:77
Stack trace:
#0 /home/www/sites2/example.com/www/magento_softone/sync_images.php(228): Magento\Catalog\Model\Product\Gallery\GalleryManagement->create('BENT.0328-\xCE\x9B\xCE\x95\xCE...', Object(Magento\Catalog\Model\Product\Gallery\Entry))
#1 {main}
  thrown in /home/www/sites2/example.com/www/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php on line 77

If I run the script directly from shell without using cron then it runs fine.

Also if I use cronjob but I change the temporary dir to "/home/sites2/tmp" then it works fine:


Code:
*/5 * * * * /usr/local/bin/php -d memory_limit=4096M -d sys_temp_dir="/home/sites2/tmp" /home/www/sites2/example.com/www/magento_softone/sync_images.php >> /home/www/sites2/out.txt

The jail is inside /home/jail/jail1 and the host /home is mounted as nosuid. The /tmp is mounted in jail using nullfs. If I remove the nosuid from host /home then the script works fine using the first cronjob.

Truss shows something about broken pipe before the script shows fatal error and stops running.

To summarize:

1) If I run the script from jail directly from console it works.
2) If I remove nosuid from host /home then running script using cron works.

Any idea why this happens?
 
There are quite a few system executables that use SUID. Those will all fail here.
These are all the suid inside the jail I don't think the php script uses any of these:
Code:
./sbin/mksnap_ffs
./sbin/ping6
./sbin/shutdown
./sbin/ping
./sbin/poweroff
./usr/bin/chpass
./usr/bin/lock
./usr/bin/login
./usr/bin/opieinfo
./usr/bin/opiepasswd
./usr/bin/passwd
./usr/bin/su
./usr/bin/at
./usr/bin/quota
./usr/bin/crontab
./usr/bin/batch
./usr/bin/atrm
./usr/bin/atq
./usr/libexec/dma-mbox-create
./usr/libexec/ulog-helper
./usr/libexec/ssh-keysign
./usr/sbin/traceroute
./usr/sbin/traceroute6

Also how we can explain that if I run it directly from jail console it works but from crontab it doesn't?

From jail console directly I still see these messages "
Warning: rename(/tmpfs/1040ca8.989258eea54e4c1301732ecbd23c2c4a.jpg,/home/www/sites2/example.com/www/pub/media/tmp/catalog/product/9/8/989258eea54e4c1301732ecbd23c2c4a.jpg): Operation not permitted in /home/www/sites2/example.com/www/lib/internal/Magento/Framework/File/Uploader.php on line 298" but it works.
 
check if the cron job path has everything you have when you work interactively
the broken pipe could be it could not start some process so the writing process bombed
the rename warning is probably because acls can't be carried when the file is moved
 
weird
php rename fails with cross device link which is expected because tries to move from /tmp to /home and then tries to copy the file
after copy issues a chown (dont know why) and that fails (i assume the script runs under uid 1006) with operation not permitted and php reports broken pipe and bombs ???
so why issue a chown
why chown fails if the file is already owned by uid 1006
why php reports broken pipe
 
Looks like the broken pipe is caused by the failed chown.

Please check this: https://www.php.net/manual/en/function.rename.php#117590

But what confuses me is that if I mount /home (jail is inside /home/jail/php71) without nosuid then chown doesn't fail.

Also if I run the php script from console it doesn't fail.

I would expect that nosuid shouldn't play any role in this and also that running the php script from cron to have the same result as running it from console.
 
chown shouldnt fail, thats the thing
you can chown your own files to you without problem
also it's somehow an expected behaviour (if the dest fs is fat or does not support chown for whatever reason)
so the warning may be there but still should not bomb
in the 2nd truss file it does not crash and the logs seem the same

ok got it
the bombing case (cron) it looks like the stderr of php proc is redirected to something that is gone
try to redir stderr to a file when running from cron
 
ok got it
the bombing case (cron) it looks like the stderr of php proc is redirected to something that is gone
try to redir stderr to a file when running from cron

Thank you very much for the help.

Previously I was using:

Code:
/usr/local/bin/php -d memory_limit=4096M /home/www/sites2/example.com/www/magento_softone/sync_images.php >> /home/www/sites2/log/sync_images.log

Now I change it to:

Code:
/usr/local/bin/php -d memory_limit=4096M /home/www/sites2/example.com/www/magento_softone/sync_images.php >> /home/www/sites2/log/sync_images_redir.log 2>&1

So far the script didn't stop so I believe this solves the issue.

I believe it's related to this: https://bugs.php.net/bug.php?id=44217

Jail has /dev/strerr and /dev/fd/2) so shouldn't it direct the errors there by default?

When I was running PHP in the host this issue didn't exist. So I believe it's related to jail.

In https://www.freebsd.org/cgi/man.cgi?jail(8) I found this:

Code:
exec.consolelog
         A file to direct command output (stdout and stderr) to.

Any clue what is going on?
 
cron should catch stderr anyway and mail it to you
probably something happens between cron and php and cron closes the end of his stderr pipe
causing php writes to it to sigpipe
 
Cron mail is disabled (I don't run sendmail) in the jail (/var/mail/sites2 doesn't exist) but is enabled in the host (/var/mail/sites2 exist). Maybe this is related?
 
I will try to enable sendmail in jail and see if this fixes it without stderr redirection.

Thank you again for the help.
 
There where some "group" suid, which I didn't find before because I was searching for "owner" suid:

/usr/bin/netstat
/usr/bin/wall
/usr/bin/write
/usr/libexec/sendmail/sendmail
/usr/libexec/dma
/usr/sbin/trpt
Cron tries to send stderr using sendmail which causes the issue.

That's why it works if I mount /home without "nosuid".
 
the nosuid + jail are probably the cause chown fails (both cron and console)
thats why a -d tmp=/home/something works because rename uses mv doesnt use copy/chown
no warning, no stderr, no bomb

anyway you may consider a same-fs $TMP because mv is much faster/less IO/ than copy + rm
 
Back
Top