[PATCH 2/4] befs: check return value of iaddr2blockno

From: Salah Triki
Date: Wed Aug 10 2016 - 18:13:19 EST


The call of iaddr2blockno may fail, so check its return value and
propagate error, if any.

Signed-off-by: Salah Triki <salah.triki@xxxxxxxxx>
---
fs/befs/datastream.c | 30 ++++++++++++++++++++----------
fs/befs/inode.c | 10 ++++++++--
fs/befs/io.c | 3 +++
fs/befs/linuxvfs.c | 12 +++++++++++-
4 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/fs/befs/datastream.c b/fs/befs/datastream.c
index 343123c..1747f64 100644
--- a/fs/befs/datastream.c
+++ b/fs/befs/datastream.c
@@ -308,8 +308,11 @@ befs_find_brun_indirect(struct super_block *sb,
befs_disk_block_run *array;

befs_block_run indirect = data->indirect;
- befs_blocknr_t indirblockno = iaddr2blockno(sb, &indirect);
int arraylen = befs_iaddrs_per_block(sb);
+ befs_blocknr_t indirblockno = iaddr2blockno(sb, &indirect);
+
+ if (indirblockno == BEFS_ERR)
+ return BEFS_ERR;

befs_debug(sb, "---> %s, find %lu", __func__, (unsigned long)blockno);

@@ -422,6 +425,7 @@ befs_find_brun_dblindirect(struct super_block *sb,
struct buffer_head *indir_block;
befs_block_run indir_run;
befs_disk_inode_addr *iaddr_array;
+ befs_blocknr_t block;

befs_blocknr_t indir_start_blk =
data->max_indirect_range >> BEFS_SB(sb)->block_shift;
@@ -461,15 +465,17 @@ befs_find_brun_dblindirect(struct super_block *sb,
return BEFS_ERR;
}

- dbl_indir_block =
- sb_bread(sb, iaddr2blockno(sb, &data->double_indirect) +
- dbl_which_block);
+ block = iaddr2blockno(sb, &data->double_indirect);
+
+ if (block == BEFS_ERR)
+ return BEFS_ERR;
+
+ dbl_indir_block = sb_bread(sb, blockno + dbl_which_block);
+
if (dbl_indir_block == NULL) {
befs_error(sb, "%s couldn't read the "
"double-indirect block at blockno %lu", __func__,
- (unsigned long)
- iaddr2blockno(sb, &data->double_indirect) +
- dbl_which_block);
+ (unsigned long)blockno + dbl_which_block);
return BEFS_ERR;
}

@@ -488,12 +494,16 @@ befs_find_brun_dblindirect(struct super_block *sb,
return BEFS_ERR;
}

- indir_block =
- sb_bread(sb, iaddr2blockno(sb, &indir_run) + which_block);
+ blockno = iaddr2blockno(sb, &indir_run);
+
+ if (blockno == BEFS_ERR)
+ return BEFS_ERR;
+
+ indir_block = sb_bread(sb, blockno + which_block);
if (indir_block == NULL) {
befs_error(sb, "%s couldn't read the indirect block "
"at blockno %lu", __func__, (unsigned long)
- iaddr2blockno(sb, &indir_run) + which_block);
+ blockno + which_block);
return BEFS_ERR;
}

diff --git a/fs/befs/inode.c b/fs/befs/inode.c
index fa4b718..495d270 100644
--- a/fs/befs/inode.c
+++ b/fs/befs/inode.c
@@ -21,6 +21,7 @@ befs_check_inode(struct super_block *sb, befs_inode * raw_inode,
u32 magic1 = fs32_to_cpu(sb, raw_inode->magic1);
befs_inode_addr ino_num = fsrun_to_cpu(sb, raw_inode->inode_num);
u32 flags = fs32_to_cpu(sb, raw_inode->flags);
+ befs_blocknr_t block;

/* check magic header. */
if (magic1 != BEFS_INODE_MAGIC1) {
@@ -33,10 +34,15 @@ befs_check_inode(struct super_block *sb, befs_inode * raw_inode,
/*
* Sanity check2: inodes store their own block address. Check it.
*/
- if (inode != iaddr2blockno(sb, &ino_num)) {
+ block = iaddr2blockno(sb, &ino_num);
+
+ if (block == BEFS_ERR)
+ return BEFS_ERR;
+
+ if (inode != block) {
befs_error(sb, "inode blocknr field disagrees with vfs "
"VFS: %lu, Inode %lu", (unsigned long)
- inode, (unsigned long)iaddr2blockno(sb, &ino_num));
+ inode, (unsigned long)block);
return BEFS_BAD_INODE;
}

diff --git a/fs/befs/io.c b/fs/befs/io.c
index 4223b77..14eef7d 100644
--- a/fs/befs/io.c
+++ b/fs/befs/io.c
@@ -42,6 +42,9 @@ befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr)

block = iaddr2blockno(sb, &iaddr);

+ if (block == BEFS_ERR)
+ goto error;
+
befs_debug(sb, "%s: offset = %lu", __func__, (unsigned long)block);

bh = sb_bread(sb, block);
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index c57f831..6635515 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -143,6 +143,9 @@ befs_get_block(struct inode *inode, sector_t block,

disk_off = (ulong) iaddr2blockno(sb, &run);

+ if (disk_off == BEFS_ERR)
+ return -EINVAL;
+
map_bh(bh_result, inode->i_sb, disk_off);

befs_debug(sb, "<--- %s for inode %lu, block %ld, disk address %lu",
@@ -756,6 +759,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
long ret = -EINVAL;
const unsigned long sb_block = 0;
const off_t x86_sb_off = 512;
+ befs_blocknr_t block;

save_mount_options(sb, data);

@@ -830,7 +834,13 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
/* Set real blocksize of fs */
sb_set_blocksize(sb, (ulong) befs_sb->block_size);
sb->s_op = &befs_sops;
- root = befs_iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir)));
+
+ block = iaddr2blockno(sb, &(befs_sb->root_dir));
+
+ if (block == BEFS_ERR)
+ goto unacquire_priv_sbp;
+
+ root = befs_iget(sb, block);
if (IS_ERR(root)) {
ret = PTR_ERR(root);
goto unacquire_priv_sbp;
--
1.9.1