dcavalca / rpms / rpm

Forked from rpms/rpm a year ago
Clone
James Antill ee2eaf
commit 8f4b3c3cab8922a2022b9e47c71f1ecf906077ef
James Antill ee2eaf
Author: Demi Marie Obenour <athena@invisiblethingslab.com>
James Antill ee2eaf
Date:   Mon Feb 8 16:05:01 2021 -0500
James Antill ee2eaf
James Antill ee2eaf
    hdrblobInit() needs bounds checks too
James Antill ee2eaf
    
James Antill ee2eaf
    Users can pass untrusted data to hdrblobInit() and it must be robust
James Antill ee2eaf
    against this.
James Antill ee2eaf
James Antill ee2eaf
diff --git a/lib/header.c b/lib/header.c
James Antill ee2eaf
index ea39e679f..ebba9c2b0 100644
James Antill ee2eaf
--- a/lib/header.c
James Antill ee2eaf
+++ b/lib/header.c
James Antill ee2eaf
@@ -11,6 +11,7 @@
James Antill ee2eaf
 #include "system.h"
James Antill ee2eaf
 #include <netdb.h>
James Antill ee2eaf
 #include <errno.h>
James Antill ee2eaf
+#include <inttypes.h>
James Antill ee2eaf
 #include <rpm/rpmtypes.h>
James Antill ee2eaf
 #include <rpm/rpmstring.h>
James Antill ee2eaf
 #include "lib/header_internal.h"
James Antill ee2eaf
@@ -1912,6 +1913,25 @@ hdrblob hdrblobFree(hdrblob blob)
James Antill ee2eaf
     return NULL;
James Antill ee2eaf
 }
James Antill ee2eaf
 
James Antill ee2eaf
+static rpmRC hdrblobVerifyLengths(rpmTagVal regionTag, uint32_t il, uint32_t dl,
James Antill ee2eaf
+				  char **emsg) {
James Antill ee2eaf
+    uint32_t il_max = HEADER_TAGS_MAX;
James Antill ee2eaf
+    uint32_t dl_max = HEADER_DATA_MAX;
James Antill ee2eaf
+    if (regionTag == RPMTAG_HEADERSIGNATURES) {
James Antill ee2eaf
+	il_max = 32;
James Antill ee2eaf
+	dl_max = 64 * 1024 * 1024;
James Antill ee2eaf
+    }
James Antill ee2eaf
+    if (hdrchkRange(il_max, il)) {
James Antill ee2eaf
+	rasprintf(emsg, _("hdr tags: BAD, no. of tags(%" PRIu32 ") out of range"), il);
James Antill ee2eaf
+	return RPMRC_FAIL;
James Antill ee2eaf
+    }
James Antill ee2eaf
+    if (hdrchkRange(dl_max, dl)) {
James Antill ee2eaf
+	rasprintf(emsg, _("hdr data: BAD, no. of bytes(%" PRIu32 ") out of range"), dl);
James Antill ee2eaf
+	return RPMRC_FAIL;
James Antill ee2eaf
+    }
James Antill ee2eaf
+    return RPMRC_OK;
James Antill ee2eaf
+}
James Antill ee2eaf
+
James Antill ee2eaf
 rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrblob blob, char **emsg)
James Antill ee2eaf
 {
James Antill ee2eaf
     int32_t block[4];
James Antill ee2eaf
@@ -1924,13 +1944,6 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
James Antill ee2eaf
     size_t nb;
James Antill ee2eaf
     rpmRC rc = RPMRC_FAIL;		/* assume failure */
James Antill ee2eaf
     int xx;
James Antill ee2eaf
-    int32_t il_max = HEADER_TAGS_MAX;
James Antill ee2eaf
-    int32_t dl_max = HEADER_DATA_MAX;
James Antill ee2eaf
-
James Antill ee2eaf
-    if (regionTag == RPMTAG_HEADERSIGNATURES) {
James Antill ee2eaf
-	il_max = 32;
James Antill ee2eaf
-	dl_max = 64 * 1024 * 1024;
James Antill ee2eaf
-    }
James Antill ee2eaf
 
James Antill ee2eaf
     memset(block, 0, sizeof(block));
James Antill ee2eaf
     if ((xx = Freadall(fd, bs, blen)) != blen) {
James Antill ee2eaf
@@ -1943,15 +1956,9 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
James Antill ee2eaf
 	goto exit;
James Antill ee2eaf
     }
James Antill ee2eaf
     il = ntohl(block[2]);
James Antill ee2eaf
-    if (hdrchkRange(il_max, il)) {
James Antill ee2eaf
-	rasprintf(emsg, _("hdr tags: BAD, no. of tags(%d) out of range"), il);
James Antill ee2eaf
-	goto exit;
James Antill ee2eaf
-    }
James Antill ee2eaf
     dl = ntohl(block[3]);
James Antill ee2eaf
-    if (hdrchkRange(dl_max, dl)) {
James Antill ee2eaf
-	rasprintf(emsg, _("hdr data: BAD, no. of bytes(%d) out of range"), dl);
James Antill ee2eaf
+    if (hdrblobVerifyLengths(regionTag, il, dl, emsg))
James Antill ee2eaf
 	goto exit;
James Antill ee2eaf
-    }
James Antill ee2eaf
 
James Antill ee2eaf
     nb = (il * sizeof(struct entryInfo_s)) + dl;
James Antill ee2eaf
     uc = sizeof(il) + sizeof(dl) + nb;
James Antill ee2eaf
@@ -1995,11 +2002,18 @@ rpmRC hdrblobInit(const void *uh, size_t uc,
James Antill ee2eaf
 		struct hdrblob_s *blob, char **emsg)
James Antill ee2eaf
 {
James Antill ee2eaf
     rpmRC rc = RPMRC_FAIL;
James Antill ee2eaf
-
James Antill ee2eaf
     memset(blob, 0, sizeof(*blob));
James Antill ee2eaf
+    if (uc && uc < 8) {
James Antill ee2eaf
+	rasprintf(emsg, _("hdr length: BAD"));
James Antill ee2eaf
+	goto exit;
James Antill ee2eaf
+    }
James Antill ee2eaf
+
James Antill ee2eaf
     blob->ei = (int32_t *) uh; /* discards const */
James Antill ee2eaf
-    blob->il = ntohl(blob->ei[0]);
James Antill ee2eaf
-    blob->dl = ntohl(blob->ei[1]);
James Antill ee2eaf
+    blob->il = ntohl((uint32_t)(blob->ei[0]));
James Antill ee2eaf
+    blob->dl = ntohl((uint32_t)(blob->ei[1]));
James Antill ee2eaf
+    if (hdrblobVerifyLengths(regionTag, blob->il, blob->dl, emsg) != RPMRC_OK)
James Antill ee2eaf
+	goto exit;
James Antill ee2eaf
+
James Antill ee2eaf
     blob->pe = (entryInfo) &(blob->ei[2]);
James Antill ee2eaf
     blob->pvlen = sizeof(blob->il) + sizeof(blob->dl) +
James Antill ee2eaf
 		  (blob->il * sizeof(*blob->pe)) + blob->dl;