alexk / rpms / rpm

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