dcavalca / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone
James Antill ee2eaf
commit d6a86b5e69e46cc283b1e06c92343319beb42e21
James Antill ee2eaf
Author: Panu Matilainen <pmatilai@redhat.com>
James Antill ee2eaf
Date:   Thu Mar 4 13:21:19 2021 +0200
James Antill ee2eaf
James Antill ee2eaf
    Be much more careful about copying data from the signature header
James Antill ee2eaf
    
James Antill ee2eaf
    Only look for known tags, and ensure correct type and size where known
James Antill ee2eaf
    before copying over. Bump the old arbitrary 16k count limit to 16M limit
James Antill ee2eaf
    though, it's not inconceivable that a package could have that many files.
James Antill ee2eaf
    While at it, ensure none of these tags exist in the main header,
James Antill ee2eaf
    which would confuse us greatly.
James Antill ee2eaf
    
James Antill ee2eaf
    This is optimized for backporting ease, upstream can remove redundancies
James Antill ee2eaf
    and further improve checking later.
James Antill ee2eaf
    
James Antill ee2eaf
    Reported and initial patches by Demi Marie Obenour.
James Antill ee2eaf
    
James Antill ee2eaf
    Fixes: RhBug:1935049, RhBug:1933867, RhBug:1935035, RhBug:1934125, ...
James Antill ee2eaf
    
James Antill ee2eaf
    Fixes: CVE-2021-3421, CVE-2021-20271
James Antill ee2eaf
James Antill ee2eaf
    Combined with e2f1f1931c5ccf3ecbe4e1e12cacb1e17a277776 and backported into
James Antill ee2eaf
    4.14.3
James Antill ee2eaf
James Antill ee2eaf
diff -up rpm-4.14.3/lib/package.c.orig rpm-4.14.3/lib/package.c
James Antill ee2eaf
--- rpm-4.14.3/lib/package.c.orig	2021-05-31 12:32:49.970393976 +0200
James Antill ee2eaf
+++ rpm-4.14.3/lib/package.c	2021-05-31 13:53:58.250673275 +0200
James Antill ee2eaf
@@ -31,76 +31,72 @@ struct pkgdata_s {
James Antill ee2eaf
     rpmRC rc;
James Antill ee2eaf
 };
James Antill ee2eaf
 
James Antill ee2eaf
+struct taglate_s {
James Antill ee2eaf
+    rpmTagVal stag;
James Antill ee2eaf
+    rpmTagVal xtag;
James Antill ee2eaf
+    rpm_count_t count;
James Antill ee2eaf
+    int quirk;
James Antill ee2eaf
+} const xlateTags[] = {
James Antill ee2eaf
+    { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1, 0 },
James Antill ee2eaf
+    { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0, 0 },
James Antill ee2eaf
+    { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16, 0 },
James Antill ee2eaf
+    { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0, 0 },
James Antill ee2eaf
+    /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0, 0 }, */ /* long obsolete, dont use */
James Antill ee2eaf
+    { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1, 1 },
James Antill ee2eaf
+    { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1, 0 },
James Antill ee2eaf
+    { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1, 0 },
James Antill ee2eaf
+    { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0, 0 },
James Antill ee2eaf
+    { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0, 0 },
James Antill ee2eaf
+    { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1, 0 },
James Antill ee2eaf
+    { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1, 0 },
James Antill ee2eaf
+    { 0 }
James Antill ee2eaf
+};
James Antill ee2eaf
+
James Antill ee2eaf
 /** \ingroup header
James Antill ee2eaf
  * Translate and merge legacy signature tags into header.
James Antill ee2eaf
  * @param h		header (dest)
James Antill ee2eaf
  * @param sigh		signature header (src)
James Antill ee2eaf
+ * @return		failing tag number, 0 on success
James Antill ee2eaf
  */
James Antill ee2eaf
 static
