proc/readproc.c: Harden fill_cgroup_cvt().
authorQualys Security Advisory <qsa@qualys.com>
Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)
committerCraig Small <csmall@enc.com.au>
Fri, 18 May 2018 21:32:22 +0000 (07:32 +1000)
Check the return value of snprintf(), otherwise dst may point
out-of-bounds when it reaches the end of the dst_buffer (the snprintf()
always returns 1 in that case, even if there is not enough space left),
and vMAX becomes negative and is passed to snprintf() as a size_t.

proc/readproc.c

index 2ee0f28dccbd166ca02f10fb42a5583b13e5eb56..18644ffb675593b2d07705241d6ef01cfbba61d2 100644 (file)
@@ -821,7 +821,7 @@ static char** vectorize_this_str (const char* src) {
 static void fill_cgroup_cvt (const char* directory, proc_t *restrict p) {
  #define vMAX ( MAX_BUFSZ - (int)(dst - dst_buffer) )
     char *src, *dst, *grp, *eob, *name;
-    int tot, x, whackable_int = MAX_BUFSZ;
+    int tot, x, whackable_int = MAX_BUFSZ, len;
 
     *(dst = dst_buffer) = '\0';                  // empty destination
     tot = read_unvectored(src_buffer, MAX_BUFSZ, directory, "cgroup", '\0');
@@ -833,7 +833,10 @@ static void fill_cgroup_cvt (const char* directory, proc_t *restrict p) {
 #if 0
         grp += strspn(grp, "0123456789:");       // jump past group number
 #endif
-        dst += snprintf(dst, vMAX, "%s", (dst > dst_buffer) ? "," : "");
+        if (vMAX <= 1) break;
+        len = snprintf(dst, vMAX, "%s", (dst > dst_buffer) ? "," : "");
+        if (len < 0 || len >= vMAX) break;
+        dst += len;
         dst += escape_str(dst, grp, vMAX, &whackable_int);
     }
     p->cgroup = vectorize_this_str(dst_buffer[0] ? dst_buffer : "-");