[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#408406: Culprit and a one line workaround

I don't believe a simple putenv() in main() will work, it is probably too late at that point.

Furthermore, the problem is somewhere below libc, probably libnss-ldap.

I rebuilt with debugging turned on, made a spot for core dumps, and enabled suid core dumping. I've collected four cores so far, they all dump at the same spot. At typical gdb backtrace is

(gdb) bt
#0  0xb7f34410 in ?? ()
#1  0xbff831c0 in ?? ()
#2  0x00000006 in ?? ()
#3  0x000060a5 in ?? ()
#4  0xb7e23811 in raise () from /lib/tls/i686/cmov/libc.so.6
#5  0xb7e24fb9 in abort () from /lib/tls/i686/cmov/libc.so.6
#6  0xb7e6437d in mprobe () from /lib/tls/i686/cmov/libc.so.6
#7  0xb7e60575 in free () from /lib/tls/i686/cmov/libc.so.6
#8  0xb7ef6231 in xdr_uint8_t () from /lib/tls/i686/cmov/libc.so.6
#9  0xb7ef6342 in xdr_uint8_t () from /lib/tls/i686/cmov/libc.so.6
#10 0xb7e877d3 in getpwnam_r () from /lib/tls/i686/cmov/libc.so.6
#11 0xb7e871ea in getpwnam () from /lib/tls/i686/cmov/libc.so.6
#12 0x0804a053 in name_context (name=0x8063190 "forumsup@microsoft.com") at context.c:60
#13 0x0804a6a9 in copy_message () at copymsg.c:238
#14 0x0804d435 in main (argc=4, argv=0xbff85594) at main.c:554
(gdb) frame 12
#12 0x0804a053 in name_context (name=0x8063190 "forumsup@microsoft.com") at context.c:60
60          if ((pw = getpwnam(name)) == NULL)

Note in frame 12 that we are looking up name that has no hope of being a local user name, so we might be exercising unusual paths in getpwnam(). The offending names from the four dumps are...

I don't think it is safe to assume that only long, spammer like names trigger it. We run over 95% spam on our incoming mail feeds so I would expect any sample of 4 to be all spam.

I placed a free(malloc(xxx)) in front of the getpwnam() call to see if the heap was pre-corrupted,
that does not help, it still dumps in the getpwnam() call.

I then created a test program that makes getpwnam() calls for everything on standard input...
#include <string.h>
#include <stdio.h>
#include <pwd.h>

    char buf[10240], *b;
    struct passwd *p;
    int c = 0;

    while( b = fgets( buf, sizeof(buf)-1, stdin)) {
        char *n = strchr(buf,'\n');

        if( n) *n = 0;
        p = getpwnam(buf);
        if ( c++ > 72) {
            c = 0;

On my machine that uses libnss_ldap for users this will fail after 100-400 calls to getpwnam() using either my list of email 'from' addresses or /usr/share/dict/ words (with the apostrophe words stripped out).

On an identical machine which does not use libnss_ldap this can process all 70k or so words without problem.

Deliver can be mostly fixed by pre-failing all the names that contain a '@' sign, these should always fail a passwd lookup on linux. In 'context.c', the name_context() function, add the line with the strchr() call...


if ( strchr(name,'@')) return 0; /* hack to keep remote names out */

    if ((pw = getpwnam(name)) == NULL)
        return NULL;

.. and most of the name look ups will not occur. It is worth noting that this makes a large difference in the total LDAP traffic as all of these '@' containing names were cache misses anyway.

Reply to: