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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: m at renton dot name
New email:
PHP Version: OS:

 

 [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: Mon Nov 11 18:01:30 2024 UTC