php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70290 Null pointer deref (segfault) in spl_autoload via ob_start
Submitted: 2015-08-18 10:24 UTC Modified: 2015-08-23 08:44 UTC
From: hugh at allthethings dot co dot nz Assigned: laruence
Status: Closed Package: Reproducible crash
PHP Version: 5.6.12 OS: Linux
Private report: No CVE-ID:
 [2015-08-18 10:24 UTC] hugh at allthethings dot co dot nz
Description:
------------
Found this using afl-fuzz, see http://lcamtuf.coredump.cx/afl/

Affects 5.6.12, 5.5.28, (couldn't compile 5.4, and EOL is basically now so meh).

To reproduce, compile PHP normally, then run ./sapi/cli/php with the test script
<?php ob_start( spl_autoload ); ?> 1
You should get a segfault.

The test case required to have SOME output displayed to screen before the ob_start is called, hence the 1 at the end of the test script (only if a file called 9 exists in the current directory and is a valid php file with a class of no name (I had <?php class {} ?>... (this is because ob_start will call spl_autoload with an empty first argument (output buffer), and second argument of 9 (the phase)), otherwise if the file doesn't exist, removing the 1 will also make it crash. I've just included it here for completeness...).

The bug happens because if the spl_autoload doesn't load anything valid, then it tries to throw an exception, but in that test it uses active_opline, which is (*EG(opline_ptr)), which is (*(executor_state.opline_ptr)) or something, which is null.

Patch to fix would either be:
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index 6b886b7..3424b90 100644
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -358,7 +358,7 @@ PHP_FUNCTION(spl_autoload)
                 * The "scope" is determined by an opcode, if it is ZEND_FETCH_CLASS we know function was called indirectly by
                 * the Zend engine.
                 */
-               if (active_opline->opcode != ZEND_FETCH_CLASS) {
+               if (EG(opline_ptr) && active_opline->opcode != ZEND_FETCH_CLASS) {
                        zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Class %s could not be loaded", class_name);
                } else {
                        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s could not be loaded", class_name);


or some code to not let you use a internal function like that. Thoughts?



Test script:
---------------
<?php ob_start( spl_autoload ); ?> 1

Expected result:
----------------
No crash

Actual result:
--------------
(gdb) bt
#0  0x00000000004e4c02 in zif_spl_autoload (ht=2, return_value=0x7ffff7fe2940, 
    return_value_ptr=0x7fffffffd218, this_ptr=0x0, return_value_used=1)
    at /root/php-src/ext/spl/php_spl.c:361
#1  0x0000000000638aa3 in zend_call_function (fci=0x7ffff7fe3838, 
    fci_cache=0x7ffff7fe3880) at /root/php-src/Zend/zend_execute_API.c:847
#2  0x000000000065936e in zend_fcall_info_call (fci=0x7ffff7fe3838, 
    fcc=0x7ffff7fe3880, retval_ptr_ptr=0x7fffffffd218, args=0x0)
    at /root/php-src/Zend/zend_API.c:3397
#3  0x00000000005dc58d in php_output_handler_op (handler=0x7ffff7fe38c0, 
    context=0x7fffffffd2b0) at /root/php-src/main/output.c:977
#4  0x00000000005dcf2d in php_output_stack_pop (flags=1)
    at /root/php-src/main/output.c:1244
#5  0x00000000005db0da in php_output_end_all () at /root/php-src/main/output.c:351
#6  0x00000000005c515f in php_request_shutdown (dummy=0x0)
    at /root/php-src/main/main.c:1840
#7  0x000000000076ee5f in do_cli (argc=2, argv=0xb747c0)
    at /root/php-src/sapi/cli/php_cli.c:1177
#8  0x000000000076f67b in main (argc=2, argv=0xb747c0)
    at /root/php-src/sapi/cli/php_cli.c:1378
(gdb) i r
rax            0x0      0
rbx            0x7fffffffd218   140737488343576
rcx            0xffffffffffffff60       -160
rdx            0x6b8    1720
rsi            0x7ffff7fe2900   140737354017024
rdi            0xb74a80 12012160
rbp            0x7fffffffcec0   0x7fffffffcec0
rsp            0x7fffffffce40   0x7fffffffce40
r8             0x3      3
r9             0x7ffff74957b8   140737342166968
r10            0x7fffffffc970   140737488341360
r11            0x246    582
r12            0x418830 4294704
r13            0x7fffffffe9f0   140737488349680
r14            0x0      0
r15            0x0      0
rip            0x4e4c02 0x4e4c02 <zif_spl_autoload+514>
eflags         0x10246  [ PF ZF IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) x/i $rip
=> 0x4e4c02 <zif_spl_autoload+514>:     mov    (%rax),%rax


With ASAN compiled
ASAN:SIGSEGV
=================================================================
==15374== ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x0000005f8f07 sp 0x7fffd148dd50 bp 0x7fffd148def0 T0)
AddressSanitizer can not provide additional info.
    #0 0x5f8f06 (/root/php-src/sapi/cli/php+0x5f8f06)
    #1 0x990c83 (/root/php-src/sapi/cli/php+0x990c83)
    #2 0x9ee97c (/root/php-src/sapi/cli/php+0x9ee97c)
    #3 0x88762b (/root/php-src/sapi/cli/php+0x88762b)
    #4 0x8891c7 (/root/php-src/sapi/cli/php+0x8891c7)
    #5 0x883d96 (/root/php-src/sapi/cli/php+0x883d96)
    #6 0x84be0a (/root/php-src/sapi/cli/php+0x84be0a)
    #7 0xd22665 (/root/php-src/sapi/cli/php+0xd22665)
    #8 0xd23c73 (/root/php-src/sapi/cli/php+0xd23c73)
    #9 0x7fcdef217ec4 (/lib/x86_64-linux-gnu/libc-2.19.so+0x21ec4)
    #10 0x418cf8 (/root/php-src/sapi/cli/php+0x418cf8)
==15374== ABORTING


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-08-19 10:49 UTC] laruence@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: laruence
 [2015-08-19 10:59 UTC] hugh at allthethings dot co dot nz
Will there be a CVE assigned for this?

Cheers,

Hugh
 [2015-08-23 05:42 UTC] stas@php.net
-Type: Security +Type: Bug
 [2015-08-23 05:42 UTC] stas@php.net
This doesn't look like a security issue, this is a specially crafted code which is extremely unlikely to happen in real application. So I do not think it needs a CVE.
 [2015-08-23 08:44 UTC] hugh at allthethings dot co dot nz
Hi stas,

No worries, next time!

Cheers,

Hugh
 [2015-09-03 18:10 UTC] ab@php.net
Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b584b513983319be170f02828bc7c12850b40320
Log: Fixed bug #70290 (Null pointer deref (segfault) in spl_autoload via ob_start)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Apr 25 16:01:40 2017 UTC