php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73677 Generating phar.phar core dump with gcc ASAN enabled build
Submitted: 2016-12-07 15:58 UTC Modified: 2017-02-16 16:38 UTC
From: ondrej@php.net Assigned:
Status: Not a bug Package: PHAR related
PHP Version: 7.0.13 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: ondrej@php.net
New email:
PHP Version: OS:

 

 [2016-12-07 15:58 UTC] ondrej@php.net
Description:
------------
I am trying to find some heap smashing that happens to affect unserialize (different bug) and as a part of that I compiled PHP with gcc -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls (and couple of other options).

Generating phar.phar aborts in phar module shutdown functions.

Generated phar.phar can be executed with standard system PHP 7.0.13:

php ext/phar/phar.phar
No command given, check ext/phar/phar.phar help

So it looks like it was generated correctly.

But again it coredumps with ASAN-enabled PHP.  Both `bt full` attached.  I would be happy to provide more information.

Test script:
---------------
Generation:

/home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext-build/sapi/cli/php -n -d opcache.fast_shutdown=0 -d extension_dir=./modules -d extension=phar.so -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' -d phar.readonly=0 -d 'safe_mode=0' ext/phar/phar.php pack -f ext/phar/phar.phar -a pharcommand -c auto -x \\.svn -p 0 -s /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar/phar.php -h sha1 -b "/home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext-build/sapi/cli/php"  /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar/

Run-time:
/home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext-build/sapi/cli/php -n -d extension_dir=./modules -d extension=phar.so -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' ext/phar/phar.phar                                                         

Actual result:
--------------
== Generation ==

Program received signal SIGABRT, Aborted.
0x00007ffff557d067 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56      ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt full
#0  0x00007ffff557d067 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
        resultvar = 0
        pid = 136372
        selftid = 136372
#1  0x00007ffff557e448 in __GI_abort () at abort.c:89
        save_stage = 2
        act = {__sigaction_handler = {sa_handler = 0x0, sa_sigaction = 0x0}, sa_mask = {__val = {0, 140737488329520, 140737351949767, 140733193388033, 0, 0, 140737309371688, 66, 140737488329520, 140737339075856, 
              140737351975653, 0, 140737336725742, 40, 0, 2}}, sa_flags = 66, sa_restorer = 0x1}
        sigs = {__val = {32, 0 <repeats 15 times>}}
#2  0x00007ffff6f66f29 in __sanitizer::Abort () at ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc:75
No locals.
#3  0x00007ffff6f5eca5 in __asan::AsanDie () at ../../../../src/libsanitizer/asan/asan_rtl.cc:57
        num_calls = {val_dont_use = 1}
#4  0x00007ffff6f62aa2 in __sanitizer::Die () at ../../../../src/libsanitizer/sanitizer_common/sanitizer_common.cc:61
No locals.
#5  0x00007ffff6f673e8 in __sanitizer::RawWrite (buffer=buffer@entry=0x7fffffff9b30 '=' <repeats 65 times>, "\n") at ../../../../src/libsanitizer/sanitizer_common/sanitizer_posix.cc:230
        buffer = 0x7fffffff9b30 '=' <repeats 65 times>, "\n"
#6  0x00007ffff6f68172 in __sanitizer::SharedPrintfCode(bool, const char *, typedef __va_list_tag __va_list_tag *) (append_pid=append_pid@entry=false, format=0x7ffff6f884d0 '=' <repeats 65 times>, "\n", 
    args=args@entry=0x7fffffff9d08) at ../../../../src/libsanitizer/sanitizer_common/sanitizer_printf.cc:260
        args2 = {{gp_offset = 8, fp_offset = 48, overflow_arg_area = 0x7fffffff9de0, reg_save_area = 0x7fffffff9d20}}
        local_buffer = '=' <repeats 65 times>, "\n\000\377\377\177\000\000@\214\247UUU\000\000\000\235\377\377\377\177\000\000\340\233\377\377\377\177\000\000|\363\377\377\377\017\000\000W\000\000\000\000\000\000\000@\253\377\377\002", '\000' <repeats 11 times>, "u0HX\000\000\000\000\220\000\000\000\000\000\000\000e\221ƫ\022\361c\252\340\233\377\377\377\177\000\000\060\314\000\000\320`\000\000\001\000\000\000W\000\000\000\263\212\265A\000\000\000\000\020\260\354UUU\000\000?m\301UUU\000\000@"...
        buffer = 0x7fffffff9b30 '=' <repeats 65 times>, "\n"
        needed_length = <optimized out>
        buffer_size = <optimized out>
