File CVE-2018-1124.patch of Package procps.openSUSE_Leap_42.3_Update
---
proc/readproc.c | 63 +++++++++++++++++++++++++++++++++++---------------------
1 file changed, 40 insertions(+), 23 deletions(-)
--- proc/readproc.c
+++ proc/readproc.c 2018-06-05 14:44:04.887873231 +0000
@@ -37,6 +37,7 @@
#include <sys/dir.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <limits.h>
// sometimes it's easier to do this manually, w/o gcc helping
#ifdef PROF
@@ -576,7 +577,7 @@ static void statm2proc(const char* s, pr
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;
+ int fd, num, tot_read = 0, len;
/* on first use we preallocate a buffer of minimum size to emulate
former 'local static' behavior -- even if this read fails, that
@@ -584,11 +585,16 @@ static int file2str(const char *director
( besides, with this xcalloc we will never need to use memcpy ) */
if (ub->buf) ub->buf[0] = '\0';
else ub->buf = xcalloc((ub->siz = buffGRW));
- sprintf(path, "%s/%s", directory, what);
+ len = snprintf(path, sizeof path, "%s/%s", directory, what);
+ if (len <= 0 || (size_t)len >= sizeof path) return -1;
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) break;
+ if (ub->siz >= INT_MAX - buffGRW) {
+ tot_read--;
+ break;
+ }
ub->buf = xrealloc(ub->buf, (ub->siz += buffGRW));
};
ub->buf[tot_read] = '\0';
@@ -600,11 +606,12 @@ static int file2str(const char *director
static char** file2strvec(const char* directory, const char* what) {
char buf[2048]; /* read buf bytes at a time */
- char *p, *rbuf = 0, *endbuf, **q, **ret;
+ char *p, *rbuf = 0, *endbuf, **q, **ret, *strp;
int fd, tot = 0, n, c, end_of_file = 0;
int align;
- sprintf(buf, "%s/%s", directory, what);
+ const int len = snprintf(buf, sizeof buf, "%s/%s", directory, what);
+ if(len <= 0 || (size_t)len >= sizeof buf) return NULL;
fd = open(buf, O_RDONLY, 0);
if(fd==-1) return NULL;
@@ -612,18 +619,23 @@ static char** file2strvec(const char* di
while ((n = read(fd, buf, sizeof buf - 1)) >= 0) {
if (n < (int)(sizeof buf - 1))
end_of_file = 1;
- if (n == 0 && rbuf == 0) {
- close(fd);
- return NULL; /* process died between our open and read */
+ if (n <= 0 && tot <= 0) { /* nothing read now, nothing read before */
+ break; /* process died between our open and read */
}
- if (n < 0) {
- if (rbuf)
- free(rbuf);
- close(fd);
- return NULL; /* read error */
+ /* ARG_LEN is our guesstimated median length of a command-line argument
+ or environment variable (the minimum is 1, the maximum is 131072) */
+ #define ARG_LEN 64
+ if (tot >= INT_MAX / (ARG_LEN + (int)sizeof(char*)) * ARG_LEN - n) {
+ end_of_file = 1; /* integer overflow: null-terminate and break */
+ n = 0; /* but tot > 0 */
}
- if (end_of_file && (n == 0 || buf[n-1]))/* last read char not null */
+ #undef ARG_LEN
+ if (end_of_file &&
+ ((n > 0 && buf[n-1] != '\0') || /* last read char not null */
+ (n <= 0 && rbuf[tot-1] != '\0'))) /* last read char not null */
buf[n++] = '\0'; /* so append null-terminator */
+
+ if (n <= 0) break; /* unneeded (end_of_file = 1) but avoid realloc */
rbuf = xrealloc(rbuf, tot + n); /* allocate more memory */
memcpy(rbuf + tot, buf, n); /* copy buffer into it */
tot += n; /* increment total byte ctr */
@@ -631,29 +643,34 @@ static char** file2strvec(const char* di
break;
}
close(fd);
- if (n <= 0 && !end_of_file) {
+ if (n < 0 || tot <= 0) { /* error, or nothing read */
if (rbuf) free(rbuf);
return NULL; /* read error */
}
+ rbuf[tot-1] = '\0'; /* belt and suspenders (the while loop did it, too) */
endbuf = rbuf + tot; /* count space for pointers */
align = (sizeof(char*)-1) - ((tot + sizeof(char*)-1) & (sizeof(char*)-1));
- for (c = 0, p = rbuf; p < endbuf; p++) {
- if (!*p || *p == '\n')
+ c = sizeof(char*); /* one extra for NULL term */
+ for (p = rbuf; p < endbuf; p++) {
+ if (!*p || *p == '\n') {
+ if (c >= INT_MAX - (tot + (int)sizeof(char*) + align)) break;
c += sizeof(char*);
+ }
if (*p == '\n')
*p = 0;
}
- c += sizeof(char*); /* one extra for NULL term */
rbuf = xrealloc(rbuf, tot + c + align); /* make room for ptrs AT END */
endbuf = rbuf + tot; /* addr just past data buf */
q = ret = (char**) (endbuf+align); /* ==> free(*ret) to dealloc */
- *q++ = p = rbuf; /* point ptrs to the strings */
- endbuf--; /* do not traverse final NUL */
- while (++p < endbuf)
- if (!*p) /* NUL char implies that */
- *q++ = p+1; /* next string -> next char */
-
+ for (strp = p = rbuf; p < endbuf; p++) {
+ if (!*p) { /* NUL char implies that */
+ if (c < 2 * (int)sizeof(char*)) break;
+ c -= sizeof(char*);
+ *q++ = strp; /* point ptrs to the strings */
+ strp = p+1; /* next string -> next char */
+ }
+ }
*q = 0; /* null ptr list terminator */
return ret;
}