diff -Nru procps-3.3.3/debian/changelog procps-3.3.3/debian/changelog --- procps-3.3.3/debian/changelog 2012-07-16 19:07:00.000000000 -0500 +++ procps-3.3.3/debian/changelog 2013-09-25 16:50:29.000000000 -0500 @@ -1,3 +1,12 @@ +procps (1:3.3.3-2ubuntu3.1) quantal; urgency=low + + * Backport of a45dace4 and 95d01362 in order to enable dynamically + allocated buffers in file2str. This fixes a number of seg fault problems + including the one related to large numbers of groups per user. + (LP: #1150413) + + -- Dave Chiluk Wed, 25 Sep 2013 16:49:54 -0500 + procps (1:3.3.3-2ubuntu3) quantal; urgency=low * debian/sysctl.d/10-magic-sysrq.conf: adjust to 176 by default, retaining diff -Nru procps-3.3.3/debian/patches/dynamic_file2str.patch procps-3.3.3/debian/patches/dynamic_file2str.patch --- procps-3.3.3/debian/patches/dynamic_file2str.patch 1969-12-31 18:00:00.000000000 -0600 +++ procps-3.3.3/debian/patches/dynamic_file2str.patch 2013-09-25 16:49:47.000000000 -0500 @@ -0,0 +1,222 @@ +Description: Enables file2str to use dynamic buffers instead of static 1024 + Backport of a45dace4 and 95d01362 in order to enable dynamically + allocated buffers in file2str. This fixes a number of seg fault problems + including the one related to large numbers of groups per user. + +Author: Dave Chiluk +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1150413 +Origin: upstream, https://gitorious.org/procps/procps/commit/a45dace4b82c9cdcda7020ca5665153b1e81275f, https://gitorious.org/procps/procps/commit/95d0136281ec00c68e2994d708fec4dd28275453 +--- procps-3.3.3.orig/proc/readproc.c ++++ procps-3.3.3/proc/readproc.c +@@ -60,6 +60,12 @@ static char *src_buffer, + *dst_buffer; + #define MAX_BUFSZ 1024*64*2 + ++// dynamic 'utility' buffer support for file2str() calls ++struct utlbuf_s { ++ char *buf; // dynamically grown buffer ++ int siz; // current len of the above ++} utlbuf_s; ++ + #ifndef SIGNAL_STRING + // convert hex string to unsigned long long + static unsigned long long unhex(const char *restrict cp){ +@@ -522,18 +528,28 @@ static void statm2proc(const char* s, pr + /* fprintf(stderr, "statm2proc converted %d fields.\n",num); */ + } + +-static int file2str(const char *directory, const char *what, char *ret, int cap) { +- static char filename[80]; +- int fd, num_read; +- +- sprintf(filename, "%s/%s", directory, what); +- fd = open(filename, O_RDONLY, 0); +- if(unlikely(fd==-1)) return -1; +- num_read = read(fd, ret, cap - 1); ++static int file2str(const char *directory, const char *what, struct utlbuf_s *ub) { ++ #define buffGRW 1024 ++ char path[PROCPATHLEN]; ++ int fd, num, tot_read = 0; ++ ++ /* on first use we preallocate a buffer of minimum size to emulate ++ former 'local static' behavior -- even if this read fails, that ++ buffer will likely soon be used for another subdirectory anyway ++ ( besides, with this xcalloc we will never need to use memcpy ) */ ++ if (ub->buf) ub->buf[0] = '\0'; ++ else ub->buf = xmalloc((ub->siz = buffGRW)); ++ sprintf(path, "%s/%s", directory, what); ++ if (-1 == (fd = open(path, O_RDONLY, 0))) return -1; ++ while (0 < (num = read(fd, ub->buf + tot_read, ub->siz - tot_read))) { ++ tot_read += num; ++ if (tot_read < ub->siz) continue; ++ ub->buf = xrealloc(ub->buf, (ub->siz += buffGRW)); ++ }; ++ ub->buf[tot_read] = '\0'; + close(fd); +- if(unlikely(num_read<=0)) return -1; +- ret[num_read] = '\0'; +- return num_read; ++ return tot_read; ++ #undef buffGRW + } + + static char** file2strvec(const char* directory, const char* what) { +@@ -722,8 +738,8 @@ int read_cmdline(char *restrict const ds + // The pid (tgid? tid?) is already in p, and a path to it in path, with some + // room to spare. + static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p) { ++ static struct utlbuf_s ub = { NULL, 0 }; // buf for stat,statm,status + static struct stat sb; // stat() buffer +- static char sbuf[1024]; // buffer for stat,statm,status + char *restrict const path = PT->path; + unsigned flags = PT->flags; + +@@ -737,19 +753,19 @@ static proc_t* simple_readproc(PROCTAB * + p->egid = sb.st_gid; /* need a way to get real gid */ + + if (flags & PROC_FILLSTAT) { // read /proc/#/stat +- if (unlikely(file2str(path, "stat", sbuf, sizeof sbuf) == -1)) ++ if (unlikely(file2str(path, "stat", &ub) == -1)) + goto next_proc; +- stat2proc(sbuf, p); ++ stat2proc(ub.buf, p); + } + + if (flags & PROC_FILLMEM) { // read /proc/#/statm +- if (likely(file2str(path, "statm", sbuf, sizeof sbuf) != -1)) +- statm2proc(sbuf, p); ++ if (likely(file2str(path, "statm", &ub) != -1)) ++ statm2proc(ub.buf, p); + } + + if (flags & PROC_FILLSTATUS) { // read /proc/#/status +- if (likely(file2str(path, "status", sbuf, sizeof sbuf) != -1)){ +- status2proc(sbuf, p, 1); ++ if (likely(file2str(path, "status", &ub) != -1)){ ++ status2proc(ub.buf, p, 1); + if (flags & PROC_FILLSUPGRP) + supgrps_from_supgids(p); + } +@@ -826,8 +842,8 @@ next_proc: + // t is the POSIX thread (task group member, generally not the leader) + // 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 utlbuf_s ub = { NULL, 0 }; // buf for stat,statm,status + static struct stat sb; // stat() buffer +- static char sbuf[1024]; // buffer for stat,statm,status + unsigned flags = PT->flags; + + if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */ +@@ -840,20 +856,20 @@ static proc_t* simple_readtask(PROCTAB * + t->egid = sb.st_gid; /* need a way to get real gid */ + + if (flags & PROC_FILLSTAT) { // read /proc/#/task/#/stat +- if (unlikely(file2str(path, "stat", sbuf, sizeof sbuf) == -1)) ++ if (unlikely(file2str(path, "stat", &ub) == -1)) + goto next_task; +- stat2proc(sbuf, t); ++ stat2proc(ub.buf, t); + } + + #ifndef QUICK_THREADS + if (flags & PROC_FILLMEM) // read /proc/#/task/#statm +- if (likely(file2str(path, "statm", sbuf, sizeof sbuf) != -1)) +- statm2proc(sbuf, t); ++ if (likely(file2str(path, "statm", &ub) != -1)) ++ statm2proc(ub.buf, t); + #endif + + if (flags & PROC_FILLSTATUS) { // read /proc/#/task/#/status +- if (likely(file2str(path, "status", sbuf, sizeof sbuf) != -1)) { +- status2proc(sbuf, t, 0); ++ if (likely(file2str(path, "status", &ub) != -1)) { ++ status2proc(ub.buf, t, 0); + #ifndef QUICK_THREADS + if (flags & PROC_FILLSUPGRP) + supgrps_from_supgids(t); +@@ -884,8 +900,8 @@ static proc_t* simple_readtask(PROCTAB * + #ifdef QUICK_THREADS + if (!p) { + if (flags & PROC_FILLMEM) +- if (likely(file2str(path, "statm", sbuf, sizeof sbuf) != -1)) +- statm2proc(sbuf, t); ++ if (likely(file2str(path, "statm", &ub) != -1)) ++ statm2proc(ub.buf, t); + + if (flags & PROC_FILLSUPGRP) + supgrps_from_supgids(t); +@@ -933,10 +949,10 @@ static proc_t* simple_readtask(PROCTAB * + + #ifdef OOMEM_ENABLE + if (unlikely(flags & PROC_FILLOOM)) { +- if (likely(file2str(path, "oom_score", sbuf, sizeof sbuf) != -1)) +- oomscore2proc(sbuf, t); +- if (likely(file2str(path, "oom_adj", sbuf, sizeof sbuf) != -1)) +- oomadj2proc(sbuf, t); ++ if (likely(file2str(path, "oom_score", ub.buf) != -1)) ++ oomscore2proc(ub.buf, t); ++ if (likely(file2str(path, "oom_adj", ub.buf) != -1)) ++ oomadj2proc(ub.buf, t); + } + #endif + +@@ -1210,13 +1226,14 @@ void freeproc(proc_t* p) { + + ////////////////////////////////////////////////////////////////////////////////// + void look_up_our_self(proc_t *p) { +- char sbuf[1024]; ++ struct utlbuf_s ub = { NULL, 0 }; + +- if(file2str("/proc/self", "stat", sbuf, sizeof sbuf) == -1){ ++ if(file2str("/proc/self", "stat", &ub) == -1){ + fprintf(stderr, "Error, do this: mount -t proc proc /proc\n"); + _exit(47); + } +- stat2proc(sbuf, p); // parse /proc/self/stat ++ stat2proc(ub.buf, p); // parse /proc/self/stat ++ free(ub.buf); + } + + HIDDEN_ALIAS(readproc); +@@ -1368,23 +1385,26 @@ proc_data_t *readproctab3 (int(*want_tas + * and filled out proc_t structure. + */ + proc_t * get_proc_stats(pid_t pid, proc_t *p) { +- static char path[32], sbuf[1024]; +- struct stat statbuf; +- +- sprintf(path, "/proc/%d", pid); +- if (stat(path, &statbuf)) { +- perror("stat"); +- return NULL; +- } ++ struct utlbuf_s ub = { NULL, 0 }; ++ static char path[32]; ++ struct stat statbuf; ++ ++ sprintf(path, "/proc/%d", pid); ++ if (stat(path, &statbuf)) { ++ perror("stat"); ++ return NULL; ++ } ++ ++ if (file2str(path, "stat", &ub) >= 0) ++ stat2proc(ub.buf, p); ++ if (file2str(path, "statm", &ub) >= 0) ++ statm2proc(ub.buf, p); ++ if (file2str(path, "status", &ub) >= 0) ++ status2proc(ub.buf, p, 0); + +- if (file2str(path, "stat", sbuf, sizeof sbuf) >= 0) +- stat2proc(sbuf, p); /* parse /proc/#/stat */ +- if (file2str(path, "statm", sbuf, sizeof sbuf) >= 0) +- statm2proc(sbuf, p); /* ignore statm errors here */ +- if (file2str(path, "status", sbuf, sizeof sbuf) >= 0) +- status2proc(sbuf, p, 0 /*FIXME*/); ++ free(ub.buf); ++ return p; + +- return p; + } + + #undef MK_THREAD diff -Nru procps-3.3.3/debian/patches/series procps-3.3.3/debian/patches/series --- procps-3.3.3/debian/patches/series 2012-07-16 18:43:56.000000000 -0500 +++ procps-3.3.3/debian/patches/series 2013-09-25 16:48:18.000000000 -0500 @@ -2,3 +2,4 @@ bts676239-pkill-u-option watch_8bit uptime_test +dynamic_file2str.patch