diff options
author | Steve Magnani <steve.magnani@digidescorp.com> | 2017-10-12 08:48:40 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2017-10-17 11:56:45 +0200 |
commit | b490bdd630cc43a5725e76c7c23f8a7e55551145 (patch) | |
tree | 9ee95e0af7d247b2a8b282b2b5ed1a783465e9da /fs/udf/balloc.c | |
parent | 503c3117d05c184b431e403cd05c463ac41370f0 (diff) | |
download | linux-b490bdd630cc43a5725e76c7c23f8a7e55551145.tar.bz2 |
udf: Fix 64-bit sign extension issues affecting blocks > 0x7FFFFFFF
Large (> 1 TiB) UDF filesystems appear subject to several problems when
mounted on 64-bit systems:
* readdir() can fail on a directory containing File Identifiers residing
above 0x7FFFFFFF. This manifests as a 'ls' command failing with EIO.
* FIBMAP on a file block located above 0x7FFFFFFF can return a negative
value. The low 32 bits are correct, but applications that don't mask the
high 32 bits of the result can perform incorrectly.
Per suggestion by Jan Kara, introduce a udf_pblk_t type for representation
of UDF block addresses. Ultimately, all driver functions that manipulate
UDF block addresses should use this type; for now, deployment is limited
to functions with actual or potential sign extension issues.
Changes to udf_readdir() and udf_block_map() address the issues noted
above; other changes address potential similar issues uncovered during
audit of the driver code.
Signed-off-by: Steven J. Magnani <steve@digidescorp.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/balloc.c')
-rw-r--r-- | fs/udf/balloc.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index e0fd65fe73e8..cbfd6043274b 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -218,16 +218,18 @@ out: return alloc_count; } -static int udf_bitmap_new_block(struct super_block *sb, +static udf_pblk_t udf_bitmap_new_block(struct super_block *sb, struct udf_bitmap *bitmap, uint16_t partition, uint32_t goal, int *err) { struct udf_sb_info *sbi = UDF_SB(sb); - int newbit, bit = 0, block, block_group, group_start; + int newbit, bit = 0; + udf_pblk_t block; + int block_group, group_start; int end_goal, nr_groups, bitmap_nr, i; struct buffer_head *bh = NULL; char *ptr; - int newblock = 0; + udf_pblk_t newblock = 0; *err = -ENOSPC; mutex_lock(&sbi->s_alloc_mutex); @@ -545,13 +547,14 @@ static int udf_table_prealloc_blocks(struct super_block *sb, return alloc_count; } -static int udf_table_new_block(struct super_block *sb, +static udf_pblk_t udf_table_new_block(struct super_block *sb, struct inode *table, uint16_t partition, uint32_t goal, int *err) { struct udf_sb_info *sbi = UDF_SB(sb); uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; - uint32_t newblock = 0, adsize; + udf_pblk_t newblock = 0; + uint32_t adsize; uint32_t elen, goal_elen = 0; struct kernel_lb_addr eloc, uninitialized_var(goal_eloc); struct extent_position epos, goal_epos; @@ -700,12 +703,12 @@ inline int udf_prealloc_blocks(struct super_block *sb, return allocated; } -inline int udf_new_block(struct super_block *sb, +inline udf_pblk_t udf_new_block(struct super_block *sb, struct inode *inode, uint16_t partition, uint32_t goal, int *err) { struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; - int block; + udf_pblk_t block; if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) block = udf_bitmap_new_block(sb, |