linux glibc sometimes improperly free()'s objects created by __libc_memalign()

Bradley C. Kuszmaul bradley at mit.edu
Thu Dec 18 19:15:28 PST 2014


I'd like to alert you to a problem that I found in linux libc.  This bug
may affect users of jemalloc.

I've submitted a bug on libc as
 https://sourceware.org/bugzilla/show_bug.cgi?id=17730

The problem is that under some conditions, libc allocates memory using
__libc_memalign or __libc_malloc and later frees it using free(), rather
than __libc_free().  This behavior is incorrect: for example, there is no
reason to believe that jemalloc will know what to do with
free(__libc_malloc(N)).   It seems quite possible that the jemalloc data
structures could become corrupted, but I haven't investigated exactly what
happens.

One possible workaround for the problem is to arrange that if jemalloc sees
a pointer that it didn't create, then pass the pointer to the system's free
as

    if (pointer_doesnt_belong_to_jemalloc(p)) {
       void (*free_p)(void*) = (void(*)(void*)) (dlsym(RTLD_NEXT, "free"));
       free_p(p);
    }

this workaround *might* fix the problem for some users.  I haven't got a
better idea except to fix libc.


The conditions are as follows:

Here are the conditions under which I can reproduce this problem:
 * The main user code defines its own malloc/free
 * The main user code dynamically loads a library using dlopen()/dlsym().
 * The library contains thread-local storage.
 * A thread runs, and then proceeds to touch the thread-local storage,
eventually invoking tls_get_addr_tail() (in /elf/dl-tls.c) and then
allocate_and_init() and then __libc_memalign().
 * Eventually, this storage is deallocated using free() instead __libc_free().

I ran this on Fedora 20, but it looks like the problem is still there
in libc-main.

A test case is attached.  This test case implements its own very
simple malloc/free library and complains if you pass free() an
improper pointer. You can run it as show below.

-Bradley

[bradley at 30-87-232 test]$ tar xfz libc-bug.tar.gz
[bradley at 30-87-232 test]$ cd libc-bug/
[bradley at 30-87-232 libc-bug]$ make check
gcc -g -W -Wall -Werror -pthread -fPIC --shared libtls.c -o libtls.so
cc -g -W -Wall -Werror -pthread -fPIC    tls.c  -ldl -o tls
./tls
malloc(32)=0x6020c0
malloc(46)=0x6020e0
malloc(1214)=0x60210e
malloc(46)=0x6025cc
malloc(56)=0x6025fa
malloc(96)=0x602632
malloc(288)=0x602692
malloc(288)=0x6027b2
malloc(288)=0x6028d2
malloc(288)=0x6029f2
1048576
1048576
1048576
malloc(288)=0x602b12
1048576
1048576
free passed 0xea1010 not in range
make: *** [check] Aborted (core dumped)
[bradley at 30-87-232 libc-bug]$
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://jemalloc.net/mailman/jemalloc-discuss/attachments/20141218/20b15fb7/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: libc-bug.tar.gz
Type: application/x-gzip
Size: 1691 bytes
Desc: not available
URL: <http://jemalloc.net/mailman/jemalloc-discuss/attachments/20141218/20b15fb7/attachment.bin>


More information about the jemalloc-discuss mailing list