Skip to content

Commit

Permalink
udf: Check LVID earlier
Browse files Browse the repository at this point in the history
[ Upstream commit 781d2a9 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
jankara authored and gregkh committed Sep 15, 2021
1 parent 3d12cce commit 4cf1551
Showing 1 changed file with 16 additions and 9 deletions.
25 changes: 16 additions & 9 deletions fs/udf/super.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -1541,6 +1535,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;
Expand All @@ -1567,15 +1562,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;
}
}

/*
Expand Down

0 comments on commit 4cf1551

Please sign in to comment.