From: sammyk
Operating system: Any
PHP version: 7.4.8
Package: opcache
Bug Type: Bug
Bug description:opcache.file_cache causes SIGSEGV when custom opcode handlers changed
Description:
------------
When opcache.file_cache is used, the memory address of the opcode
handlers are serialized into the op_array that is stored in the
second-level cache files. This includes custom opcode handlers provided
by extensions.
On process restart, the cached files are loaded into memory on the next
request. The issue is that after a process restart, the extensions that
were present when the op_array was serialized are not guaranteed to be
there on restart. Or a user could have upgraded an extension and it
hooks different opcodes than the previous version. If either of these
are the case, the request will cause a SIGSEGV when it tries to access
the address of the custom opcode handler that no longer exists.
To repro this issue:
1. Install an extension that provides custom opcode handlers
2. Start up a process with opcache.file_cache set
3. Run a request that emits an opcode hooked by the installed extension
4. Then disable the extension, restart, and run the request again
Here's an example using Xdebug and the test script below.
```bash
$ mkdir tmp && php-cgi \
-d opcache.file_cache=$(pwd)/tmp \
-d xdebug.scream=1 \
-f bug.php
# Remove Xdebug before running
$ php-cgi \
-d opcache.file_cache=$(pwd)/tmp \
-f bug.php
Segmentation fault (core dumped)
$ gdb php-cgi core
[...]
Core was generated by `php-cgi -d
opcache.file_cache=/home/circleci/app/tmp -f bug.php'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000000000000000 in ?? ()
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x0000559d9da3bdf0 in ZEND_USER_OPCODE_SPEC_HANDLER ()
at /usr/local/src/php/Zend/zend_vm_execute.h:2637
#2 0x0000559d9da991ef in execute_ex (ex=0x7f1188014020)
at /usr/local/src/php/Zend/zend_vm_execute.h:53902
#3 0x0000559d9da9d18d in zend_execute (op_array=0x7f1188065000,
return_value=0x0)
at /usr/local/src/php/Zend/zend_vm_execute.h:57922
#4 0x0000559d9d9c9f01 in zend_execute_scripts (type=8, retval=0x0,
file_count=3)
at /usr/local/src/php/Zend/zend.c:1666
#5 0x0000559d9d93328a in php_execute_script
(primary_file=0x7ffe9fb82610)
at /usr/local/src/php/main/main.c:2617
#6 0x0000559d9daa6e31 in main (argc=5, argv=0x7ffe9fb82858)
at /usr/local/src/php/sapi/cgi/cgi_main.c:2556
(gdb)
```
Test script:
---------------
<?php
# xdebug.scream=1 overloads ZEND_BEGIN_SILENCE & ZEND_END_SILENCE
# @see
https://github.com/xdebug/xdebug/blob/f83939c/src/develop/develop.c#L79-L81
@var_dump('foo');
Expected result:
----------------
string(3) "foo"
Actual result:
--------------
Segmentation fault (core dumped)
--
Edit bug report at https://bugs.php.net/bug.php?id=79825&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=79825&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=79825&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=79825&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=79825&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=79825&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=79825&r=support
Expected behavior: https://bugs.php.net/fix.php?id=79825&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=79825&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=79825&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=79825&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=79825&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=79825&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=79825&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=79825&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=79825&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=79825&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=79825&r=mysqlcfg