summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/rpm/files
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/rpm/files')
-rw-r--r--meta/recipes-devtools/rpm/files/0001-rpm-rpmio.c-restrict-virtual-memory-usage-if-limit-s.patch25
-rw-r--r--meta/recipes-devtools/rpm/files/0001-rpmio-Fix-lzopen_internal-mode-parsing-when-Tn-is-us.patch34
-rw-r--r--meta/recipes-devtools/rpm/files/CVE-2021-20266.patch109
-rw-r--r--meta/recipes-devtools/rpm/files/CVE-2021-3421.patch197
-rw-r--r--meta/recipes-devtools/rpm/files/CVE-2021-3521-01.patch60
-rw-r--r--meta/recipes-devtools/rpm/files/CVE-2021-3521-02.patch55
-rw-r--r--meta/recipes-devtools/rpm/files/CVE-2021-3521-03.patch34
-rw-r--r--meta/recipes-devtools/rpm/files/CVE-2021-3521.patch330
8 files changed, 833 insertions, 11 deletions
diff --git a/meta/recipes-devtools/rpm/files/0001-rpm-rpmio.c-restrict-virtual-memory-usage-if-limit-s.patch b/meta/recipes-devtools/rpm/files/0001-rpm-rpmio.c-restrict-virtual-memory-usage-if-limit-s.patch
index 6454785254..dc3f74fecd 100644
--- a/meta/recipes-devtools/rpm/files/0001-rpm-rpmio.c-restrict-virtual-memory-usage-if-limit-s.patch
+++ b/meta/recipes-devtools/rpm/files/0001-rpm-rpmio.c-restrict-virtual-memory-usage-if-limit-s.patch
@@ -11,36 +11,39 @@ CPU thread.
11Upstream-Status: Pending [merge of multithreading patches to upstream] 11Upstream-Status: Pending [merge of multithreading patches to upstream]
12 12
13Signed-off-by: Peter Bergin <peter@berginkonsult.se> 13Signed-off-by: Peter Bergin <peter@berginkonsult.se>
14Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
14--- 15---
15 rpmio/rpmio.c | 34 ++++++++++++++++++++++++++++++++++ 16 rpmio/rpmio.c | 36 ++++++++++++++++++++++++++++++++++++
16 1 file changed, 34 insertions(+) 17 1 file changed, 36 insertions(+)
17 18
18diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c 19diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c
19index e051c98..b3c56b6 100644 20index e051c98..b3c56b6 100644
20--- a/rpmio/rpmio.c 21--- a/rpmio/rpmio.c
21+++ b/rpmio/rpmio.c 22+++ b/rpmio/rpmio.c
22@@ -845,6 +845,40 @@ static LZFILE *lzopen_internal(const char *mode, int fd, int xz) 23@@ -845,6 +845,42 @@ static LZFILE *lzopen_internal(const char *mode, int fd, int xz)
23 } 24 }
24 #endif 25 #endif
25 26
26+ struct rlimit virtual_memory; 27+ struct rlimit virtual_memory = {RLIM_INFINITY , RLIM_INFINITY};
27+ getrlimit(RLIMIT_AS, &virtual_memory); 28+ int status = getrlimit(RLIMIT_AS, &virtual_memory);
28+ if (virtual_memory.rlim_cur != RLIM_INFINITY) { 29+ if ((status != -1) && (virtual_memory.rlim_cur != RLIM_INFINITY)) {
29+ const uint64_t virtual_memlimit = virtual_memory.rlim_cur; 30+ const uint64_t virtual_memlimit = virtual_memory.rlim_cur;
31+ uint32_t threads_max = lzma_cputhreads();
30+ const uint64_t virtual_memlimit_per_cpu_thread = 32+ const uint64_t virtual_memlimit_per_cpu_thread =
31+ virtual_memlimit / lzma_cputhreads(); 33+ virtual_memlimit / ((threads_max == 0) ? 1 : threads_max);
32+ uint64_t memory_usage_virt;
33+ rpmlog(RPMLOG_NOTICE, "XZ: virtual memory restricted to %lu and " 34+ rpmlog(RPMLOG_NOTICE, "XZ: virtual memory restricted to %lu and "
34+ "per CPU thread %lu\n", virtual_memlimit, virtual_memlimit_per_cpu_thread); 35+ "per CPU thread %lu\n", virtual_memlimit, virtual_memlimit_per_cpu_thread);
36+ uint64_t memory_usage_virt;
35+ /* keep reducing the number of compression threads until memory 37+ /* keep reducing the number of compression threads until memory
36+ usage falls below the limit per CPU thread*/ 38+ usage falls below the limit per CPU thread*/
37+ while ((memory_usage_virt = lzma_stream_encoder_mt_memusage(&mt_options)) > 39+ while ((memory_usage_virt = lzma_stream_encoder_mt_memusage(&mt_options)) >
38+ virtual_memlimit_per_cpu_thread) { 40+ virtual_memlimit_per_cpu_thread) {
39+ /* If number of threads goes down to zero lzma_stream_encoder will 41+ /* If number of threads goes down to zero or in case of any other error
40+ * will return UINT64_MAX. We must check here to avoid an infinite loop. 42+ * lzma_stream_encoder_mt_memusage will return UINT64_MAX. We must check
43+ * for both the cases here to avoid an infinite loop.
41+ * If we get into situation that one thread requires more virtual memory 44+ * If we get into situation that one thread requires more virtual memory
42+ * than available we set one thread, print error message and try anyway. */ 45+ * than available we set one thread, print error message and try anyway. */
43+ if (--mt_options.threads == 0) { 46+ if ((--mt_options.threads == 0) || (memory_usage_virt == UINT64_MAX)) {
44+ mt_options.threads = 1; 47+ mt_options.threads = 1;
45+ rpmlog(RPMLOG_WARNING, 48+ rpmlog(RPMLOG_WARNING,
46+ "XZ: Could not adjust number of threads to get below " 49+ "XZ: Could not adjust number of threads to get below "
diff --git a/meta/recipes-devtools/rpm/files/0001-rpmio-Fix-lzopen_internal-mode-parsing-when-Tn-is-us.patch b/meta/recipes-devtools/rpm/files/0001-rpmio-Fix-lzopen_internal-mode-parsing-when-Tn-is-us.patch
new file mode 100644
index 0000000000..9a5ebb9115
--- /dev/null
+++ b/meta/recipes-devtools/rpm/files/0001-rpmio-Fix-lzopen_internal-mode-parsing-when-Tn-is-us.patch
@@ -0,0 +1,34 @@
1From 405fc8998181353bd510864ca251dc233afec276 Mon Sep 17 00:00:00 2001
2From: Vitaly Chikunov <vt@altlinux.org>
3Date: Wed, 6 Jan 2021 23:43:41 +0300
4Subject: [PATCH] rpmio: Fix lzopen_internal mode parsing when 'Tn' is used
5
6When there is number after "T" (suggested number of threads or "0" for
7getncpus), lzopen_internal() mode parser would skip one byte, and when
8it's at the end of the string it would then parse undesired garbage from
9the memory, making intermittent compression failures.
10
11Fixes: 7740d1098 ("Add support for multithreaded xz compression")
12Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
13
14Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/commit/405fc8998181353bd510864ca251dc233afec276]
15
16---
17 rpmio/rpmio.c | 1 +
18 1 file changed, 1 insertion(+)
19
20diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c
21index ed1e25140..9d32ec6d9 100644
22--- a/rpmio/rpmio.c
23+++ b/rpmio/rpmio.c
24@@ -798,6 +798,7 @@ static LZFILE *lzopen_internal(const char *mode, int fd, int xz)
25 * should've processed
26 * */
27 while (isdigit(*++mode));
28+ --mode;
29 }
30 #ifdef HAVE_LZMA_MT
31 else
32--
332.25.1
34
diff --git a/meta/recipes-devtools/rpm/files/CVE-2021-20266.patch b/meta/recipes-devtools/rpm/files/CVE-2021-20266.patch
new file mode 100644
index 0000000000..f2fc47e321
--- /dev/null
+++ b/meta/recipes-devtools/rpm/files/CVE-2021-20266.patch
@@ -0,0 +1,109 @@
1From ebbf0f0133c498d229e94ecf2ed0b41d6e6a142a Mon Sep 17 00:00:00 2001
2From: Demi Marie Obenour <athena@invisiblethingslab.com>
3Date: Mon, 8 Feb 2021 16:05:01 -0500
4Subject: [PATCH] hdrblobInit() needs bounds checks too
5
6Users can pass untrusted data to hdrblobInit() and it must be robust
7against this.
8
9Backported from commit 8f4b3c3cab8922a2022b9e47c71f1ecf906077ef
10
11Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/pull/1587/commits/9646711891df851dfbf7ef54cc171574a0914b15]
12CVE: CVE-2021-20266
13Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
14
15---
16 lib/header.c | 48 +++++++++++++++++++++++++++++++-----------------
17 1 file changed, 31 insertions(+), 17 deletions(-)
18
19diff --git a/lib/header.c b/lib/header.c
20index 5b09f8352..ad5b6dc57 100644
21--- a/lib/header.c
22+++ b/lib/header.c
23@@ -11,6 +11,7 @@
24 #include "system.h"
25 #include <netdb.h>
26 #include <errno.h>
27+#include <inttypes.h>
28 #include <rpm/rpmtypes.h>
29 #include <rpm/rpmstring.h>
30 #include "lib/header_internal.h"
31@@ -1890,6 +1891,25 @@ hdrblob hdrblobFree(hdrblob blob)
32 return NULL;
33 }
34
35+static rpmRC hdrblobVerifyLengths(rpmTagVal regionTag, uint32_t il, uint32_t dl,
36+ char **emsg) {
37+ uint32_t il_max = HEADER_TAGS_MAX;
38+ uint32_t dl_max = HEADER_DATA_MAX;
39+ if (regionTag == RPMTAG_HEADERSIGNATURES) {
40+ il_max = 32;
41+ dl_max = 8192;
42+ }
43+ if (hdrchkRange(il_max, il)) {
44+ rasprintf(emsg, _("hdr tags: BAD, no. of tags(%" PRIu32 ") out of range"), il);
45+ return RPMRC_FAIL;
46+ }
47+ if (hdrchkRange(dl_max, dl)) {
48+ rasprintf(emsg, _("hdr data: BAD, no. of bytes(%" PRIu32 ") out of range"), dl);
49+ return RPMRC_FAIL;
50+ }
51+ return RPMRC_OK;
52+}
53+
54 rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrblob blob, char **emsg)
55 {
56 int32_t block[4];
57@@ -1902,13 +1922,6 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
58 size_t nb;
59 rpmRC rc = RPMRC_FAIL; /* assume failure */
60 int xx;
61- int32_t il_max = HEADER_TAGS_MAX;
62- int32_t dl_max = HEADER_DATA_MAX;
63-
64- if (regionTag == RPMTAG_HEADERSIGNATURES) {
65- il_max = 32;
66- dl_max = 8192;
67- }
68
69 memset(block, 0, sizeof(block));
70 if ((xx = Freadall(fd, bs, blen)) != blen) {
71@@ -1921,15 +1934,9 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
72 goto exit;
73 }
74 il = ntohl(block[2]);
75- if (hdrchkRange(il_max, il)) {
76- rasprintf(emsg, _("hdr tags: BAD, no. of tags(%d) out of range"), il);
77- goto exit;
78- }
79 dl = ntohl(block[3]);
80- if (hdrchkRange(dl_max, dl)) {
81- rasprintf(emsg, _("hdr data: BAD, no. of bytes(%d) out of range"), dl);
82+ if (hdrblobVerifyLengths(regionTag, il, dl, emsg))
83 goto exit;
84- }
85
86 nb = (il * sizeof(struct entryInfo_s)) + dl;
87 uc = sizeof(il) + sizeof(dl) + nb;
88@@ -1973,11 +1980,18 @@ rpmRC hdrblobInit(const void *uh, size_t uc,
89 struct hdrblob_s *blob, char **emsg)
90 {
91 rpmRC rc = RPMRC_FAIL;
92-
93 memset(blob, 0, sizeof(*blob));
94+ if (uc && uc < 8) {
95+ rasprintf(emsg, _("hdr length: BAD"));
96+ goto exit;
97+ }
98+
99 blob->ei = (int32_t *) uh; /* discards const */
100- blob->il = ntohl(blob->ei[0]);
101- blob->dl = ntohl(blob->ei[1]);
102+ blob->il = ntohl((uint32_t)(blob->ei[0]));
103+ blob->dl = ntohl((uint32_t)(blob->ei[1]));
104+ if (hdrblobVerifyLengths(regionTag, blob->il, blob->dl, emsg) != RPMRC_OK)
105+ goto exit;
106+
107 blob->pe = (entryInfo) &(blob->ei[2]);
108 blob->pvlen = sizeof(blob->il) + sizeof(blob->dl) +
109 (blob->il * sizeof(*blob->pe)) + blob->dl;
diff --git a/meta/recipes-devtools/rpm/files/CVE-2021-3421.patch b/meta/recipes-devtools/rpm/files/CVE-2021-3421.patch
new file mode 100644
index 0000000000..b1a05b6863
--- /dev/null
+++ b/meta/recipes-devtools/rpm/files/CVE-2021-3421.patch
@@ -0,0 +1,197 @@
1From 1e5b70cab83c95aa138107a38ecda75ff70e8985 Mon Sep 17 00:00:00 2001
2From: Minjae Kim <flowergom@gmail.com>
3Date: Thu, 24 Jun 2021 01:11:26 +0000
4Subject: [PATCH] Be much more careful about copying data from the signature
5 header
6
7Only look for known tags, and ensure correct type and size where known
8before copying over. Bump the old arbitrary 16k count limit to 16M limit
9though, it's not inconceivable that a package could have that many files.
10While at it, ensure none of these tags exist in the main header,
11which would confuse us greatly.
12
13This is optimized for backporting ease, upstream can remove redundancies
14and further improve checking later.
15
16Reported and initial patches by Demi Marie Obenour.
17
18Fixes: RhBug:1935049, RhBug:1933867, RhBug:1935035, RhBug:1934125, ...
19
20Fixes: CVE-2021-3421, CVE-2021-20271
21
22Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/commit/d6a86b5e69e46cc283b1e06c92343319beb42e21]
23CVE: CVE-2021-3421
24Signed-off-by: Minjae Kim <flowergom@gmail.com>
25---
26 lib/package.c | 115 ++++++++++++++++++++++++--------------------------
27 lib/rpmtag.h | 4 ++
28 2 files changed, 58 insertions(+), 61 deletions(-)
29
30diff --git a/lib/package.c b/lib/package.c
31index 081123d84e..7c26ea323f 100644
32--- a/lib/package.c
33+++ b/lib/package.c
34@@ -20,76 +20,68 @@
35
36 #include "debug.h"
37
38+struct taglate_s {
39+ rpmTagVal stag;
40+ rpmTagVal xtag;
41+ rpm_count_t count;
42+} const xlateTags[] = {
43+ { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1 },
44+ { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0 },
45+ { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16 },
46+ { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0 },
47+ /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0 }, */ /* long obsolete, dont use */
48+ { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1 },
49+ { RPMSIGTAG_FILESIGNATURES, RPMTAG_FILESIGNATURES, 0 },
50+ { RPMSIGTAG_FILESIGNATURELENGTH, RPMTAG_FILESIGNATURELENGTH, 1 },
51+ { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1 },
52+ { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1 },
53+ { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0 },
54+ { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0 },
55+ { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1 },
56+ { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1 },
57+ { 0 }
58+};
59+
60 /** \ingroup header
61 * Translate and merge legacy signature tags into header.
62 * @param h header (dest)
63 * @param sigh signature header (src)
64 */
65 static
66-void headerMergeLegacySigs(Header h, Header sigh)
67+rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg)
68 {
69- HeaderIterator hi;
70+ const struct taglate_s *xl;
71 struct rpmtd_s td;
72
73- hi = headerInitIterator(sigh);
74- for (; headerNext(hi, &td); rpmtdFreeData(&td))
75- {
76- switch (td.tag) {
77- /* XXX Translate legacy signature tag values. */
78- case RPMSIGTAG_SIZE:
79- td.tag = RPMTAG_SIGSIZE;
80- break;
81- case RPMSIGTAG_PGP:
82- td.tag = RPMTAG_SIGPGP;
83- break;
84- case RPMSIGTAG_MD5:
85- td.tag = RPMTAG_SIGMD5;
86- break;
87- case RPMSIGTAG_GPG:
88- td.tag = RPMTAG_SIGGPG;
89- break;
90- case RPMSIGTAG_PGP5:
91- td.tag = RPMTAG_SIGPGP5;
92- break;
93- case RPMSIGTAG_PAYLOADSIZE:
94- td.tag = RPMTAG_ARCHIVESIZE;
95- break;
96- case RPMSIGTAG_SHA1:
97- case RPMSIGTAG_SHA256:
98- case RPMSIGTAG_DSA:
99- case RPMSIGTAG_RSA:
100- default:
101- if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
102- continue;
103- break;
104- }
105- if (!headerIsEntry(h, td.tag)) {
106- switch (td.type) {
107- case RPM_NULL_TYPE:
108- continue;
109- break;
110- case RPM_CHAR_TYPE:
111- case RPM_INT8_TYPE:
112- case RPM_INT16_TYPE:
113- case RPM_INT32_TYPE:
114- case RPM_INT64_TYPE:
115- if (td.count != 1)
116- continue;
117- break;
118- case RPM_STRING_TYPE:
119- case RPM_BIN_TYPE:
120- if (td.count >= 16*1024)
121- continue;
122- break;
123- case RPM_STRING_ARRAY_TYPE:
124- case RPM_I18NSTRING_TYPE:
125- continue;
126- break;
127- }
128- (void) headerPut(h, &td, HEADERPUT_DEFAULT);
129- }
130+ rpmtdReset(&td);
131+ for (xl = xlateTags; xl->stag; xl++) {
132+ /* There mustn't be one in the main header */
133+ if (headerIsEntry(h, xl->xtag))
134+ break;
135+ if (headerGet(sigh, xl->stag, &td, HEADERGET_RAW|HEADERGET_MINMEM)) {
136+ /* Translate legacy tags */
137+ if (xl->stag != xl->xtag)
138+ td.tag = xl->xtag;
139+ /* Ensure type and tag size match expectations */
140+ if (td.type != rpmTagGetTagType(td.tag))
141+ break;
142+ if (td.count < 1 || td.count > 16*1024*1024)
143+ break;
144+ if (xl->count && td.count != xl->count)
145+ break;
146+ if (!headerPut(h, &td, HEADERPUT_DEFAULT))
147+ break;
148+ rpmtdFreeData(&td);
149+ }
150+ }
151+ rpmtdFreeData(&td);
152+
153+ if (xl->stag) {
154+ rasprintf(msg, "invalid signature tag %s (%d)",
155+ rpmTagGetName(xl->xtag), xl->xtag);
156 }
157- headerFreeIterator(hi);
158+
159+ return xl->stag;
160 }
161
162 /**
163@@ -337,7 +329,8 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
164 goto exit;
165
166 /* Append (and remap) signature tags to the metadata. */
167- headerMergeLegacySigs(h, sigh);
168+ if (headerMergeLegacySigs(h, sigh,&msg))
169+ goto exit;
170 applyRetrofits(h);
171
172 /* Bump reference count for return. */
173diff --git a/lib/rpmtag.h b/lib/rpmtag.h
174index 8c718b31b5..d562572c6f 100644
175--- a/lib/rpmtag.h
176+++ b/lib/rpmtag.h
177@@ -65,6 +65,8 @@ typedef enum rpmTag_e {
178 RPMTAG_LONGARCHIVESIZE = RPMTAG_SIG_BASE+15, /* l */
179 /* RPMTAG_SIG_BASE+16 reserved */
180 RPMTAG_SHA256HEADER = RPMTAG_SIG_BASE+17, /* s */
181+ /* RPMTAG_SIG_BASE+18 reserved for RPMSIGTAG_FILESIGNATURES */
182+ /* RPMTAG_SIG_BASE+19 reserved for RPMSIGTAG_FILESIGNATURELENGTH */
183
184 RPMTAG_NAME = 1000, /* s */
185 #define RPMTAG_N RPMTAG_NAME /* s */
186@@ -422,6 +424,8 @@ typedef enum rpmSigTag_e {
187 RPMSIGTAG_LONGSIZE = RPMTAG_LONGSIGSIZE, /*!< internal Header+Payload size (64bit) in bytes. */
188 RPMSIGTAG_LONGARCHIVESIZE = RPMTAG_LONGARCHIVESIZE, /*!< internal uncompressed payload size (64bit) in bytes. */
189 RPMSIGTAG_SHA256 = RPMTAG_SHA256HEADER,
190+ RPMSIGTAG_FILESIGNATURES = RPMTAG_SIG_BASE + 18,
191+ RPMSIGTAG_FILESIGNATURELENGTH = RPMTAG_SIG_BASE + 19,
192 } rpmSigTag;
193
194
195--
1962.17.1
197
diff --git a/meta/recipes-devtools/rpm/files/CVE-2021-3521-01.patch b/meta/recipes-devtools/rpm/files/CVE-2021-3521-01.patch
new file mode 100644
index 0000000000..0882d6f310
--- /dev/null
+++ b/meta/recipes-devtools/rpm/files/CVE-2021-3521-01.patch
@@ -0,0 +1,60 @@
1From b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8 Mon Sep 17 00:00:00 2001
2From: Panu Matilainen <pmatilai@redhat.com>
3Date: Thu, 30 Sep 2021 09:51:10 +0300
4Subject: [PATCH] Process MPI's from all kinds of signatures
5
6No immediate effect but needed by the following commits.
7
8Dependent patch:
9CVE: CVE-2021-3521
10Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/commit/b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8]
11Signed-off-by: Riyaz Khan <Riyaz.Khan@kpit.com>
12
13---
14 rpmio/rpmpgp.c | 12 +++++-------
15 1 file changed, 5 insertions(+), 7 deletions(-)
16
17diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
18index ee5c81e246..340de5fc9a 100644
19--- a/rpmio/rpmpgp.c
20+++ b/rpmio/rpmpgp.c
21@@ -511,7 +511,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg)
22 return NULL;
23 }
24
25-static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
26+static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo,
27 const uint8_t *p, const uint8_t *h, size_t hlen,
28 pgpDigParams sigp)
29 {
30@@ -524,10 +524,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
31 int mpil = pgpMpiLen(p);
32 if (p + mpil > pend)
33 break;
34- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
35- if (sigalg->setmpi(sigalg, i, p))
36- break;
37- }
38+ if (sigalg->setmpi(sigalg, i, p))
39+ break;
40 p += mpil;
41 }
42
43@@ -600,7 +598,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
44 }
45
46 p = ((uint8_t *)v) + sizeof(*v);
47- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
48+ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp);
49 } break;
50 case 4:
51 { pgpPktSigV4 v = (pgpPktSigV4)h;
52@@ -658,7 +656,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
53 if (p > (h + hlen))
54 return 1;
55
56- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
57+ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp);
58 } break;
59 default:
60 rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version);
diff --git a/meta/recipes-devtools/rpm/files/CVE-2021-3521-02.patch b/meta/recipes-devtools/rpm/files/CVE-2021-3521-02.patch
new file mode 100644
index 0000000000..c5f88a8c72
--- /dev/null
+++ b/meta/recipes-devtools/rpm/files/CVE-2021-3521-02.patch
@@ -0,0 +1,55 @@
1From 9f03f42e2614a68f589f9db8fe76287146522c0c Mon Sep 17 00:00:00 2001
2From: Panu Matilainen <pmatilai@redhat.com>
3Date: Thu, 30 Sep 2021 09:56:20 +0300
4Subject: [PATCH] Refactor pgpDigParams construction to helper function
5
6No functional changes, just to reduce code duplication and needed by
7the following commits.
8
9Dependent patch:
10CVE: CVE-2021-3521
11Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/commit/9f03f42e2614a68f589f9db8fe76287146522c0c]
12Signed-off-by: Riyaz Khan <Riyaz.Khan@kpit.com>
13
14---
15 rpmio/rpmpgp.c | 13 +++++++++----
16 1 file changed, 9 insertions(+), 4 deletions(-)
17
18diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
19index 340de5fc9a..aad7c275c9 100644
20--- a/rpmio/rpmpgp.c
21+++ b/rpmio/rpmpgp.c
22@@ -1055,6 +1055,13 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype)
23 return algo;
24 }
25
26+static pgpDigParams pgpDigParamsNew(uint8_t tag)
27+{
28+ pgpDigParams digp = xcalloc(1, sizeof(*digp));
29+ digp->tag = tag;
30+ return digp;
31+}
32+
33 int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
34 pgpDigParams * ret)
35 {
36@@ -1072,8 +1079,7 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
37 if (pkttype && pkt.tag != pkttype) {
38 break;
39 } else {
40- digp = xcalloc(1, sizeof(*digp));
41- digp->tag = pkt.tag;
42+ digp = pgpDigParamsNew(pkt.tag);
43 }
44 }
45
46@@ -1121,8 +1127,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
47 digps = xrealloc(digps, alloced * sizeof(*digps));
48 }
49
50- digps[count] = xcalloc(1, sizeof(**digps));
51- digps[count]->tag = PGPTAG_PUBLIC_SUBKEY;
52+ digps[count] = pgpDigParamsNew(PGPTAG_PUBLIC_SUBKEY);
53 /* Copy UID from main key to subkey */
54 digps[count]->userid = xstrdup(mainkey->userid);
55
diff --git a/meta/recipes-devtools/rpm/files/CVE-2021-3521-03.patch b/meta/recipes-devtools/rpm/files/CVE-2021-3521-03.patch
new file mode 100644
index 0000000000..fd31f11beb
--- /dev/null
+++ b/meta/recipes-devtools/rpm/files/CVE-2021-3521-03.patch
@@ -0,0 +1,34 @@
1From 5ff86764b17f31535cb247543a90dd739076ec38 Mon Sep 17 00:00:00 2001
2From: Demi Marie Obenour <demi@invisiblethingslab.com>
3Date: Thu, 6 May 2021 18:34:45 -0400
4Subject: [PATCH] Do not allow extra packets to follow a signature
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9According to RFC 4880 § 11.4, a detached signature is “simply a
10Signature packet”. Therefore, extra packets following a detached
11signature are not allowed.
12
13Dependent patch:
14CVE: CVE-2021-3521
15Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/commit/5ff86764b17f31535cb247543a90dd739076ec38]
16Signed-off-by: Riyaz Khan <Riyaz.Khan@kpit.com>
17
18---
19 rpmio/rpmpgp.c | 2 ++
20 1 file changed, 2 insertions(+)
21
22diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
23index f1a99e7169..5b346a8253 100644
24--- a/rpmio/rpmpgp.c
25+++ b/rpmio/rpmpgp.c
26@@ -1068,6 +1068,8 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
27 break;
28
29 p += (pkt.body - pkt.head) + pkt.blen;
30+ if (pkttype == PGPTAG_SIGNATURE)
31+ break;
32 }
33
34 rc = (digp && (p == pend)) ? 0 : -1;
diff --git a/meta/recipes-devtools/rpm/files/CVE-2021-3521.patch b/meta/recipes-devtools/rpm/files/CVE-2021-3521.patch
new file mode 100644
index 0000000000..cb9e9842fe
--- /dev/null
+++ b/meta/recipes-devtools/rpm/files/CVE-2021-3521.patch
@@ -0,0 +1,330 @@
1From bd36c5dc9fb6d90c46fbfed8c2d67516fc571ec8 Mon Sep 17 00:00:00 2001
2From: Panu Matilainen <pmatilai@redhat.com>
3Date: Thu, 30 Sep 2021 09:59:30 +0300
4Subject: [PATCH] Validate and require subkey binding signatures on PGP public
5 keys
6
7All subkeys must be followed by a binding signature by the primary key
8as per the OpenPGP RFC, enforce the presence and validity in the parser.
9
10The implementation is as kludgey as they come to work around our
11simple-minded parser structure without touching API, to maximise
12backportability. Store all the raw packets internally as we decode them
13to be able to access previous elements at will, needed to validate ordering
14and access the actual data. Add testcases for manipulated keys whose
15import previously would succeed.
16
17Depends on the two previous commits:
187b399fcb8f52566e6f3b4327197a85facd08db91 and
19236b802a4aa48711823a191d1b7f753c82a89ec5
20
21CVE: CVE-2021-3521
22Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/commit/bd36c5dc9fb6d90c46fbfed8c2d67516fc571ec8]
23Comment: Hunk refreshed
24Signed-off-by: Riyaz Khan <Riyaz.Khan@kpit.com>
25
26Fixes CVE-2021-3521.
27---
28 rpmio/rpmpgp.c | 98 +++++++++++++++++--
29 tests/Makefile.am | 3 +
30 tests/data/keys/CVE-2021-3521-badbind.asc | 25 +++++
31 .../data/keys/CVE-2021-3521-nosubsig-last.asc | 25 +++++
32 tests/data/keys/CVE-2021-3521-nosubsig.asc | 37 +++++++
33 tests/rpmsigdig.at | 28 ++++++
34 6 files changed, 209 insertions(+), 7 deletions(-)
35 create mode 100644 tests/data/keys/CVE-2021-3521-badbind.asc
36 create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig-last.asc
37 create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig.asc
38
39diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
40index aad7c275c9..d70802ae86 100644
41--- a/rpmio/rpmpgp.c
42+++ b/rpmio/rpmpgp.c
43@@ -1004,37 +1004,121 @@ static pgpDigParams pgpDigParamsNew(uint8_t tag)
44 return digp;
45 }
46
47+static int hashKey(DIGEST_CTX hash, const struct pgpPkt *pkt, int exptag)
48+{
49+ int rc = -1;
50+ if (pkt->tag == exptag) {
51+ uint8_t head[] = {
52+ 0x99,
53+ (pkt->blen >> 8),
54+ (pkt->blen ),
55+ };
56+
57+ rpmDigestUpdate(hash, head, 3);
58+ rpmDigestUpdate(hash, pkt->body, pkt->blen);
59+ rc = 0;
60+ }
61+ return rc;
62+}
63+
64+static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig,
65+ const struct pgpPkt *all, int i)
66+{
67+ int rc = -1;
68+ DIGEST_CTX hash = NULL;
69+
70+ switch (selfsig->sigtype) {
71+ case PGPSIGTYPE_SUBKEY_BINDING:
72+ hash = rpmDigestInit(selfsig->hash_algo, 0);
73+ if (hash) {
74+ rc = hashKey(hash, &all[0], PGPTAG_PUBLIC_KEY);
75+ if (!rc)
76+ rc = hashKey(hash, &all[i-1], PGPTAG_PUBLIC_SUBKEY);
77+ }
78+ break;
79+ default:
80+ /* ignore types we can't handle */
81+ rc = 0;
82+ break;
83+ }
84+
85+ if (hash && rc == 0)
86+ rc = pgpVerifySignature(key, selfsig, hash);
87+
88+ rpmDigestFinal(hash, NULL, NULL, 0);
89+
90+ return rc;
91+}
92+
93 int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
94 pgpDigParams * ret)
95 {
96 const uint8_t *p = pkts;
97 const uint8_t *pend = pkts + pktlen;
98 pgpDigParams digp = NULL;
99- struct pgpPkt pkt;
100+ pgpDigParams selfsig = NULL;
101+ int i = 0;
102+ int alloced = 16; /* plenty for normal cases */
103+ struct pgpPkt *all = xmalloc(alloced * sizeof(*all));
104 int rc = -1; /* assume failure */
105+ int expect = 0;
106+ int prevtag = 0;
107
108 while (p < pend) {
109- if (decodePkt(p, (pend - p), &pkt))
110+ struct pgpPkt *pkt = &all[i];
111+ if (decodePkt(p, (pend - p), pkt))
112 break;
113
114 if (digp == NULL) {
115- if (pkttype && pkt.tag != pkttype) {
116+ if (pkttype && pkt->tag != pkttype) {
117 break;
118 } else {
119- digp = pgpDigParamsNew(pkt.tag);
120+ digp = pgpDigParamsNew(pkt->tag);
121 }
122 }
123
124- if (pgpPrtPkt(&pkt, digp))
125+ if (expect) {
126+ if (pkt->tag != expect)
127+ break;
128+ selfsig = pgpDigParamsNew(pkt->tag);
129+ }
130+
131+ if (pgpPrtPkt(pkt, selfsig ? selfsig : digp))
132 break;
133
134- p += (pkt.body - pkt.head) + pkt.blen;
135+ if (selfsig) {
136+ /* subkeys must be followed by binding signature */
137+ if (prevtag == PGPTAG_PUBLIC_SUBKEY) {
138+ if (selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING)
139+ break;
140+ }
141+
142+ int xx = pgpVerifySelf(digp, selfsig, all, i);
143+
144+ selfsig = pgpDigParamsFree(selfsig);
145+ if (xx)
146+ break;
147+ expect = 0;
148+ }
149+
150+ if (pkt->tag == PGPTAG_PUBLIC_SUBKEY)
151+ expect = PGPTAG_SIGNATURE;
152+ prevtag = pkt->tag;
153+
154+ i++;
155+ p += (pkt->body - pkt->head) + pkt->blen;
156 if (pkttype == PGPTAG_SIGNATURE)
157 break;
158+
159+ if (alloced <= i) {
160+ alloced *= 2;
161+ all = xrealloc(all, alloced * sizeof(*all));
162+ }
163 }
164
165- rc = (digp && (p == pend)) ? 0 : -1;
166+ rc = (digp && (p == pend) && expect == 0) ? 0 : -1;
167
168+ free(all);
169 if (ret && rc == 0) {
170 *ret = digp;
171 } else {
172diff --git a/tests/Makefile.am b/tests/Makefile.am
173index b4a2e2e1ce..bc535d2833 100644
174--- a/tests/Makefile.am
175+++ b/tests/Makefile.am
176@@ -87,6 +87,9 @@ EXTRA_DIST += data/SPECS/hello-config-buildid.spec
177 EXTRA_DIST += data/SPECS/hello-cd.spec
178 EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.pub
179 EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.secret
180+EXTRA_DIST += data/keys/CVE-2021-3521-badbind.asc
181+EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig.asc
182+EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig-last.asc
183 EXTRA_DIST += data/macros.testfile
184
185 # testsuite voodoo
186diff --git a/tests/data/keys/CVE-2021-3521-badbind.asc b/tests/data/keys/CVE-2021-3521-badbind.asc
187new file mode 100644
188index 0000000000..aea00f9d7a
189--- /dev/null
190+++ b/tests/data/keys/CVE-2021-3521-badbind.asc
191@@ -0,0 +1,25 @@
192+-----BEGIN PGP PUBLIC KEY BLOCK-----
193+Version: rpm-4.17.90 (NSS-3)
194+
195+mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
196+HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
197+91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
198+eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
199+7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
200+1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
201+c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
202+CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
203+Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
204+BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
205+XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
206+fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
207++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
208+BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
209+zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
210+iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
211+Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
212+KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
213+L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE=
214+=WCfs
215+-----END PGP PUBLIC KEY BLOCK-----
216+
217diff --git a/tests/data/keys/CVE-2021-3521-nosubsig-last.asc b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc
218new file mode 100644
219index 0000000000..aea00f9d7a
220--- /dev/null
221+++ b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc
222@@ -0,0 +1,25 @@
223+-----BEGIN PGP PUBLIC KEY BLOCK-----
224+Version: rpm-4.17.90 (NSS-3)
225+
226+mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
227+HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
228+91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
229+eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
230+7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
231+1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
232+c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
233+CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
234+Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
235+BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
236+XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
237+fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
238++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
239+BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
240+zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
241+iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
242+Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
243+KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
244+L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE=
245+=WCfs
246+-----END PGP PUBLIC KEY BLOCK-----
247+
248diff --git a/tests/data/keys/CVE-2021-3521-nosubsig.asc b/tests/data/keys/CVE-2021-3521-nosubsig.asc
249new file mode 100644
250index 0000000000..3a2e7417f8
251--- /dev/null
252+++ b/tests/data/keys/CVE-2021-3521-nosubsig.asc
253@@ -0,0 +1,37 @@
254+-----BEGIN PGP PUBLIC KEY BLOCK-----
255+Version: rpm-4.17.90 (NSS-3)
256+
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
287+E4XX4jtDmdZPreZALsiB
288+=rRop
289+-----END PGP PUBLIC KEY BLOCK-----
290+
291diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
292index 0f8f2b4884..c8b9f139e1 100644
293--- a/tests/rpmsigdig.at
294+++ b/tests/rpmsigdig.at
295@@ -240,6 +240,34 @@ gpg(185e6146f00650f8) = 4:185e6146f00650f8-58e63918
296 [])
297 AT_CLEANUP
298
299+AT_SETUP([rpmkeys --import invalid keys])
300+AT_KEYWORDS([rpmkeys import])
301+RPMDB_INIT
302+
303+AT_CHECK([
304+runroot rpmkeys --import /data/keys/CVE-2021-3521-badbind.asc
305+],
306+[1],
307+[],
308+[error: /data/keys/CVE-2021-3521-badbind.asc: key 1 import failed.]
309+)
310+AT_CHECK([
311+runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig.asc
312+],
313+[1],
314+[],
315+[error: /data/keys/CVE-2021-3521-nosubsig.asc: key 1 import failed.]
316+)
317+
318+AT_CHECK([
319+runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig-last.asc
320+],
321+[1],
322+[],
323+[error: /data/keys/CVE-2021-3521-nosubsig-last.asc: key 1 import failed.]
324+)
325+AT_CLEANUP
326+
327 # ------------------------------
328 # Test pre-built package verification
329 AT_SETUP([rpmkeys -K <signed> 1])
330