Bug #76337 [Opn->Csd]: segfault when opcache enabled + extension use zend_register_class_alias

From: 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

« previous php.bugs (#215302) next »