Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AddressSanitizer fails on PHP __zend_malloc() #760

Closed
oerdnj opened this issue Jan 10, 2017 · 3 comments
Closed

AddressSanitizer fails on PHP __zend_malloc() #760

oerdnj opened this issue Jan 10, 2017 · 3 comments

Comments

@oerdnj
Copy link

oerdnj commented Jan 10, 2017

Hi,

PHP seems to crash (SIGSEGV) when compiled with ASAN in ext/phar/phar.c memory management. I have suspected PHP at first, but I have simplified the code to:

    void *p = NULL;
    fprintf(stderr, "p = %p\n", p);
    p = __zend_malloc(sizeof(phar_mime_type));
    fprintf(stderr, "p = %p\n", p);
    free(p);
    fprintf(stderr, "p = %p\n", p);

And that should definitely not crash as __zend_malloc is a simple function:

static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void)
{
    fprintf(stderr, "Out of memory\n");
    exit(1);
}

ZEND_API void * __zend_malloc(size_t len)
{
    void *tmp = malloc(len);
    if (EXPECTED(tmp)) {
        return tmp;
    }
    zend_out_of_memory();
}

and copying the __zend_malloc under different name into ext/phar/phar.c results in no SIGSEGV.

To reproduce, download current PHP-7.0 branch from https://github.com/php/php-src, apply following patch:

diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 65ebce0f08..dbc02e5e13 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -3350,9 +3350,17 @@ PHP_GINIT_FUNCTION(phar) /* {{{ */
 #endif
        phar_mime_type mime;
 
+    void *p = NULL;
+       fprintf(stderr, "p = %p\n", p);
+       p = __zend_malloc(sizeof(phar_mime_type));
+       fprintf(stderr, "p = %p\n", p);
+       free(p);
+       fprintf(stderr, "p = %p\n", p);
+       return;
+
        memset(phar_globals, 0, sizeof(zend_phar_globals));
        phar_globals->readonly = 1;
-
+       
        zend_hash_init(&phar_globals->mime_types, 0, NULL, mime_type_dtor, 1);
 
 #define PHAR_SET_MIME(mimetype, ret, fileext) \

and compile with:

./buildconf
CC=clang-4.0 CFLAGS="-O0 -g -fsanitize=address -fno-omit-frame-pointer" ./configure --disable-all --enable-phar=shared
make

to reproduce the SIGSEGV that happens during build process, do:

$(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 ''

This should result in something like this:

p = (nil)
p = 0x6020000014d0
ASAN:DEADLYSIGNAL
=================================================================
==24265==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x7fd76261ef00 bp 0x7fd76293fb00 sp 0x7ffc900bca90 T0)
==24265==The signal is caused by a READ memory access.
==24265==Hint: address points to the zero page.
    #0 0x7fd76261eeff  (/lib/x86_64-linux-gnu/libc.so.6+0x77eff)
    #1 0x7fd75f86ef72 in zm_globals_ctor_phar /home/ondrej/Projects/php-src/ext/phar/phar.c:3357:2
    #2 0xf90991 in zend_startup_module_ex /home/ondrej/Projects/php-src/Zend/zend_API.c:1837:4
    #3 0xf92074 in zend_startup_module_zval /home/ondrej/Projects/php-src/Zend/zend_API.c:1858:10
    #4 0x10199d7 in zend_hash_apply /home/ondrej/Projects/php-src/Zend/zend_hash.c:1505:12
    #5 0xf91aa6 in zend_startup_modules /home/ondrej/Projects/php-src/Zend/zend_API.c:1969:2
    #6 0xcfa362 in php_module_startup /home/ondrej/Projects/php-src/main/main.c:2258:2
    #7 0x165474a in php_cli_startup /home/ondrej/Projects/php-src/sapi/cli/php_cli.c:431:6
    #8 0x164f705 in main /home/ondrej/Projects/php-src/sapi/cli/php_cli.c:1357:6
    #9 0x7fd7625c72b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
    #10 0x436e59 in _start (/home/ondrej/Projects/php-src/sapi/cli/php+0x436e59)

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

