diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2016-10-19 14:48:08 +0300 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2016-11-02 10:41:53 +0200 |
commit | 489769fea8ddbe187be92bc5b247c211a3bb065d (patch) | |
tree | 49cc0dd2e68f0924d89339518f9987b173d14728 | |
parent | 648d717f231cccb1ce976d5fa038c9255e7bf6b9 (diff) | |
download | rpm-489769fea8ddbe187be92bc5b247c211a3bb065d.tar.gz |
Verify data is within range and does not overlap in headerVerifyInfo()
Checking whether data start offset is within header data area is of no use
whatsoever if the entire chunk doesn't fit. Validate the entire data
fits within range and that it does not overlap, however with string
types we can only check the array size is sane but we cant check the
actual content.
Adjust the upper limit for region trailer in headerVerifyRegion() so
it fits the new rules, but in reality calling headerVerifyInfo() for
the region tags is rather pointless since they're so different.
Partial fix for RhBug:1373107.
(cherry picked from commit 89dce2b91d7d73a1e225461a7392c3d6d7a30a95)
-rw-r--r-- | lib/header.c | 21 | ||||
-rw-r--r-- | lib/package.c | 2 |
2 files changed, 17 insertions, 6 deletions
diff --git a/lib/header.c b/lib/header.c index f78ba788f..3f9d0e70c 100644 --- a/lib/header.c +++ b/lib/header.c @@ -194,7 +194,8 @@ int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate) { entryInfo pe = (entryInfo) pev; entryInfo info = iv; - int i; + int i, tsize; + int32_t end = 0; for (i = 0; i < il; i++) { info->tag = ntohl(pe[i].tag); @@ -204,16 +205,26 @@ int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate) info->offset = -info->offset; info->count = ntohl(pe[i].count); + /* Previous data must not overlap */ + if (end > info->offset) + return i; + if (hdrchkType(info->type)) return i; if (hdrchkAlign(info->type, info->offset)) return i; - if (hdrchkRange(dl, info->offset)) - return i; - if (hdrchkData(info->count)) - return i; + /* For string types we can only check the array size is sane */ + tsize = typeSizes[info->type]; + if (tsize < 1) + tsize = 1; + + /* Verify the data actually fits */ + end = info->offset + (info->count * tsize); + if (hdrchkRange(dl, end)) + return i; } + return -1; } diff --git a/lib/package.c b/lib/package.c index fb2ff9194..890816a2f 100644 --- a/lib/package.c +++ b/lib/package.c @@ -333,7 +333,7 @@ rpmRC headerVerifyRegion(rpmTagVal regionTag, regionEnd += REGION_TAG_COUNT; rdl = regionEnd - dataStart; - if (headerVerifyInfo(1, il * sizeof(*pe), &info, &entry->info, 1) != -1 || + if (headerVerifyInfo(1, il * sizeof(*pe) + REGION_TAG_COUNT, &info, &entry->info, 1) != -1 || !(entry->info.tag == regionTag && entry->info.type == REGION_TAG_TYPE && entry->info.count == REGION_TAG_COUNT)) |