Bug #76337 [Opn->Csd]: segfault when opcache enabled + extension use zend_register_class_alias
| From: | ab@php.net | Date: | Sun, 20 May 2018 11:34:51 +0000 |
| Subject: | Bug #76337 [Opn->Csd]: segfault when opcache enabled + extension use zend_register_class_alias | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-215302@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=76337&edit=1
ID: 76337
Updated by: ab@php.net
Reported by: xKhorasan+php at gmail dot com
Summary: segfault when opcache enabled + extension use
zend_register_class_alias
-Status: Open
+Status: Closed
Type: Bug
Package: Reproducible crash
Operating System: Linux (CentOS6)
PHP Version: 7.2.5
Block user comment: N
Private report: N
New Comment:
Automatic comment on behalf of xKhorasan@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=5681f6523bb36d6b49ab802ddba75e53d8d45268
Log: Fixed bug #76337
Previous Comments:
------------------------------------------------------------------------
[2018-05-16 16:36:01] xKhorasan+php at gmail dot com
Detail explanation:
When PHP start running,
accel_use_shm_interned_strings() is called and interned strings
are copied to opcache shared memory space.
https://github.com/php/php-src/blob/php-7.2.6RC1/ext/opcache/ZendAccelerator.c#L642
In this operation, the entry key in CG(class_table) are copied to the opcache shared
memory space.
Each address of class name string changes to point to shared memory space.
```
(gdb) source .gdbinit
(gdb) b accel_use_shm_interned_strings
(gdb) run -v
Starting program: /usr/local/bin/php -v
[Thread debugging using libthread_db enabled]
Breakpoint 1, accel_use_shm_interned_strings ()
at /php-7.2.6RC1/ext/opcache/ZendAccelerator.c:643
643 {
(gdb) print_zstr compiler_globals->class_table->arData[155]->key
string(14) "_zendtestclass"
(gdb) p compiler_globals->class_table->arData[155]->key
$1 = (zend_string *) 0x1219f80
(gdb) print_zstr compiler_globals->class_table->arData[157]->key
string(19) "_zendtestclassalias"
(gdb) p compiler_globals->class_table->arData[157]->key
$2 = (zend_string *) 0x121a710
(gdb) fin
(gdb) p compiler_globals->class_table->arData[155]->key
$3 = (zend_string *) 0x7fffee783ac0
(gdb) p compiler_globals->class_table->arData[157]->key
$4 = (zend_string *) 0x7fffee783bd8
```
on PHP shutdown, accel_shutdown() is called, and in the function,
accel_use_permanent_interned_strings() is called.
https://github.com/php/php-src/blob/php-7.2.6RC1/ext/opcache/ZendAccelerator.c#L2796
In this operation, interned strings are replaced using
accel_replace_string_by_process_permanent().
https://github.com/php/php-src/blob/php-7.2.6RC1/ext/opcache/ZendAccelerator.c#L629
So each entry key in CG(class_table) is replaced by original interned string.
However, since the class name created by zend_regiser_class_alias() is not an interned
string,
(see: https://github.com/php/php-src/blob/php-7.2.6RC1/Zend/zend_API.c#L2774-L2795
)
its address still points to the shared memory, not an original interned string.
```
(gdb) b accel_shutdown
(gdb) c
(gdb) b accel_reset_pcre_cache
(gdb) c
(gdb) p compiler_globals->class_table->arData[155]->key
$20 = (zend_string *) 0x1219f80
(gdb) p compiler_globals->class_table->arData[157]->key
$21 = (zend_string *) 0x7fffee783bd8
```
After accel_use_permanent_interned_strings(), zend_shared_alloc_shutdown()
is called, and the shared memory space is removed.
So the class alias name in CG(class_table), still points to the shared memory, becomes
a dangling pointer.
```
(gdb) b zend_shared_alloc_shutdown
(gdb) print_zstr compiler_globals->class_table->arData[157]->key
string(19) "_zendtestclassalias"
(gdb) n
(gdb) fin
(gdb) print_zstr compiler_globals->class_table->arData[157]->key
Cannot access memory at address 0x7fffee783be8
```
After that, zend_hash_destroy(GLOBAL_CLASS_TABLE) is called in
zend_shutdown(),
But as noted adove, CG(class_table) contains dangling pointer, so this operation cause
segmentation fault.
```
(gdb) c
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
zend_hash_destroy (ht=0x10ffbb0) at /php-7.2.6RC1/Zend/zend_hash.c:1247
1247 zend_string_release(p->key);
(gdb) bt
#0 zend_hash_destroy (ht=0x10ffbb0) at /php-7.2.6RC1/Zend/zend_hash.c:1247
#1 0x00000000007279f1 in zend_shutdown () at /php-7.2.6RC1/Zend/zend.c:911
#2 0x00000000006c626a in php_module_shutdown () at /php-7.2.6RC1/main/main.c:2453
#3 0x00000000007d7cb5 in main (argc=2, argv=0x10ff800)
at /php-7.2.6RC1/sapi/cli/php_cli.c:1419
(gdb) frame 1
#1 0x00000000007279f1 in zend_shutdown () at /php-7.2.6RC1/Zend/zend.c:911
911 zend_hash_destroy(GLOBAL_CLASS_TABLE);
```
------------------------------------------------------------------------
[2018-05-15 22:17:18] xKhorasan+php at gmail dot com
created pull request in https://github.com/php/php-src/pull/3241
(cannot add the pull request with "Add a Pull Request")
------------------------------------------------------------------------
[2018-05-15 22:02:43] xKhorasan+php at gmail dot com
Confirmed that this still occur in PHP 7.2.6 rc1 ( https://downloads.php.net/~pollita/ ).
------------------------------------------------------------------------
[2018-05-14 21:52:19] xKhorasan+php at gmail dot com
Note that this does not occur in PHP 7.1 (confirmed with 7.1.17)
------------------------------------------------------------------------
[2018-05-13 23:45:59] xKhorasan+php at gmail dot com
Description:
------------
configure option: --with-config-file-path=/etc/ --with-config-file-scan-dir=/etc/php.d/
change to php.ini: added lines below
> zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/opcache.so
> opcache.enable_cli=1
> extension=couchbase.so
steps to reproduce:
1. download this file: https://gist.github.com/xKerman/a987581d3d137644460dd15c1d25c612
2: run command: docker build -t php/bug-report .
3: run command in docker container:
```
$ docker run --rm -it php/bug-report bash
[root@236b3ee9e1ec /]# php -v
```
gdb backtrace:
```
[root@236b3ee9e1ec /]# ulimit -c unlimited
[root@236b3ee9e1ec /]# php -v
[cb,WARN] (pcbc/ext L:426) igbinary serializer is not found
PHP 7.2.5 (cli) (built: May 11 2018 21:40:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.5, Copyright (c) 1999-2018, by Zend Technologies
Segmentation fault (core dumped)
[root@236b3ee9e1ec /]# gdb php -c core
(gdb) bt
#0 zend_string_release (ht=0x2fbbb50) at /php-7.2.5/Zend/zend_string.h:289
#1 zend_hash_destroy (ht=0x2fbbb50) at /php-7.2.5/Zend/zend_hash.c:1247
#2 0x0000000000726f91 in zend_shutdown () at /php-7.2.5/Zend/zend.c:911
#3 0x00000000006c581a in php_module_shutdown () at /php-7.2.5/main/main.c:2453
#4 0x00000000007d7225 in main (argc=2, argv=0x2fbb7a0)
at /php-7.2.5/sapi/cli/php_cli.c:1419
(gdb) frame 2
#2 0x0000000000726f91 in zend_shutdown () at /php-7.2.5/Zend/zend.c:911
911 zend_hash_destroy(GLOBAL_CLASS_TABLE);
```
Some extesion, e.g. couchbase, calls zend_register_class_alias().
https://github.com/couchbase/php-couchbase/blob/48d7f6626461c0941c4637dd93810f7556b9a387/src/couchbase/search/facet.c#L29
zend_register_class_alias() add alias name to CG(class_table), bug does
not intern the class alias name string.
https://github.com/php/php-src/blob/php-7.2.5/Zend/zend_API.c#L2774-L2795
Compared to zend_regiser_class_alias(), other CG(class_table) update
operations, like zend_register_internal_class(), does intern string class name.
https://github.com/php/php-src/blob/php-7.2.5/Zend/zend_API.c#L2720
So, CG(class_table) contains interned class name string and not interned clas name
string, if extension use zend_resiger_class_alias().
And it seems that this causes segmentation fault on zend_shutdown().
Expected result:
----------------
php -v return exit code 0
Actual result:
--------------
segmentation fault occur:
```
[root@236b3ee9e1ec /]# php -v
[cb,WARN] (pcbc/ext L:426) igbinary serializer is not found
PHP 7.2.5 (cli) (built: May 11 2018 21:40:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.5, Copyright (c) 1999-2018, by Zend Technologies
Segmentation fault
```
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=76337&edit=1