#7  0x00007ffff6f68301 in __sanitizer::Printf (format=<optimized out>) at ../../../../src/libsanitizer/sanitizer_common/sanitizer_printf.cc:271
        args = {{gp_offset = 8, fp_offset = 48, overflow_arg_area = 0x7fffffff9de0, reg_save_area = 0x7fffffff9d20}}
#8  0x00007ffff6f5dde9 in ScopedInErrorReport (this=<optimized out>) at ../../../../src/libsanitizer/asan/asan_report.cc:536
        num_calls = {val_dont_use = 1}
        reporting_thread_tid = 0
#9  __asan_report_error (pc=93824997881664, bp=136372, sp=140737488332504, addr=106721347469152, is_write=66, access_size=8) at ../../../../src/libsanitizer/asan/asan_report.cc:712
        curr_tid = 1
        tname = "@m\000\000\311\\\241\036\022\000\200\n\000\000\000\000\200\236\377\377\377\177\000\000\060\370\001\000 a\000\000@\370\001\000 a\000\000)\r\366\366\377\177\000\000\240\236\377\377\377\177\000\000\251\002\366\366\377\177\000\000\000\360\177\377\377\177\000\000\071\070\362\366\377\177\000\000\000\020\216\364\377\177\000\000\240\236\377\377\377\177\000\000\340\246\377\377\377\177\000\000@\370\001\000 a\000\000\000\020\216\364\377\177\000\000\001\000\000\000\000\000\000"
        bug_descr = 0x3 <error: Cannot access memory at address 0x3>
        stack = {top_frame_bp = 140737479962624, size = 140737336677590, trace = {140737336677672, 140737488351232, 140737488332512, 14, 140737336677672, 93824998293578, 93824998988354, 140737260296090, 140737260297413, 
            140737260407727, 93824996037755, 93824999517223, 93824998538929, 93824998731069, 93824997615377, 93825000948019, 93825000952938, 140737309481797, 93824999517223, 93824998538929, 93824998731069, 93824997615377, 
            93825000948019, 93825000952938, 140737309481797, 10, 140737336677672, 93824998293578, 93824996037858, 93824999517223, 93824998538929, 93824998731069, 93824997615377, 93825000948019, 93825000952938, 
            140737309481797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7957631179261175855, 8030569250133733988, 7741739932370298218, 8458375209990237543, 7018141356025736297, 7525567128463958317, 3471773029970622320, 
            3275375204984107310, 7022008352362820962, 8083795770394765680, 28776, 0 <repeats 68 times>, 140737336739617, 0, 0, 1154619927949213696, 805306369, 0, 56, 40, 140737336708393, 140737488331648, 140737336705705, 
            140737336758880, 140737336449116, 0, 140737336739617, 72057594037927936, 0, 12905557468058222584, 1308622850, 7355902136086953984, 105965433185008, 105965433185024, 140737336708393, 140737488331680, 
            140737336705705, 140737479962624, 140737336457273, 140737296338944, 140737488331680, 140737488333792, 105965433185024, 140737296338944, 1, 140737479962624, 140737336677590, 140737336678208, 140737488351232, 
            140737488333792, 10, 140737336677672, 93824998293578, 93824998709206, 93824998210871, 93824998208979, 93824997704690, 93824997619934, 93825000935172, 93825000952746, 140737309481797, 140737488333888, 8, 
            140737336678208, 93824998260091, 93825000935726, 3278577354, 1, 17, 106721347411712, 140737351931278, 0, 140737488331920, 140737336343032, 140737336358680, 140737488332192, 51227771, 140737488332176, 
            140737336739617, 0, 0, 140737354101960, 140737336375894, 140737336374904, 140737336358680, 4294967296, 4294967948, 140737488332096, 0, 140737488332336, 140737354102816, 140737488332376, 140737354101960, 1, 
            140737351931709, 0, 0, 140733193388033, 0, 140733193388033, 140737354101960, 140737488334208, 13, 140737336677672, 107545981468736, 0, 140737354102816, 140737488332192, 140737488332176, 3278577354, 
            140737336375894, 4294967295, 106652627926848, 140737336358680, 140737354101960, 106652627926872, 0, 140737488332240, 106721347410752, 11, 106721347410852, 106721347410880, 0, 140737488332288, 93824998293578, 
            140737488332368, 140737339075528, 0, 107820859040000, 93825002196288, 93825002199236, 140737488332512, 140737351949767, 17587891077121, 0, 140737488332384, 140737336358680, 106721347468992, 140737488332512, 3, 
            140737351975653, 13340168433644, 106721347469152}}
