Package: procps Version: 1:3.2.8-9squeeze1 Severity: normal
We found that under the following circumstances: * Kernel > 3.2.29 (which shows > 32 groups in /proc/${pid}/status) * one or more users logged in with lots of supplementary groups then ps(1) fails with a SIGSEGV after attempting to allocate lots of memory. This appears to be due flawed assumption in ps: That the contents of /proc/${pid}/status will fit into a buffer of 1024 bytes: if the file is larger, only the first 1024 bytes are read, and when subsequently scanning the buffer the code "falls off the end": http://forums.grsecurity.net/viewtopic.php?f=3&t=3298 Although 32 groups sounds ample, sites using Active Directory will often find their users being members of lots of groups, as group membership is a recursive concept in AD. And the numeric group IDs are (in our case) 9 characters each, thus easily overflowing the 1024 byte buffer. Here's an example: ----------------------------- 8< cut here 8< ----------------- karl@someserver: ~$ ps Signal 11 (SEGV) caught by ps (procps version 3.2.8). Please send bug reports to <feedb...@lists.sf.net> or <alb...@users.sf.net> karl@someserver: ~$ strace ps 2>&1 | tail -30 stat("/proc/1997", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0 open("/proc/1997/stat", O_RDONLY) = 6 read(6, "1997 (sshd) S 1989 1989 1989 0 -"..., 1023) = 191 close(6) = 0 open("/proc/1997/status", O_RDONLY) = 6 read(6, "Name:\tsshd\nState:\tS (sleeping)\nT"..., 1023) = 1023 close(6) = 0 mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f037a2fd000 mremap(0x7f037a2fd000, 135168, 266240, MREMAP_MAYMOVE) = 0x7f0379cd9000 mremap(0x7f0379cd9000, 266240, 528384, MREMAP_MAYMOVE) = 0x7f0379c58000 mremap(0x7f0379c58000, 528384, 1052672, MREMAP_MAYMOVE) = 0x7f0379b57000 mremap(0x7f0379b57000, 1052672, 2101248, MREMAP_MAYMOVE) = 0x7f0379956000 mremap(0x7f0379956000, 2101248, 4198400, MREMAP_MAYMOVE) = 0x7f0379555000 mremap(0x7f0379555000, 4198400, 8392704, MREMAP_MAYMOVE) = 0x7f0378d54000 mremap(0x7f0378d54000, 8392704, 16781312, MREMAP_MAYMOVE) = 0x7f0377d53000 mremap(0x7f0377d53000, 16781312, 33558528, MREMAP_MAYMOVE) = 0x7f0375d52000 mremap(0x7f0375d52000, 33558528, 67112960, MREMAP_MAYMOVE) = 0x7f0371d51000 mremap(0x7f0371d51000, 67112960, 134221824, MREMAP_MAYMOVE) = 0x7f0369d50000 mremap(0x7f0369d50000, 134221824, 268439552, MREMAP_MAYMOVE) = 0x7f0359d4f000 mremap(0x7f0359d4f000, 268439552, 536875008, MREMAP_MAYMOVE) = 0x7f0339d4e000 mremap(0x7f0339d4e000, 536875008, 1073745920, MREMAP_MAYMOVE) = 0x7f02f9d4d000 mremap(0x7f02f9d4d000, 1073745920, 2147487744, MREMAP_MAYMOVE) = 0x7f0279d4c000 mremap(0x7f0279d4c000, 2147487744, 4096, MREMAP_MAYMOVE) = 0x7f0279d4c000 --- SIGSEGV (Segmentation fault) @ 0 (0) --- write(2, "\n\nSignal 11 (SEGV) caught by ps "..., 132 Signal 11 (SEGV) caught by ps (procps version 3.2.8). Please send bug reports to <feedb...@lists.sf.net> or <alb...@users.sf.net> ) = 132 exit_group(139) = ? karl@someserver: ~$ wc --bytes < /proc/1997/status 1810 ----------------------------- 8< cut here 8< ----------------- I have a (temporary) patch which increases the buffer size to 8K, which appears sufficient in our case. But this does not fix the underlying problem of having a limited buffer size to start with... ----------------------------- 8< cut here 8< ----------------- --- a/proc/readproc.c 2013-03-12 19:43:24.000000000 +0000 +++ b/proc/readproc.c 2013-03-13 10:12:47.744038428 +0000 @@ -28,6 +28,15 @@ #include <sys/types.h> #include <sys/stat.h> +/* Max # of bytes to expect in /proc/%d/status. + + This may be a crazy amount if lots of supplementary groups are + listed. Most kernels will limit the contents to 32 (NGROUPS_SMALL) + groups, but kernels > 3.2.29 may show ALL of the supplementary + groups... + */ +#define PROC_STATUS_BUFSIZE 8192 + // sometimes it's easier to do this manually, w/o gcc helping #ifdef PROF extern void __cyg_profile_func_enter(void*,void*); @@ -560,7 +569,7 @@ // room to spare. static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p) { static struct stat sb; // stat() buffer - static char sbuf[1024]; // buffer for stat,statm + static char sbuf[PROC_STATUS_BUFSIZE]; // buffer for stat,statm,status char *restrict const path = PT->path; unsigned flags = PT->flags; @@ -655,7 +664,7 @@ // path is a path to the task, with some room to spare. static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path) { static struct stat sb; // stat() buffer - static char sbuf[1024]; // buffer for stat,statm + static char sbuf[PROC_STATUS_BUFSIZE]; // buffer for stat,statm,status unsigned flags = PT->flags; //printf("hhh\n"); @@ -1108,7 +1117,7 @@ * and filled out proc_t structure. */ proc_t * get_proc_stats(pid_t pid, proc_t *p) { - static char path[32], sbuf[1024]; + static char path[32], sbuf[PROC_STATUS_BUFSIZE]; // buffer for stat,statm,status struct stat statbuf; sprintf(path, "/proc/%d", pid); ----------------------------- 8< cut here 8< ----------------- -- System Information: Debian Release: 6.0.6 APT prefers stable APT policy: (500, 'stable') Architecture: amd64 (x86_64) Kernel: Linux 3.2.0-0.bpo.4-amd64 (SMP w/2 CPU cores) Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages procps depends on: ii initscripts 2.88dsf-13.1+squeeze1 scripts for initializing and shutt ii libc6 2.11.3-4 Embedded GNU C Library: Shared lib ii libncurses5 5.7+20100313-5 shared libraries for terminal hand ii libncursesw5 5.7+20100313-5 shared libraries for terminal hand ii lsb-base 3.2-23.2squeeze1 Linux Standard Base 3.2 init scrip Versions of packages procps recommends: ii psmisc 22.16-1~bpo60+1 utilities that use the proc file s procps suggests no packages. -- Configuration Files: /etc/sysctl.conf changed [not included] -- no debconf information -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org