aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTahsin Erdogan <tahsin@google.com>2017-06-21 21:57:36 -0400
committerTheodore Ts'o <tytso@mit.edu>2017-06-21 21:57:36 -0400
commit909666933210eb145bc93426ce07f66bf3d1f798 (patch)
tree2860c6d369f273f7f3854c0c52c4c8bc43753524
parentbab79b04999ccbbf59f1693d0783cd6ae27e4278 (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.c35
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,
278/* 278/*
279 * Read the EA value from an inode. 279 * Read the EA value from an inode.
280 */ 280 */
281static int 281static int ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t size)
282ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t *size)
283{ 282{
284 unsigned long block = 0; 283 unsigned long block = 0;
285 struct buffer_head *bh = NULL; 284 struct buffer_head *bh = NULL;
286 int blocksize; 285 int blocksize = ea_inode->i_sb->s_blocksize;
287 size_t csize, ret_size = 0; 286 size_t csize, copied = 0;
288
289 if (*size == 0)
290 return 0;
291 287
292 blocksize = ea_inode->i_sb->s_blocksize; 288 while (copied < size) {
293 289 csize = (size - copied) > blocksize ? blocksize : size - copied;
294 while (ret_size < *size) {
295 csize = (*size - ret_size) > blocksize ? blocksize :
296 *size - ret_size;
297 bh = ext4_bread(NULL, ea_inode, block, 0); 290 bh = ext4_bread(NULL, ea_inode, block, 0);
298 if (IS_ERR(bh)) { 291 if (IS_ERR(bh))
299 *size = ret_size;
300 return PTR_ERR(bh); 292 return PTR_ERR(bh);
301 } 293 if (!bh)
294 return -EFSCORRUPTED;
295
302 memcpy(buf, bh->b_data, csize); 296 memcpy(buf, bh->b_data, csize);
303 brelse(bh); 297 brelse(bh);
304 298
305 buf += csize; 299 buf += csize;
306 block += 1; 300 block += 1;
307 ret_size += csize; 301 copied += csize;
308 } 302 }
309
310 *size = ret_size;
311
312 return 0; 303 return 0;
313} 304}
314 305
@@ -360,7 +351,7 @@ error:
360 */ 351 */
361static int 352static int
362ext4_xattr_inode_get(struct inode *inode, unsigned long ea_ino, void *buffer, 353ext4_xattr_inode_get(struct inode *inode, unsigned long ea_ino, void *buffer,
363 size_t *size) 354 size_t size)
364{ 355{
365 struct inode *ea_inode; 356 struct inode *ea_inode;
366 int ret; 357 int ret;
@@ -417,7 +408,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
417 if (entry->e_value_inum) { 408 if (entry->e_value_inum) {
418 error = ext4_xattr_inode_get(inode, 409 error = ext4_xattr_inode_get(inode,
419 le32_to_cpu(entry->e_value_inum), 410 le32_to_cpu(entry->e_value_inum),
420 buffer, &size); 411 buffer, size);
421 if (error) 412 if (error)
422 goto cleanup; 413 goto cleanup;
423 } else { 414 } else {
@@ -467,7 +458,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
467 if (entry->e_value_inum) { 458 if (entry->e_value_inum) {
468 error = ext4_xattr_inode_get(inode, 459 error = ext4_xattr_inode_get(inode,
469 le32_to_cpu(entry->e_value_inum), 460 le32_to_cpu(entry->e_value_inum),
470 buffer, &size); 461 buffer, size);
471 if (error) 462 if (error)
472 goto cleanup; 463 goto cleanup;
473 } else { 464 } else {