dcavalca / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone
5523e9
Adjusted lib/package.c section to apply, and 4.11.x requires the
5523e9
same change in lib/signature.c as well.
5523e9
5523e9
From 89dce2b91d7d73a1e225461a7392c3d6d7a30a95 Mon Sep 17 00:00:00 2001
5523e9
From: Panu Matilainen <pmatilai@redhat.com>
5523e9
Date: Wed, 19 Oct 2016 14:48:08 +0300
5523e9
Subject: [PATCH] Verify data is within range and does not overlap in
5523e9
 headerVerifyInfo()
5523e9
5523e9
Checking whether data start offset is within header data area is of no use
5523e9
whatsoever if the entire chunk doesn't fit. Validate the entire data
5523e9
fits within range and that it does not overlap, however with string
5523e9
types we can only check the array size is sane but we cant check the
5523e9
actual content.
5523e9
5523e9
Adjust the upper limit for region trailer in headerVerifyRegion() so
5523e9
it fits the new rules, but in reality calling headerVerifyInfo() for
5523e9
the region tags is rather pointless since they're so different.
5523e9
5523e9
Partial fix for RhBug:1373107.
5523e9
---
5523e9
 lib/header.c  | 21 ++++++++++++++++-----
5523e9
 lib/package.c |  2 +-
5523e9
 2 files changed, 17 insertions(+), 6 deletions(-)
5523e9
5523e9
diff --git a/lib/header.c b/lib/header.c
5523e9
index 7f7c115..cac5c94 100644
5523e9
--- a/lib/header.c
5523e9
+++ b/lib/header.c
5523e9
@@ -196,7 +196,8 @@ int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
5523e9
 {
5523e9
     entryInfo pe = (entryInfo) pev;
5523e9
     entryInfo info = iv;
5523e9
-    int i;
5523e9
+    int i, tsize;
5523e9
+    int32_t end = 0;
5523e9
 
5523e9
     for (i = 0; i < il; i++) {
5523e9
 	info->tag = ntohl(pe[i].tag);
5523e9
@@ -206,16 +207,26 @@ int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
5523e9
 	    info->offset = -info->offset;
5523e9
 	info->count = ntohl(pe[i].count);
5523e9
 
5523e9
+	/* Previous data must not overlap */
5523e9
+	if (end > info->offset)
5523e9
+	    return i;
5523e9
+
5523e9
 	if (hdrchkType(info->type))
5523e9
 	    return i;
5523e9
 	if (hdrchkAlign(info->type, info->offset))
5523e9
 	    return i;
5523e9
-	if (hdrchkRange(dl, info->offset))
5523e9
-	    return i;
5523e9
-	if (hdrchkData(info->count))
5523e9
-	    return i;
5523e9
 
5523e9
+	/* For string types we can only check the array size is sane */
5523e9
+	tsize = typeSizes[info->type];
5523e9
+	if (tsize < 1)
5523e9
+	    tsize = 1;
5523e9
+
5523e9
+	/* Verify the data actually fits */
5523e9
+	end = info->offset + (info->count * tsize);
5523e9
+	if (hdrchkRange(dl, end))
5523e9
+	    return i;
5523e9
     }
5523e9
+
5523e9
     return -1;
5523e9
 }
5523e9
5523e9
diff --git a/lib/package.c b/lib/package.c
5523e9
index b6bea09..bb83163 100644
5523e9
--- a/lib/package.c
5523e9
+++ b/lib/package.c
5523e9
@@ -339,7 +339,7 @@ static rpmRC headerVerify(rpmKeyring keyring, rpmVSFlags vsflags,
5523e9
     (void) memcpy(&info, regionEnd, REGION_TAG_COUNT);
5523e9
     regionEnd += REGION_TAG_COUNT;
5523e9
 
5523e9
-    if (headerVerifyInfo(1, il * sizeof(*pe), &info, &entry.info, 1) != -1 ||
5523e9
+    if (headerVerifyInfo(1, il * sizeof(*pe) + REGION_TAG_COUNT, &info, &entry.info, 1) != -1 ||
5523e9
 	!(entry.info.tag == RPMTAG_HEADERIMMUTABLE
5523e9
        && entry.info.type == REGION_TAG_TYPE
5523e9
        && entry.info.count == REGION_TAG_COUNT))
5523e9
diff --git a/lib/signature.c b/lib/signature.c
5523e9
index d8017dc..ddf2eb8 100644
5523e9
--- a/lib/signature.c
5523e9
+++ b/lib/signature.c
5523e9
@@ -165,7 +165,7 @@ rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
5523e9
 	}
5523e9
 	dataEnd += REGION_TAG_COUNT;
5523e9
 
5523e9
-	xx = headerVerifyInfo(1, il * sizeof(*pe), &info, &entry.info, 1);
5523e9
+	xx = headerVerifyInfo(1, il * sizeof(*pe) + REGION_TAG_COUNT, &info, &entry.info, 1);
5523e9
 	if (xx != -1 ||
5523e9
 	    !((entry.info.tag == RPMTAG_HEADERSIGNATURES || entry.info.tag == RPMTAG_HEADERIMAGE)
5523e9
 	   && entry.info.type == REGION_TAG_TYPE