forked from luck/tmp_suning_uos_patched
udf: Use correct partition reference number for metadata
UDF/OSTA terminology is confusing. Partition Numbers (PNs) are arbitrary 16-bit values, one for each physical partition in the volume. Partition Reference Numbers (PRNs) are indices into the the Partition Map Table and do not necessarily equal the PN of the mapped partition. The current metadata code mistakenly uses the PN instead of the PRN when mapping metadata blocks to physical/sparable blocks. Windows-created UDF 2.5 discs for some reason use large, arbitrary PNs, resulting in mount failure and KASAN read warnings in udf_read_inode(). For example, a NetBSD UDF 2.5 partition might look like this: PRN PN Type --- -- ---- 0 0 Sparable 1 0 Metadata Since PRN == PN, we are fine. But Windows could gives us: PRN PN Type --- ---- ---- 0 8192 Sparable 1 8192 Metadata So udf_read_inode() will start out by checking the partition length in sbi->s_partmaps[8192], which is obviously out of bounds. Fix this by creating a new field (s_phys_partition_ref) in struct udf_meta_data, referencing whatever physical or sparable map has the same partition number as the metadata partition. [JK: Add comment about s_phys_partition_ref, change its name] Signed-off-by: Alden Tondettar <alden.tondettar@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
3743a03e72
commit
7888824b0b
|
@ -295,7 +295,8 @@ static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
|
|||
map = &UDF_SB(sb)->s_partmaps[partition];
|
||||
/* map to sparable/physical partition desc */
|
||||
phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
|
||||
map->s_partition_num, ext_offset + offset);
|
||||
map->s_type_specific.s_metadata.s_phys_partition_ref,
|
||||
ext_offset + offset);
|
||||
}
|
||||
|
||||
brelse(epos.bh);
|
||||
|
@ -325,7 +326,8 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
|
|||
udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n");
|
||||
if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) {
|
||||
mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
|
||||
mdata->s_mirror_file_loc, map->s_partition_num);
|
||||
mdata->s_mirror_file_loc,
|
||||
mdata->s_phys_partition_ref);
|
||||
if (IS_ERR(mdata->s_mirror_fe))
|
||||
mdata->s_mirror_fe = NULL;
|
||||
mdata->s_flags |= MF_MIRROR_FE_LOADED;
|
||||
|
|
|
@ -951,13 +951,13 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
|
|||
}
|
||||
|
||||
struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
|
||||
u32 meta_file_loc, u32 partition_num)
|
||||
u32 meta_file_loc, u32 partition_ref)
|
||||
{
|
||||
struct kernel_lb_addr addr;
|
||||
struct inode *metadata_fe;
|
||||
|
||||
addr.logicalBlockNum = meta_file_loc;
|
||||
addr.partitionReferenceNum = partition_num;
|
||||
addr.partitionReferenceNum = partition_ref;
|
||||
|
||||
metadata_fe = udf_iget_special(sb, &addr);
|
||||
|
||||
|
@ -974,7 +974,8 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
|
|||
return metadata_fe;
|
||||
}
|
||||
|
||||
static int udf_load_metadata_files(struct super_block *sb, int partition)
|
||||
static int udf_load_metadata_files(struct super_block *sb, int partition,
|
||||
int type1_index)
|
||||
{
|
||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||
struct udf_part_map *map;
|
||||
|
@ -984,20 +985,21 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
|
|||
|
||||
map = &sbi->s_partmaps[partition];
|
||||
mdata = &map->s_type_specific.s_metadata;
|
||||
mdata->s_phys_partition_ref = type1_index;
|
||||
|
||||
/* metadata address */
|
||||
udf_debug("Metadata file location: block = %d part = %d\n",
|
||||
mdata->s_meta_file_loc, map->s_partition_num);
|
||||
mdata->s_meta_file_loc, mdata->s_phys_partition_ref);
|
||||
|
||||
fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc,
|
||||
map->s_partition_num);
|
||||
mdata->s_phys_partition_ref);
|
||||
if (IS_ERR(fe)) {
|
||||
/* mirror file entry */
|
||||
udf_debug("Mirror metadata file location: block = %d part = %d\n",
|
||||
mdata->s_mirror_file_loc, map->s_partition_num);
|
||||
mdata->s_mirror_file_loc, mdata->s_phys_partition_ref);
|
||||
|
||||
fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc,
|
||||
map->s_partition_num);
|
||||
mdata->s_phys_partition_ref);
|
||||
|
||||
if (IS_ERR(fe)) {
|
||||
udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
|
||||
|
@ -1015,7 +1017,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
|
|||
*/
|
||||
if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
|
||||
addr.logicalBlockNum = mdata->s_bitmap_file_loc;
|
||||
addr.partitionReferenceNum = map->s_partition_num;
|
||||
addr.partitionReferenceNum = mdata->s_phys_partition_ref;
|
||||
|
||||
udf_debug("Bitmap file location: block = %d part = %d\n",
|
||||
addr.logicalBlockNum, addr.partitionReferenceNum);
|
||||
|
@ -1283,7 +1285,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
|
|||
p = (struct partitionDesc *)bh->b_data;
|
||||
partitionNumber = le16_to_cpu(p->partitionNumber);
|
||||
|
||||
/* First scan for TYPE1, SPARABLE and METADATA partitions */
|
||||
/* First scan for TYPE1 and SPARABLE partitions */
|
||||
for (i = 0; i < sbi->s_partitions; i++) {
|
||||
map = &sbi->s_partmaps[i];
|
||||
udf_debug("Searching map: (%d == %d)\n",
|
||||
|
@ -1333,7 +1335,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
|
|||
goto out_bh;
|
||||
|
||||
if (map->s_partition_type == UDF_METADATA_MAP25) {
|
||||
ret = udf_load_metadata_files(sb, i);
|
||||
ret = udf_load_metadata_files(sb, i, type1_idx);
|
||||
if (ret < 0) {
|
||||
udf_err(sb, "error loading MetaData partition map %d\n",
|
||||
i);
|
||||
|
|
|
@ -61,6 +61,11 @@ struct udf_meta_data {
|
|||
__u32 s_bitmap_file_loc;
|
||||
__u32 s_alloc_unit_size;
|
||||
__u16 s_align_unit_size;
|
||||
/*
|
||||
* Partition Reference Number of the associated physical / sparable
|
||||
* partition
|
||||
*/
|
||||
__u16 s_phys_partition_ref;
|
||||
int s_flags;
|
||||
struct inode *s_metadata_fe;
|
||||
struct inode *s_mirror_fe;
|
||||
|
|
Loading…
Reference in New Issue
Block a user