* [PATCH 0/3 STABLE] udf: Do not crash on corrupted media @ 2012-07-04 10:55 Jan Kara 2012-07-04 10:55 ` [PATCH 1/3] udf: Use 'ret' instead of abusing 'i' in udf_load_logicalvol() Jan Kara ` (2 more replies) 0 siblings, 3 replies; 5+ messages in thread From: Jan Kara @ 2012-07-04 10:55 UTC (permalink / raw) To: stable; +Cc: linux-fsdevel Hi, these patches went upstream recently and they improve UDF handling of corrupted media. These patches are adjusted to work with 3.0 kernel (udf_err() is called udf_error() in that kernel). Honza ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] udf: Use 'ret' instead of abusing 'i' in udf_load_logicalvol() 2012-07-04 10:55 [PATCH 0/3 STABLE] udf: Do not crash on corrupted media Jan Kara @ 2012-07-04 10:55 ` Jan Kara 2012-07-04 10:55 ` [PATCH 2/3] udf: Avoid run away loop when partition table length is corrupted Jan Kara 2012-07-04 10:55 ` [PATCH 3/3] udf: Fortify loading of sparing table Jan Kara 2 siblings, 0 replies; 5+ messages in thread From: Jan Kara @ 2012-07-04 10:55 UTC (permalink / raw) To: stable; +Cc: linux-fsdevel, Jan Kara Signed-off-by: Jan Kara <jack@suse.cz> --- fs/udf/super.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index ac8a348..9da6f4e 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1233,11 +1233,9 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, BUG_ON(ident != TAG_IDENT_LVD); lvd = (struct logicalVolDesc *)bh->b_data; - i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); - if (i != 0) { - ret = i; + ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); + if (ret) goto out_bh; - } for (i = 0, offset = 0; i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength); -- 1.7.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] udf: Avoid run away loop when partition table length is corrupted 2012-07-04 10:55 [PATCH 0/3 STABLE] udf: Do not crash on corrupted media Jan Kara 2012-07-04 10:55 ` [PATCH 1/3] udf: Use 'ret' instead of abusing 'i' in udf_load_logicalvol() Jan Kara @ 2012-07-04 10:55 ` Jan Kara 2012-07-04 10:55 ` [PATCH 3/3] udf: Fortify loading of sparing table Jan Kara 2 siblings, 0 replies; 5+ messages in thread From: Jan Kara @ 2012-07-04 10:55 UTC (permalink / raw) To: stable; +Cc: linux-fsdevel, Jan Kara Check provided length of partition table so that (possibly maliciously) corrupted partition table cannot cause accessing data beyond current buffer. Signed-off-by: Jan Kara <jack@suse.cz> --- fs/udf/super.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-) Index: linux-3.0-SLE11-SP2/fs/udf/super.c =================================================================== --- linux-3.0-SLE11-SP2.orig/fs/udf/super.c +++ linux-3.0-SLE11-SP2/fs/udf/super.c @@ -1254,6 +1254,7 @@ static int udf_load_logicalvol(struct su struct genericPartitionMap *gpm; uint16_t ident; struct buffer_head *bh; + unsigned int table_len; int ret = 0; bh = udf_read_tagged(sb, block, block, &ident); @@ -1261,13 +1262,20 @@ static int udf_load_logicalvol(struct su return 1; BUG_ON(ident != TAG_IDENT_LVD); lvd = (struct logicalVolDesc *)bh->b_data; + table_len = le32_to_cpu(lvd->mapTableLength); + if (sizeof(*lvd) + table_len > sb->s_blocksize) { + udf_error(sb, __func__, "error loading logical volume descriptor: " + "Partition table too long (%u > %lu)\n", table_len, + sb->s_blocksize - sizeof(*lvd)); + goto out_bh; + } ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); if (ret) goto out_bh; for (i = 0, offset = 0; - i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength); + i < sbi->s_partitions && offset < table_len; i++, offset += gpm->partitionMapLength) { struct udf_part_map *map = &sbi->s_partmaps[i]; gpm = (struct genericPartitionMap *) ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 3/3] udf: Fortify loading of sparing table 2012-07-04 10:55 [PATCH 0/3 STABLE] udf: Do not crash on corrupted media Jan Kara 2012-07-04 10:55 ` [PATCH 1/3] udf: Use 'ret' instead of abusing 'i' in udf_load_logicalvol() Jan Kara 2012-07-04 10:55 ` [PATCH 2/3] udf: Avoid run away loop when partition table length is corrupted Jan Kara @ 2012-07-04 10:55 ` Jan Kara 2 siblings, 0 replies; 5+ messages in thread From: Jan Kara @ 2012-07-04 10:55 UTC (permalink / raw) To: stable; +Cc: linux-fsdevel, Jan Kara Add sanity checks when loading sparing table from disk to avoid accessing unallocated memory or writing to it. Signed-off-by: Jan Kara <jack@suse.cz> --- fs/udf/super.c | 86 ++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 53 insertions(+), 33 deletions(-) Index: linux-3.0-SLE11-SP2/fs/udf/super.c =================================================================== --- linux-3.0-SLE11-SP2.orig/fs/udf/super.c +++ linux-3.0-SLE11-SP2/fs/udf/super.c @@ -56,6 +56,7 @@ #include <linux/seq_file.h> #include <linux/bitmap.h> #include <linux/crc-itu-t.h> +#include <linux/log2.h> #include <asm/byteorder.h> #include "udf_sb.h" @@ -1244,11 +1245,59 @@ out_bh: return ret; } +static int udf_load_sparable_map(struct super_block *sb, + struct udf_part_map *map, + struct sparablePartitionMap *spm) +{ + uint32_t loc; + uint16_t ident; + struct sparingTable *st; + struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing; + int i; + struct buffer_head *bh; + + map->s_partition_type = UDF_SPARABLE_MAP15; + sdata->s_packet_len = le16_to_cpu(spm->packetLength); + if (!is_power_of_2(sdata->s_packet_len)) { + udf_error(sb, __func__, "error loading logical volume descriptor: " + "Invalid packet length %u\n", + (unsigned)sdata->s_packet_len); + return -EIO; + } + if (spm->numSparingTables > 4) { + udf_error(sb, __func__, "error loading logical volume descriptor: " + "Too many sparing tables (%d)\n", + (int)spm->numSparingTables); + return -EIO; + } + + for (i = 0; i < spm->numSparingTables; i++) { + loc = le32_to_cpu(spm->locSparingTable[i]); + bh = udf_read_tagged(sb, loc, loc, &ident); + if (!bh) + continue; + + st = (struct sparingTable *)bh->b_data; + if (ident != 0 || + strncmp(st->sparingIdent.ident, UDF_ID_SPARING, + strlen(UDF_ID_SPARING)) || + sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > + sb->s_blocksize) { + brelse(bh); + continue; + } + + sdata->s_spar_map[i] = bh; + } + map->s_partition_func = udf_get_pblock_spar15; + return 0; +} + static int udf_load_logicalvol(struct super_block *sb, sector_t block, struct kernel_lb_addr *fileset) { struct logicalVolDesc *lvd; - int i, j, offset; + int i, offset; uint8_t type; struct udf_sb_info *sbi = UDF_SB(sb); struct genericPartitionMap *gpm; @@ -1310,38 +1359,9 @@ static int udf_load_logicalvol(struct su } else if (!strncmp(upm2->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { - uint32_t loc; - struct sparingTable *st; - struct sparablePartitionMap *spm = - (struct sparablePartitionMap *)gpm; - - map->s_partition_type = UDF_SPARABLE_MAP15; - map->s_type_specific.s_sparing.s_packet_len = - le16_to_cpu(spm->packetLength); - for (j = 0; j < spm->numSparingTables; j++) { - struct buffer_head *bh2; - - loc = le32_to_cpu( - spm->locSparingTable[j]); - bh2 = udf_read_tagged(sb, loc, loc, - &ident); - map->s_type_specific.s_sparing. - s_spar_map[j] = bh2; - - if (bh2 == NULL) - continue; - - st = (struct sparingTable *)bh2->b_data; - if (ident != 0 || strncmp( - st->sparingIdent.ident, - UDF_ID_SPARING, - strlen(UDF_ID_SPARING))) { - brelse(bh2); - map->s_type_specific.s_sparing. - s_spar_map[j] = NULL; - } - } - map->s_partition_func = udf_get_pblock_spar15; + if (udf_load_sparable_map(sb, map, + (struct sparablePartitionMap *)gpm) < 0) + goto out_bh; } else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA))) { ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 0/3 STABLE] udf: Do not crash on corrupted media @ 2012-07-04 11:01 Jan Kara 2012-07-04 11:01 ` [PATCH 3/3] udf: Fortify loading of sparing table Jan Kara 0 siblings, 1 reply; 5+ messages in thread From: Jan Kara @ 2012-07-04 11:01 UTC (permalink / raw) To: stable; +Cc: linux-fsdevel Hi, these patches went upstream recently and they improve UDF handling of corrupted media. These patches are adjusted to work with 3.0 kernel (udf_err() is called udf_error() in that kernel). Honza ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 3/3] udf: Fortify loading of sparing table 2012-07-04 11:01 [PATCH 0/3 STABLE] udf: Do not crash on corrupted media Jan Kara @ 2012-07-04 11:01 ` Jan Kara 0 siblings, 0 replies; 5+ messages in thread From: Jan Kara @ 2012-07-04 11:01 UTC (permalink / raw) To: stable; +Cc: linux-fsdevel, Jan Kara Add sanity checks when loading sparing table from disk to avoid accessing unallocated memory or writing to it. Signed-off-by: Jan Kara <jack@suse.cz> --- fs/udf/super.c | 86 ++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 53 insertions(+), 33 deletions(-) Index: linux-3.0-SLE11-SP2/fs/udf/super.c =================================================================== --- linux-3.0-SLE11-SP2.orig/fs/udf/super.c +++ linux-3.0-SLE11-SP2/fs/udf/super.c @@ -56,6 +56,7 @@ #include <linux/seq_file.h> #include <linux/bitmap.h> #include <linux/crc-itu-t.h> +#include <linux/log2.h> #include <asm/byteorder.h> #include "udf_sb.h" @@ -1244,11 +1245,59 @@ out_bh: return ret; } +static int udf_load_sparable_map(struct super_block *sb, + struct udf_part_map *map, + struct sparablePartitionMap *spm) +{ + uint32_t loc; + uint16_t ident; + struct sparingTable *st; + struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing; + int i; + struct buffer_head *bh; + + map->s_partition_type = UDF_SPARABLE_MAP15; + sdata->s_packet_len = le16_to_cpu(spm->packetLength); + if (!is_power_of_2(sdata->s_packet_len)) { + udf_error(sb, __func__, "error loading logical volume descriptor: " + "Invalid packet length %u\n", + (unsigned)sdata->s_packet_len); + return -EIO; + } + if (spm->numSparingTables > 4) { + udf_error(sb, __func__, "error loading logical volume descriptor: " + "Too many sparing tables (%d)\n", + (int)spm->numSparingTables); + return -EIO; + } + + for (i = 0; i < spm->numSparingTables; i++) { + loc = le32_to_cpu(spm->locSparingTable[i]); + bh = udf_read_tagged(sb, loc, loc, &ident); + if (!bh) + continue; + + st = (struct sparingTable *)bh->b_data; + if (ident != 0 || + strncmp(st->sparingIdent.ident, UDF_ID_SPARING, + strlen(UDF_ID_SPARING)) || + sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > + sb->s_blocksize) { + brelse(bh); + continue; + } + + sdata->s_spar_map[i] = bh; + } + map->s_partition_func = udf_get_pblock_spar15; + return 0; +} + static int udf_load_logicalvol(struct super_block *sb, sector_t block, struct kernel_lb_addr *fileset) { struct logicalVolDesc *lvd; - int i, j, offset; + int i, offset; uint8_t type; struct udf_sb_info *sbi = UDF_SB(sb); struct genericPartitionMap *gpm; @@ -1310,38 +1359,9 @@ static int udf_load_logicalvol(struct su } else if (!strncmp(upm2->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { - uint32_t loc; - struct sparingTable *st; - struct sparablePartitionMap *spm = - (struct sparablePartitionMap *)gpm; - - map->s_partition_type = UDF_SPARABLE_MAP15; - map->s_type_specific.s_sparing.s_packet_len = - le16_to_cpu(spm->packetLength); - for (j = 0; j < spm->numSparingTables; j++) { - struct buffer_head *bh2; - - loc = le32_to_cpu( - spm->locSparingTable[j]); - bh2 = udf_read_tagged(sb, loc, loc, - &ident); - map->s_type_specific.s_sparing. - s_spar_map[j] = bh2; - - if (bh2 == NULL) - continue; - - st = (struct sparingTable *)bh2->b_data; - if (ident != 0 || strncmp( - st->sparingIdent.ident, - UDF_ID_SPARING, - strlen(UDF_ID_SPARING))) { - brelse(bh2); - map->s_type_specific.s_sparing. - s_spar_map[j] = NULL; - } - } - map->s_partition_func = udf_get_pblock_spar15; + if (udf_load_sparable_map(sb, map, + (struct sparablePartitionMap *)gpm) < 0) + goto out_bh; } else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA))) { ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-07-04 11:01 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-07-04 10:55 [PATCH 0/3 STABLE] udf: Do not crash on corrupted media Jan Kara 2012-07-04 10:55 ` [PATCH 1/3] udf: Use 'ret' instead of abusing 'i' in udf_load_logicalvol() Jan Kara 2012-07-04 10:55 ` [PATCH 2/3] udf: Avoid run away loop when partition table length is corrupted Jan Kara 2012-07-04 10:55 ` [PATCH 3/3] udf: Fortify loading of sparing table Jan Kara -- strict thread matches above, loose matches on Subject: below -- 2012-07-04 11:01 [PATCH 0/3 STABLE] udf: Do not crash on corrupted media Jan Kara 2012-07-04 11:01 ` [PATCH 3/3] udf: Fortify loading of sparing table Jan Kara
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).