From 9173d8cd3a6b21cf438683d47d5927246ac67f37 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Fri, 16 Sep 2022 12:17:48 +0530 Subject: [PATCH] rpm: further fixes to CVE-2021-3521 - CVE-2021-3521.patch taken from https://git.rockylinux.org/staging/rpms/rpm/-/blob/r9/SOURCES/rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch - And add rpm upstream commit https://github.com/rpm-software-management/rpm/commit/daeddb01de50c53b98eae75e11234132ae63538a This is based on suggestion https://github.com/rpm-software-management/rpm/pull/1795#issuecomment-1246543099 Change-Id: If30dfde170dcb2ee6496b632feb0597f2f7b13a1 Signed-off-by: Shreenidhi Shedi Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/17875 Reviewed-by: Tapas Kundu Tested-by: Tapas Kundu --- SPECS/rpm/CVE-2021-3521-1.patch | 59 ---- SPECS/rpm/CVE-2021-3521-2.patch | 52 --- ...-2021-3521-3.patch => CVE-2021-3521.patch} | 269 +++++++++++---- SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch | 308 ------------------ SPECS/rpm/rpm.spec | 101 +++--- 5 files changed, 257 insertions(+), 532 deletions(-) delete mode 100644 SPECS/rpm/CVE-2021-3521-1.patch delete mode 100644 SPECS/rpm/CVE-2021-3521-2.patch rename SPECS/rpm/{CVE-2021-3521-3.patch => CVE-2021-3521.patch} (60%) delete mode 100644 SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch diff --git a/SPECS/rpm/CVE-2021-3521-1.patch b/SPECS/rpm/CVE-2021-3521-1.patch deleted file mode 100644 index e5cbb9ee5e..0000000000 --- a/SPECS/rpm/CVE-2021-3521-1.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 2c916bd21f6ae4e24523cd3d251ae9310d450959 Mon Sep 17 00:00:00 2001 -From: Panu Matilainen -Date: Thu, 30 Sep 2021 09:51:10 +0300 -Subject: [PATCH] Process MPI's from all kinds of signatures - -No immediate effect but needed by the following commits. - -[sshedi: back port to v4.16.1.3] ---- - rpmio/rpmpgp.c | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - -diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c -index 01dca84..e336682 100644 ---- a/rpmio/rpmpgp.c -+++ b/rpmio/rpmpgp.c -@@ -543,7 +543,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg) - return NULL; - } - --static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, -+static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, - const uint8_t *p, const uint8_t *h, size_t hlen, - pgpDigParams sigp) - { -@@ -556,10 +556,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, - int mpil = pgpMpiLen(p); - if (mpil > pend - p) - break; -- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) { -- if (sigalg->setmpi(sigalg, i, p)) -- break; -- } -+ if (sigalg->setmpi(sigalg, i, p)) -+ break; - p += mpil; - } - -@@ -619,7 +617,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - } - - p = ((uint8_t *)v) + sizeof(*v); -- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); -+ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp); - } break; - case 4: - { pgpPktSigV4 v = (pgpPktSigV4)h; -@@ -668,7 +666,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - memcpy(_digp->signhash16, p, sizeof(_digp->signhash16)); - } - -- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p + 2, h, hlen, _digp); -+ rc = pgpPrtSigParams(tag, v->pubkey_algo, p + 2, h, hlen, _digp); - } break; - default: - rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version); --- -2.25.1 - diff --git a/SPECS/rpm/CVE-2021-3521-2.patch b/SPECS/rpm/CVE-2021-3521-2.patch deleted file mode 100644 index dde2938910..0000000000 --- a/SPECS/rpm/CVE-2021-3521-2.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 273f0aedd538efc1a26664b44ff269fa8e14b746 Mon Sep 17 00:00:00 2001 -From: Panu Matilainen -Date: Thu, 30 Sep 2021 09:56:20 +0300 -Subject: [PATCH 2/3] Refactor pgpDigParams construction to helper function - -No functional changes, just to reduce code duplication and needed by -the following commits. ---- - rpmio/rpmpgp.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c -index 80b77661c..fd516f420 100644 ---- a/rpmio/rpmpgp.c -+++ b/rpmio/rpmpgp.c -@@ -1039,6 +1039,13 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype) - return algo; - } - -+static pgpDigParams pgpDigParamsNew(uint8_t tag) -+{ -+ pgpDigParams digp = xcalloc(1, sizeof(*digp)); -+ digp->tag = tag; -+ return digp; -+} -+ - int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, - pgpDigParams * ret) - { -@@ -1056,8 +1063,7 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, - if (pkttype && pkt.tag != pkttype) { - break; - } else { -- digp = xcalloc(1, sizeof(*digp)); -- digp->tag = pkt.tag; -+ digp = pgpDigParamsNew(pkt.tag); - } - } - -@@ -1103,8 +1109,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen, - digps = xrealloc(digps, alloced * sizeof(*digps)); - } - -- digps[count] = xcalloc(1, sizeof(**digps)); -- digps[count]->tag = PGPTAG_PUBLIC_SUBKEY; -+ digps[count] = pgpDigParamsNew(PGPTAG_PUBLIC_SUBKEY); - /* Copy UID from main key to subkey */ - digps[count]->userid = xstrdup(mainkey->userid); - --- -2.25.1 - diff --git a/SPECS/rpm/CVE-2021-3521-3.patch b/SPECS/rpm/CVE-2021-3521.patch similarity index 60% rename from SPECS/rpm/CVE-2021-3521-3.patch rename to SPECS/rpm/CVE-2021-3521.patch index 07dea5b327..3f18488e59 100644 --- a/SPECS/rpm/CVE-2021-3521-3.patch +++ b/SPECS/rpm/CVE-2021-3521.patch @@ -1,8 +1,8 @@ -From 9feb7d34f52457930695ccdc0ccbbd6e33f73f41 Mon Sep 17 00:00:00 2001 -From: Shreenidhi Shedi -Date: Thu, 30 Sep 2021 09:59:30 +0300 -Subject: [PATCH] Validate and require subkey binding signatures on PGP public - keys +From c70efcd353fe8d7fe52ae27207686f1aa6027f6f Mon Sep 17 00:00:00 2001 +From: Demi Marie Obenour +Date: Thu, 6 May 2021 18:34:45 -0400 +Subject: [PATCH 1/2] Validate and require subkey binding signatures on PGP + public keys All subkeys must be followed by a binding signature by the primary key as per the OpenPGP RFC, enforce the presence and validity in the parser. @@ -14,75 +14,122 @@ to be able to access previous elements at will, needed to validate ordering and access the actual data. Add testcases for manipulated keys whose import previously would succeed. -Depends on the two previous commits: -7b399fcb8f52566e6f3b4327197a85facd08db91 and -236b802a4aa48711823a191d1b7f753c82a89ec5 +Combined with: +5ff86764b17f31535cb247543a90dd739076ec38 +b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8 +9f03f42e2614a68f589f9db8fe76287146522c0c +b6dffb6dc5ffa2ddc389743f0507876cab341315 (mem-leak fix) +ae3d2d234ae47ff85229d3fce97a266fa1aa5a61 (use-after-free fix) Fixes CVE-2021-3521. - -[sshedi: back port to v4.16.1.3] - -Signed-off-by: Shreenidhi Shedi --- - rpmio/rpmpgp.c | 107 ++++++++++++++++-- + rpmio/rpmpgp.c | 122 +++++++++++++++--- + sign/rpmgensig.c | 2 +- tests/Makefile.am | 3 + tests/data/keys/CVE-2021-3521-badbind.asc | 25 ++++ .../data/keys/CVE-2021-3521-nosubsig-last.asc | 25 ++++ tests/data/keys/CVE-2021-3521-nosubsig.asc | 37 ++++++ - tests/rpmsigdig.at | 28 +++++ - 6 files changed, 213 insertions(+), 12 deletions(-) + tests/rpmsigdig.at | 28 ++++ + 7 files changed, 224 insertions(+), 18 deletions(-) create mode 100644 tests/data/keys/CVE-2021-3521-badbind.asc create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig-last.asc create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig.asc diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c -index 5d6bd95..0b237e4 100644 +index b278a65..6d661a6 100644 --- a/rpmio/rpmpgp.c +++ b/rpmio/rpmpgp.c -@@ -1056,37 +1056,120 @@ static pgpDigParams pgpDigParamsNew(uint8_t tag) - return digp; +@@ -546,7 +546,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg) + return NULL; + } + +-static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, ++static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, + const uint8_t *p, const uint8_t *h, size_t hlen, + pgpDigParams sigp) + { +@@ -559,10 +559,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, + int mpil = pgpMpiLen(p); + if (p + mpil > pend) + break; +- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) { +- if (sigalg->setmpi(sigalg, i, p)) +- break; +- } ++ if (sigalg->setmpi(sigalg, i, p)) ++ break; + p += mpil; + } + +@@ -622,7 +620,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, + } + + p = ((uint8_t *)v) + sizeof(*v); +- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); ++ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp); + } break; + case 4: + { pgpPktSigV4 v = (pgpPktSigV4)h; +@@ -680,7 +678,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, + if (p > (h + hlen)) + return 1; + +- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); ++ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp); + } break; + default: + rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version); +@@ -1059,36 +1057,127 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype) + return algo; } ++static pgpDigParams pgpDigParamsNew(uint8_t tag) ++{ ++ pgpDigParams digp = xcalloc(1, sizeof(*digp)); ++ digp->tag = tag; ++ return digp; ++} ++ +static int hashKey(DIGEST_CTX hash, const struct pgpPkt *pkt, int exptag) +{ + int rc = -1; + if (pkt->tag == exptag) { -+ uint8_t head[] = { -+ 0x99, -+ (pkt->blen >> 8), -+ (pkt->blen ), -+ }; ++ uint8_t head[] = { ++ 0x99, ++ (pkt->blen >> 8), ++ (pkt->blen ), ++ }; + -+ rpmDigestUpdate(hash, head, 3); -+ rpmDigestUpdate(hash, pkt->body, pkt->blen); -+ rc = 0; ++ rpmDigestUpdate(hash, head, 3); ++ rpmDigestUpdate(hash, pkt->body, pkt->blen); ++ rc = 0; + } + return rc; +} + +static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig, -+ const struct pgpPkt *all, int i) ++ const struct pgpPkt *all, int i) +{ + int rc = -1; + DIGEST_CTX hash = NULL; + + switch (selfsig->sigtype) { + case PGPSIGTYPE_SUBKEY_BINDING: -+ hash = rpmDigestInit(selfsig->hash_algo, 0); -+ if (hash) { -+ rc = hashKey(hash, &all[0], PGPTAG_PUBLIC_KEY); -+ if (!rc) -+ rc = hashKey(hash, &all[i-1], PGPTAG_PUBLIC_SUBKEY); -+ } -+ break; ++ hash = rpmDigestInit(selfsig->hash_algo, 0); ++ if (hash) { ++ rc = hashKey(hash, &all[0], PGPTAG_PUBLIC_KEY); ++ if (!rc) ++ rc = hashKey(hash, &all[i-1], PGPTAG_PUBLIC_SUBKEY); ++ } ++ break; + default: -+ /* ignore types we can't handle */ -+ rc = 0; -+ break; ++ /* ignore types we can't handle */ ++ rc = 0; ++ break; + } + + if (hash && rc == 0) -+ rc = pgpVerifySignature(key, selfsig, hash); ++ rc = pgpVerifySignature(key, selfsig, hash); + + rpmDigestFinal(hash, NULL, NULL, 0); + @@ -90,8 +137,7 @@ index 5d6bd95..0b237e4 100644 +} + int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, -- pgpDigParams * ret) -+ pgpDigParams * ret) + pgpDigParams * ret) { const uint8_t *p = pkts; const uint8_t *pend = pkts + pktlen; @@ -107,19 +153,17 @@ index 5d6bd95..0b237e4 100644 while (p < pend) { - if (decodePkt(p, (pend - p), &pkt)) -- break; -+ struct pgpPkt *pkt = &all[i]; -+ if (decodePkt(p, (pend - p), pkt)) -+ break; ++ struct pgpPkt *pkt = &all[i]; ++ if (decodePkt(p, (pend - p), pkt)) + break; -- if (digp == NULL) { + if (digp == NULL) { - if (pkttype && pkt.tag != pkttype) { -- break; -+ if (digp == NULL) { -+ if (pkttype && pkt->tag != pkttype) { -+ break; ++ if (pkttype && pkt->tag != pkttype) { + break; } else { -- digp = pgpDigParamsNew(pkt.tag); +- digp = xcalloc(1, sizeof(*digp)); +- digp->tag = pkt.tag; + digp = pgpDigParamsNew(pkt->tag); } } @@ -130,18 +174,18 @@ index 5d6bd95..0b237e4 100644 + break; + selfsig = pgpDigParamsNew(pkt->tag); + } ++ + if (pgpPrtPkt(pkt, selfsig ? selfsig : digp)) break; - p += (pkt.body - pkt.head) + pkt.blen; + if (selfsig) { + /* subkeys must be followed by binding signature */ -+ if (prevtag == PGPTAG_PUBLIC_SUBKEY) { -+ if (selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING) -+ break; -+ } ++ int xx = 1; /* assume failure */ + -+ int xx = pgpVerifySelf(digp, selfsig, all, i); ++ if (!(prevtag == PGPTAG_PUBLIC_SUBKEY && ++ selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING)) ++ xx = pgpVerifySelf(digp, selfsig, all, i); + + selfsig = pgpDigParamsFree(selfsig); + if (xx) @@ -155,23 +199,45 @@ index 5d6bd95..0b237e4 100644 + + i++; + p += (pkt->body - pkt->head) + pkt->blen; - if (pkttype == PGPTAG_SIGNATURE) - break; -- } - -- rc = (digp && (p == pend)) ? 0 : -1; ++ if (pkttype == PGPTAG_SIGNATURE) ++ break; ++ + if (alloced <= i) { + alloced *= 2; + all = xrealloc(all, alloced * sizeof(*all)); + } -+ } + } + +- rc = (digp && (p == pend)) ? 0 : -1; + rc = (digp && (p == pend) && expect == 0) ? 0 : -1; + free(all); -+ selfsig = pgpDigParamsFree(selfsig); if (ret && rc == 0) { *ret = digp; } else { +@@ -1123,8 +1212,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen, + digps = xrealloc(digps, alloced * sizeof(*digps)); + } + +- digps[count] = xcalloc(1, sizeof(**digps)); +- digps[count]->tag = PGPTAG_PUBLIC_SUBKEY; ++ digps[count] = pgpDigParamsNew(PGPTAG_PUBLIC_SUBKEY); + /* Copy UID from main key to subkey */ + digps[count]->userid = xstrdup(mainkey->userid); + +diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c +index e5d191c..988a0f6 100644 +--- a/sign/rpmgensig.c ++++ b/sign/rpmgensig.c +@@ -351,7 +351,7 @@ static int haveSignature(rpmtd sigtd, Header h) + pgpPrtParams(oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2); + if (pgpDigParamsCmp(sig1, sig2) == 0) + rc = 1; +- pgpDigParamsFree(sig2); ++ sig2 = pgpDigParamsFree(sig2); + } + pgpDigParamsFree(sig1); + rpmtdFreeData(&oldtd); diff --git a/tests/Makefile.am b/tests/Makefile.am index f742a9e..3282342 100644 --- a/tests/Makefile.am @@ -333,3 +399,82 @@ index e1a3ab0..705fc58 100644 -- 2.25.1 +From 10648296411a37083d182f03a5acb2abb1d21681 Mon Sep 17 00:00:00 2001 +From: Demi Marie Obenour +Date: Thu, 6 May 2021 20:03:10 -0400 +Subject: [PATCH 2/2] verifySignature(): package signatures must be + PGPSIGTYPE_BINARY + +RPM packages are binary documents and must be signed as such. To avoid +having to access the fields of pgpDigParams() directly, this adds a new +accessor function, pgpSignatureType(). pgpSignatureType() returns the +type of a signature, or -1 if the PGP data is NULL or is not a +signature. + +Prior to commit b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8 this was kind +of checked inside the parser but incorrectly. +--- + lib/rpmvs.c | 4 +++- + rpmio/rpmpgp.c | 10 ++++++++++ + rpmio/rpmpgp.h | 9 +++++++++ + 3 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index 7255069..20a3e28 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -566,7 +566,9 @@ exit: + static rpmRC + verifySignature(rpmKeyring keyring, struct rpmsinfo_s *sinfo) + { +- rpmRC res = rpmKeyringVerifySig(keyring, sinfo->sig, sinfo->ctx); ++ rpmRC res = RPMRC_FAIL; ++ if (pgpSignatureType(sinfo->sig) == PGPSIGTYPE_BINARY) ++ res = rpmKeyringVerifySig(keyring, sinfo->sig, sinfo->ctx); + + return res; + } +diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c +index 6d661a6..041d16d 100644 +--- a/rpmio/rpmpgp.c ++++ b/rpmio/rpmpgp.c +@@ -441,6 +441,16 @@ static int pgpVersion(const uint8_t *h, size_t hlen, uint8_t *version) + return 0; + } + ++int pgpSignatureType(pgpDigParams _digp) ++{ ++ int rc = -1; ++ ++ if (_digp && _digp->tag == PGPTAG_SIGNATURE) ++ rc = _digp->sigtype; ++ ++ return rc; ++} ++ + static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype, + pgpDigParams _digp) + { +diff --git a/rpmio/rpmpgp.h b/rpmio/rpmpgp.h +index 469b5b3..94f970c 100644 +--- a/rpmio/rpmpgp.h ++++ b/rpmio/rpmpgp.h +@@ -1160,6 +1160,15 @@ rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx) + */ + rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx); + ++/** \ingroup rpmpgp ++ * Return the type of a PGP signature. If `sig` is NULL, or is not a signature, ++ * returns -1. ++ * ++ * @param sig signature ++ * @return type of the signature ++ */ ++int pgpSignatureType(pgpDigParams sig); ++ + /** \ingroup rpmpgp + * Return a string identification of a PGP signature/pubkey. + * @param digp signature/pubkey container +-- +2.25.1 + diff --git a/SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch b/SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch deleted file mode 100644 index b8c01c504e..0000000000 --- a/SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch +++ /dev/null @@ -1,308 +0,0 @@ -From 8586c041219bc408500ae083aa506483bdafac7a Mon Sep 17 00:00:00 2001 -From: Demi Marie Obenour -Date: Fri, 30 Apr 2021 15:01:33 +0530 -Subject: [PATCH] Fix OpenPGP parsing bugs - -- signatures of the wrong type were accepted -- signatures were allowed to contain multiple packets -- numerous out-of-bounds reads -- undefined pointer arithmetic - -[sshedi: Changes to rpmio/rpmpgp.h from original patch are dropped] - -Signed-off-by: Shreenidhi Shedi ---- - rpmio/rpmpgp.c | 146 +++++++++++++++++++++++++++---------------------- - 1 file changed, 81 insertions(+), 65 deletions(-) - -diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c -index d0688ebe9..01dca84db 100644 ---- a/rpmio/rpmpgp.c -+++ b/rpmio/rpmpgp.c -@@ -320,14 +320,17 @@ size_t pgpLen(const uint8_t *s, size_t slen, size_t * lenp) - if (*s < 192) { - lenlen = 1; - dlen = *s; -- } else if (*s < 255 && slen > 2) { -+ } else if (*s < 224 && slen > 2) { - lenlen = 2; - dlen = (((s[0]) - 192) << 8) + s[1] + 192; -- } else if (slen > 5) { -+ } else if (slen > 5 && *s == 255) { - lenlen = 5; - dlen = pgpGrab(s+1, 4); - } - -+ /* Check that the buffer can hold the computed amount of bytes */ -+ if (slen - lenlen < dlen) -+ lenlen = 0; - if (lenlen) - *lenp = dlen; - -@@ -341,12 +344,38 @@ struct pgpPkt { - size_t blen; /* length of body in bytes */ - }; - -+/** \ingroup rpmpgp -+ * Read a length field `nbytes` long. Checks that the buffer is big enough to -+ * hold `nbytes + *valp` bytes. -+ * @param s pointer to read from -+ * @param nbytes length of length field -+ * @param send pointer past end of buffer -+ * @param[out] *valp decoded length -+ * @return 0 if buffer can hold `nbytes + *valp` of data, -+ * otherwise -1. -+ */ -+static int pgpGet(const uint8_t *s, size_t nbytes, const uint8_t *send, -+ size_t *valp) -+{ -+ int rc = -1; -+ -+ if (nbytes <= send - s) { -+ unsigned int val = pgpGrab(s, nbytes); -+ if (val <= send - s - nbytes) { -+ rc = 0; -+ *valp = val; -+ } -+ } -+ -+ return rc; -+} -+ - static int decodePkt(const uint8_t *p, size_t plen, struct pgpPkt *pkt) - { - int rc = -1; /* assume failure */ - - /* Valid PGP packet header must always have two or more bytes in it */ -- if (p && plen >= 2 && p[0] & 0x80) { -+ if (p && plen >= 2 && (p[0] & 0x80)) { - size_t lenlen = 0; - size_t hlen = 0; - -@@ -357,15 +386,14 @@ static int decodePkt(const uint8_t *p, size_t plen, struct pgpPkt *pkt) - } else { - /* Old format packet, body length encoding in tag byte */ - lenlen = (1 << (p[0] & 0x3)); -- if (plen > lenlen) { -- pkt->blen = pgpGrab(p+1, lenlen); -- } -+ if (lenlen > 4 || pgpGet(p + 1, lenlen, p + plen, &pkt->blen)) -+ return rc; - pkt->tag = (p[0] >> 2) & 0xf; - } - hlen = lenlen + 1; - - /* Does the packet header and its body fit in our boundaries? */ -- if (lenlen && (hlen + pkt->blen <= plen)) { -+ if (lenlen) { - pkt->head = p; - pkt->body = pkt->head + hlen; - rc = 0; -@@ -418,7 +446,7 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype, - - while (hlen > 0) { - i = pgpLen(p, hlen, &plen); -- if (i == 0 || plen < 1 || i + plen > hlen) -+ if (i == 0 || plen < 1) - break; - - p += i; -@@ -524,9 +552,9 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, - int i; - pgpDigAlg sigalg = pgpSignatureNew(pubkey_algo); - -- for (i = 0; i < sigalg->mpis && p + 2 <= pend; i++) { -+ for (i = 0; i < sigalg->mpis && 2 < pend - p; i++) { - int mpil = pgpMpiLen(p); -- if (p + mpil > pend) -+ if (mpil > pend - p) - break; - if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) { - if (sigalg->setmpi(sigalg, i, p)) -@@ -548,25 +576,12 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, - return rc; - } - --static int pgpGet(const uint8_t *s, size_t nbytes, const uint8_t *send, -- unsigned int *valp) --{ -- int rc = -1; -- -- if (s + nbytes <= send) { -- *valp = pgpGrab(s, nbytes); -- rc = 0; -- } -- -- return rc; --} -- - static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - pgpDigParams _digp) - { - uint8_t version = 0; -- uint8_t * p; -- unsigned int plen; -+ const uint8_t * p; -+ size_t plen; - int rc = 1; - - if (pgpVersion(h, hlen, &version)) -@@ -608,6 +623,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - } break; - case 4: - { pgpPktSigV4 v = (pgpPktSigV4)h; -+ const uint8_t *const hend = h + hlen; - - if (hlen <= sizeof(*v)) - return 1; -@@ -618,15 +634,12 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype); - pgpPrtNL(); - -- p = &v->hashlen[0]; -- if (pgpGet(v->hashlen, sizeof(v->hashlen), h + hlen, &plen)) -- return 1; -- p += sizeof(v->hashlen); -- -- if ((p + plen) > (h + hlen)) -+ if (pgpGet(v->hashlen, sizeof(v->hashlen), hend, &plen)) - return 1; -+ p = h + sizeof *v; - - if (_digp->pubkey_algo == 0) { -+ /* Get the hashed data */ - _digp->hashlen = sizeof(*v) + plen; - _digp->hash = memcpy(xmalloc(_digp->hashlen), v, _digp->hashlen); - } -@@ -634,18 +647,15 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - return 1; - p += plen; - -- if (pgpGet(p, 2, h + hlen, &plen)) -+ if (pgpGet(p, 2, hend, &plen)) - return 1; - p += 2; - -- if ((p + plen) > (h + hlen)) -- return 1; -- - if (pgpPrtSubType(p, plen, v->sigtype, _digp)) - return 1; - p += plen; - -- if (pgpGet(p, 2, h + hlen, &plen)) -+ if (hend - p < 2) - return 1; - pgpPrtHex(" signhash16", p, 2); - pgpPrtNL(); -@@ -658,11 +668,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - memcpy(_digp->signhash16, p, sizeof(_digp->signhash16)); - } - -- p += 2; -- if (p > (h + hlen)) -- return 1; -- -- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); -+ rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p + 2, h, hlen, _digp); - } break; - default: - rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version); -@@ -717,15 +723,15 @@ static int pgpPrtPubkeyParams(uint8_t pubkey_algo, - pgpDigAlg keyalg; - if (pubkey_algo == PGPPUBKEYALGO_EDDSA) { - int len = p + 1 < pend ? p[0] : 0; -- if (len == 0 || len == 0xff || p + 1 + len > pend) -+ if (len == 0 || len == 0xff || 1 + len > pend - p) - goto exit; - curve = pgpCurveByOid(p + 1, len); - p += len + 1; - } - keyalg = pgpPubkeyNew(pubkey_algo, curve); -- for (i = 0; i < keyalg->mpis && p + 2 <= pend; i++) { -+ for (i = 0; i < keyalg->mpis && 2 < pend - p; i++) { - int mpil = pgpMpiLen(p); -- if (p + mpil > pend) -+ if (mpil > pend - p) - break; - if (keyalg->setmpi(keyalg, i, p)) - break; -@@ -817,30 +823,34 @@ int pgpPubkeyFingerprint(const uint8_t *h, size_t hlen, - int mpis = -1; - - /* Packet must be larger than v to have room for the required MPIs */ -- if (hlen > sizeof(*v)) { -- switch (v->pubkey_algo) { -- case PGPPUBKEYALGO_RSA: -- mpis = 2; -- break; -- case PGPPUBKEYALGO_DSA: -- mpis = 4; -- break; -- case PGPPUBKEYALGO_EDDSA: -- mpis = 1; -- break; -- } -+ if (hlen <= sizeof(*v)) -+ return rc; -+ se = (uint8_t *)(v + 1); -+ -+ switch (v->pubkey_algo) { -+ case PGPPUBKEYALGO_RSA: -+ mpis = 2; -+ break; -+ case PGPPUBKEYALGO_DSA: -+ mpis = 4; -+ break; -+ case PGPPUBKEYALGO_EDDSA: -+ mpis = 1; -+ /* EdDSA has a curve id before the MPIs */ -+ if (se[0] == 0x00 || se[0] == 0xff || pend - se <= se[0]) -+ return rc; -+ se += 1 + se[0]; -+ break; -+ default: -+ return rc; - } - -- se = (uint8_t *)(v + 1); -- /* EdDSA has a curve id before the MPIs */ -- if (v->pubkey_algo == PGPPUBKEYALGO_EDDSA) { -- if (se < pend && se[0] != 0x00 && se[0] != 0xff) -- se += 1 + se[0]; -- else -- se = pend; /* error out when reading the MPI */ -+ while (pend - se >= 2 && mpis-- > 0) { -+ int i = pgpMpiLen(se); -+ if (pend - se < i) -+ return rc; -+ se += i; - } -- while (se < pend && mpis-- > 0) -- se += pgpMpiLen(se); - - /* Does the size and number of MPI's match our expectations? */ - if (se == pend && mpis == 0) { -@@ -1067,6 +1077,8 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, - break; - - p += (pkt.body - pkt.head) + pkt.blen; -+ if (pkttype == PGPTAG_SIGNATURE) -+ break; - } - - rc = (digp && (p == pend)) ? 0 : -1; -@@ -1189,6 +1201,10 @@ rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx) - if (sig == NULL || ctx == NULL) - goto exit; - -+ /* RPM signatures are always binary */ -+ if (sig->sigtype != PGPSIGTYPE_BINARY) -+ goto exit; -+ - if (sig->hash != NULL) - rpmDigestUpdate(ctx, sig->hash, sig->hashlen); - --- -2.17.1 - diff --git a/SPECS/rpm/rpm.spec b/SPECS/rpm/rpm.spec index 9b13aeb5e4..a605c2b649 100644 --- a/SPECS/rpm/rpm.spec +++ b/SPECS/rpm/rpm.spec @@ -3,7 +3,7 @@ Summary: Package manager Name: rpm Version: 4.16.1.3 -Release: 12%{?dist} +Release: 13%{?dist} License: GPLv2+ URL: http://rpm.org Group: Applications/System @@ -13,54 +13,51 @@ Distribution: Photon Source0: https://github.com/rpm-software-management/rpm/archive/%{name}-%{version}.tar.gz %define sha512 %{name}=dc1be96d433223e764f20fc7807f46baf44d2ec23a54edcf570251f0fec4b5040a311f62521e6fb4cd96723a4b791c51fa1f5fb5bc86b478e89b587ea36b46a4 -Source1: brp-strip-debug-symbols -Source2: brp-strip-unneeded -Source3: macros -Source4: macros.php -Source5: macros.perl -Source6: macros.vpath -Source7: macros.ldconfig -Source8: rpmdb-rebuild.sh -Source9: rpmdb-rebuild.service -Source10: rpm.conf -Source11: lock.c - -Patch0: find-debuginfo-do-not-generate-dir-entries.patch -Patch1: Fix-OpenPGP-parsing-bugs.patch -Patch2: Header-signatures-alone-are-not-sufficient.patch -Patch3: Fix-regression-reading-rpm-v3.patch -Patch4: rpmdb-rename-dir.patch -Patch5: silence-warning.patch -Patch6: sync-buf-cache.patch -Patch7: wait-for-lock.patch -Patch8: CVE-2021-3521-1.patch -Patch9: CVE-2021-3521-2.patch -Patch10: CVE-2021-3521-3.patch - -Requires: bash -Requires: zstd-libs -Requires: lua -Requires: openssl >= 1.1.1 -Requires: %{name}-libs = %{version}-%{release} - -BuildRequires: systemd-devel -BuildRequires: dbus-devel >= 1.3 -BuildRequires: systemd-rpm-macros -BuildRequires: lua-devel -BuildRequires: popt-devel -BuildRequires: nss-devel -BuildRequires: elfutils-devel -BuildRequires: libcap-devel -BuildRequires: xz-devel -BuildRequires: file-devel -BuildRequires: python3-devel -BuildRequires: openssl >= 1.1.1 -BuildRequires: zstd-devel -BuildRequires: sqlite-devel -BuildRequires: python3-setuptools -BuildRequires: libtool -BuildRequires: libltdl-devel -BuildRequires: openssl-devel +Source1: brp-strip-debug-symbols +Source2: brp-strip-unneeded +Source3: macros +Source4: macros.php +Source5: macros.perl +Source6: macros.vpath +Source7: macros.ldconfig +Source8: rpmdb-rebuild.sh +Source9: rpmdb-rebuild.service +Source10: rpm.conf +Source11: lock.c + +Patch0: find-debuginfo-do-not-generate-dir-entries.patch +Patch1: Header-signatures-alone-are-not-sufficient.patch +Patch2: Fix-regression-reading-rpm-v3.patch +Patch3: rpmdb-rename-dir.patch +Patch4: silence-warning.patch +Patch5: sync-buf-cache.patch +Patch6: wait-for-lock.patch +Patch7: CVE-2021-3521.patch + +Requires: bash +Requires: zstd-libs +Requires: lua +Requires: openssl >= 1.1.1 +Requires: %{name}-libs = %{version}-%{release} + +BuildRequires: systemd-devel +BuildRequires: dbus-devel >= 1.3 +BuildRequires: systemd-rpm-macros +BuildRequires: lua-devel +BuildRequires: popt-devel +BuildRequires: nss-devel +BuildRequires: elfutils-devel +BuildRequires: libcap-devel +BuildRequires: xz-devel +BuildRequires: file-devel +BuildRequires: python3-devel +BuildRequires: openssl >= 1.1.1 +BuildRequires: zstd-devel +BuildRequires: sqlite-devel +BuildRequires: python3-setuptools +BuildRequires: libtool +BuildRequires: libltdl-devel +BuildRequires: openssl-devel %description RPM package manager @@ -299,10 +296,8 @@ rm -rf %{buildroot} %{rpmhome}/ocamldeps.sh %{rpmhome}/*.prov %{rpmhome}/sepdebugcrcfix - %{rpmhome}/rpmdeps %{rpmhome}/pythondistdeps.py - %{_mandir}/man1/gendiff.1* %{_mandir}/man8/rpmbuild.8* %{_mandir}/man8/rpmdeps.8* @@ -326,10 +321,14 @@ rm -rf %{buildroot} %{python3_sitelib}/* %files plugin-systemd-inhibit +%defattr(-,root,root,-) %{_libdir}/rpm-plugins/systemd_inhibit.so %{_mandir}/man8/rpm-plugin-systemd-inhibit.8* %changelog +* Wed Sep 14 2022 Shreenidhi Shedi 4.16.1.3-13 +- Further fixes to CVE-2021-3521 +- Remove pgp related fixes, it's not used by other distros * Tue Aug 30 2022 Shreenidhi Shedi 4.16.1.3-12 - Fix CVE-2021-3521 * Wed Jun 22 2022 Harinadh D 4.16.1.3-11