Bug #69295 [Ver->Csd]: segfault w/ memory corruption in _efree() on unserialize

From: Date: Sun, 01 Jan 2017 13:48:24 +0000
Subject: Bug #69295 [Ver->Csd]: segfault w/ memory corruption in _efree() on unserialize
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-206284@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69295&edit=1 ID: 69295 Updated by: nikic@php.net Reported by: brian dot carpenter at gmail dot com Summary: segfault w/ memory corruption in _efree() on unserialize -Status: Verified +Status: Closed Type: Bug Package: Reproducible crash Operating System: Debian 7 PHP Version: PHP-7 -Assigned To: +Assigned To: nikic Block user comment: N Private report: N New Comment: Some time ago the USE_ZEND_ALLOC=0 fallback allocator handlers have been adjusted to check for OOM, so this issue is resolved now. Previous Comments: ------------------------------------------------------------------------ [2016-08-08 15:27:29] cmb@php.net I can reproduce invalid reads/writes (apparently NULL pointer derefs) with current PHP-5.6 and master (didn't check other versions) with Anatol's test script (the original isn't available anymore; I had to concatenate the strings in Anatol's script to make it work). However, valgrind doesn't report an unrecognised instruction (which might be bogus anyway, as it's possible that "the instruction is legitimate but Valgrind doesn't handle it"). The following has been produced by running against a debug build of current master (e20e9c6): vagrant@debian-8:/vagrant/php-src$ USE_ZEND_ALLOC=0 valgrind -q sapi/cli/php -n ../69295.php ==4581== Invalid write of size 8 ==4581== at 0x4C2F467: memset (vg_replace_strmem.c:1094) ==4581== by 0x63F8B1: zend_hash_real_init_ex (zend_hash.c:154) ==4581== by 0x63FB50: zend_hash_real_init (zend_hash.c:203) ==4581== by 0x59000E: php_var_unserialize_ex (var_unserializer.re:716) ==4581== by 0x58EAB1: process_nested_data (var_unserializer.re:372) ==4581== by 0x58EEA0: object_common2 (var_unserializer.re:469) ==4581== by 0x58FD4F: php_var_unserialize_ex (var_unserializer.re:875) ==4581== by 0x58EAB1: process_nested_data (var_unserializer.re:372) ==4581== by 0x58EEA0: object_common2 (var_unserializer.re:469) ==4581== by 0x58FD4F: php_var_unserialize_ex (var_unserializer.re:875) ==4581== by 0x58EAB1: process_nested_data (var_unserializer.re:372) ==4581== by 0x590051: php_var_unserialize_ex (var_unserializer.re:719) ==4581== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==4581== ==4581== ==4581== Process terminating with default action of signal 11 (SIGSEGV) ==4581== Access not within mapped region at address 0x0 ==4581== at 0x4C2F467: memset (vg_replace_strmem.c:1094) ==4581== by 0x63F8B1: zend_hash_real_init_ex (zend_hash.c:154) ==4581== by 0x63FB50: zend_hash_real_init (zend_hash.c:203) ==4581== by 0x59000E: php_var_unserialize_ex (var_unserializer.re:716) ==4581== by 0x58EAB1: process_nested_data (var_unserializer.re:372) ==4581== by 0x58EEA0: object_common2 (var_unserializer.re:469) ==4581== by 0x58FD4F: php_var_unserialize_ex (var_unserializer.re:875) ==4581== by 0x58EAB1: process_nested_data (var_unserializer.re:372) ==4581== by 0x58EEA0: object_common2 (var_unserializer.re:469) ==4581== by 0x58FD4F: php_var_unserialize_ex (var_unserializer.re:875) ==4581== by 0x58EAB1: process_nested_data (var_unserializer.re:372) ==4581== by 0x590051: php_var_unserialize_ex (var_unserializer.re:719) ==4581== If you believe this happened as a result of a stack ==4581== overflow in your program's main thread (unlikely but ==4581== possible), you can try to increase the size of the ==4581== main thread stack using the --main-stacksize= flag. ==4581== The main thread stack size used in this run was 8388608. Segmentation fault ------------------------------------------------------------------------ [2015-06-08 20:09:47] stas@php.net As these seem to be reproducible only in PHP 7, no need to list as security. Also, the second one seems to be completely different issue, so I'd suggest filing a separate issue. ------------------------------------------------------------------------ [2015-06-08 18:37:30] brian dot carpenter at gmail dot com I have another test case that causes a similar crash (at least according to the valgrind output). vex amd64->IR: unhandled instruction bytes: 0xF3 0x4D 0xF 0xBC 0xE4 0x45 0x1 0xC4 ==59766== valgrind: Unrecognised instruction at address 0x1319a3a. ==59766== at 0x1319A3A: zend_mm_alloc_pages (zend_alloc.c:483) ==59766== by 0x131B81C: zend_mm_alloc_small_slow (zend_alloc.c:1190) ==59766== by 0x155F573: virtual_cwd_startup (zend_virtual_cwd.c:431) ==59766== by 0x1412DCC: zend_startup (zend.c:640) ==59766== by 0x11C6F98: php_module_startup (main.c:2066) ==59766== by 0x181CFCC: php_cgi_startup (cgi_main.c:915) ==59766== by 0x43B4AC: main (cgi_main.c:1894) ==59766== Your program just tried to execute an instruction that Valgrind ==59766== did not recognise. There are two possible reasons for this. ==59766== 1. Your program has a bug and erroneously jumped to a non-code ==59766== location. If you are running Memcheck and you just saw a ==59766== warning about a bad jump, it's probably your program's fault. ==59766== 2. The instruction is legitimate but Valgrind doesn't handle it, ==59766== i.e. it's Valgrind's fault. If you think this is the case or ==59766== you are not sure, please let us know and we'll try to fix it. ==59766== Either way, Valgrind will now raise a SIGILL signal which will ==59766== probably kill your program. ==59766== ==59766== Process terminating with default action of signal 4 (SIGILL) ==59766== Illegal opcode at address 0x1319A3A ==59766== at 0x1319A3A: zend_mm_alloc_pages (zend_alloc.c:483) ==59766== by 0x131B81C: zend_mm_alloc_small_slow (zend_alloc.c:1190) ==59766== by 0x155F573: virtual_cwd_startup (zend_virtual_cwd.c:431) ==59766== by 0x1412DCC: zend_startup (zend.c:640) ==59766== by 0x11C6F98: php_module_startup (main.c:2066) ==59766== by 0x181CFCC: php_cgi_startup (cgi_main.c:915) ==59766== by 0x43B4AC: main (cgi_main.c:1894) Illegal instruction I can't get a stack trace in gdb, all I get is this: Starting program: /home/geeknik/php-src/sapi/cgi/php-cgi test00-min [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". X-Powered-By: PHP/7.0.0-dev Content-type: text/html; charset=UTF-8 <br /> <b>Fatal error</b>: Uncaught EngineException: Call to undefined function t() in /home/geeknik/php-tmp/out/fuzzer04/crashes/test00-min:2 Stack trace: #0 {main} thrown in <b>/home/geeknik/php-tmp/out/fuzzer04/crashes/test00-min</b> on line <b>2</b><br /> [Inferior 1 (process 41113) exited with code 0377] Hexdump: 0000000 3f3c 6870 0a70 6124 613d 7272 7961 8028 0000010 612e 7272 7961 2928 3b29 2874 3b29 000001e Test case: https://www.dropbox.com/s/zhelyjjnuw67v39/test00-min?dl=0 ------------------------------------------------------------------------ [2015-05-22 09:54:39] kaplan@php.net Let's start by fixing it for PHP 7? Then we can dig into the 5.5/5.6 reproduction. ------------------------------------------------------------------------ [2015-04-28 05:38:57] stas@php.net I am still unable to reproduce it anywhere but PHP 7. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=69295 -- Edit this bug report at https://bugs.php.net/bug.php?id=69295&edit=1

« previous php.bugs (#206284) next »