[rpm] - fix header data length calculation breakage - fix keyid size bogosity causing breakage on 32bit sy

Panu Matilainen pmatilai at fedoraproject.org
Fri Mar 23 13:50:03 UTC 2012


commit e56f273491cc29a7168e408ebf176a1c209f0368
Author: Panu Matilainen <pmatilai at redhat.com>
Date:   Fri Mar 23 14:41:26 2012 +0200

    - fix header data length calculation breakage
    - fix keyid size bogosity causing breakage on 32bit systems

 rpm-4.9.90-header-datalength.patch |   70 ++++++++++++++++++++++++++++++++++++
 rpm-4.9.90-keyid-size.patch        |   37 +++++++++++++++++++
 rpm.spec                           |   12 ++++++-
 3 files changed, 118 insertions(+), 1 deletions(-)
---
diff --git a/rpm-4.9.90-header-datalength.patch b/rpm-4.9.90-header-datalength.patch
new file mode 100644
index 0000000..4cdf0b6
--- /dev/null
+++ b/rpm-4.9.90-header-datalength.patch
@@ -0,0 +1,70 @@
+commit 0b8c3218027c99a6d92c2ca53fe7f42cf87f30a4
+Author: Panu Matilainen <pmatilai at redhat.com>
+Date:   Fri Mar 23 14:17:47 2012 +0200
+
+    Eliminate broken data end calculation in dataLength()
+    
+    - If the caller doesn't know the end pointer, we dont have a whole lot
+      of chance to come up with a reasonable one either. Just assume
+      the terminating \0's are there when end boundary is not specified:
+      when this happens we're dealing with relatively "trusted" data
+      anyway, the more critical case of reading in unknown headers does
+      always pass end pointers.
+    - While capping the end pointer to HEADER_DATA_MAX seems like a
+      reasonable thing to do (as was done in commit
+      f79909d04e43cbfbbcdc588530a8c8033c5e0a7c), it doesn't really help
+      (bad data would likely run past bounds anyway), and it's not right
+      either: the pointer can be to a stack address, and the stack can be
+      near the top of addressable range, and ptr + HEADER_DATA_MAX can
+      cause pointer wraparound. Notably that's exactly what happens
+      when running 32bit personality process on 64bit system on Linux,
+      at least in case of i386 process on x86_64, causing all sorts of
+      breakage..
+
+diff --git a/lib/header.c b/lib/header.c
+index d741552..023c6e3 100644
+--- a/lib/header.c
++++ b/lib/header.c
+@@ -301,16 +301,27 @@ unsigned headerSizeof(Header h, int magicp)
+     return size;
+ }
+ 
+-/* Bounded header string (array) size calculation, return -1 on error */
++/*
++ * Header string (array) size calculation, bounded if end is non-NULL.
++ * Return length (including \0 termination) on success, -1 on error.
++ */
+ static inline int strtaglen(const char *str, rpm_count_t c, const char *end)
+ {
+     const char *start = str;
+     const char *s;
+ 
+-    while ((s = memchr(start, '\0', end-start))) {
+-	if (--c == 0 || s > end)
+-	    break;
+-	start = s + 1;
++    if (end) {
++	while ((s = memchr(start, '\0', end-start))) {
++	    if (--c == 0 || s > end)
++		break;
++	    start = s + 1;
++	}
++    } else {
++	while ((s = strchr(start, '\0'))) {
++	    if (--c == 0)
++		break;
++	    start = s + 1;
++	}
+     }
+     return (c > 0) ? -1 : (s - str + 1);
+ }
+@@ -328,8 +339,7 @@ static int dataLength(rpm_tagtype_t type, rpm_constdata_t p, rpm_count_t count,
+ 			 int onDisk, rpm_constdata_t pend)
+ {
+     const char * s = p;
+-    /* Not all callers supply data end, avoid falling over edge of the world */
+-    const char * se = pend ? pend : s + HEADER_DATA_MAX;
++    const char * se = pend;
+     int length = 0;
+ 
+     switch (type) {
diff --git a/rpm-4.9.90-keyid-size.patch b/rpm-4.9.90-keyid-size.patch
new file mode 100644
index 0000000..51bf603
--- /dev/null
+++ b/rpm-4.9.90-keyid-size.patch
@@ -0,0 +1,37 @@
+commit c5a140133505dbe3cf59c97bbf40c2f5526e5f5b
+Author: Panu Matilainen <pmatilai at redhat.com>
+Date:   Thu Mar 22 12:24:55 2012 +0200
+
+    Oops, "magic eight" is necessary here afterall
+    
+    - Fix regression from commit 807b402d95702f3f91e9e2bfbd2b5ca8c9964ed9,
+      the array gets passed as a pointer (how else would it work at all),
+      so despite having seemingly correct type, sizeof(keyid) depends
+      on the pointer size. This happens to be 8 on x86_64 and friends
+      but breaks on eg i386.
+    - Also return the explicit size from pgpExtractPubkeyFingerprint(),
+      this has been "broken" for much longer but then all callers should
+      really care about is -1 for error.
+
+diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
+index 4aac23d..e70cf70 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -757,7 +757,7 @@ static int getFingerprint(const uint8_t *h, size_t hlen, pgpKeyID_t keyid)
+ 	    (void) rpmDigestFinal(ctx, (void **)&d, &dlen, 0);
+ 
+ 	    if (d) {
+-		memcpy(keyid, (d + (dlen-sizeof(keyid))), sizeof(keyid));
++		memcpy(keyid, (d + (dlen-8)), 8);
+ 		free(d);
+ 		rc = 0;
+ 	    }
+@@ -787,7 +787,7 @@ int pgpExtractPubkeyFingerprint(const char * b64pkt, pgpKeyID_t keyid)
+     if (rpmBase64Decode(b64pkt, (void **)&pkt, &pktlen) == 0) {
+ 	if (pgpPubkeyFingerprint(pkt, pktlen, keyid) == 0) {
+ 	    /* if there ever was a bizarre return code for success... */
+-	    rc = sizeof(keyid);
++	    rc = 8;
+ 	}
+ 	free(pkt);
+     }
diff --git a/rpm.spec b/rpm.spec
index c1be359..4f96669 100644
--- a/rpm.spec
+++ b/rpm.spec
@@ -22,7 +22,7 @@
 Summary: The RPM package management system
 Name: rpm
 Version: %{rpmver}
-Release: %{?snapver:0.%{snapver}.}5%{?dist}
+Release: %{?snapver:0.%{snapver}.}7%{?dist}
 Group: System Environment/Base
 Url: http://www.rpm.org/
 Source0: http://rpm.org/releases/testing/%{name}-%{srcver}.tar.bz2
@@ -46,6 +46,8 @@ Patch6: rpm-4.9.0-armhfp-logic.patch
 # Patches already in upstream
 Patch200: rpm-4.9.90-rpmte-fileinfo.patch
 Patch201: rpm-4.9.90-rpmte-fileinfo-2.patch
+Patch202: rpm-4.9.90-keyid-size.patch
+Patch203: rpm-4.9.90-header-datalength.patch
 
 # These are not yet upstream
 Patch301: rpm-4.6.0-niagara.patch
@@ -227,6 +229,8 @@ packages on a system.
 
 %patch200 -p1 -b .rpmte-fileinfo
 %patch201 -p1 -b .rpmte-fileinfo-2
+%patch202 -p1 -b .keyid-size
+%patch203 -p1 -b .header-datalength
 
 %patch301 -p1 -b .niagara
 %patch302 -p1 -b .geode
@@ -453,6 +457,12 @@ exit 0
 %doc COPYING doc/librpm/html/*
 
 %changelog
+* Fri Mar 23 2012 Panu Matilainen <pmatilai at redhat.com> - 4.9.90-0.git11505.7
+- fix header data length calculation breakage
+
+* Thu Mar 22 2012 Panu Matilainen <pmatilai at redhat.com> - 4.9.90-0.git11505.6
+- fix keyid size bogosity causing breakage on 32bit systems
+
 * Wed Mar 21 2012 Panu Matilainen <pmatilai at redhat.com> - 4.9.90-0.git11505.5
 - add temporary fake library provides to get around deltarpm "bootstrap"
   dependency (yes its dirty)


More information about the scm-commits mailing list