forked from Minki/linux
udf: Check LVID earlier
We were checking validity of LVID entries only when getting implementation use information from LVID in udf_sb_lvidiu(). However if the LVID is suitably corrupted, it can cause problems also to code such as udf_count_free() which doesn't use udf_sb_lvidiu(). So check validity of LVID already when loading it from the disk and just disable LVID altogether when it is not valid. Reported-by: syzbot+7fbfe5fed73ebb675748@syzkaller.appspotmail.com Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
902e7f373f
commit
781d2a9a2f
@ -108,16 +108,10 @@ struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb)
|
||||
return NULL;
|
||||
lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data;
|
||||
partnum = le32_to_cpu(lvid->numOfPartitions);
|
||||
if ((sb->s_blocksize - sizeof(struct logicalVolIntegrityDescImpUse) -
|
||||
offsetof(struct logicalVolIntegrityDesc, impUse)) /
|
||||
(2 * sizeof(uint32_t)) < partnum) {
|
||||
udf_err(sb, "Logical volume integrity descriptor corrupted "
|
||||
"(numOfPartitions = %u)!\n", partnum);
|
||||
return NULL;
|
||||
}
|
||||
/* The offset is to skip freeSpaceTable and sizeTable arrays */
|
||||
offset = partnum * 2 * sizeof(uint32_t);
|
||||
return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]);
|
||||
return (struct logicalVolIntegrityDescImpUse *)
|
||||
(((uint8_t *)(lvid + 1)) + offset);
|
||||
}
|
||||
|
||||
/* UDF filesystem type */
|
||||
@ -1542,6 +1536,7 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
|
||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||
struct logicalVolIntegrityDesc *lvid;
|
||||
int indirections = 0;
|
||||
u32 parts, impuselen;
|
||||
|
||||
while (++indirections <= UDF_MAX_LVID_NESTING) {
|
||||
final_bh = NULL;
|
||||
@ -1568,15 +1563,27 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
|
||||
|
||||
lvid = (struct logicalVolIntegrityDesc *)final_bh->b_data;
|
||||
if (lvid->nextIntegrityExt.extLength == 0)
|
||||
return;
|
||||
goto check;
|
||||
|
||||
loc = leea_to_cpu(lvid->nextIntegrityExt);
|
||||
}
|
||||
|
||||
udf_warn(sb, "Too many LVID indirections (max %u), ignoring.\n",
|
||||
UDF_MAX_LVID_NESTING);
|
||||
out_err:
|
||||
brelse(sbi->s_lvid_bh);
|
||||
sbi->s_lvid_bh = NULL;
|
||||
return;
|
||||
check:
|
||||
parts = le32_to_cpu(lvid->numOfPartitions);
|
||||
impuselen = le32_to_cpu(lvid->lengthOfImpUse);
|
||||
if (parts >= sb->s_blocksize || impuselen >= sb->s_blocksize ||
|
||||
sizeof(struct logicalVolIntegrityDesc) + impuselen +
|
||||
2 * parts * sizeof(u32) > sb->s_blocksize) {
|
||||
udf_warn(sb, "Corrupted LVID (parts=%u, impuselen=%u), "
|
||||
"ignoring.\n", parts, impuselen);
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user