]> code.ossystems Code Review - openembedded-core.git/commitdiff
rpm: fix CVE-2021-3421
authorMinjae Kim <flowergom@gmail.com>
Thu, 24 Jun 2021 13:29:04 +0000 (22:29 +0900)
committerSteve Sakoman <steve@sakoman.com>
Tue, 29 Jun 2021 14:15:00 +0000 (04:15 -1000)
unsigned signature header leads to string injection into an rpm database

reference:
https://nvd.nist.gov/vuln/detail/CVE-2021-3421
https://github.com/rpm-software-management/rpm/commit/d6a86b5e69e46cc283b1e06c92343319beb42e21
Signed-off-by: Steve Sakoman <steve@sakoman.com>
meta/recipes-devtools/rpm/files/CVE-2021-3421.patch [new file with mode: 0644]
meta/recipes-devtools/rpm/rpm_4.14.2.1.bb

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 (file)
index 0000000..b1a05b6
--- /dev/null
@@ -0,0 +1,197 @@
+From 1e5b70cab83c95aa138107a38ecda75ff70e8985 Mon Sep 17 00:00:00 2001
+From: Minjae Kim <flowergom@gmail.com>
+Date: Thu, 24 Jun 2021 01:11:26 +0000
+Subject: [PATCH] Be much more careful about copying data from the signature
+ header
+
+Only look for known tags, and ensure correct type and size where known
+before copying over. Bump the old arbitrary 16k count limit to 16M limit
+though, it's not inconceivable that a package could have that many files.
+While at it, ensure none of these tags exist in the main header,
+which would confuse us greatly.
+
+This is optimized for backporting ease, upstream can remove redundancies
+and further improve checking later.
+
+Reported and initial patches by Demi Marie Obenour.
+
+Fixes: RhBug:1935049, RhBug:1933867, RhBug:1935035, RhBug:1934125, ...
+
+Fixes: CVE-2021-3421, CVE-2021-20271
+
+Upstream-Status: Backport [https://github.com/rpm-software-management/rpm/commit/d6a86b5e69e46cc283b1e06c92343319beb42e21]
+CVE: CVE-2021-3421
+Signed-off-by: Minjae Kim <flowergom@gmail.com>
+---
+ lib/package.c | 115 ++++++++++++++++++++++++--------------------------
+ lib/rpmtag.h  |   4 ++
+ 2 files changed, 58 insertions(+), 61 deletions(-)
+
+diff --git a/lib/package.c b/lib/package.c
+index 081123d84e..7c26ea323f 100644
+--- a/lib/package.c
++++ b/lib/package.c
+@@ -20,76 +20,68 @@
+ #include "debug.h"
++struct taglate_s {
++    rpmTagVal stag;
++    rpmTagVal xtag;
++    rpm_count_t count;
++} const xlateTags[] = {
++    { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1 },
++    { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0 },
++    { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16 },
++    { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0 },
++    /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0 }, */ /* long obsolete, dont use */
++    { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1 },
++    { RPMSIGTAG_FILESIGNATURES, RPMTAG_FILESIGNATURES, 0 },
++    { RPMSIGTAG_FILESIGNATURELENGTH, RPMTAG_FILESIGNATURELENGTH, 1 },
++    { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1 },
++    { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1 },
++    { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0 },
++    { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0 },
++    { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1 },
++    { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1 },
++    { 0 }
++};
++
+ /** \ingroup header
+  * Translate and merge legacy signature tags into header.
+  * @param h           header (dest)
+  * @param sigh                signature header (src)
+  */
+ static
+-void headerMergeLegacySigs(Header h, Header sigh)
++rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg)
+ {
+-    HeaderIterator hi;
++    const struct taglate_s *xl;
+     struct rpmtd_s td;
+-    hi = headerInitIterator(sigh);
+-    for (; headerNext(hi, &td); rpmtdFreeData(&td))
+-    {
+-      switch (td.tag) {
+-      /* XXX Translate legacy signature tag values. */
+-      case RPMSIGTAG_SIZE:
+-          td.tag = RPMTAG_SIGSIZE;
+-          break;
+-      case RPMSIGTAG_PGP:
+-          td.tag = RPMTAG_SIGPGP;
+-          break;
+-      case RPMSIGTAG_MD5:
+-          td.tag = RPMTAG_SIGMD5;
+-          break;
+-      case RPMSIGTAG_GPG:
+-          td.tag = RPMTAG_SIGGPG;
+-          break;
+-      case RPMSIGTAG_PGP5:
+-          td.tag = RPMTAG_SIGPGP5;
+-          break;
+-      case RPMSIGTAG_PAYLOADSIZE:
+-          td.tag = RPMTAG_ARCHIVESIZE;
+-          break;
+-      case RPMSIGTAG_SHA1:
+-      case RPMSIGTAG_SHA256:
+-      case RPMSIGTAG_DSA:
+-      case RPMSIGTAG_RSA:
+-      default:
+-          if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
+-              continue;
+-          break;
+-      }
+-      if (!headerIsEntry(h, td.tag)) {
+-          switch (td.type) {
+-          case RPM_NULL_TYPE:
+-              continue;
+-              break;
+-          case RPM_CHAR_TYPE:
+-          case RPM_INT8_TYPE:
+-          case RPM_INT16_TYPE:
+-          case RPM_INT32_TYPE:
+-          case RPM_INT64_TYPE:
+-              if (td.count != 1)
+-                  continue;
+-              break;
+-          case RPM_STRING_TYPE:
+-          case RPM_BIN_TYPE:
+-              if (td.count >= 16*1024)
+-                  continue;
+-              break;
+-          case RPM_STRING_ARRAY_TYPE:
+-          case RPM_I18NSTRING_TYPE:
+-              continue;
+-              break;
+-          }
+-          (void) headerPut(h, &td, HEADERPUT_DEFAULT);
+-      }
++    rpmtdReset(&td);
++    for (xl = xlateTags; xl->stag; xl++) {
++        /* There mustn't be one in the main header */
++        if (headerIsEntry(h, xl->xtag))
++            break;
++        if (headerGet(sigh, xl->stag, &td, HEADERGET_RAW|HEADERGET_MINMEM)) {
++            /* Translate legacy tags */
++            if (xl->stag != xl->xtag)
++                td.tag = xl->xtag;
++            /* Ensure type and tag size match expectations */
++            if (td.type != rpmTagGetTagType(td.tag))
++                break;
++            if (td.count < 1 || td.count > 16*1024*1024)
++                break;
++            if (xl->count && td.count != xl->count)
++                break;
++            if (!headerPut(h, &td, HEADERPUT_DEFAULT))
++                break;
++            rpmtdFreeData(&td);
++        }
++    }
++    rpmtdFreeData(&td);
++
++    if (xl->stag) {
++        rasprintf(msg, "invalid signature tag %s (%d)",
++                        rpmTagGetName(xl->xtag), xl->xtag);
+     }
+-    headerFreeIterator(hi);
++
++    return xl->stag;
+ }
+ /**
+@@ -337,7 +329,8 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
+               goto exit;
+           /* Append (and remap) signature tags to the metadata. */
+-          headerMergeLegacySigs(h, sigh);
++          if (headerMergeLegacySigs(h, sigh,&msg))
++                  goto exit;
+           applyRetrofits(h);
+           /* Bump reference count for return. */
+diff --git a/lib/rpmtag.h b/lib/rpmtag.h
+index 8c718b31b5..d562572c6f 100644
+--- a/lib/rpmtag.h
++++ b/lib/rpmtag.h
+@@ -65,6 +65,8 @@ typedef enum rpmTag_e {
+     RPMTAG_LONGARCHIVESIZE    = RPMTAG_SIG_BASE+15,   /* l */
+     /* RPMTAG_SIG_BASE+16 reserved */
+     RPMTAG_SHA256HEADER               = RPMTAG_SIG_BASE+17,   /* s */
++    /* RPMTAG_SIG_BASE+18 reserved for RPMSIGTAG_FILESIGNATURES */
++    /* RPMTAG_SIG_BASE+19 reserved for RPMSIGTAG_FILESIGNATURELENGTH */
+     RPMTAG_NAME               = 1000, /* s */
+ #define       RPMTAG_N        RPMTAG_NAME     /* s */
+@@ -422,6 +424,8 @@ typedef enum rpmSigTag_e {
+     RPMSIGTAG_LONGSIZE        = RPMTAG_LONGSIGSIZE,   /*!< internal Header+Payload size (64bit) in bytes. */
+     RPMSIGTAG_LONGARCHIVESIZE = RPMTAG_LONGARCHIVESIZE, /*!< internal uncompressed payload size (64bit) in bytes. */
+     RPMSIGTAG_SHA256  = RPMTAG_SHA256HEADER,
++    RPMSIGTAG_FILESIGNATURES            = RPMTAG_SIG_BASE + 18,
++    RPMSIGTAG_FILESIGNATURELENGTH       = RPMTAG_SIG_BASE + 19,
+ } rpmSigTag;
+-- 
+2.17.1
+
index 4029217d0823721a1c51fbf0ff36301685ccbd48..018b2f8700eab7a572aeb1065607e7a609dbd4dd 100644 (file)
@@ -44,6 +44,7 @@ SRC_URI = "git://github.com/rpm-software-management/rpm;branch=rpm-4.14.x \
            file://0001-mono-find-provides-requires-do-not-use-monodis-from-.patch \
            file://0001-Rip-out-partial-support-for-unused-MD2-and-RIPEMD160.patch \
            file://0001-rpmplugins.c-call-dlerror-prior-to-dlsym.patch \
+           file://CVE-2021-3421.patch \
            "
 
 PE = "1"