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, '=');

Reply via email to