summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/rpm/files/CVE-2021-20266.patch
blob: f2fc47e321260223a97c54abc0db5f752795454f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
From ebbf0f0133c498d229e94ecf2ed0b41d6e6a142a Mon Sep 17 00:00:00 2001
From: Demi Marie Obenour <athena@invisiblethingslab.com>
Date: Mon, 8 Feb 2021 16:05:01 -0500
Subject: [PATCH] hdrblobInit() needs bounds checks too

Users can pass untrusted data to hdrblobInit() and it must be robust
against this.

Backported from commit 8f4b3c3cab8922a2022b9e47c71f1ecf906077ef

Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/pull/1587/commits/9646711891df851dfbf7ef54cc171574a0914b15]
CVE: CVE-2021-20266
Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>

---
 lib/header.c | 48 +++++++++++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 17 deletions(-)

diff --git a/lib/header.c b/lib/header.c
index 5b09f8352..ad5b6dc57 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -11,6 +11,7 @@
 #include "system.h"
 #include <netdb.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <rpm/rpmtypes.h>
 #include <rpm/rpmstring.h>
 #include "lib/header_internal.h"
@@ -1890,6 +1891,25 @@ hdrblob hdrblobFree(hdrblob blob)
     return NULL;
 }
 
+static rpmRC hdrblobVerifyLengths(rpmTagVal regionTag, uint32_t il, uint32_t dl,
+				  char **emsg) {
+    uint32_t il_max = HEADER_TAGS_MAX;
+    uint32_t dl_max = HEADER_DATA_MAX;
+    if (regionTag == RPMTAG_HEADERSIGNATURES) {
+	il_max = 32;
+	dl_max = 8192;
+    }
+    if (hdrchkRange(il_max, il)) {
+	rasprintf(emsg, _("hdr tags: BAD, no. of tags(%" PRIu32 ") out of range"), il);
+	return RPMRC_FAIL;
+    }
+    if (hdrchkRange(dl_max, dl)) {
+	rasprintf(emsg, _("hdr data: BAD, no. of bytes(%" PRIu32 ") out of range"), dl);
+	return RPMRC_FAIL;
+    }
+    return RPMRC_OK;
+}
+
 rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrblob blob, char **emsg)
 {
     int32_t block[4];
@@ -1902,13 +1922,6 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
     size_t nb;
     rpmRC rc = RPMRC_FAIL;		/* assume failure */
     int xx;
-    int32_t il_max = HEADER_TAGS_MAX;
-    int32_t dl_max = HEADER_DATA_MAX;
-
-    if (regionTag == RPMTAG_HEADERSIGNATURES) {
-	il_max = 32;
-	dl_max = 8192;
-    }
 
     memset(block, 0, sizeof(block));
     if ((xx = Freadall(fd, bs, blen)) != blen) {
@@ -1921,15 +1934,9 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
 	goto exit;
     }
     il = ntohl(block[2]);
-    if (hdrchkRange(il_max, il)) {
-	rasprintf(emsg, _("hdr tags: BAD, no. of tags(%d) out of range"), il);
-	goto exit;
-    }
     dl = ntohl(block[3]);
-    if (hdrchkRange(dl_max, dl)) {
-	rasprintf(emsg, _("hdr data: BAD, no. of bytes(%d) out of range"), dl);
+    if (hdrblobVerifyLengths(regionTag, il, dl, emsg))
 	goto exit;
-    }
 
     nb = (il * sizeof(struct entryInfo_s)) + dl;
     uc = sizeof(il) + sizeof(dl) + nb;
@@ -1973,11 +1980,18 @@ rpmRC hdrblobInit(const void *uh, size_t uc,
 		struct hdrblob_s *blob, char **emsg)
 {
     rpmRC rc = RPMRC_FAIL;
-
     memset(blob, 0, sizeof(*blob));
+    if (uc && uc < 8) {
+	rasprintf(emsg, _("hdr length: BAD"));
+	goto exit;
+    }
+
     blob->ei = (int32_t *) uh; /* discards const */
-    blob->il = ntohl(blob->ei[0]);
-    blob->dl = ntohl(blob->ei[1]);
+    blob->il = ntohl((uint32_t)(blob->ei[0]));
+    blob->dl = ntohl((uint32_t)(blob->ei[1]));
+    if (hdrblobVerifyLengths(regionTag, blob->il, blob->dl, emsg) != RPMRC_OK)
+	goto exit;
+
     blob->pe = (entryInfo) &(blob->ei[2]);
     blob->pvlen = sizeof(blob->il) + sizeof(blob->dl) +
 		  (blob->il * sizeof(*blob->pe)) + blob->dl;