Skip to content

Commit 7888824

Browse files
Alden Tondettarjankara
authored andcommitted
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>
1 parent 3743a03 commit 7888824

File tree

3 files changed

+21
-12
lines changed

3 files changed

+21
-12
lines changed

fs/udf/partition.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,8 @@ static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
295295
map = &UDF_SB(sb)->s_partmaps[partition];
296296
/* map to sparable/physical partition desc */
297297
phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
298-
map->s_partition_num, ext_offset + offset);
298+
map->s_type_specific.s_metadata.s_phys_partition_ref,
299+
ext_offset + offset);
299300
}
300301

301302
brelse(epos.bh);
@@ -325,7 +326,8 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
325326
udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n");
326327
if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) {
327328
mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
328-
mdata->s_mirror_file_loc, map->s_partition_num);
329+
mdata->s_mirror_file_loc,
330+
mdata->s_phys_partition_ref);
329331
if (IS_ERR(mdata->s_mirror_fe))
330332
mdata->s_mirror_fe = NULL;
331333
mdata->s_flags |= MF_MIRROR_FE_LOADED;

fs/udf/super.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -951,13 +951,13 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
951951
}
952952

953953
struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
954-
u32 meta_file_loc, u32 partition_num)
954+
u32 meta_file_loc, u32 partition_ref)
955955
{
956956
struct kernel_lb_addr addr;
957957
struct inode *metadata_fe;
958958

959959
addr.logicalBlockNum = meta_file_loc;
960-
addr.partitionReferenceNum = partition_num;
960+
addr.partitionReferenceNum = partition_ref;
961961

962962
metadata_fe = udf_iget_special(sb, &addr);
963963

@@ -974,7 +974,8 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
974974
return metadata_fe;
975975
}
976976

977-
static int udf_load_metadata_files(struct super_block *sb, int partition)
977+
static int udf_load_metadata_files(struct super_block *sb, int partition,
978+
int type1_index)
978979
{
979980
struct udf_sb_info *sbi = UDF_SB(sb);
980981
struct udf_part_map *map;
@@ -984,20 +985,21 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
984985

985986
map = &sbi->s_partmaps[partition];
986987
mdata = &map->s_type_specific.s_metadata;
988+
mdata->s_phys_partition_ref = type1_index;
987989

988990
/* metadata address */
989991
udf_debug("Metadata file location: block = %d part = %d\n",
990-
mdata->s_meta_file_loc, map->s_partition_num);
992+
mdata->s_meta_file_loc, mdata->s_phys_partition_ref);
991993

992994
fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc,
993-
map->s_partition_num);
995+
mdata->s_phys_partition_ref);
994996
if (IS_ERR(fe)) {
995997
/* mirror file entry */
996998
udf_debug("Mirror metadata file location: block = %d part = %d\n",
997-
mdata->s_mirror_file_loc, map->s_partition_num);
999+
mdata->s_mirror_file_loc, mdata->s_phys_partition_ref);
9981000

9991001
fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc,
1000-
map->s_partition_num);
1002+
mdata->s_phys_partition_ref);
10011003

10021004
if (IS_ERR(fe)) {
10031005
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)
10151017
*/
10161018
if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
10171019
addr.logicalBlockNum = mdata->s_bitmap_file_loc;
1018-
addr.partitionReferenceNum = map->s_partition_num;
1020+
addr.partitionReferenceNum = mdata->s_phys_partition_ref;
10191021

10201022
udf_debug("Bitmap file location: block = %d part = %d\n",
10211023
addr.logicalBlockNum, addr.partitionReferenceNum);
@@ -1283,7 +1285,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
12831285
p = (struct partitionDesc *)bh->b_data;
12841286
partitionNumber = le16_to_cpu(p->partitionNumber);
12851287

1286-
/* First scan for TYPE1, SPARABLE and METADATA partitions */
1288+
/* First scan for TYPE1 and SPARABLE partitions */
12871289
for (i = 0; i < sbi->s_partitions; i++) {
12881290
map = &sbi->s_partmaps[i];
12891291
udf_debug("Searching map: (%d == %d)\n",
@@ -1333,7 +1335,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
13331335
goto out_bh;
13341336

13351337
if (map->s_partition_type == UDF_METADATA_MAP25) {
1336-
ret = udf_load_metadata_files(sb, i);
1338+
ret = udf_load_metadata_files(sb, i, type1_idx);
13371339
if (ret < 0) {
13381340
udf_err(sb, "error loading MetaData partition map %d\n",
13391341
i);

fs/udf/udf_sb.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ struct udf_meta_data {
6161
__u32 s_bitmap_file_loc;
6262
__u32 s_alloc_unit_size;
6363
__u16 s_align_unit_size;
64+
/*
65+
* Partition Reference Number of the associated physical / sparable
66+
* partition
67+
*/
68+
__u16 s_phys_partition_ref;
6469
int s_flags;
6570
struct inode *s_metadata_fe;
6671
struct inode *s_mirror_fe;

0 commit comments

Comments
 (0)