aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2009-10-25 20:30:49 +0000
committerFabian Groffen <grobian@gentoo.org>2009-10-25 20:30:49 +0000
commitcd68c6c1bef86d0865ba35f9a9d06f65e7882a43 (patch)
tree082b0e58e1644af51b4080570f0d3924ecad52d9 /paxmacho.c
parentfixup warning about caps code -- caps_free() does not take a const (diff)
downloadpax-utils-cd68c6c1bef86d0865ba35f9a9d06f65e7882a43.tar.gz
pax-utils-cd68c6c1bef86d0865ba35f9a9d06f65e7882a43.tar.bz2
pax-utils-cd68c6c1bef86d0865ba35f9a9d06f65e7882a43.zip
A little protection against invalid files. This needs more work to be
fully defensive. For now we just check if we can read the fat_headers and mach_headers, which is enough to get around the problem of Java bytecode objects sharing the same magic with FAT files. Thanks Heiko Przybyl for noticing and the initial patch
Diffstat (limited to 'paxmacho.c')
-rw-r--r--paxmacho.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/paxmacho.c b/paxmacho.c
index 2b2cfbb..da54a5c 100644
--- a/paxmacho.c
+++ b/paxmacho.c
@@ -1,7 +1,7 @@
/*
* Copyright 2003-2008 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/pax-utils/paxmacho.c,v 1.14 2008/12/30 13:27:09 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/pax-utils/paxmacho.c,v 1.15 2009/10/25 20:30:49 grobian Exp $
*
* Copyright 2005-2007 Ned Ludd - <solar@gentoo.org>
* Copyright 2005-2007 Mike Frysinger - <vapier@gentoo.org>
@@ -156,7 +156,8 @@ const char *get_machosubcputype(fatobj *fobj)
/* Determines the type of this object, and sets the right 32-bit or
* 64-bits pointer. The ismach64 flag is filled in appropriately. The
* return of this function is the read magic value, or 0 when the file
- * is not recognised. */
+ * is not recognised.
+ * Note: the input addr must be enough to map on struct mach_header! */
inline static uint32_t read_mach_header(fatobj *fobj, void *addr)
{
struct mach_header *mhdr = addr;
@@ -213,10 +214,6 @@ fatobj *readmacho_fd(const char *filename, int fd, size_t len)
return NULL;
}
- /* make sure we have enough bytes to scan */
- if (len <= sizeof(struct fat_header))
- return NULL;
-
data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
if (data == MAP_FAILED) {
warn("mmap on '%s' of %zu bytes failed :(", filename, len);
@@ -247,6 +244,10 @@ fatobj *readmacho_buffer(const char *filename, char *buffer, size_t buffer_len)
ret->data = buffer;
ret->swapped = 0;
+ /* make sure we have enough bytes to scan */
+ if (ret->len <= sizeof(struct fat_header))
+ return NULL;
+
fhdr = (struct fat_header *)ret->data;
/* Check what kind of file this is. Unfortunately we don't have
* configure, so we don't know if we're on big or little endian, so
@@ -258,6 +259,7 @@ fatobj *readmacho_buffer(const char *filename, char *buffer, size_t buffer_len)
fatobj *fobj = ret;
struct fat_arch *farch;
char *dptr = ret->data + sizeof(struct fat_header);
+ uint32_t bufleft = ret->len - sizeof(struct fat_header);
char swapped = 0;
uint32_t narchs = fhdr->nfat_arch;
uint32_t offset;
@@ -269,10 +271,17 @@ fatobj *readmacho_buffer(const char *filename, char *buffer, size_t buffer_len)
narchs = bswap_32(narchs);
}
+ /* can we read the headers at all?
+ * beware of corrupt files and Java bytecode which shares
+ * the same magic with us :( */
+ if (sizeof(struct fat_arch) * narchs > bufleft)
+ return NULL;
+
for (i = 1; i <= narchs; i++) {
farch = (struct fat_arch *)dptr;
offset = MGET(swapped, farch->offset);
- if (read_mach_header(fobj, ret->data + offset) == 0)
+ if (offset + sizeof(struct mach_header) >= bufleft ||
+ read_mach_header(fobj, ret->data + offset) == 0)
return NULL;
if (i < narchs) {
fobj = fobj->next = xzalloc(sizeof(*fobj));
@@ -284,10 +293,12 @@ fatobj *readmacho_buffer(const char *filename, char *buffer, size_t buffer_len)
fobj->next = NULL;
}
dptr += sizeof(struct fat_arch);
+ bufleft -= sizeof(struct fat_arch);
}
} else {
/* simple Mach-O file, treat as single arch FAT file */
- if (read_mach_header(ret, ret->data) == 0)
+ if (ret->len < sizeof(struct mach_header) ||
+ read_mach_header(ret, ret->data) == 0)
return NULL;
ret->next = NULL;
}