From 2a64d89e6e6fee4893ab4809342870acba0ea465 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sat, 19 Aug 2017 16:55:08 +0200 Subject: [PATCH] Refuse to read CE data blocks from after the end of ISO filesystem --- libisofs/fs_image.c | 7 ++++--- libisofs/libisofs.h | 3 ++- libisofs/messages.c | 2 +- libisofs/rockridge.h | 2 +- libisofs/rockridge_read.c | 9 ++++++++- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index 82c7250..e4bc89d 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -1577,8 +1577,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent, SuspIterator *iter; - iter = susp_iter_new(fsdata->src, record, fsdata->len_skp, - fsdata->msgid); + iter = susp_iter_new(fsdata->src, record, fsdata->nblocks, + fsdata->len_skp, fsdata->msgid); if (iter == NULL) { {ret = ISO_OUT_OF_MEM; goto ex;} } @@ -2404,7 +2404,8 @@ int read_root_susp_entries(_ImageFsData *data, uint32_t block) * In that case, we need to set info->len_skp to 15!! */ - iter = susp_iter_new(data->src, record, data->len_skp, data->msgid); + iter = susp_iter_new(data->src, record, data->nblocks, data->len_skp, + data->msgid); if (iter == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 95a9a7b..8c6977a 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -8883,7 +8883,8 @@ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len, /** Unable to obtain root directory (FATAL,HIGH, -418) */ #define ISO_NO_ROOT_DIR 0xF030FE5E -/** Zero sized or oversized SUSP CE area found (FAILURE, HIGH, -419) */ +/** Zero sized, oversized, or mislocated SUSP CE area found + (FAILURE, HIGH, -419) */ #define ISO_SUSP_WRONG_CE_SIZE 0xE830FE5D diff --git a/libisofs/messages.c b/libisofs/messages.c index 6ff0a36..84d4cc0 100644 --- a/libisofs/messages.c +++ b/libisofs/messages.c @@ -550,7 +550,7 @@ const char *iso_error_to_msg(int errcode) case ISO_NO_ROOT_DIR: return "Unable to obtain root directory"; case ISO_SUSP_WRONG_CE_SIZE: - return "Zero sized or oversized SUSP CE area found"; + return "Zero sized, oversized, or mislocated SUSP CE area found"; default: return "Unknown error"; } diff --git a/libisofs/rockridge.h b/libisofs/rockridge.h index 88eed0a..ba0efc4 100644 --- a/libisofs/rockridge.h +++ b/libisofs/rockridge.h @@ -254,7 +254,7 @@ typedef struct susp_iterator SuspIterator; SuspIterator * susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record, - uint8_t len_skp, int msgid); + uint32_t fs_blocks, uint8_t len_skp, int msgid); /** * Get the next SUSP System User Entry using given iterator. diff --git a/libisofs/rockridge_read.c b/libisofs/rockridge_read.c index d1d63f8..cc1b70c 100644 --- a/libisofs/rockridge_read.c +++ b/libisofs/rockridge_read.c @@ -35,6 +35,9 @@ struct susp_iterator IsoDataSource *src; int msgid; + /* Number of blocks in the ISO 9660 filesystem */ + uint32_t fs_blocks; + /* block and offset for next continuation area */ uint32_t ce_block; uint32_t ce_off; @@ -47,7 +50,7 @@ struct susp_iterator SuspIterator* susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record, - uint8_t len_skp, int msgid) + uint32_t fs_blocks, uint8_t len_skp, int msgid) { int pad = (record->len_fi[0] + 1) % 2; struct susp_iterator *iter = malloc(sizeof(struct susp_iterator)); @@ -60,6 +63,7 @@ susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record, iter->size = record->len_dr[0] - record->len_fi[0] - 33 - pad; iter->src = src; iter->msgid = msgid; + iter->fs_blocks = fs_blocks; iter->ce_len = 0; iter->buffer = NULL; @@ -108,6 +112,9 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue, BLOCK_SIZE); if (nblocks <= 0 || iter->ce_len > ISO_SUSP_MAX_CE_BYTES) return ISO_SUSP_WRONG_CE_SIZE; + if (((uint64_t) iter->ce_block) + skipped_blocks + nblocks > + (uint64_t) iter->fs_blocks) + return ISO_SUSP_WRONG_CE_SIZE; iter->buffer = realloc(iter->buffer, nblocks * BLOCK_SIZE); /* Read blocks needed to cache the given CE area range */