Bug 358980

Summary: 32 byte leak reported when code uses dlopen and links against pthread
Product: [Developer tools] valgrind Reporter: kdebugzilla
Component: memcheckAssignee: Julian Seward <jseward>
Status: CONFIRMED ---    
Severity: normal CC: ivosh
Priority: NOR    
Version: 3.11.0   
Target Milestone: ---   
Platform: Other   
OS: Linux   
Latest Commit: Version Fixed In:

Description kdebugzilla 2016-02-04 13:13:32 UTC
Trivial program reports 32 byte memory leak when it's linked against libdl an libpthread.

Several command outputs:

$ uname -a
Linux Calmarius 3.13.0-77-generic #121-Ubuntu SMP Wed Jan 20 10:50:42 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 14.04.3 LTS
Release:	14.04
Codename:	trusty

$ gcc -v
Reading specs from /usr/lib/gcc/x86_64-linux-gnu/4.8/specs
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc driver version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) executing gcc version 4.8.1

Consider this trivial program:

#include <dlfcn.h>

int main()
{
    void* handle = 0;

    handle = dlopen("libm.so", RTLD_NOW);
    dlclose(handle);    
    
    return 0;
}

Compile this program with this command line:

$ gcc -Wl,--no-as-needed -g -fPIC -o stuff  main.c -ldl -lpthread

The -Wl,--no-as-needed is crucial as it won't link against the specified libraries otherwise.

Then just run valgrind:

$ valgrind -v --leak-check=full --show-reachable=yes ./stuff
==4995== Memcheck, a memory error detector
==4995== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4995== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==4995== Command: ./stuff
==4995== 
--4995-- Valgrind options:
--4995--    -v
--4995--    --leak-check=full
--4995--    --show-reachable=yes
--4995-- Contents of /proc/version:
--4995--   Linux version 3.13.0-77-generic (buildd@lcy01-30) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #121-Ubuntu SMP Wed Jan 20 10:50:42 UTC 2016
--4995-- 
--4995-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-rdtscp-sse3-avx
--4995-- Page sizes: currently 4096, max supported 4096
--4995-- Valgrind library directory: /usr/local/lib/valgrind
--4995-- Reading syms from /home/dcsirmaz/workdir/crucible/dlopen/stuff
--4995-- Reading syms from /lib/x86_64-linux-gnu/ld-2.19.so
--4995--   Considering /lib/x86_64-linux-gnu/ld-2.19.so ..
--4995--   .. CRC mismatch (computed 4cbae35e wanted 8d683c31)
--4995--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.19.so ..
--4995--   .. CRC is valid
--4995-- Reading syms from /usr/local/lib/valgrind/memcheck-amd64-linux
--4995--    object doesn't have a dynamic symbol table
--4995-- Scheduler: using generic scheduler lock implementation.
--4995-- Reading suppressions file: /usr/local/lib/valgrind/default.supp
==4995== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-4995-by-dcsirmaz-on-???
==4995== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-4995-by-dcsirmaz-on-???
==4995== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-4995-by-dcsirmaz-on-???
==4995== 
==4995== TO CONTROL THIS PROCESS USING vgdb (which you probably
==4995== don't want to do, unless you know exactly what you're doing,
==4995== or are doing some strange experiment):
==4995==   /usr/local/lib/valgrind/../../bin/vgdb --pid=4995 ...command...
==4995== 
==4995== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==4995==   /path/to/gdb ./stuff
==4995== and then give GDB the following command
==4995==   target remote | /usr/local/lib/valgrind/../../bin/vgdb --pid=4995
==4995== --pid is optional if only one valgrind process is running
==4995== 
--4995-- REDIR: 0x4019ca0 (ld-linux-x86-64.so.2:strlen) redirected to 0x38056b11 (vgPlain_amd64_linux_REDIR_FOR_strlen)
--4995-- Reading syms from /usr/local/lib/valgrind/vgpreload_core-amd64-linux.so
--4995-- Reading syms from /usr/local/lib/valgrind/vgpreload_memcheck-amd64-linux.so
==4995== WARNING: new redirection conflicts with existing -- ignoring it
--4995--     old: 0x04019ca0 (strlen              ) R-> (0000.0) 0x38056b11 vgPlain_amd64_linux_REDIR_FOR_strlen
--4995--     new: 0x04019ca0 (strlen              ) R-> (2007.0) 0x04c2dc80 strlen
--4995-- REDIR: 0x4019a50 (ld-linux-x86-64.so.2:index) redirected to 0x4c2d830 (index)
--4995-- REDIR: 0x4019c70 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4c2edd0 (strcmp)
--4995-- REDIR: 0x401a9c0 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4c31e10 (mempcpy)
--4995-- Reading syms from /lib/x86_64-linux-gnu/libdl-2.19.so
--4995--   Considering /lib/x86_64-linux-gnu/libdl-2.19.so ..
--4995--   .. CRC mismatch (computed c1315e8c wanted 37097b60)
--4995--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libdl-2.19.so ..
--4995--   .. CRC is valid
--4995-- Reading syms from /lib/x86_64-linux-gnu/libpthread-2.19.so
--4995--   Considering /lib/x86_64-linux-gnu/libpthread-2.19.so ..
--4995--   .. CRC mismatch (computed d568bf33 wanted fb00d679)
--4995--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libpthread-2.19.so ..
--4995--   .. CRC is valid
--4995-- Reading syms from /lib/x86_64-linux-gnu/libc-2.19.so
--4995--   Considering /lib/x86_64-linux-gnu/libc-2.19.so ..
--4995--   .. CRC mismatch (computed dc620abc wanted 148cbd6e)
--4995--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.19.so ..
--4995--   .. CRC is valid
--4995-- REDIR: 0x52e5d60 (libc.so.6:strcasecmp) redirected to 0x4a25706 (_vgnU_ifunc_wrapper)
--4995-- REDIR: 0x52e8050 (libc.so.6:strncasecmp) redirected to 0x4a25706 (_vgnU_ifunc_wrapper)
--4995-- REDIR: 0x52e5530 (libc.so.6:memcpy@GLIBC_2.2.5) redirected to 0x4a25706 (_vgnU_ifunc_wrapper)
--4995-- REDIR: 0x52e37c0 (libc.so.6:rindex) redirected to 0x4c2d510 (rindex)
--4995-- REDIR: 0x52dc220 (libc.so.6:calloc) redirected to 0x4c2c8fe (calloc)
--4995-- REDIR: 0x52db750 (libc.so.6:malloc) redirected to 0x4c2ab96 (malloc)
--4995-- Reading syms from /lib/x86_64-linux-gnu/libm-2.19.so
--4995--   Considering /lib/x86_64-linux-gnu/libm-2.19.so ..
--4995--   .. CRC mismatch (computed a46ef660 wanted 767bfa33)
--4995--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libm-2.19.so ..
--4995--   .. CRC is valid
--4995-- Discarding syms at 0x5a23610-0x5a921b6 in /lib/x86_64-linux-gnu/libm-2.19.so due to munmap()
--4995-- REDIR: 0x52dbdf0 (libc.so.6:free) redirected to 0x4c2bcb0 (free)
==4995== 
==4995== HEAP SUMMARY:
==4995==     in use at exit: 32 bytes in 1 blocks
==4995==   total heap usage: 6 allocs, 5 frees, 1,524 bytes allocated
==4995== 
==4995== Searching for pointers to 1 not-freed blocks
==4995== Checked 102,648 bytes
==4995== 
==4995== 32 bytes in 1 blocks are still reachable in loss record 1 of 1
==4995==    at 0x4C2C994: calloc (vg_replace_malloc.c:711)
==4995==    by 0x4E3868F: _dlerror_run (dlerror.c:141)
==4995==    by 0x4E380C0: dlopen@@GLIBC_2.2.5 (dlopen.c:87)
==4995==    by 0x40066D: main (main.c:7)
==4995== 
==4995== LEAK SUMMARY:
==4995==    definitely lost: 0 bytes in 0 blocks
==4995==    indirectly lost: 0 bytes in 0 blocks
==4995==      possibly lost: 0 bytes in 0 blocks
==4995==    still reachable: 32 bytes in 1 blocks
==4995==         suppressed: 0 bytes in 0 blocks
==4995== 
==4995== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==4995== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

