summaryrefslogtreecommitdiffstats
path: root/fs/udf/balloc.c
diff options
context:
space:
mode:
authorSteve Magnani <steve.magnani@digidescorp.com>2017-10-12 08:48:40 -0500
committerJan Kara <jack@suse.cz>2017-10-17 11:56:45 +0200
commitb490bdd630cc43a5725e76c7c23f8a7e55551145 (patch)
tree9ee95e0af7d247b2a8b282b2b5ed1a783465e9da /fs/udf/balloc.c
parent503c3117d05c184b431e403cd05c463ac41370f0 (diff)
downloadlinux-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.c17
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,