php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79128 Preloading segfaults if preload_user is used
Submitted: 2020-01-16 14:24 UTC Modified: 2020-01-24 15:17 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:0 (0.0%)
From: dotbox at gmail dot com Assigned: nikic (profile)
Status: Closed Package: opcache
PHP Version: 7.4.2 OS: Debian Buster
Private report: No CVE-ID: None
 [2020-01-16 14:24 UTC] dotbox at gmail dot com
Description:
------------
I tried to play with preloading in OXID eShop and PHP 7.4, but Apache dies with "double free or corruption (!prev)", so i build a debugging enabled version of PHP and used the PHP built in web server, same problem.

Same problem appears in PHP 7.4.1, as well es 7.4.2RC1 (did not try 7.4.0).

We have a view dependencies, but it doesn't matter if you install those or not, PHP will die with the exact same stack trace and error whether the dependencies have been installed or not. So for the sake of simplicity, it could strip it down to a few steps.

Could be related to https://bugs.php.net/bug.php?id=78894

Test script:
---------------
- git clone git@github.com:OXID-eSales/oxideshop_ce.git
- add a preload.php (see below) to source/preload.php
- php -S localhost:8000 -t oxideshop_ce/source/ -d opcache.preload=oxideshop_ce/source/preload.php
- in another terminal: curl localhost:8000

