Prevented endless CE loops when reading a very bad ISO fileystem
This commit is contained in:
parent
d35435b5a0
commit
7109ba5675
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Vreixo Formoso
|
* Copyright (c) 2007 Vreixo Formoso
|
||||||
* Copyright (c) 2009 Thomas Schmitt
|
* Copyright (c) 2009 - 2023 Thomas Schmitt
|
||||||
*
|
*
|
||||||
* This file is part of the libisofs project; you can redistribute it and/or
|
* This file is part of the libisofs project; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License version 2
|
* modify it under the terms of the GNU General Public License version 2
|
||||||
@ -38,6 +38,9 @@ struct susp_iterator
|
|||||||
/* Number of blocks in the ISO 9660 filesystem */
|
/* Number of blocks in the ISO 9660 filesystem */
|
||||||
uint32_t fs_blocks;
|
uint32_t fs_blocks;
|
||||||
|
|
||||||
|
/* For detecting (nearly) endless loops */
|
||||||
|
uint32_t ce_counter;
|
||||||
|
|
||||||
/* block and offset for next continuation area */
|
/* block and offset for next continuation area */
|
||||||
uint32_t ce_block;
|
uint32_t ce_block;
|
||||||
uint32_t ce_off;
|
uint32_t ce_off;
|
||||||
@ -65,7 +68,10 @@ susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record,
|
|||||||
iter->msgid = msgid;
|
iter->msgid = msgid;
|
||||||
iter->fs_blocks = fs_blocks;
|
iter->fs_blocks = fs_blocks;
|
||||||
|
|
||||||
|
iter->ce_counter = 0;
|
||||||
iter->ce_len = 0;
|
iter->ce_len = 0;
|
||||||
|
iter->ce_block = 0;
|
||||||
|
iter->ce_off = 0;
|
||||||
iter->buffer = NULL;
|
iter->buffer = NULL;
|
||||||
|
|
||||||
return iter;
|
return iter;
|
||||||
@ -74,6 +80,9 @@ susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record,
|
|||||||
/* More than 1 MiB in a single file's CE area is suspicious */
|
/* More than 1 MiB in a single file's CE area is suspicious */
|
||||||
#define ISO_SUSP_MAX_CE_BYTES (1024 * 1024)
|
#define ISO_SUSP_MAX_CE_BYTES (1024 * 1024)
|
||||||
|
|
||||||
|
/* More than 100000 CE entries in a file is suspicious */
|
||||||
|
#define ISO_SUSP_MAX_CE_HOPS 100000
|
||||||
|
|
||||||
|
|
||||||
/* @param flag bit0 = First call on root:
|
/* @param flag bit0 = First call on root:
|
||||||
Not yet clear whether this is SUSP at all
|
Not yet clear whether this is SUSP at all
|
||||||
@ -83,6 +92,7 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue,
|
|||||||
{
|
{
|
||||||
struct susp_sys_user_entry *entry;
|
struct susp_sys_user_entry *entry;
|
||||||
|
|
||||||
|
process_entry:;
|
||||||
entry = (struct susp_sys_user_entry*)(iter->base + iter->pos);
|
entry = (struct susp_sys_user_entry*)(iter->base + iter->pos);
|
||||||
|
|
||||||
if (flag & 1) {
|
if (flag & 1) {
|
||||||
@ -94,6 +104,9 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue,
|
|||||||
if (entry->len_sue[0] < 7)
|
if (entry->len_sue[0] < 7)
|
||||||
return 0;
|
return 0;
|
||||||
/* Looks like SUSP enough to pass the further processing here. */
|
/* Looks like SUSP enough to pass the further processing here. */
|
||||||
|
|
||||||
|
/* In case of CE hop do not run this check again */
|
||||||
|
flag &= ~1;
|
||||||
}
|
}
|
||||||
if ( (iter->pos + 4 > iter->size) || (SUSP_SIG(entry, 'S', 'T'))) {
|
if ( (iter->pos + 4 > iter->size) || (SUSP_SIG(entry, 'S', 'T'))) {
|
||||||
|
|
||||||
@ -151,9 +164,9 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue,
|
|||||||
if (iter->ce_len) {
|
if (iter->ce_len) {
|
||||||
int ret;
|
int ret;
|
||||||
ret = iso_msg_submit(iter->msgid, ISO_UNSUPPORTED_SUSP, 0,
|
ret = iso_msg_submit(iter->msgid, ISO_UNSUPPORTED_SUSP, 0,
|
||||||
"More than one CE System user entry has found in a single "
|
"More than one CE System user entry was found in a single "
|
||||||
"System Use field or continuation area. This breaks SUSP "
|
"System Use field or continuation area. This breaks SUSP "
|
||||||
"standard and it's not supported. Ignoring last CE. Maybe "
|
"standard and is not supported. Ignoring last CE. Maybe "
|
||||||
"the image is damaged.");
|
"the image is damaged.");
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
@ -165,10 +178,15 @@ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* we don't want to return CE entry to the user */
|
/* we don't want to return CE entry to the user */
|
||||||
return susp_iter_next(iter, sue, 0);
|
if (++(iter->ce_counter) > ISO_SUSP_MAX_CE_HOPS) {
|
||||||
|
iso_msg_submit(iter->msgid, ISO_WRONG_RR, 0,
|
||||||
|
"Damaged RR/SUSP information: Too many CE hops.");
|
||||||
|
return ISO_WRONG_RR;
|
||||||
|
}
|
||||||
|
goto process_entry;
|
||||||
} else if (SUSP_SIG(entry, 'P', 'D')) {
|
} else if (SUSP_SIG(entry, 'P', 'D')) {
|
||||||
/* skip padding */
|
/* skip padding */
|
||||||
return susp_iter_next(iter, sue, 0);
|
goto process_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
*sue = entry;
|
*sue = entry;
|
||||||
|
Loading…
Reference in New Issue
Block a user