Skip to content

Latest commit

 

History

History
 
 

CVE-2016-6700

Description

Several missing bounds checks were discovered in libzipfile(the affected version is 4.4.4, 5.0.2, 5.1.1). It could occur while uncompressing a specially crafted file.

http://androidxref.com/5.1.1_r6/xref/system/core/libzipfile/centraldir.c

The patch is as follows:

--- a/centraldir.c	2016-08-17 11:44:37.661604000 +0800
+++ b/centraldir.c	2016-08-17 12:09:49.273598000 +0800
@@ -32,6 +32,11 @@
     return buf[0] | (buf[1] << 8);
 }
 
+static int is_valid_pointer(const void* ptr, const void *start, const void *end)
+{
+    return (ptr >= start) && (ptr < end);
+}
+
 static int
 read_central_dir_values(Zipfile* file, const unsigned char* buf, int len)
 {
@@ -102,23 +107,48 @@
         entry->fileName = NULL;
     }
     p += entry->fileNameLength;
-
+    if (!is_valid_pointer(p, file->buf, file->buf + file->bufsize)) {
+        fprintf(stderr, "invalid pointer\n");
+        return -1;
+    }
     // extra field
     p += extraFieldLength;
+    if (!is_valid_pointer(p, file->buf, file->buf + file->bufsize)) {
+        fprintf(stderr, "invalid pointer\n");
+        return -1;
+    }
 
     // comment, if any
     p += fileCommentLength;
+    if (!is_valid_pointer(p, file->buf, file->buf + file->bufsize)) {
+        fprintf(stderr, "invalid pointer\n");
+        return -1;
+    }
 
     *buf = p;
 
     // the size of the extraField in the central dir is how much data there is,
     // but the one in the local file header also contains some padding.
     p = file->buf + localHeaderRelOffset;
+    if (!is_valid_pointer(p, file->buf, file->buf + file->bufsize) || 
+        !is_valid_pointer(p + 0x1d, file->buf, file->buf + file->bufsize)) {
+        fprintf(stderr, "invalid pointer\n");
+        return -1;
+    }
     extraFieldLength = read_le_short(&p[0x1c]);
 
     dataOffset = localHeaderRelOffset + LFH_SIZE
         + entry->fileNameLength + extraFieldLength;
     entry->data = file->buf + dataOffset;
+    if (!is_valid_pointer(entry->data, file->buf, file->buf + file->bufsize)) {
+        fprintf(stderr, "invalid pointer\n");
+        return -1;        
+    }
+    if (entry->compressionMethod == STORED && 
+        entry->uncompressedSize > (unsigned int) (file->buf + file->bufsize - entry->data)) {
+        fprintf(stderr, "unkown error\n");
+        return -1;
+    }
 #if 0
     printf("file->buf=%p entry->data=%p dataOffset=%x localHeaderRelOffset=%d "
            "entry->fileNameLength=%d extraFieldLength=%d\n",
@@ -199,6 +229,10 @@
 
     // Loop through and read the central dir entries.
     p = buf + file->centralDirOffest;
+    if (!is_valid_pointer(p, file->buf, file->buf + file->bufsize)) {
+        fprintf(stderr, "invalid pointer\n");
+        return -1;
+    }
     len = (buf+bufsize)-p;
     for (i=0; i < file->totalEntryCount; i++) {
         Zipentry* entry = malloc(sizeof(Zipentry));

These vulnerabilities may result in corruption of sensitive information, a crash, or code execution among other things.

Poc

fastboot update xxx.zip