It looks like it's a regression to me. As this very exact bug was reported before and fixed:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=700899
Comment 1 Ivo Raisr 2017-05-05 14:35:47 UTC
With your small example, I got much more interesting results on Ubuntu 16.10 with gcc 6.3.0 and glibc 2.24.


==24182== Invalid read of size 1
==24182==    at 0x4017251: _dl_close (dl-close.c:817)
==24182==    by 0x40106C3: _dl_catch_error (dl-error.c:187)
==24182==    by 0x4E3B580: _dlerror_run (dlerror.c:163)
==24182==    by 0x4E3AFDE: dlclose (dlclose.c:46)
==24182==    by 0x108748: main (dl.c:6)
==24182==  Address 0x3d4 is not stack'd, malloc'd or (recently) free'd
==24182== 
==24182== 
==24182== Process terminating with default action of signal 11 (SIGSEGV)
==24182==  Access not within mapped region at address 0x3D4
==24182==    at 0x4017251: _dl_close (dl-close.c:817)
==24182==    by 0x40106C3: _dl_catch_error (dl-error.c:187)
==24182==    by 0x4E3B580: _dlerror_run (dlerror.c:163)
==24182==    by 0x4E3AFDE: dlclose (dlclose.c:46)
==24182==    by 0x108748: main (dl.c:6)
Segmentation fault (core dumped)
Comment 2 Ivo Raisr 2017-05-05 14:36:49 UTC
Forgot to say, native program run crashes as well.