#10 0x00007ffff6f5f014 in __asan::__asan_report_load8 (addr=addr@entry=106721347469152) at ../../../../src/libsanitizer/asan/asan_rtl.cc:253
        bp = 140737488332512
        pc = <optimized out>
        local_stack = 13357348296855
        sp = 140737488332504
#11 0x0000555555ab7740 in _php_stream_free (stream=0x611000017ec0, close_options=close_options@entry=3) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/main/streams/streams.c:371
        ret = 1
        preserve_handle = 0
        release_cast = 1
        context = 0x0
#12 0x00007ffff2681a05 in phar_destroy_phar_data (phar=phar@entry=0x61300000c440) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar.c:254
No locals.
#13 0x00007ffff2681cc5 in phar_archive_delref (phar=0x61300000c440) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar.c:279
No locals.
#14 0x00007ffff269cbaf in phar_spl_foreign_dtor (object=0x62100000a100) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar_object.c:1083
        phar = <optimized out>
#15 0x00005555558f547b in spl_filesystem_object_free_storage (object=0x62100000b190) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/spl/spl_directory.c:80
No locals.
#16 0x0000555555c46c27 in zend_objects_store_free_object_storage (objects=objects@entry=0x5555562c75b0 <executor_globals+816>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_objects_API.c:99
        obj_ptr = 0x625000005118
        end = 0x625000005108
        obj = 0x62100000b190
#17 0x0000555555b57eb1 in shutdown_executor () at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_execute_API.c:357
        __orig_bailout = <optimized out>
        func = <optimized out>
        ce = <optimized out>
#18 0x0000555555b86d3d in zend_deactivate () at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend.c:967
No locals.
#19 0x0000555555a76711 in php_request_shutdown (dummy=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/main/main.c:1833
        report_memleaks = 1 '\001'
#20 0x0000555555da4133 in do_cli (argc=<optimized out>, argv=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/sapi/cli/php_cli.c:1141
        c = <optimized out>
        behavior = <optimized out>
        reflection_what = <optimized out>
        exec_direct = <optimized out>
        exec_run = <optimized out>
        exec_begin = <optimized out>
        exec_end = <optimized out>
        arg_free = <optimized out>
        arg_excp = <optimized out>
        script_file = <optimized out>
        translated_path = 0x60800005a320 "/home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext-build/ext/phar/phar.php"
        param_error = <optimized out>
#21 0x0000555555da546a in main (argc=<optimized out>, argv=0x61200000bd40) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/sapi/cli/php_cli.c:1344
        __orig_bailout = 0x0
        __bailout = {{__jmpbuf = {105759274745344, -4294967279, -9223142581604977250, 105759274745392, 105759274745248, -4294967279, -9223142580990550501, 105759274745296}, __mask_was_saved = 48448, __saved_mask = {__val = {
                18446744069414584337, 9223372043239708525, 105759274745200, 105759274745104, 21474836497, 9230944079081521229, 105827994212880, 105759274745008, 18446744069414584337, 9223378990047502327, 105759274745056, 0, 
                0, 0, 0, 3429799609}}}}
        c = <optimized out>
        exit_status = 0
        module_started = 1
        sapi_started = 1
        php_optarg = 0x60300000bec0 <incomplete sequence \360\276>
        php_optind = 964689930
        use_extended_info = 0
        ini_path_override = 0x0
        ini_entries = 0x61200000ba40 "html_errors=0\nregister_argc_argv=1\nimplicit_flush=1\noutput_buffering=0\nmax_execution_time=0\nmax_input_time=-1\nopcache.fast_shutdown=0\nextension_dir=\"./modules\"\nextension=phar.so\nopen_basedir=\noutput_b"...
        ini_entries_len = 147
        ini_ignore = 1
        sapi_module = <optimized out>

== Runtime ==
Program received signal SIGSEGV, Segmentation fault.
_int_free (av=0x7ffff58ed620 <main_arena>, p=0x60200000d500, have_lock=0) at malloc.c:3960
3960    malloc.c: No such file or directory.
(gdb) bt full
#0  _int_free (av=0x7ffff58ed620 <main_arena>, p=0x60200000d500, have_lock=0) at malloc.c:3960
        size = 4935945256022573072
        fb = <optimized out>
        nextchunk = 0x4480602f0000d510
        nextsize = <optimized out>
        nextinuse = <optimized out>
        prevsize = <optimized out>
        bck = <optimized out>
        fwd = <optimized out>
        errstr = 0x0
        locked = 1
        __func__ = "_int_free"
#1  0x00007ffff267c7ff in mime_type_dtor (zv=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar.c:3345
No locals.
#2  0x0000555555bc564b in zend_hash_destroy (ht=0x7ffff28e0ae0 <phar_globals+480>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_hash.c:1276
        p = 0x61d000013780
        end = 0x61d000013c80
#3  0x00007ffff267c7dc in zm_globals_dtor_phar (phar_globals=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar.c:3413
No locals.
#4  0x0000555555b9f5e1 in module_destructor (module=module@entry=0x60f00000e320) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_API.c:2514
No locals.
#5  0x0000555555b8378e in module_destructor_zval (zv=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend.c:615
        module = 0x60f00000e320
#6  0x0000555555bc823b in _zend_hash_del_el_ex (prev=<optimized out>, p=<optimized out>, idx=<optimized out>, ht=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_hash.c:1026
No locals.
#7  _zend_hash_del_el (p=0x619000003980, idx=12, ht=0x5555562c83a0 <module_registry>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_hash.c:1050
        prev = <optimized out>
#8  zend_hash_graceful_reverse_destroy (ht=ht@entry=0x5555562c83a0 <module_registry>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_hash.c:1506
        idx = 12
        p = 0x619000003980
#9  0x0000555555b99b64 in zend_destroy_modules () at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_API.c:1982
No locals.
#10 0x0000555555b8646e in zend_shutdown () at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend.c:840
No locals.
#11 0x0000555555a782c0 in php_module_shutdown () at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/main/main.c:2362
No locals.
#12 0x0000555555da5501 in main (argc=<optimized out>, argv=0x60b00000af90) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/sapi/cli/php_cli.c:1359
        c = <optimized out>
        exit_status = 1
        module_started = 1
        sapi_started = 1
        php_optarg = 0x7ffff7ffe1a8 ""
        php_optind = -865167687
        use_extended_info = 0
        ini_path_override = 0x0
        ini_entries = 0x611000009f00 "\021"
        ini_entries_len = 95
        ini_ignore = 1
        sapi_module = <optimized out>
#0  _int_free (av=0x7ffff58ed620 <main_arena>, p=0x60200000d500, have_lock=0) at malloc.c:3960
        size = 4935945256022573072
        fb = <optimized out>
        nextchunk = 0x4480602f0000d510
        nextsize = <optimized out>
        nextinuse = <optimized out>
        prevsize = <optimized out>
        bck = <optimized out>
        fwd = <optimized out>
        errstr = 0x0
        locked = 1
        __func__ = "_int_free"
