summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-06-27 22:20:22 +0400
committerJan Kara <jack@suse.cz>2012-06-28 21:30:58 +0400
commitadee11b2085bee90bd8f4f52123ffb07882d6256 (patch)
treec0219a7105329d633a9101235548a587bfcebee2
parentcb14d340ef1737c24125dd663eff77734a482d47 (diff)
downloadlinux-adee11b2085bee90bd8f4f52123ffb07882d6256.tar.xz
udf: Avoid run away loop when partition table length is corrupted
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>
-rw-r--r--fs/udf/super.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 9da6f4ee112c..ce911f50b39d 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1225,6 +1225,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
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);
@@ -1232,13 +1233,20 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
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_err(sb, "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 *)