Browse code

bb12332 - fix segfault when scanning bz2 compressed iso9660s by limiting total page prefaulting to the 4GB max

Mickey Sola authored on 2020/01/31 02:14:43
Showing 3 changed files
... ...
@@ -230,7 +230,7 @@ extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len,
230 230
     }
231 231
 
232 232
     pages = fmap_align_items(len, pgsz);
233
-    hdrsz = fmap_align_to(sizeof(fmap_t) + (pages - 1) * sizeof(uint32_t), pgsz); /* fmap_t includes 1 bitmap slot, hence (pages-1) */
233
+    hdrsz = fmap_align_to(sizeof(fmap_t) + (pages - 1) * sizeof(uint64_t), pgsz); /* fmap_t includes 1 bitmap slot, hence (pages-1) */
234 234
     mapsz = pages * pgsz + hdrsz;
235 235
 
236 236
 #ifndef ANONYMOUS_MAP
... ...
@@ -351,12 +351,17 @@ static void fmap_aging(fmap_t *m)
351 351
 #endif
352 352
 }
353 353
 
354
-static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count, unsigned int lock_count)
354
+static int fmap_readpage(fmap_t *m, uint64_t first_page, uint32_t count, uint32_t lock_count)
355 355
 {
356 356
     size_t readsz = 0, eintr_off;
357 357
     char *pptr    = NULL, errtxt[256];
358
-    uint32_t s;
359
-    unsigned int i, page = first_page, force_read = 0;
358
+    uint32_t sbitmap;
359
+    uint64_t i, page = first_page, force_read = 0;
360
+
361
+    if ((size_t)(m->real_len) > (size_t)(UINT_MAX)) {
362
+        cli_dbgmsg("fmap_readage: size of file exceeds total prefaultible page size (unpacked file is too large)\n");
363
+        return 1;
364
+    }
360 365
 
361 366
     fmap_lock;
362 367
     for (i = 0; i < count; i++) { /* prefault */
... ...
@@ -377,14 +382,14 @@ static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count,
377 377
             /* we count one page too much to flush pending reads */
378 378
             if (!pptr) return 0; /* if we have any */
379 379
             force_read = 1;
380
-        } else if ((s = fmap_bitmap[page]) & FM_MASK_PAGED) {
380
+        } else if ((sbitmap = fmap_bitmap[page]) & FM_MASK_PAGED) {
381 381
             /* page already paged */
382 382
             if (lock) {
383 383
                 /* we want locking */
384
-                if (s & FM_MASK_LOCKED) {
384
+                if (sbitmap & FM_MASK_LOCKED) {
385 385
                     /* page already locked */
386
-                    s &= FM_MASK_COUNT;
387
-                    if (s == FM_MASK_COUNT) { /* lock count already at max: fial! */
386
+                    sbitmap &= FM_MASK_COUNT;
387
+                    if (sbitmap == FM_MASK_COUNT) { /* lock count already at max: fial! */
388 388
                         cli_errmsg("fmap_readpage: lock count exceeded\n");
389 389
                         return 1;
390 390
                     }
... ...
@@ -394,7 +399,7 @@ static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count,
394 394
                     fmap_bitmap[page] = 1 | FM_MASK_LOCKED | FM_MASK_PAGED;
395 395
             } else {
396 396
                 /* we don't want locking */
397
-                if (!(s & FM_MASK_LOCKED)) {
397
+                if (!(sbitmap & FM_MASK_LOCKED)) {
398 398
                     /* page is not locked: we reset aging to max */
399 399
                     fmap_bitmap[page] = FM_MASK_PAGED | FM_MASK_COUNT;
400 400
                 }
... ...
@@ -478,7 +483,7 @@ static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count,
478 478
 
479 479
 static const void *handle_need(fmap_t *m, size_t at, size_t len, int lock)
480 480
 {
481
-    unsigned int first_page, last_page, lock_count;
481
+    uint64_t first_page, last_page, lock_count;
482 482
     char *ret;
483 483
 
484 484
     if (!len)
... ...
@@ -47,8 +47,8 @@ struct cl_fmap {
47 47
     /* internal */
48 48
     time_t mtime;
49 49
     unsigned int pages;
50
-    unsigned int hdrsz;
51
-    unsigned int pgsz;
50
+    uint64_t hdrsz;
51
+    uint64_t pgsz;
52 52
     unsigned int paged;
53 53
     unsigned short aging;
54 54
     unsigned short dont_cache_flag;
... ...
@@ -1269,7 +1269,7 @@ static int cli_scanbzip(cli_ctx *ctx)
1269 1269
 static int cli_scanbzip(cli_ctx *ctx)
1270 1270
 {
1271 1271
     int ret = CL_CLEAN, fd, rc;
1272
-    unsigned long int size = 0;
1272
+    uint64_t size = 0;
1273 1273
     char *tmpname;
1274 1274
     bz_stream strm;
1275 1275
     size_t off = 0;