php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73188 Use after free in user_wrapper_opener()
Submitted: 2016-09-27 19:15 UTC Modified: 2016-10-12 06:23 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:2 (100.0%)
From: admin at fullspace dot ru Assigned: pollita
Status: Closed Package: Streams related
PHP Version: 5.6.26 OS: Gentoo
Private report: No CVE-ID:
 [2016-09-27 19:15 UTC] admin at fullspace dot ru
Description:
------------
There is use after free bug in streams.

This is production site and I can't reproduce bug in short script, but it appears all the time.

Core was generated by `/usr/sbin/apache2 -D PHP5.6 -D MACRO -D RPAF -d /usr/lib64/apache2 -f /etc/apac'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f5c23af639e in ?? () from /lib64/libc.so.6
(gdb) bt
#0  0x00007f5c23af639e in ?? () from /lib64/libc.so.6
#1  0x00007f5c1f214f8f in user_wrapper_opener (wrapper=0x2133828, 
    filename=0x2cce9b8 "udata://custom/getMyDelivCity/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0/.json", mode=0x7f5c1f8019c3 "rb", options=0, opened_path=0x0, 
    context=0x257df30, __php_stream_call_depth=1, 
    __zend_filename=0x7f5c1f82a198 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/main/streams/streams.c", __zend_lineno=2061, 
    __zend_orig_filename=0x7f5c1f801288 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/ext/standard/file.c", __zend_orig_lineno=550)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/main/streams/userspace.c:347
#2  0x00007f5c1f20c892 in _php_stream_open_wrapper_ex (path=0x2cce9b8 "udata://custom/getMyDelivCity/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0/.json", 
    mode=0x7f5c1f8019c3 "rb", options=8, opened_path=0x0, context=0x257df30, __php_stream_call_depth=0, 
    __zend_filename=0x7f5c1f801288 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/ext/standard/file.c", __zend_lineno=550, 
    __zend_orig_filename=0x0, __zend_orig_lineno=0) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/main/streams/streams.c:2059
#3  0x00007f5c1f0b61f6 in zif_file_get_contents (ht=1, return_value=0x2cd1658, return_value_ptr=0x7f5c25bb01b8, this_ptr=0x0, return_value_used=1)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/ext/standard/file.c:548
#4  0x00007f5c1ef77327 in phar_file_get_contents (ht=1, return_value=0x2cd1658, return_value_ptr=0x7f5c25bb01b8, this_ptr=0x0, return_value_used=1)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/ext/phar/func_interceptors.c:225
#5  0x00007f5c1f2d1910 in zend_do_fcall_common_helper_SPEC (execute_data=0x7f5c25bb0210)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend_vm_execute.h:558
#6  0x00007f5c1f2d7422 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x7f5c25bb0210)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend_vm_execute.h:2602
#7  0x00007f5c1f2d0f79 in execute_ex (execute_data=0x7f5c25bb0210) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend_vm_execute.h:363
#8  0x00007f5c1f2d1002 in zend_execute (op_array=0x7f5c25be5bb0) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend_vm_execute.h:388
#9  0x00007f5c1f289010 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend.c:1341
#10 0x00007f5c1f1eb211 in php_execute_script (primary_file=0x7ffc4d68bcf0) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/main/main.c:2613
#11 0x00007f5c1f345fb3 in php_handler (r=0x2018de0) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/sapi/apache2handler/sapi_apache2.c:667
#12 0x0000000000438df0 in ap_run_handler ()
#13 0x00000000004391b9 in ap_invoke_handler ()
#14 0x00000000004454ec in ap_internal_redirect ()
#15 0x00007f5c207f2462 in ?? () from /usr/lib64/apache2/modules/mod_rewrite.so
#16 0x0000000000438df0 in ap_run_handler ()
#17 0x00000000004391b9 in ap_invoke_handler ()
#18 0x0000000000445d90 in ap_process_request ()
#19 0x0000000000442f30 in ?? ()
#20 0x000000000043f1e0 in ap_run_process_connection ()
#21 0x000000000044a3af in ?? ()
#22 0x000000000044a7d4 in ?? ()
#23 0x000000000044b6e4 in ap_mpm_run ()
#24 0x0000000000424c21 in main ()


Segfault is in strcmp() here:

(gdb) up
#1  0x00007f5c1f214f8f in user_wrapper_opener (wrapper=0x2133828, 
    filename=0x2cce9b8 "udata://custom/getMyDelivCity/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0/.json", mode=0x7f5c1f8019c3 "rb", options=0, opened_path=0x0, 
    context=0x257df30, __php_stream_call_depth=1, 
    __zend_filename=0x7f5c1f82a198 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/main/streams/streams.c", __zend_lineno=2061, 
    __zend_orig_filename=0x7f5c1f801288 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/ext/standard/file.c", __zend_orig_lineno=550)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/main/streams/userspace.c:347
347		if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
(gdb) print file_globals.user_stream_current_filename
$1 = 0x7f5c15714ab0 <error: Cannot access memory at address 0x7f5c15714ab0>




Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-09-27 19:22 UTC] admin at fullspace dot ru
There is use after free bug in streams.

apache 2.2.31 (prefork) + mod_php (5.6.26)

This is production site and I can't reproduce bug in short script, but it appears all the time.

Core was generated by `/usr/sbin/apache2 -D PHP5.6 -D MACRO -D RPAF -d /usr/lib64/apache2 -f /etc/apac'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f5c23af639e in ?? () from /lib64/libc.so.6
(gdb) bt
#0  0x00007f5c23af639e in ?? () from /lib64/libc.so.6
#1  0x00007f5c1f214f8f in user_wrapper_opener (wrapper=0x2133828, 
    filename=0x2cce9b8 "udata://custom/getMyDelivCity/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0/.json", mode=0x7f5c1f8019c3 "rb", options=0, opened_path=0x0, 
    context=0x257df30, __php_stream_call_depth=1, 
    __zend_filename=0x7f5c1f82a198 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/main/streams/streams.c", __zend_lineno=2061, 
    __zend_orig_filename=0x7f5c1f801288 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/ext/standard/file.c", __zend_orig_lineno=550)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/main/streams/userspace.c:347
