When calling getpwuid(), a memory leak of 60 bytes is reported by valgrind. This is consistently reported on on debian squeeze, ubuntu 10.04, and when compiling and linking with the the latest glibc (git commit e6bdb741d11a5c408f1f162b4d649b93d8012ec9). Here is a minimal program for testing. #include <pwd.h> main() { struct passwd *q = getpwuid(geteuid()); }
Please provide actual Valgrind output. Here is what I see using current glibc git (64-bit): ... ==10335== HEAP SUMMARY: ==10335== in use at exit: 0 bytes in 0 blocks ==10335== total heap usage: 53 allocs, 53 frees, 7,672 bytes allocated ==10335== ==10335== All heap blocks were freed -- no leaks are possible same for 32-bit build.
My glibc built from the git repository is not working, and these results were valid. Below are the results on my platform, using the glibc 2.11.1. ==17631== HEAP SUMMARY: ==17631== in use at exit: 300 bytes in 11 blocks ==17631== total heap usage: 68 allocs, 57 frees, 9,898 bytes allocated ==17631== ==17631== 300 (60 direct, 240 indirect) bytes in 1 blocks are definitely lost in loss record 11 of 11 ==17631== at 0x4C274A8: malloc (vg_replace_malloc.c:236) ==17631== by 0x4F27DCA: nss_parse_service_list (nsswitch.c:622) ==17631== by 0x4F286ED: __nss_database_lookup (nsswitch.c:164) ==17631== by 0x55B23CF: ??? ==17631== by 0x55B4244: ??? ==17631== by 0x4ED69FC: getpwuid_r@@GLIBC_2.2.5 (getXXbyYY_r.c:253) ==17631== by 0x4ED62EE: getpwuid (getXXbyYY.c:117) ==17631== by 0x40058C: main (in /tmp/a.out) ==17631== ==17631== LEAK SUMMARY: ==17631== definitely lost: 60 bytes in 1 blocks ==17631== indirectly lost: 240 bytes in 10 blocks ==17631== possibly lost: 0 bytes in 0 blocks ==17631== still reachable: 0 bytes in 0 blocks ==17631== suppressed: 0 bytes in 0 blocks ==17631== ==17631== For counts of detected and suppressed errors, rerun with: -v ==17631== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
correction 1st sentence: s/valid/invalid
Thanks. I do see several possibilities for a leak in nss_parse_service_list: new_service = (service_user *) malloc (sizeof (service_user) + (line - name + 1)); ... /* Compare with known statii. */ if (line - name == 7) { if (__strncasecmp (name, "SUCCESS", 7) == 0) status = NSS_STATUS_SUCCESS; else if (__strncasecmp (name, "UNAVAIL", 7) == 0) status = NSS_STATUS_UNAVAIL; else return result; /* <<< Leak? */ } ... What does your /etc/nsswitch.conf look like? > My glibc built from the git repository is not working In what way does it not work? It might be hard to verify the fix, unless I can reproduce the leak, or you can get a git build working.
I've reproduced your leak: ==14114== 300 (60 direct, 240 indirect) bytes in 1 blocks are definitely lost in loss record 14 of 14 ==14114== at 0x4C2A4D6: malloc (vg_replace_malloc.c:263) ==14114== by 0x4F2DDCA: nss_parse_service_list (/build/buildd/eglibc-2.11.1/nss/nsswitch.c:622) ==14114== by 0x4F2E6ED: __nss_database_lookup (/build/buildd/eglibc-2.11.1/nss/nsswitch.c:164) ==14114== by 0x55B83CF: ??? ==14114== by 0x55BA244: ??? ==14114== by 0x4EDC9FC: getpwuid_r@@GLIBC_2.2.5 (/build/buildd/eglibc-2.11.1/pwd/../nss/getXXbyYY_r.c:253) ==14114== by 0x4EDC2EE: getpwuid (/build/buildd/eglibc-2.11.1/pwd/../nss/getXXbyYY.c:117) ==14114== by 0x40058C: main (/tmp/t.c:3) by sticking an invalid entry into /etc/nsswitch.conf: passwd: [FOOFFOO] files cache Also reproduces with current git trunk build: ==14568== 292 (52 direct, 240 indirect) bytes in 1 blocks are definitely lost in loss record 14 of 14 ==14568== at 0x4A0A4D6: malloc (vg_replace_malloc.c:263) ==14568== by 0x4D09804: nss_parse_service_list (/glibc-git/nss/nsswitch.c:595) ==14568== by 0x4D09F3B: __nss_database_lookup (/glibc-git/nss/nsswitch.c:144) ==14568== by 0x53DD3CF: ??? ==14568== by 0x53DF244: ??? ==14568== by 0x4CC8B3B: getpwuid_r@@GLIBC_2.2.5 (/glibc-git/pwd/../nss/getXXbyYY_r.c:255) ==14568== by 0x4CC83ED: getpwuid (/glibc-git/pwd/../nss/getXXbyYY.c:116) ==14568== by 0x40058C: main (/tmp/t.c:3)
(In reply to comment #2) > ==17631== 300 (60 direct, 240 indirect) bytes in 1 blocks are definitely lost > in loss record 11 of 11 > ==17631== at 0x4C274A8: malloc (vg_replace_malloc.c:236) > ==17631== by 0x4F27DCA: nss_parse_service_list (nsswitch.c:622) > ==17631== by 0x4F286ED: __nss_database_lookup (nsswitch.c:164) Alois, I can only reproduce the leak using invalid nsswitch.conf entry. What does your /etc/nsswitch.conf look like?
Paul, looks like you're on the right track. Looking at the function it calls malloc and returns result (which might be NULL) without freeing the malloc struct. But I didn't dive deeper into it.
Created attachment 6416 [details] /etc/nsswitch.conf Attached is the /etc/nsswitch.conf on my systems. It came with Debian/squeeze and Ubuntu 10.04, I did not change it. Alois P.S.: I tried to built the latest glibc. In userspace, make failed in the following way: ... /bin/sh ../scripts/rellns-sh /home/schloegl/glibc/lib/libnss_files.so.2 /home/schloegl/glibc/lib/libnss_files.so.new mv -f /home/schloegl/glibc/lib/libnss_files.so.new /home/schloegl/glibc/lib/libnss_files.so /usr/bin/install -c /home/schloegl/src/glibc_built/nss/libnss_db.so /home/schloegl/glibc/lib/libnss_db-2.15.90.so.new mv -f /home/schloegl/glibc/lib/libnss_db-2.15.90.so.new /home/schloegl/glibc/lib/libnss_db-2.15.90.so echo libnss_db-2.15.90.so /home/schloegl/glibc/lib/libnss_db.so.2 >> /home/schloegl/src/glibc_built/elf/symlink.list rm -f /home/schloegl/glibc/lib/libnss_db.so.new /bin/sh ../scripts/rellns-sh /home/schloegl/glibc/lib/libnss_db.so.2 /home/schloegl/glibc/lib/libnss_db.so.new mv -f /home/schloegl/glibc/lib/libnss_db.so.new /home/schloegl/glibc/lib/libnss_db.so .././scripts/mkinstalldirs /var/db mkdir /var/db mkdir: cannot create directory `/var/db': Permission denied make[2]: *** [/var/db/Makefile] Error 1 make[2]: Leaving directory `/home/schloegl/src/glibc/nss' make[1]: *** [nss/subdir_install] Error 2 make[1]: Leaving directory `/home/schloegl/src/glibc' make: *** [install] Error 2 Compiling the test file according to http://sourceware.org/glibc/wiki/Testing/Builds failed in this way: $ gcc q.c -I /home/schloegl/glibc/include/ --sysroot=${SYSROOT} -Wl,-rpath=${SYSROOT}/lib -Wl,--dynamic-linker=${SYSROOT}/lib/ld.so.1 In file included from /home/schloegl/glibc/include/features.h:399, from /home/schloegl/glibc/include/pwd.h:26, from q.c:3: /home/schloegl/glibc/include/gnu/stubs.h:9:27: error: gnu/stubs-64.h: No such file or directory
I sent a patch to handle leaks on error paths: http://sourceware.org/ml/libc-alpha/2012-05/msg01433.html However, with the patch applied, using Alois's copy of nsswitch.conf, or just completely empty nsswitch.conf, I still see the leak. It's kind of a false positive, and I am not sure we can reasonably do anything about it. The problem is this code in nss/getXXbyYY_r.c: 152 static service_user *startp; ... 230 tmp_ptr = nip; 231 PTR_MANGLE (tmp_ptr); 232 startp = tmp_ptr; That is, the returned (allocated) value is in "nip" variable, and it gets saved into startp (static), so it is not a leak. But it is saved in mangled form, which makes that invisible to Valgrind. Perhaps we should free PTR_DEMANGLE(startp) on __libc_freeres ?
(In reply to comment #9) > Perhaps we should free PTR_DEMANGLE(startp) on __libc_freeres ? No, that wasn't the right solution. Better patch that fixes the leak from empty nsswitch.conf, and also from Alois's copy: http://sourceware.org/ml/libc-alpha/2012-05/msg01435.html
Fixed by http://sourceware.org/git/?p=glibc.git;a=commit;h=d44638b0a7fc1f01c3b2153cfa1bbb849f01f217