Running under gdb results in:

p = (nil)
p = 0x602000001530

Program received signal SIGSEGV, Segmentation fault.
_int_free (av=0x7ffff6c29b00 <main_arena>, p=0x602000001520, have_lock=0) at malloc.c:4013
4013	malloc.c: No such file or directory.
#0  _int_free (av=0x7ffff6c29b00 <main_arena>, p=0x602000001520, have_lock=0) at malloc.c:4013
        size = 8935141712242671632
        fb = <optimized out>
        nextchunk = 0x7c00602c00001530
        nextsize = <optimized out>
        nextinuse = <optimized out>
        prevsize = <optimized out>
        bck = <optimized out>
        fwd = <optimized out>
        errstr = 0x0
        locked = <optimized out>
        __func__ = "_int_free"
#1  0x00007ffff3b6ef73 in zm_globals_ctor_phar (phar_globals=0x7ffff3dff328 <phar_globals>) at ext/phar/phar.c:3357
        mime = {mime = 0x2971c10 <module_registry> "\001", len = 384, type = -112 '\220'}
        p = 0x602000001530
#2  0x0000000000f90992 in zend_startup_module_ex (module=0x60f0000006d0) at Zend/zend_API.c:1837
        name_len = 3
        lcname = 0x60300001b9a0
#3  0x0000000000f92075 in zend_startup_module_zval (zv=0x6190000001c0) at Zend/zend_API.c:1858
        module = 0x60f0000006d0
#4  0x00000000010199d8 in zend_hash_apply (ht=0x2971c10 <module_registry>, apply_func=0xf92030 <zend_startup_module_zval>) at Zend/zend_hash.c:1505
        idx = 6
        p = 0x6190000001c0
        result = 0
#5  0x0000000000f91aa7 in zend_startup_modules () at Zend/zend_API.c:1969
No locals.
#6  0x0000000000cfa363 in php_module_startup (sf=0x1cc80c0 <cli_sapi_module>, additional_modules=0x0, num_additional_modules=0) at main/main.c:2258
        retval = 0
        module_number = 0
        php_os = 0x1839cc0 <.str.32> "Linux"
        module = 0x6030000007c0
        zuf = <optimized out>
        zuv = <optimized out>
#7  0x000000000165474b in php_cli_startup (sapi_module=0x1cc80c0 <cli_sapi_module>) at sapi/cli/php_cli.c:431
No locals.
#8  0x000000000164f706 in main (argc=14, argv=0x60c000000040) at sapi/cli/php_cli.c:1357
        c = -1
        exit_status = 0
        module_started = 0
        sapi_started = 1
        use_extended_info = 0
        ini_path_override = 0x0
        ini_entries = 0x611000000040 "html_errors=0\nregister_argc_argv=1\nimplicit_flush=1\noutput_buffering=0\nmax_execution_time=0\nmax_input_time=-1\nextension_dir=\"./modules\"\nextension=phar.so\nopen_basedir=\noutput_buffering=0\nmemory_limit="...
        ini_entries_len = 205
        ini_ignore = 1
        sapi_module = 0x1cc80c0 <cli_sapi_module>
        php_optarg = 0x602000000350 ""
        php_optind = 14

Program terminated with signal SIGSEGV, Segmentation fault.
@yugr
Copy link

yugr commented Feb 15, 2017

Does the error happen inside a module loaded via dlopen with RTLD_DEEPBIND set? In that case it may be a dup of #611

@oerdnj
Copy link
Author

oerdnj commented Feb 15, 2017

I think that might be the case:

# 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)
#  define DL_LOAD(libname)          dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_DEEPBIND)
# else
#  define DL_LOAD(libname)          dlopen(libname, RTLD_LAZY | RTLD_GLOBAL)
# endif

Should I keep this open or close it as dup?

@yugr
Copy link

yugr commented Feb 15, 2017

I think better close as dup.

@oerdnj oerdnj closed this as completed Feb 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants