Package: libpam-tmpdir Version: 0.07-1 Severity: normal Tags: patch -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
I installed libpam-tmpdir on three of my machines. It worked fine on two of them, but on the third I was unable to log in until I disabled it. I found that pam-tmpdir-helper was crashing with errors like: > *** glibc detected *** /sbin/pam-tmpdir-helper: realloc(): invalid next size: > 0x0804b1a0 *** > ======= Backtrace: ========= > /lib/libc.so.6[0xb7e89afb] > /lib/libc.so.6(realloc+0xf8)[0xb7e8ba08] > /sbin/pam-tmpdir-helper[0x8049024] > /sbin/pam-tmpdir-helper[0x80490f0] > /sbin/pam-tmpdir-helper[0x80491dd] > /sbin/pam-tmpdir-helper[0x804893f] > /lib/libc.so.6(__libc_start_main+0xdc)[0xb7e35ebc] > /sbin/pam-tmpdir-helper[0x8048881] > ======= Memory map: ======== > 08048000-0804a000 r-xp 00000000 03:03 29653 /sbin/pam-tmpdir-helper > 0804a000-0804b000 rw-p 00001000 03:03 29653 /sbin/pam-tmpdir-helper > 0804b000-0806c000 rw-p 0804b000 00:00 0 [heap] > b7d00000-b7d21000 rw-p b7d00000 00:00 0 (blah blah blah) I discovered two distinct problems, both in util.c, and caused by the fact that I'd inadvertently added a second (blank) line in the config file. The first is in freadline(): > char buf[512]; > size_t alloc = 0; > char *ret = NULL; > char *t; > t = fgets(buf, sizeof(buf), stream); > if (t == NULL) { > return NULL; > } > ret = xmalloc(sizeof(buf)); > strcpy(ret, buf); > t = fgets(buf, sizeof(buf), stream); > while (t != NULL) { > alloc += (strlen(t)); > ret = xrealloc(ret, alloc); > strcat(ret,buf); > } > return ret; I'm a little puzzled by the comment about libc lacking a method to read a line from a file, since fgets() seems to do much the same thing as Python's f.readline, but maybe I've missed something. The problem here is the while() loop: this will loop forever if there's more than one line in the file, since t is never updated within the loop (in fact, you eventually get a memory fault). Additionally, alloc is never set to the original length of the first line. But since we're only interested in one line at a time, and fgets() reads until it encounters the supplied size OR an end-of-file OR a newline character, we don't need any second fgets() call nor the associated while loop. Unless, of course, we're looking for really long lines. (Apologies if I've missed some subtle point here). The second problem is in get_tmp_dir(), where the program checks for a comment or non-assignment line: > line = freadline(conf); > while (line) { > char *key, *value; > if ((line[0] == '#') || (strchr(line, '=') == NULL)) { > free(line); > continue; > } This will also loop forever, or at least till it gets a memory fault, since it doesn't read a fresh line if one of these lines is encountered. We need to add a 'line = freadline(conf);' before the continue statement. Patch attached. I didn't remove the extra lines in freadline(), just commented them out. .....Ron - -- System Information: Debian Release: lenny/sid APT prefers testing APT policy: (500, 'testing'), (500, 'stable') Architecture: i386 (i686) Kernel: Linux 2.6.21.5-merlin-0 Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) Shell: /bin/sh linked to /bin/bash Versions of packages libpam-tmpdir depends on: ii libc6 2.5-9+b1 GNU C Library: Shared libraries ii libpam0g 0.79-4 Pluggable Authentication Modules l libpam-tmpdir recommends no packages. - -- no debconf information -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFGiDpeitqjxNhsdN4RAtePAJ0QTq91SqRewfFAnWzGW3nY2PQCWQCghIqX 5y5q5dZPovZryIw1gLXcXxI= =JruA -----END PGP SIGNATURE-----
*** ../util.c Mon Jul 17 05:13:04 2006 --- util.c Sun Jul 1 18:35:11 2007 *************** *** 41,52 **** } ret = xmalloc(sizeof(buf)); strcpy(ret, buf); ! t = fgets(buf, sizeof(buf), stream); while (t != NULL) { alloc += (strlen(t)); ret = xrealloc(ret, alloc); strcat(ret,buf); } return ret; } --- 41,53 ---- } ret = xmalloc(sizeof(buf)); strcpy(ret, buf); ! /* t = fgets(buf, sizeof(buf), stream); while (t != NULL) { alloc += (strlen(t)); ret = xrealloc(ret, alloc); strcat(ret,buf); } + */ return ret; } *************** *** 127,132 **** --- 128,134 ---- char *key, *value; if ((line[0] == '#') || (strchr(line, '=') == NULL)) { free(line); + line = freadline(conf); continue; } tmp = strchr(line, '=');