#1  0x00007ffff267c7ff in mime_type_dtor (zv=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar.c:3345
No locals.
#2  0x0000555555bc564b in zend_hash_destroy (ht=0x7ffff28e0ae0 <phar_globals+480>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_hash.c:1276
        p = 0x61d000013780
        end = 0x61d000013c80
#3  0x00007ffff267c7dc in zm_globals_dtor_phar (phar_globals=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/ext/phar/phar.c:3413
No locals.
#4  0x0000555555b9f5e1 in module_destructor (module=module@entry=0x60f00000e320) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_API.c:2514
No locals.
#5  0x0000555555b8378e in module_destructor_zval (zv=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend.c:615
        module = 0x60f00000e320
#6  0x0000555555bc823b in _zend_hash_del_el_ex (prev=<optimized out>, p=<optimized out>, idx=<optimized out>, ht=<optimized out>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_hash.c:1026
No locals.
#7  _zend_hash_del_el (p=0x619000003980, idx=12, ht=0x5555562c83a0 <module_registry>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_hash.c:1050
        prev = <optimized out>
#8  zend_hash_graceful_reverse_destroy (ht=ht@entry=0x5555562c83a0 <module_registry>) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_hash.c:1506
        idx = 12
        p = 0x619000003980
#9  0x0000555555b99b64 in zend_destroy_modules () at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend_API.c:1982
No locals.
#10 0x0000555555b8646e in zend_shutdown () at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/Zend/zend.c:840
No locals.
#11 0x0000555555a782c0 in php_module_shutdown () at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/main/main.c:2362
No locals.
#12 0x0000555555da5501 in main (argc=<optimized out>, argv=0x60b00000af90) at /home/ondrej/Projects/pkg-php/build-area-asan/php7.0-7.0.13/sapi/cli/php_cli.c:1359
        c = <optimized out>
        exit_status = 1
        module_started = 1
        sapi_started = 1
        php_optarg = 0x7ffff7ffe1a8 ""
        php_optind = -865167687
        use_extended_info = 0
        ini_path_override = 0x0
        ini_entries = 0x611000009f00 "\021"
        ini_entries_len = 95
        ini_ignore = 1
        sapi_module = <optimized out>


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-12-07 15:59 UTC] ondrej@php.net
-Type: Bug +Type: Security -Private report: No +Private report: Yes
 [2016-12-27 07:00 UTC] stas@php.net
-Status: Open +Status: Feedback
 [2016-12-27 07:00 UTC] stas@php.net
Not sure I understand - how is it a security issue?
 [2017-01-05 11:13 UTC] ondrej@php.net
> Not sure I understand - how is it a security issue?

As I said in security@php.net:

> ASAN enable builds of PHP 7.0.13 fails on phar extension shutdown,
> possibly indicating stack smashing. I have marked the bug as security
> and private just to be on safe side and I would appreciate if somebody
> more knowledgeable in PHP internals could take a look at this:

So if you don't think it's a security bug, please feel free to unmark it as such.
 [2017-01-06 08:50 UTC] stas@php.net
-Status: Feedback +Status: Open
 [2017-01-06 09:19 UTC] stas@php.net
I can't see any issue with regular PHP. I'm not familiar with ASAN and how it changes the build - maybe something went wrong there? I'm afraid without being able to demonstrate the problem somehow on a regular PHP I can't make anything out of it. I manually checked invocations of mime_type_dtor and seen nothing wrong. Also, streams.c:371 is this:

       if (EG(active)) {

where EG is a static structure. So I am not sure how such access could fail at all. 

Could you explain a bit more how you determined there is a stack smashing going on?
 [2017-01-06 09:19 UTC] stas@php.net
-Status: Open +Status: Feedback
 [2017-01-10 10:07 UTC] ondrej@php.net
Few notes after a bit of experimenting with this crash.

I can't reproduce the crash with --enable-phar (statically compiled in module).

I can reproduce it on PHP-7.0 branch with:

CC=clang-4.0 CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer" ./configure --disable-all --enable-phar=shared
make # this will crash in phar.phar generation

and now run:

gdb -ex=r --args $(pwd)/sapi/cli/php -n -d extension_dir=./modules -d extension=phar.so -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' ext/phar/phar.phar

bt full produces:

(gdb) bt full
#0  _int_free (av=0x7ffff6c29b00 <main_arena>, p=0x602000000e40, have_lock=0) at malloc.c:4013
        size = 3891110155357519888
        fb = <optimized out>
        nextchunk = 0x3600603200000e50
        nextsize = <optimized out>
        nextinuse = <optimized out>
        prevsize = <optimized out>
        bck = <optimized out>
        fwd = <optimized out>
        errstr = 0x0
        locked = <optimized out>
        __func__ = "_int_free"
#1  0x0000000000953a15 in zend_hash_destroy (ht=<optimized out>) at Zend/zend_hash.c:1276
        p = 0x61d000008d80
        end = 0x61d000009280
#2  0x000000000092a50d in module_destructor (module=0x60f0000006d0) at Zend/zend_API.c:2514
No locals.
#3  0x0000000000913951 in module_destructor_zval (zv=<optimized out>) at Zend/zend.c:615
        module = 0x60f0000006d0
#4  0x0000000000956794 in _zend_hash_del_el_ex (idx=<optimized out>, p=0x6190000001c0, prev=<optimized out>, ht=<optimized out>) at Zend/zend_hash.c:1026
No locals.
#5  _zend_hash_del_el (idx=<optimized out>, p=0x6190000001c0, ht=<optimized out>) at Zend/zend_hash.c:1050
        prev = <optimized out>
#6  zend_hash_graceful_reverse_destroy (ht=<optimized out>) at Zend/zend_hash.c:1506
        idx = 6
        p = 0x6190000001c0
#7  0x00000000009144a6 in zend_shutdown () at Zend/zend.c:850
No locals.
#8  0x00000000008050ae in php_module_shutdown () at main/main.c:2360
No locals.
#9  0x0000000000b29243 in main (argc=<optimized out>, argv=0x60b000000040) at sapi/cli/php_cli.c:1362
        php_optarg = <optimized out>
        sapi_started = 0
        module_started = 1
        exit_status = 0
        sapi_module = <optimized out>
        ini_ignore = 0
        ini_entries_len = <optimized out>
        ini_entries = 0x611000000040 "\f"
        c = <optimized out>
        ini_path_override = <optimized out>

But all it takes for PHP to crash is to load the phar.so module:

gdb -ex=r --args $(pwd)/sapi/cli/php -n -d extension_dir=./modules -d extension=phar.so -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1'  -r 'exit(0);'

Program received signal SIGSEGV, Segmentation fault.
_int_free (av=0x7ffff6c29b00 <main_arena>, p=0x602000000e80, have_lock=0) at malloc.c:4013
4013    malloc.c: No such file or directory.
(gdb) bt full
#0  _int_free (av=0x7ffff6c29b00 <main_arena>, p=0x602000000e80, have_lock=0) at malloc.c:4013
        size = 3891110155357519888
        fb = <optimized out>
        nextchunk = 0x3600603200000e90
        nextsize = <optimized out>
        nextinuse = <optimized out>
        prevsize = <optimized out>
        bck = <optimized out>
        fwd = <optimized out>
        errstr = 0x0
        locked = <optimized out>
        __func__ = "_int_free"
#1  0x0000000000953a15 in zend_hash_destroy (ht=<optimized out>) at Zend/zend_hash.c:1276
        p = 0x61d000008d80
        end = 0x61d000009280
#2  0x000000000092a50d in module_destructor (module=0x60f0000006d0) at Zend/zend_API.c:2514
No locals.
#3  0x0000000000913951 in module_destructor_zval (zv=<optimized out>) at Zend/zend.c:615
        module = 0x60f0000006d0
#4  0x0000000000956794 in _zend_hash_del_el_ex (idx=<optimized out>, p=0x6190000001c0, prev=<optimized out>, ht=<optimized out>) at Zend/zend_hash.c:1026
No locals.
#5  _zend_hash_del_el (idx=<optimized out>, p=0x6190000001c0, ht=<optimized out>) at Zend/zend_hash.c:1050
        prev = <optimized out>
#6  zend_hash_graceful_reverse_destroy (ht=<optimized out>) at Zend/zend_hash.c:1506
        idx = 6
        p = 0x6190000001c0
#7  0x00000000009144a6 in zend_shutdown () at Zend/zend.c:850
No locals.
#8  0x00000000008050ae in php_module_shutdown () at main/main.c:2360
No locals.
#9  0x0000000000b29243 in main (argc=<optimized out>, argv=0x60c000000040) at sapi/cli/php_cli.c:1362
        php_optarg = <optimized out>
        sapi_started = 0
        module_started = 1
        exit_status = 0
        sapi_module = <optimized out>
        ini_ignore = 0
        ini_entries_len = <optimized out>
        ini_entries = 0x611000000040 "\f"
        c = <optimized out>
        ini_path_override = <optimized out>

To check whether this is just isolated to phar extension, I tried also building json.so shared extension and:

$(pwd)/sapi/cli/php -n -d extension_dir=./modules -d extension=json.so -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1'  -r 'exit(0);'

is just fine.

The crash can also be triggered by running nothing:

$ export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-4.0/bin/llvm-symbolizer
$ echo '<?php ?>' | $(pwd)/sapi/cli/php -n -d extension_dir=./modules -d extension=phar.so -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1'
ASAN:DEADLYSIGNAL
=================================================================
==70879==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x7f3c9f731f00 bp 0x7f3c9fa52b00 sp 0x7ffeeff12520 T0)
==70879==The signal is caused by a READ memory access.
==70879==Hint: address points to the zero page.
    #0 0x7f3c9f731eff  (/lib/x86_64-linux-gnu/libc.so.6+0x77eff)
    #1 0x953a14 in zend_hash_destroy /home/ondrej/Projects/pkg-php/php-src/Zend/zend_hash.c:1276:6
    #2 0x92a50c in module_destructor /home/ondrej/Projects/pkg-php/php-src/Zend/zend_API.c:2514:4
    #3 0x913950 in module_destructor_zval /home/ondrej/Projects/pkg-php/php-src/Zend/zend.c:615:2
    #4 0x956793 in _zend_hash_del_el_ex /home/ondrej/Projects/pkg-php/php-src/Zend/zend_hash.c:1026:3
    #5 0x956793 in _zend_hash_del_el /home/ondrej/Projects/pkg-php/php-src/Zend/zend_hash.c:1050
    #6 0x956793 in zend_hash_graceful_reverse_destroy /home/ondrej/Projects/pkg-php/php-src/Zend/zend_hash.c:1506
    #7 0x9144a5 in zend_shutdown /home/ondrej/Projects/pkg-php/php-src/Zend/zend.c:850:2
    #8 0x8050ad in php_module_shutdown /home/ondrej/Projects/pkg-php/php-src/main/main.c:2360:2
    #9 0xb29242 in main /home/ondrej/Projects/pkg-php/php-src/sapi/cli/php_cli.c:1362:3
    #10 0x7f3c9f6da2b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
    #11 0x436639 in _start (/home/ondrej/Projects/pkg-php/php-src/sapi/cli/php+0x436639)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libc.so.6+0x77eff)
==70879==ABORTING
Aborted (core dumped)

So, the crash is reproducible with AddressSanitizer and all it takes is to load shared phar.so extension.
 [2017-01-10 11:21 UTC] ondrej@php.net
Additional info:

The problem is triggered in global shutdown function calling:

zend_hash_destroy(&phar_globals->mime_types);

There's probably some memory corruption when calling zend_hash_str_add_mem, as redefining:

#define PHAR_SET_MIME(mimetype, ret, fileext)

(e.g. do nothing) makes the problem to go away.

Adding even one mimetype to phar_globals->mime_types with PHAR_SET_MIME triggers the problem.
 [2017-01-10 14:30 UTC] ondrej@php.net
There's something fishy going on in this particular module.  The SIGSEGV happens in mime_type_dtor() on free(Z_PTR_P(zv)).  I have debugged the pointer passed to the function and the memory address seems to be consistent with the one allocated in zend_hash_str_add_mem().

However it sigsegv on the first try to free() that string.

Is it possible, that PHP is doing something to the standard malloc/free?  Because even a simple:

    void *p = NULL;
    fprintf(stderr, "p = %p\n", p);
    p = pemalloc(sizeof(phar_mime_type), 1);
    fprintf(stderr, "p = %p\n", p);
    pefree(p, 1);
    fprintf(stderr, "p = %p\n", p);