#2  0x00007f5c1f20c892 in _php_stream_open_wrapper_ex (path=0x2cce9b8 "udata://custom/getMyDelivCity/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0/.json", 
    mode=0x7f5c1f8019c3 "rb", options=8, opened_path=0x0, context=0x257df30, __php_stream_call_depth=0, 
    __zend_filename=0x7f5c1f801288 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/ext/standard/file.c", __zend_lineno=550, 
    __zend_orig_filename=0x0, __zend_orig_lineno=0) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/main/streams/streams.c:2059
#3  0x00007f5c1f0b61f6 in zif_file_get_contents (ht=1, return_value=0x2cd1658, return_value_ptr=0x7f5c25bb01b8, this_ptr=0x0, return_value_used=1)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/ext/standard/file.c:548
#4  0x00007f5c1ef77327 in phar_file_get_contents (ht=1, return_value=0x2cd1658, return_value_ptr=0x7f5c25bb01b8, this_ptr=0x0, return_value_used=1)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/ext/phar/func_interceptors.c:225
#5  0x00007f5c1f2d1910 in zend_do_fcall_common_helper_SPEC (execute_data=0x7f5c25bb0210)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend_vm_execute.h:558
#6  0x00007f5c1f2d7422 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x7f5c25bb0210)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend_vm_execute.h:2602
#7  0x00007f5c1f2d0f79 in execute_ex (execute_data=0x7f5c25bb0210) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend_vm_execute.h:363
#8  0x00007f5c1f2d1002 in zend_execute (op_array=0x7f5c25be5bb0) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend_vm_execute.h:388
#9  0x00007f5c1f289010 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/Zend/zend.c:1341
#10 0x00007f5c1f1eb211 in php_execute_script (primary_file=0x7ffc4d68bcf0) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/main/main.c:2613
#11 0x00007f5c1f345fb3 in php_handler (r=0x2018de0) at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/sapi/apache2handler/sapi_apache2.c:667
#12 0x0000000000438df0 in ap_run_handler ()
#13 0x00000000004391b9 in ap_invoke_handler ()
#14 0x00000000004454ec in ap_internal_redirect ()
#15 0x00007f5c207f2462 in ?? () from /usr/lib64/apache2/modules/mod_rewrite.so
#16 0x0000000000438df0 in ap_run_handler ()
#17 0x00000000004391b9 in ap_invoke_handler ()
#18 0x0000000000445d90 in ap_process_request ()
#19 0x0000000000442f30 in ?? ()
#20 0x000000000043f1e0 in ap_run_process_connection ()
#21 0x000000000044a3af in ?? ()
#22 0x000000000044a7d4 in ?? ()
#23 0x000000000044b6e4 in ap_mpm_run ()
#24 0x0000000000424c21 in main ()


Segfault is in strcmp() here:

(gdb) up
#1  0x00007f5c1f214f8f in user_wrapper_opener (wrapper=0x2133828, 
    filename=0x2cce9b8 "udata://custom/getMyDelivCity/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0/.json", mode=0x7f5c1f8019c3 "rb", options=0, opened_path=0x0, 
    context=0x257df30, __php_stream_call_depth=1, 
    __zend_filename=0x7f5c1f82a198 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/main/streams/streams.c", __zend_lineno=2061, 
    __zend_orig_filename=0x7f5c1f801288 "/var/tmp/portage/dev-lang/php-5.6.26/work/sapis-build/apache2/ext/standard/file.c", __zend_orig_lineno=550)
    at /usr/src/debug/dev-lang/php-5.6.26/sapis-build/apache2/main/streams/userspace.c:347
347		if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
(gdb) print file_globals.user_stream_current_filename
$1 = 0x7f5c15714ab0 <error: Cannot access memory at address 0x7f5c15714ab0>
 [2016-10-12 04:16 UTC] pollita@php.net
-Assigned To: +Assigned To: pollita
 [2016-10-12 05:00 UTC] pollita@php.net
-Status: Assigned +Status: Closed
 [2016-10-12 05:00 UTC] pollita@php.net
That was a fun one to track down.

Looks like the opener method is valid enough IF you assume that it'll always reach a return statement.

Because of the way PHP handles fatal errors (and die/exit for that matter), if the stream_open() method fataled/died/exited, the recursion protection variable wouldn't get reset, and its (now invalid) pointer would carry over into the next request.

Next request tried to compare to invalid memory == boom.

https://github.com/php/php-src/commit/9f86cdaf7fc44c0d97a35bc4d04622e3d3d53f4d

This fix (which has been applied to 5.6 and later) should take care of the problem.
 [2016-10-12 06:23 UTC] admin at fullspace dot ru
Many thanks, Sara!
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC