alexk / rpms / rpm

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