diff options
author | Tahsin Erdogan <tahsin@google.com> | 2017-06-21 21:57:36 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2017-06-21 21:57:36 -0400 |
commit | 909666933210eb145bc93426ce07f66bf3d1f798 (patch) | |
tree | 2860c6d369f273f7f3854c0c52c4c8bc43753524 | |
parent | bab79b04999ccbbf59f1693d0783cd6ae27e4278 (diff) |
ext4: clean up ext4_xattr_inode_get()
The input and output values of *size parameter are equal on successful
return from ext4_xattr_inode_get(). On error return, the callers ignore
the output value so there is no need to update it.
Also check for NULL return from ext4_bread(). If the actual xattr inode
size happens to be smaller than the expected size, ext4_bread() may
return NULL which would indicate data corruption.
Signed-off-by: Tahsin Erdogan <tahsin@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | fs/ext4/xattr.c | 35 |
1 files changed, 13 insertions, 22 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index f16a90824d44..61c67a04a7e1 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -278,37 +278,28 @@ ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index, /* * Read the EA value from an inode. */ -static int -ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t *size) +static int ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t size) { unsigned long block = 0; struct buffer_head *bh = NULL; - int blocksize; - size_t csize, ret_size = 0; - - if (*size == 0) - return 0; + int blocksize = ea_inode->i_sb->s_blocksize; + size_t csize, copied = 0; - blocksize = ea_inode->i_sb->s_blocksize; - - while (ret_size < *size) { - csize = (*size - ret_size) > blocksize ? blocksize : - *size - ret_size; + while (copied < size) { + csize = (size - copied) > blocksize ? blocksize : size - copied; bh = ext4_bread(NULL, ea_inode, block, 0); - if (IS_ERR(bh)) { - *size = ret_size; + if (IS_ERR(bh)) return PTR_ERR(bh); - } + if (!bh) + return -EFSCORRUPTED; + memcpy(buf, bh->b_data, csize); brelse(bh); buf += csize; block += 1; - ret_size += csize; + copied += csize; } - - *size = ret_size; - return 0; } @@ -360,7 +351,7 @@ error: */ static int ext4_xattr_inode_get(struct inode *inode, unsigned long ea_ino, void *buffer, - size_t *size) + size_t size) { struct inode *ea_inode; int ret; @@ -417,7 +408,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, if (entry->e_value_inum) { error = ext4_xattr_inode_get(inode, le32_to_cpu(entry->e_value_inum), - buffer, &size); + buffer, size); if (error) goto cleanup; } else { @@ -467,7 +458,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, if (entry->e_value_inum) { error = ext4_xattr_inode_get(inode, le32_to_cpu(entry->e_value_inum), - buffer, &size); + buffer, size); if (error) goto cleanup; } else { |