From 46ded4611836f6191cf18ee525e62f26282c11a1 Mon Sep 17 00:00:00 2001 From: jbj Date: Fri, 20 Jul 2001 16:41:09 +0000 Subject: [PATCH] - fix: yet another segfault from bad metadata prevented. CVS patchset: 4962 CVS date: 2001/07/20 16:41:09 --- CHANGES | 1 + lib/header.c | 39 ++++++++++++++++++++++++++++++++------- lib/header.h | 13 ++++++++----- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index 71d1247..ae564cb 100644 --- a/CHANGES +++ b/CHANGES @@ -180,6 +180,7 @@ - fix: %dev(...) needs to map rdev and mtime from metadata. - resurrect --specedit for i18n. - fix: 4 memory leaks eliminated. + - fix: yet another segfault from bad metadata prevented. 4.0 -> 4.0.[12] - add doxygen and lclint annotations most everywhere. diff --git a/lib/header.c b/lib/header.c index c1ebb94..26df74f 100644 --- a/lib/header.c +++ b/lib/header.c @@ -43,6 +43,18 @@ static unsigned char header_magic[8] = { */ static size_t headerMaxbytes = (32*1024*1024); +/** + * Sanity check on no. of tags. + * This check imposes a limit of 65K tags, more than enough. + */ +#define hdrchkTags(_ntags) ((_ntags) & 0xffff0000) + +/** + * Sanity check on data size and/or offset. + * This check imposes a limit of 16Mb, more than enough. + */ +#define hdrchkData(_nbytes) ((_nbytes) & 0xff000000) + /** \ingroup header * Alignment needs (and sizeof scalars types) for internal rpm data types. */ @@ -492,6 +504,11 @@ static /*@only@*/ /*@null@*/ void * doHeaderUnload(Header h, driplen += entry->length; dl += entry->length; } + + /* Sanity checks on header intro. */ + if (hdrchkTags(il) || hdrchkData(dl)) + goto errxit; + len = sizeof(il) + sizeof(dl) + (il * sizeof(*pe)) + dl; ei = xmalloc(len); @@ -700,19 +717,24 @@ Header headerLoad(void * uh) size_t pvlen = sizeof(il) + sizeof(dl) + (il * sizeof(struct entryInfo)) + dl; void * pv = uh; - Header h = xcalloc(1, sizeof(*h)); + Header h = NULL; entryInfo pe; char * dataStart; indexEntry entry; int rdlen; int i; + /* Sanity checks on header intro. */ + if (hdrchkTags(il) || hdrchkData(dl)) + goto errxit; + ei = (int_32 *) pv; /*@-castexpose@*/ pe = (entryInfo) &ei[2]; /*@=castexpose@*/ dataStart = (char *) (pe + il); + h = xcalloc(1, sizeof(*h)); /*@-assignexpose@*/ h->hv = *hdrVec; /* structure assignment */ /*@=assignexpose@*/ @@ -763,19 +785,19 @@ Header headerLoad(void * uh) goto errxit; entry->info.count = htonl(pe->count); - /* XXX imposes limit of 65K tags, more than enough. */ - if (entry->info.count & 0xffff0000) + if (hdrchkTags(entry->info.count)) goto errxit; { int off = ntohl(pe->offset); - /* XXX imposes limit of 16Mb on metadata, more than enough. */ - if (off & 0xff000000) + if (hdrchkData(off)) goto errxit; if (off) { int_32 * stei = memcpy(alloca(nb), dataStart + off, nb); rdl = -ntohl(stei[2]); /* negative offset */ ril = rdl/sizeof(*pe); + if (hdrchkTags(ril) || hdrchkData(rdl)) + goto errxit; entry->info.tag = htonl(pe->tag); } else { ril = il; @@ -857,7 +879,8 @@ Header headerCopyLoad(const void * uh) void * nuh = NULL; Header h = NULL; - if (pvlen < headerMaxbytes) { + /* Sanity checks on header intro. */ + if (!(hdrchkTags(il) || hdrchkData(dl)) && pvlen < headerMaxbytes) { nuh = memcpy(xmalloc(pvlen), uh, pvlen); if ((h = headerLoad(nuh)) != NULL) h->flags |= HEADERFLAG_ALLOCATED; @@ -900,7 +923,9 @@ Header headerRead(FD_t fd, enum hMagic magicp) dl = ntohl(block[i++]); len = sizeof(il) + sizeof(dl) + (il * sizeof(struct entryInfo)) + dl; - if (len > headerMaxbytes) + + /* Sanity checks on header intro. */ + if (hdrchkTags(il) || hdrchkData(dl) || len > headerMaxbytes) goto exit; ei = xmalloc(len); diff --git a/lib/header.h b/lib/header.h index 52e97dc..8a72c27 100644 --- a/lib/header.h +++ b/lib/header.h @@ -46,6 +46,10 @@ * - (rpm-4.0.3) A SHA1 digest of the original header is appended * (i.e. detached digest) to the immutable header region to verify * changes to the original header. + * - (rpm-4.0.3) Private methods (e.g. headerLoad(), headerUnload(), etc.) + * to permit header data to be manipulated opaquely through vectors. + * - (rpm-4.0.3) Sanity checks on header data to limit #tags to 65K, + * #bytes to 16Mb, and total metadata size to 32Mb added. * . * * \par Development Issues @@ -54,11 +58,9 @@ * will be added to headers. * * - Private header methods. - * - Private methods (e.g. headerLoad(), headerUnload(), etc.) to - * permit header data to be manipulated opaquely. Initially - * the transaction element file info TFI_t will be used as - * proof-of-concept, binary XML will probably be implemented - * soon thereafter. + * - Private methods for the transaction element file info TFI_t may + * be used as proof-of-concept, binary XML may be implemented + * as a header format representation soon thereafter. * - DSA signature for header metadata. * - The manner in which rpm packages are signed is going to change. * The SHA1 digest in the header will be signed, equivalent to a DSA @@ -70,6 +72,7 @@ * only the name field in the cpio header is used to associate an * archive file member with the corresponding entry for the file * in header metadata. + * . */ /* RPM - Copyright (C) 1995-2001 Red Hat Software */ -- 2.7.4