michal-grzedzicki / rpms / rpm

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