in the GINIT function triggers the error.

Making this not persistent (calling pemalloc/pefree with 0 as second arg, aka using emalloc/efree) makes this problem to go away.
 [2017-01-10 14:58 UTC] ondrej@php.net
I have reported this as https://github.com/google/sanitizers/issues/760, as I am more and more convinced that this is a bug in AddressSanitizer.
 [2017-01-10 17:21 UTC] stas@php.net
-Status: Feedback +Status: Open
 [2017-01-16 08:07 UTC] stas@php.net
-Status: Open +Status: Not a bug
 [2017-01-16 08:07 UTC] stas@php.net
Looks like not a PHP issue. Please reopen if it turns out otherwise.
 [2017-02-15 10:23 UTC] ondrej@php.net
Turns out AddressSanitizer is not compatible with RTLD_DEEPBIND, so simple patch like this should fix the -fsanitize=address builds:

From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ondrej@sury.org>
Date: Wed, 15 Feb 2017 11:06:08 +0100
Subject: Disable RTLD_DEEPBIND for ASAN builds

---
 Zend/zend_portability.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h
index c1e17c30f..dd4fcdc84 100644
--- a/Zend/zend_portability.h
+++ b/Zend/zend_portability.h
@@ -131,6 +131,12 @@

 #if defined(HAVE_LIBDL) && !defined(ZEND_WIN32)

+# if defined(__has_feature)
+#  if __has_feature(address_sanitizer)
+#   define __SANITIZE_ADDRESS__)
+#  endif
+# endif
+
 # ifndef RTLD_LAZY
 #  define RTLD_LAZY 1    /* Solaris 1, FreeBSD's (2.1.7.1 and older) */
 # endif
@@ -141,7 +147,7 @@

 # if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT)
 #  define DL_LOAD(libname)                     dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
-# elif defined(RTLD_DEEPBIND)
+# elif defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__)
 #  define DL_LOAD(libname)                     dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_DEEPBIND)
 # else
 #  define DL_LOAD(libname)                     dlopen(libname, RTLD_LAZY | RTLD_GLOBAL)
 [2017-02-15 20:48 UTC] stas@php.net
Since this patch is not security-sensitive, I'd submit it as pull request, and if nobody objects, I think it's ok to merge it. Would like more eyes on it since I'm not 100% sure what is the effect of disabling RTLD_DEEPBIND.
 [2017-02-15 20:55 UTC] ondrej@php.net
I think this whole report should not be private, as this is a condition caused by AddressSanitizer.

Feel free to do a PR, or I will do that.

As far as I understand the effect of RTLD_DEEPBIND, it only affects the symbol ordering with DEEPBIND preferring symbols from the .so library to the global symbols.

So in theory, it might have some side effects, but we are talking about builds with AddressSanitizer only here, and this is not expected to run in a production environment.
 [2017-02-15 22:15 UTC] stas@php.net
-Type: Security +Type: Bug
 [2017-02-16 12:10 UTC] ondrej@php.net
For the reference: https://github.com/php/php-src/pull/2386
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 15:01:29 2024 UTC