php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79917 File cache segfault with a static variable in inherited method
Submitted: 2020-07-30 12:41 UTC Modified: 2020-08-11 10:23 UTC
From: m at renton dot name Assigned: nikic (profile)
Status: Closed Package: opcache
PHP Version: 7.4.8 OS: Linux x86_64
Private report: No CVE-ID: None
 [2020-07-30 12:41 UTC] m at renton dot name
Description:
------------
While researching joomla update issue, I came across an error that causes the Apache worker process to crash with a segfault. Digging deeper, I found that the error only appears with the following opcache settings,

opcache.file_cache="somefile"
opcache.file_cache_only=1

Segfault happens on:
https://github.com/joomla/joomla-cms/blob/1dceaf228a25100963ee044e7c886244742ca0af/administrator/components/com_joomlaupdate/restore.php#L1110

if I replace s/static $baseextension;/$baseextension;/ the error goes away. If I remove some functions from restore.php or I add some new code the error goes away, so that is why that is a problem for me to write simple test code.
However the error is 100% reproducible as the code is.


xdebug here:
[skip]
    0.0142    1995744             -> fwrite(resource(7) of type (stream), 'Preparing to scan archives\n') /administrator/components/com_joomlaupdate/restore.php:146
    0.0142    1995744              >=> 27
    0.0142    1995688             -> fclose(resource(7) of type (stream)) /administrator/components/com_joomlaupdate/restore.php:147
    0.0143    1995256              >=> TRUE
    0.0143    1995232           -> dirname('/tmp/Joomla_3.9.20-Stable-Update_Package.zip') /administrator/components/com_joomlaupdate/restore.php:1052
    0.0143    1995360            >=> '/tmp'
    0.0143    1995360           -> AKUnarchiverZIP->getBaseExtension() /administrator/components/com_joomlaupdate/restore.php:1054

gdb:
Program terminated with signal 11, Segmentation fault.
#0  0x000079e12a3773f5 in ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER () at /usr/src/tmp.UWHRMKf3Xq/php-7.4.8.swn/Zend/zend_vm_execute.h:31847
31847                   if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
(gdb) bt
#0  0x000079e12a3773f5 in ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER () at /usr/src/tmp.UWHRMKf3Xq/php-7.4.8.swn/Zend/zend_vm_execute.h:31847
#1  0x000079e12a39d1cb in execute_ex (ex=0x79e120218020) at /usr/src/tmp.UWHRMKf3Xq/php-7.4.8.swn/Zend/zend_vm_execute.h:56526
#2  0x000079e12a39e888 in zend_execute (op_array=0x79e12025e400, return_value=0x0) at /usr/src/tmp.UWHRMKf3Xq/php-7.4.8.swn/Zend/zend_vm_execute.h:57920
#3  0x000079e12a2c1a93 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/tmp.UWHRMKf3Xq/php-7.4.8.swn/Zend/zend.c:1678
#4  0x000079e12a2207c6 in php_execute_script (primary_file=0x7e2247747e10) at /usr/src/tmp.UWHRMKf3Xq/php-7.4.8.swn/main/main.c:2621
#5  0x000079e12a3a15c9 in php_handler (r=0x32d9c90) at /usr/src/tmp.UWHRMKf3Xq/php-7.4.8.swn/sapi/apache2handler/sapi_apache2.c:700
#6  0x000000000045ef76 in ap_run_handler (r=0x32d9c90) at config.c:170
#7  0x000000000045fa9e in ap_invoke_handler (r=0x32d9c90) at config.c:444
#8  0x00000000004973ba in ap_process_async_request (r=0x32d9c90) at http_request.c:508
#9  0x000000000049768c in ap_process_request (r=0x32d9c90) at http_request.c:586
#10 0x00000000004934b6 in ap_process_http_sync_connection (c=0x32943f0) at http_core.c:214
#11 0x00000000004935d8 in ap_process_http_connection (c=0x32943f0) at http_core.c:255
#12 0x000000000046da1d in ap_run_process_connection (c=0x32943f0) at connection.c:42
#13 0x000000000046e0ec in ap_process_connection (c=0x32943f0, csd=0x3294200) at connection.c:219
#14 0x00000000004e96c6 in child_main (child_num_arg=0, child_bucket=0) at prefork.c:615
#15 0x00000000004e9922 in make_child (s=0x2fd9b00, slot=0) at prefork.c:717
#16 0x00000000004e9983 in startup_children (number_to_start=1) at prefork.c:735
#17 0x00000000004e9f65 in prefork_run (_pconf=0x2fac978, plog=0x2fe4388, s=0x2fd9b00) at prefork.c:897
#18 0x000000000043911e in ap_run_mpm (pconf=0x2fac978, plog=0x2fe4388, s=0x2fd9b00) at mpm_common.c:94
#19 0x000000000042f49f in main (argc=11, argv=0x7e22477488f8) at main.c:819




Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-08-11 09:36 UTC] nikic@php.net
-Status: Open +Status: Verified
 [2020-08-11 09:36 UTC] nikic@php.net
When running under -fsanitize=address in run-tests.php --file-cache-use mode I see a couple of failures in tests doing something like

<?php
class A {
    public function test() {
        static $x;
    }
}
class B extends A {}

with trace

==428713==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x562bd2f402f9 bp 0x7ffde732e370 sp 0x7ffde732de80 T0)
==428713==The signal is caused by a READ memory access.
==428713==Hint: this fault was caused by a dereference of a high value address (see register values below).  Dissassemble the provided pc to learn which register was used.
    #0 0x562bd2f402f9 in shutdown_executor /home/nikic/php/php-7.4/Zend/zend_execute_API.c:309
    #1 0x562bd2f805d9 in zend_deactivate /home/nikic/php/php-7.4/Zend/zend.c:1198
    #2 0x562bd2e1fdff in php_request_shutdown /home/nikic/php/php-7.4/main/main.c:1921
    #3 0x562bd31e26d6 in do_cli /home/nikic/php/php-7.4/sapi/cli/php_cli.c:1132
    #4 0x562bd31e36d4 in main /home/nikic/php/php-7.4/sapi/cli/php_cli.c:1359
    #5 0x7f134a5ef0b2 in __libc_start_main (/usr/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #6 0x562bd20bee1d in _start (/home/nikic/php/php-7.4/sapi/cli/php+0x60ee1d)

I remember touching this code in https://github.com/php/php-src/commit/8819d247c68bd1b86959b3e7dfb66d54803c5d85, but that fix was clearly either incorrect or incomplete.
 [2020-08-11 10:22 UTC] nikic@php.net
-Assigned To: +Assigned To: nikic
 [2020-08-11 10:22 UTC] nikic@php.net
I believe the problem is that, when unserializing from file cache, if the opcodes have already been unserialized, we will not perform the MAP_PTR initialization for static_variables and end up using whatever it was during serialization, which in this case points past the end of the MAP_PTR area.
 [2020-08-11 10:23 UTC] nikic@php.net
-Summary: Segfault with a static variable +Summary: File cache segfault with a static variable in inherited method
 [2020-08-11 13:00 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=4609ded082fb5381bb39b408d471e88df9b81674
Log: Fixed bug #79917
 [2020-08-11 13:00 UTC] nikic@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 08:01:29 2024 UTC