Server dies with:
[Thu Jan 16 14:14:35 2020] PHP 7.4.2RC1 Development Server (http://localhost:8000) started
[Thu Jan 16 14:14:44 2020] 127.0.0.1:47674 Accepted
double free or corruption (!prev)
Aborted (core dumped)


contents of preload.php

<?php

$files= [];
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Contract/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/vendor/composer/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/vendor/composer/*/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Autoload/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Controller/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Contract/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Dao/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/DataObject/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Edition/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Service/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Routing/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Model/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/Module/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Application/Controller/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Application/Model/*.php'));
$files = array_merge($files, glob('/var/www/oxideshop/source/Core/*.php'));

foreach ($files as $file) {
    echo $file, PHP_EOL;
    opcache_compile_file($file);
}


Expected result:
----------------
- Built in webserver should not crash
- client should (in this case) see a error message about missing vendor/autoload.php ;-)

Actual result:
--------------
Program received signal SIGABRT, Aborted.
0x00007f3f6acb27bb in raise () from target:/lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007f3f6acb27bb in raise () from target:/lib/x86_64-linux-gnu/libc.so.6
#1  0x00007f3f6ac9d535 in abort () from target:/lib/x86_64-linux-gnu/libc.so.6
#2  0x00007f3f6acf4508 in ?? () from target:/lib/x86_64-linux-gnu/libc.so.6
#3  0x00007f3f6acfac1a in ?? () from target:/lib/x86_64-linux-gnu/libc.so.6
#4  0x00007f3f6acfc73c in ?? () from target:/lib/x86_64-linux-gnu/libc.so.6
#5  0x00007f3f69f14bc4 in zend_hash_do_resize (ht=0x55665071d310) at /usr/src/php/Zend/zend_hash.c:1164
#6  0x00007f3f69f137a9 in _zend_hash_add_or_update_i (ht=0x55665071d310, key=0x7f3f65e85600, pData=0x7ffd8559ec90, flag=2) at /usr/src/php/Zend/zend_hash.c:772
#7  0x00007f3f69f13d2e in zend_hash_add (ht=0x55665071d310, key=0x7f3f65e85600, pData=0x7ffd8559ec90) at /usr/src/php/Zend/zend_hash.c:874
#8  0x00007f3f69ec4f8e in zend_hash_add_ptr (ht=0x55665071d310, key=0x7f3f65e85600, pData=0x7f3f65e02100) at Zend/zend_hash.h:591
#9  0x00007f3f69ed8322 in zend_compile_class_decl (ast=0x7f3f65e795c8, toplevel=1 '\001') at /usr/src/php/Zend/zend_compile.c:6523
#10 0x00007f3f69ede15a in zend_compile_top_stmt (ast=0x7f3f65e795c8) at /usr/src/php/Zend/zend_compile.c:8429
#11 0x00007f3f69ede0c9 in zend_compile_top_stmt (ast=0x7f3f65e7b6c0) at /usr/src/php/Zend/zend_compile.c:8418
#12 0x00007f3f69e9d22d in zend_compile (type=2) at Zend/zend_language_scanner.l:614
#13 0x00007f3f69e9d3cc in compile_file (file_handle=0x7ffd8559f480, type=8) at Zend/zend_language_scanner.l:650
#14 0x00007f3f69c52832 in phar_compile_file (file_handle=0x7ffd8559f480, type=8) at /usr/src/php/ext/phar/phar.c:3299
#15 0x00007f3f65d2e419 in opcache_compile_file (file_handle=0x7ffd8559f480, type=8, key=0x7f3f65e59a98 "/var/www/oxideshop/source/bootstrap.php", op_array_p=0x7ffd8559f318)
    at /usr/src/php/ext/opcache/ZendAccelerator.c:1754
#16 0x00007f3f65d2f888 in persistent_compile_file (file_handle=0x7ffd8559f480, type=8) at /usr/src/php/ext/opcache/ZendAccelerator.c:2127
#17 0x00007f3f6602659c in xdebug_compile_file (file_handle=0x7ffd8559f480, type=8) at /tmp/pear/temp/xdebug/src/base/base.c:147
#18 0x00007f3f69f6e31a in zend_include_or_eval (inc_filename=0x7f3f65e13080, type=16) at /usr/src/php/Zend/zend_execute.c:4214
#19 0x00007f3f69f89dfc in ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER () at /usr/src/php/Zend/zend_vm_execute.h:13655
#20 0x00007f3f69f757a7 in ZEND_USER_OPCODE_SPEC_HANDLER () at /usr/src/php/Zend/zend_vm_execute.h:2647
#21 0x00007f3f69fd74ab in execute_ex (ex=0x7f3f65e13020) at /usr/src/php/Zend/zend_vm_execute.h:53893
#22 0x00007f3f66026ed1 in xdebug_execute_ex (execute_data=0x7f3f65e13020) at /tmp/pear/temp/xdebug/src/base/base.c:384
#23 0x00007f3f69fdb45e in zend_execute (op_array=0x7f3f65e6d000, return_value=0x0) at /usr/src/php/Zend/zend_vm_execute.h:57913
#24 0x00007f3f69efe7be in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/php/Zend/zend.c:1665
#25 0x00007f3f69e607a1 in php_execute_script (primary_file=0x7ffd855a1ba0) at /usr/src/php/main/main.c:2617
#26 0x00007f3f69fde14c in php_handler (r=0x7f3f66bc70a0) at /usr/src/php/sapi/apache2handler/sapi_apache2.c:700
#27 0x0000556650567a40 in ap_run_handler ()
#28 0x0000556650567fd6 in ap_invoke_handler ()
#29 0x0000556650580453 in ap_process_async_request ()
#30 0x00005566505805be in ap_process_request ()
#31 0x000055665057c82d in ?? ()
#32 0x00005566505718b0 in ap_run_process_connection ()
#33 0x00007f3f6a9123df in ?? () from target:/usr/lib/apache2/modules/mod_mpm_prefork.so
#34 0x00007f3f6a9126d4 in ?? () from target:/usr/lib/apache2/modules/mod_mpm_prefork.so
#35 0x00007f3f6a91272f in ?? () from target:/usr/lib/apache2/modules/mod_mpm_prefork.so
#36 0x00007f3f6a9132f3 in ?? () from target:/usr/lib/apache2/modules/mod_mpm_prefork.so
#37 0x000055665054a67e in ap_run_mpm ()
#38 0x0000556650542f57 in main ()


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-01-17 09:48 UTC] nikic@php.net
-Status: Open +Status: Feedback
 [2020-01-17 09:48 UTC] nikic@php.net
I was not able to reproduce this with current 7.4 and the provided instructions. I also didn't get any relevant warnings under valgrind.

(I did adjust the paths in the preload.php file and I also copied the config.php.inc file after seeing the error message about that. I did not install vendor dependencies per your comment about that.)
 [2020-01-17 12:59 UTC] dotbox at gmail dot com
-Status: Feedback +Status: Open
 [2020-01-17 12:59 UTC] dotbox at gmail dot com
Thanks Nikita for having a look.

I tried on my local workstation (Fedora 30) with compiling from source (7.4.1 and 7.4.2RC1) and also could not reproduce in this case, but i was able to reproduce this with the official PHP docker images.

You can try with 7.4.1-cli-buster image:
docker run -t -i --rm -p 8000:8000 php:7.4.1-cli-buster /bin/bash
cd /tmp
curl -L -o oxid.tar.gz https://github.com/OXID-eSales/oxideshop_ce/archive/v6.5.0.tar.gz
tar -xvzf oxid.tar.gz 
cd oxideshop_ce-6.5.0/
curl -o source/preload.php https://pastebin.com/raw/g2Pzm16r
php -n -d zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20190902/opcache.so -S localhost:8000 -t source/ -d opcache.preload=source/preload.php -d opcache.preload_user=root &
curl localhost:8000

And with the 7.4.1-cli-alpine image:
docker run -t -i --rm -p 8000:8000 php:7.4.1-cli-alpine3.11 /bin/sh
cd /tmp
curl -L -o oxid.tar.gz https://github.com/OXID-eSales/oxideshop_ce/archive/v6.5.0.tar.gz
tar -xvzf oxid.tar.gz 
cd oxideshop_ce-6.5.0/
curl -o source/preload.php https://pastebin.com/raw/g2Pzm16r
php -n -d zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20190902/opcache.so -S localhost:8000 -t source/ -d opcache.preload=source/preload.php -d opcache.preload_user=root &
curl localhost:8000

(the only difference is /bin/sh instead of /bin/bash)

I played around with those Dockerfiles for 7.4.1-cli-buster and 7.4.1-cli-alpine3.11, i tried removing the CFLAGS, CPPFLAGS, LDFLAGS as well as all configure options besides --enable-opcache, but it still core dumped with the same stack trace as in the original report (besides the apache part of course, but the rest is exactly the same).

As i could rule out Ubuntu (be using Fedora without a problem and Alpine having the same problem), compile flags and other modules (by not compiling and calling with php -n), the only common denominator i could find in this case is docker (or LXC).

Disclaimer: i am not very much used to debug C code, so there could be other differences as well ;-)

Could you assist me with how to proceed?
 [2020-01-17 13:06 UTC] nikic@php.net
PHP 7.4.1 has known issues with preloading, so I'm not surprised that they exhibit this issue. I'm assuming that images for 7.4.2rc1 are not available?
 [2020-01-17 13:26 UTC] dotbox at gmail dot com
I could not find official PHP 7.4.2rc1 docker images, so i build my own by cloning the repo from https://github.com/docker-library/php, then i changed the 7.4/buster/cli/Dockerfile lines 67 to 69:

-ENV PHP_VERSION 7.4.1
-ENV PHP_URL="https://www.php.net/get/php-7.4.1.tar.xz/from/this/mirror" PHP_ASC_URL="https://www.php.net/get/php-7.4.1.tar.xz.asc/from/this/mirror"
-ENV PHP_SHA256="561bb866bdd509094be00f4ece7c3543ec971c4d878645ee81437e291cffc762" PHP_MD5=""
+ENV PHP_VERSION 7.4.2RC1
+ENV PHP_URL="https://downloads.php.net/~derick/php-7.4.2RC1.tar.xz" PHP_ASC_URL=""
+ENV PHP_SHA256="" PHP_MD5=""

then i build with docker build . --tag php:dbg and then run with docker run -t -i --rm -p 8000:8000 php:dbg /bin/bash, sadly the same problem :-(
 [2020-01-17 14:14 UTC] w3goodies dot com at gmail dot com
Can vote to this same case. I am using official PHP docker images and tested with PHP 7.4.1 and 7.4 and built 7.4.2 myself using same code as in 7.4.1 by just changing the download urls of PHP source. The issue persists in all the versions.
 [2020-01-24 11:12 UTC] dotbox at gmail dot com
-PHP Version: 7.4.2RC1 +PHP Version: 7.4.2
 [2020-01-24 11:12 UTC] dotbox at gmail dot com
As PHP 7.4.2 was released, although the changes between 7.4.2rc1 and 7.4.2 are minimal, I gave it a try with the new docker images available and I have the exact same segfault.
 [2020-01-24 14:46 UTC] nikic@php.net
-Status: Open +Status: Verified
 [2020-01-24 14:46 UTC] nikic@php.net
I was able to reproduce this issue outside Docker using "sudo !! -d opcache.preload_user=root".
 [2020-01-24 15:10 UTC] nikic@php.net
Here is the valgrind trace:

==375== Invalid write of size 8
==375==    at 0x126BA2AA: _zend_hash_append_ex (zend_hash.h:1126)
==375==    by 0x126C5EEE: preload_load (ZendAccelerator.c:4217)
==375==    by 0x126C7906: accel_finish_startup (ZendAccelerator.c:4657)
==375==    by 0x126C1FBD: accel_post_startup (ZendAccelerator.c:3032)
==375==    by 0x93BE3F: zend_post_startup (zend.c:1002)
==375==    by 0x89F166: php_module_startup (main.c:2356)
==375==    by 0xA1C48F: php_cli_startup (php_cli.c:407)
==375==    by 0xA1E62A: main (php_cli.c:1319)
==375==  Address 0x115818a0 is 0 bytes after a block of size 10,240 alloc'd
==375==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==375==    by 0x903A4E: __zend_malloc (zend_alloc.c:2975)
==375==    by 0x9540EE: zend_hash_do_resize (zend_hash.c:1160)
==375==    by 0x952D91: _zend_hash_add_or_update_i (zend_hash.c:772)
==375==    by 0x953345: zend_hash_update (zend_hash.c:879)
==375==    by 0x93E9C0: zend_hash_update_ptr (zend_hash.h:647)
==375==    by 0x94928F: do_register_internal_class (zend_API.c:2713)
==375==    by 0x94943D: zend_register_internal_class (zend_API.c:2757)
==375==    by 0x6BB2C9: spl_register_std_class (spl_functions.c:44)
==375==    by 0x6DB4C6: zm_startup_spl_observer (spl_observer.c:1338)
==375==    by 0x6BAFDA: zm_startup_spl (php_spl.c:1008)
==375==    by 0x945EFA: zend_startup_module_ex (zend_API.c:1860)
 [2020-01-24 15:17 UTC] nikic@php.net
-Summary: SIGABRT double free or corruption with preloading +Summary: Preloading segfaults if preload_user is used -Assigned To: +Assigned To: nikic
 [2020-01-24 15:20 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=3291891408556cb412bf1093a6112951dec1421e
Log: Fixed bug #79128
 [2020-01-24 15:20 UTC] nikic@php.net
-Status: Verified +Status: Closed
 [2020-01-24 15:58 UTC] dotbox at gmail dot com
I can confirm this works. You ROCK! :-D
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Thu Dec 03 23:01:24 2020 UTC