https://bugzilla.redhat.com/show_bug.cgi?id=843141
link:
http://post-office.corp.redhat.com/archives/rhkernel-list/2012-October/ms...
commit adee11b2085bee90bd8f4f52123ffb07882d6256
Author: Jan Kara <jack(a)suse.cz>
Date: Wed Jun 27 20:20:22 2012 +0200
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(a)suse.cz>
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
fs/udf/super.c | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 6f84480..f4a1800 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1032,13 +1032,22 @@ udf_load_logicalvol(struct super_block *sb, struct buffer_head *
bh, kernel_lb_a
struct logicalVolDesc *lvd;
int i, j, offset;
uint8_t type;
-
+ unsigned table_len;
lvd = (struct logicalVolDesc *)bh->b_data;
+ table_len = le32_to_cpu(lvd->mapTableLength);
+ if (sizeof(*lvd) + table_len > sb->s_blocksize) {
+ udf_error(sb, __FUNCTION__,
+ "error loading logical volume descriptor: "
+ "Partition table too long (%u > %lu)\n", table_len,
+ sb->s_blocksize - sizeof(*lvd));
+ return 1;
+ }
+
UDF_SB_ALLOC_PARTMAPS(sb, le32_to_cpu(lvd->numPartitionMaps));
for (i=0,offset=0;
- i<UDF_SB_NUMPARTS(sb) && offset<le32_to_cpu(lvd->mapTableLength);
+ i<UDF_SB_NUMPARTS(sb) && offset<table_len;
i++,offset+=((struct genericPartitionMap
*)&(lvd->partitionMaps[offset]))->partitionMapLength)
{
type = ((struct genericPartitionMap
*)&(lvd->partitionMaps[offset]))->partitionMapType;
@@ -1258,8 +1267,12 @@ udf_process_sequence(struct super_block *sb, long block, long
lastblock, kernel_
if (i == VDS_POS_PRIMARY_VOL_DESC)
udf_load_pvoldesc(sb, bh);
- else if (i == VDS_POS_LOGICAL_VOL_DESC)
- udf_load_logicalvol(sb, bh, fileset);
+ else if (i == VDS_POS_LOGICAL_VOL_DESC) {
+ if (udf_load_logicalvol(sb, bh, fileset)) {
+ brelse(bh);
+ return 1;
+ }
+ }
else if (i == VDS_POS_PARTITION_DESC)
{
struct buffer_head *bh2 = NULL;
@@ -1338,13 +1351,12 @@ udf_load_partition(struct super_block *sb, kernel_lb_addr
*fileset)
brelse(bh);
- /* Process the main & reserve sequences */
+ /* Process the main sequence */
/* responsible for finding the PartitionDesc(s) */
- if (!(udf_process_sequence(sb, main_s, main_e, fileset) &&
- udf_process_sequence(sb, reserve_s, reserve_e, fileset)))
- {
+ if (udf_process_sequence(sb, main_s, main_e, fileset))
+ return 1;
+ else
break;
- }
}
}
--
1.8.0.2