James Antill ee2eaf
-void headerMergeLegacySigs(Header h, Header sigh)
James Antill ee2eaf
+rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg)
James Antill ee2eaf
 {
James Antill ee2eaf
-    HeaderIterator hi;
James Antill ee2eaf
+    const struct taglate_s *xl;
James Antill ee2eaf
     struct rpmtd_s td;
James Antill ee2eaf
 
James Antill ee2eaf
-    hi = headerInitIterator(sigh);
James Antill ee2eaf
-    for (; headerNext(hi, &td); rpmtdFreeData(&td))
James Antill ee2eaf
-    {
James Antill ee2eaf
-	switch (td.tag) {
James Antill ee2eaf
-	/* XXX Translate legacy signature tag values. */
James Antill ee2eaf
-	case RPMSIGTAG_SIZE:
James Antill ee2eaf
-	    td.tag = RPMTAG_SIGSIZE;
James Antill ee2eaf
-	    break;
James Antill ee2eaf
-	case RPMSIGTAG_PGP:
James Antill ee2eaf
-	    td.tag = RPMTAG_SIGPGP;
James Antill ee2eaf
-	    break;
James Antill ee2eaf
-	case RPMSIGTAG_MD5:
James Antill ee2eaf
-	    td.tag = RPMTAG_SIGMD5;
James Antill ee2eaf
-	    break;
James Antill ee2eaf
-	case RPMSIGTAG_GPG:
James Antill ee2eaf
-	    td.tag = RPMTAG_SIGGPG;
James Antill ee2eaf
-	    break;
James Antill ee2eaf
-	case RPMSIGTAG_PGP5:
James Antill ee2eaf
-	    td.tag = RPMTAG_SIGPGP5;
James Antill ee2eaf
-	    break;
James Antill ee2eaf
-	case RPMSIGTAG_PAYLOADSIZE:
James Antill ee2eaf
-	    td.tag = RPMTAG_ARCHIVESIZE;
James Antill ee2eaf
-	    break;
James Antill ee2eaf
-	case RPMSIGTAG_SHA1:
James Antill ee2eaf
-	case RPMSIGTAG_SHA256:
James Antill ee2eaf
-	case RPMSIGTAG_DSA:
James Antill ee2eaf
-	case RPMSIGTAG_RSA:
James Antill ee2eaf
-	default:
James Antill ee2eaf
-	    if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
James Antill ee2eaf
+    rpmtdReset(&td);
James Antill ee2eaf
+    for (xl = xlateTags; xl->stag; xl++) {
James Antill ee2eaf
+	/* There mustn't be one in the main header */
James Antill ee2eaf
+	if (headerIsEntry(h, xl->xtag)) {
James Antill ee2eaf
+	    /* Some tags may exist in either header, but never both */
James Antill ee2eaf
+	    if (xl->quirk && !headerIsEntry(sigh, xl->stag))
James Antill ee2eaf
 		continue;
James Antill ee2eaf
 	    break;
James Antill ee2eaf
 	}
James Antill ee2eaf
-	if (!headerIsEntry(h, td.tag)) {
James Antill ee2eaf
-	    switch (td.type) {
James Antill ee2eaf
-	    case RPM_NULL_TYPE:
James Antill ee2eaf
-		continue;
James Antill ee2eaf
+	if (headerGet(sigh, xl->stag, &td, HEADERGET_RAW|HEADERGET_MINMEM)) {
James Antill ee2eaf
+	    /* Translate legacy tags */
James Antill ee2eaf
+	    if (xl->stag != xl->xtag)
James Antill ee2eaf
+		td.tag = xl->xtag;
James Antill ee2eaf
+	    /* Ensure type and tag size match expectations */
James Antill ee2eaf
+	    if (td.type != rpmTagGetTagType(td.tag))
James Antill ee2eaf
 		break;
James Antill ee2eaf
-	    case RPM_CHAR_TYPE:
James Antill ee2eaf
-	    case RPM_INT8_TYPE:
James Antill ee2eaf
-	    case RPM_INT16_TYPE:
James Antill ee2eaf
-	    case RPM_INT32_TYPE:
James Antill ee2eaf
-	    case RPM_INT64_TYPE:
James Antill ee2eaf
-		if (td.count != 1)
James Antill ee2eaf
-		    continue;
James Antill ee2eaf
+	    if (td.count < 1 || td.count > 16*1024*1024)
James Antill ee2eaf
 		break;
James Antill ee2eaf
-	    case RPM_STRING_TYPE:
James Antill ee2eaf
-	    case RPM_BIN_TYPE:
James Antill ee2eaf
-		if (td.count >= 16*1024)
James Antill ee2eaf
-		    continue;
James Antill ee2eaf
+	    if (xl->count && td.count != xl->count)
James Antill ee2eaf
 		break;
James Antill ee2eaf
-	    case RPM_STRING_ARRAY_TYPE:
James Antill ee2eaf
-	    case RPM_I18NSTRING_TYPE:
James Antill ee2eaf
-		continue;
James Antill ee2eaf
+	    if (!headerPut(h, &td, HEADERPUT_DEFAULT))
James Antill ee2eaf
 		break;
James Antill ee2eaf
-	    }
James Antill ee2eaf
-	    (void) headerPut(h, &td, HEADERPUT_DEFAULT);
James Antill ee2eaf
+	    rpmtdFreeData(&td);
James Antill ee2eaf
 	}
James Antill ee2eaf
     }
James Antill ee2eaf
-    headerFreeIterator(hi);
James Antill ee2eaf
+    rpmtdFreeData(&td);
James Antill ee2eaf
+
James Antill ee2eaf
+    if (xl->stag) {
James Antill ee2eaf
+	rasprintf(msg, "invalid signature tag %s (%d)",
James Antill ee2eaf
+			rpmTagGetName(xl->xtag), xl->xtag);
James Antill ee2eaf
+    }
James Antill ee2eaf
+
James Antill ee2eaf
+    return xl->stag;
James Antill ee2eaf
 }
James Antill ee2eaf
 
James Antill ee2eaf
 /**
James Antill ee2eaf
@@ -363,7 +359,8 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t
James Antill ee2eaf
 		goto exit;
James Antill ee2eaf
 
James Antill ee2eaf
 	    /* Append (and remap) signature tags to the metadata. */
James Antill ee2eaf
-	    headerMergeLegacySigs(h, sigh);
James Antill ee2eaf
+	    if (headerMergeLegacySigs(h, sigh, &msg))
James Antill ee2eaf
+		goto exit;
James Antill ee2eaf
 	    applyRetrofits(h);
James Antill ee2eaf
 
James Antill ee2eaf
 	    /* Bump reference count for return. */