Bug #79820 [Com]: double-free causing heap corruption
| From: | christopher dot broadbent at zencontrol dot com | Date: | Mon, 13 Jul 2020 23:54:05 +0000 |
| Subject: | Bug #79820 [Com]: double-free causing heap corruption | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-228016@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=79820&edit=1
ID: 79820
Comment by: christopher dot broadbent at zencontrol dot com
Reported by: christopher dot broadbent at zencontrol dot com
Summary: double-free causing heap corruption
Status: Open
Type: Bug
Package: Reproducible crash
Operating System: linux debian buster
PHP Version: 7.4.7
Block user comment: N
Private report: N
New Comment:
Upgraded to 7.4.8, still crashes.
> I can't find any version of PHP 7.4 that has a zend_string_release call in
> php_reflection.c:225
This might be the inline of the release call being assigned weird line numbers as it runs? The frame
#4 reflection_free_objects_storage (object=0x7ff047a6cb18) at ./ext/reflection/php_reflection.c:230
is calling:
zend_string_release(ZEND_TYPE_NAME(type_ref->type));
Regardless, I've asked the package maintainer if there are any patches applied before he
builds: https://github.com/oerdnj/deb.sury.org/issues/1433
I doubt that is the problem though as we're also hitting this issue on the official docker
containers, and they don't seem to do any patching.
Docker images: https://hub.docker.com/layers/php/library/php/7.4.8-buster/images/sha256-96e4c07b30977303a1bc53a269ea5284b3d85d4d89787948c3a594dc89a03698?context=explore
Docker image source: https://github.com/docker-library/php/tree/master/7.4/buster
Previous Comments:
------------------------------------------------------------------------
[2020-07-09 08:47:51] nikic@php.net
Not seeing what could cause this. Property types getting resolved while being held by reflection is
something we specifically protect against.
------------------------------------------------------------------------
[2020-07-09 08:41:17] nikic@php.net
On which version/commit of PHP were the gdb backtraces gathered? I can't find any version of
PHP 7.4 that has a zend_string_release call in php_reflection.c:225. The valgrind trace looks more
plausible.
There might be some relation to https://github.com/php/php-src/commit/c9abfaec6bf61bcef6d9651827b49cc7789018fd.
------------------------------------------------------------------------
[2020-07-09 05:44:47] christopher dot broadbent at zencontrol dot com
Description:
------------
We're currently hitting a fairly random segfault inside PHP. It's reproducible on each
run, but we're having difficulty making a minimal reproduction case to upload here.
The builds we're using are from https://deb.sury.org/, but
we're also hitting the problem on the builds from docker.io
I have a capture running under the rr debugger, and have the first free with a backtrace of
#0 zend_mm_free_small (bin_num=<optimized out>, ptr=0x7ff047a6caf0, heap=<optimized
out>) at ./Zend/zend_alloc.c:1279
#1 zend_mm_free_heap (ptr=0x7ff047a6caf0, heap=<optimized out>) at ./Zend/zend_alloc.c:1370
#2 _efree (ptr=0x7ff047a6caf0) at ./Zend/zend_alloc.c:2550
#3 0x000056422fc1cb24 in zend_objects_store_del (object=0x7ff047a6cb18) at
./Zend/zend_objects_API.c:197
#4 0x000056422fc6c92f in zend_object_release (obj=<optimized out>) at
./Zend/zend_objects_API.h:75
#5 ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at ./Zend/zend_vm_execute.h:1767
#6 execute_ex (ex=0x7ff047a6caf0) at ./Zend/zend_vm_execute.h:53830
#7 0x000056422fc6da71 in zend_execute (op_array=0x7ff04a27f2a0, return_value=<optimized out>)
at ./Zend/zend_vm_execute.h:57922
#8 0x000056422fbe74b3 in zend_execute_scripts (type=type@entry=0x8, retval=0x7ff04a21ca80,
retval@entry=0x0, file_count=file_count@entry=0x3) at ./Zend/zend.c:1672
#9 0x000056422fb86b70 in php_execute_script (primary_file=<optimized out>) at
./main/main.c:2621
#10 0x000056422fc6fb86 in do_cli (argc=0xb, argv=0x564230f0cf40) at ./sapi/cli/php_cli.c:961
#11 0x000056422fa4e96b in main (argc=0xb, argv=0x564230f0cf40) at ./sapi/cli/php_cli.c:1356
and the double free has a backtrace of
#0 0x000056422fbc1e4b in zend_mm_free_small (bin_num=<optimized out>, ptr=0x7ff047a6caf0,
heap=0x7ff04a200040) at ./Zend/zend_alloc.c:1278
#1 zend_mm_free_heap (ptr=0x7ff047a6caf0, heap=0x7ff04a200040) at ./Zend/zend_alloc.c:1370
#2 _efree (ptr=0x7ff047a6caf0) at ./Zend/zend_alloc.c:2550
#3 0x000056422fac9ce4 in zend_string_release (s=<optimized out>) at
./ext/reflection/php_reflection.c:225
#4 reflection_free_objects_storage (object=0x7ff047a6cb18) at ./ext/reflection/php_reflection.c:230
#5 0x000056422fc1cb66 in zend_objects_store_del (object=0x7ff047a6cb18) at
./Zend/zend_objects_API.c:193
#6 0x000056422fc6c92f in zend_object_release (obj=<optimized out>) at
./Zend/zend_objects_API.h:75
#7 ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at ./Zend/zend_vm_execute.h:1767
#8 execute_ex (ex=0x7ff047a6caf0) at ./Zend/zend_vm_execute.h:53830
#9 0x000056422fc6da71 in zend_execute (op_array=0x7ff04a27f2a0, return_value=<optimized out>)
at ./Zend/zend_vm_execute.h:57922
#10 0x000056422fbe74b3 in zend_execute_scripts (type=type@entry=0x8, retval=0x7ff04a21ca80,
retval@entry=0x0, file_count=file_count@entry=0x3) at ./Zend/zend.c:1672
#11 0x000056422fb86b70 in php_execute_script (primary_file=<optimized out>) at
./main/main.c:2621
#12 0x000056422fc6fb86 in do_cli (argc=0xb, argv=0x564230f0cf40) at ./sapi/cli/php_cli.c:961
#13 0x000056422fa4e96b in main (argc=0xb, argv=0x564230f0cf40) at ./sapi/cli/php_cli.c:1356
This sticks the heap in to a state where
(rr) p $heap->free_slot[8]
$59 = (zend_mm_free_slot *) 0x7ff047a6caf0
(rr) p $heap->free_slot[8]->next_free_slot
$60 = (zend_mm_free_slot *) 0x7ff047a6caf0
(rr) p $heap->free_slot[8]->next_free_slot->next_free_slot
$61 = (zend_mm_free_slot *) 0x7ff047a6caf0
etc, and ends up segfaulting on the second-next allocation
Running under valgrind gives a double free in a sightly different place:
USE_ZEND_ALLOC=0 valgrind -- php our_args
outputs a lot of..stuff before eventually crashing with
==29090== Invalid free() / delete / delete[] / realloc()
==29090== at 0x48369AB: free (vg_replace_malloc.c:530)
==29090== by 0x28ACE3: zend_string_release (zend_string.h:277)
==29090== by 0x28ACE3: reflection_free_objects_storage (php_reflection.c:230)
==29090== by 0x3DDB65: zend_objects_store_del (zend_objects_API.c:193)
==29090== by 0x42D92E: zend_object_release (zend_objects_API.h:75)
==29090== by 0x42D92E: ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER (zend_vm_execute.h:1767)
==29090== by 0x42D92E: execute_ex (zend_vm_execute.h:53830)
==29090== by 0x42EA70: zend_execute (zend_vm_execute.h:57922)
==29090== by 0x3A84B2: zend_execute_scripts (zend.c:1672)
==29090== by 0x347B6F: php_execute_script (main.c:2621)
==29090== by 0x430B85: do_cli (php_cli.c:961)
==29090== by 0x20F96A: main (php_cli.c:1356)
==29090== Address 0xc432c40 is 0 bytes inside a block of size 80 free'd
==29090== at 0x48369AB: free (vg_replace_malloc.c:530)
==29090== by 0x3E3E64: zend_string_release (zend_string.h:277)
==29090== by 0x3E3E64: zend_resolve_class_type (zend_execute.c:947)
==29090== by 0x410B64: i_zend_check_property_type (zend_execute.c:961)
==29090== by 0x410B64: i_zend_verify_property_type (zend_execute.c:984)
==29090== by 0x410B64: zend_verify_property_type (zend_execute.c:993)
==29090== by 0x3DBA85: zend_std_write_property (zend_object_handlers.c:897)
==29090== by 0x3B244E: zend_update_property_ex (zend_API.c:4115)
==29090== by 0x289C4B: zim_reflection_property_setValue (php_reflection.c:5485)
==29090== by 0x42DE5F: ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1618)
==29090== by 0x42DE5F: execute_ex (zend_vm_execute.h:53826)
==29090== by 0x42EA70: zend_execute (zend_vm_execute.h:57922)
==29090== by 0x3A84B2: zend_execute_scripts (zend.c:1672)
==29090== by 0x347B6F: php_execute_script (main.c:2621)
==29090== by 0x430B85: do_cli (php_cli.c:961)
==29090== by 0x20F96A: main (php_cli.c:1356)
==29090== Block was alloc'd at
==29090== at 0x483577F: malloc (vg_replace_malloc.c:299)
==29090== by 0x37EF38: __zend_malloc (zend_alloc.c:2976)
==29090== by 0x38629B: zend_string_alloc (zend_string.h:133)
==29090== by 0x38629B: zend_concat3 (zend_compile.c:791)
==29090== by 0x387243: zend_compile_typename (zend_compile.c:5318)
==29090== by 0x38BF6F: zend_compile_prop_decl (zend_compile.c:6100)
==29090== by 0x393EF0: zend_compile_prop_group (zend_compile.c:6178)
==29090== by 0x393EF0: zend_compile_stmt (zend_compile.c:8538)
==29090== by 0x394E46: zend_compile_stmt_list (zend_compile.c:5262)
==29090== by 0x394E46: zend_compile_stmt_list (zend_compile.c:5257)
==29090== by 0x393D59: zend_compile_stmt (zend_compile.c:8479)
==29090== by 0x395BDD: zend_compile_class_decl (zend_compile.c:6467)
==29090== by 0x396AA6: zend_compile_top_stmt (zend_compile.c:8454)
==29090== by 0x396ACF: zend_compile_top_stmt (zend_compile.c:8443)
==29090== by 0x36E844: zend_compile (zend_language_scanner.l:614)
I can probably get the full run from the rr debugger uploaded, as well as the valgrind logs, if
needed
$ php -m
[PHP Modules]
amqp
bcmath
calendar
Core
ctype
curl
date
dom
exif
FFI
fileinfo
filter
ftp
gettext
hash
iconv
intl
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
Phar
posix
rdkafka
readline
redis
Reflection
session
shmop
SimpleXML
sockets
sodium
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
xsl
Zend OPcache
zlib
[Zend Modules]
Zend OPcache
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=79820&edit=1