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, | |||
278 | /* | 278 | /* |
279 | * Read the EA value from an inode. | 279 | * Read the EA value from an inode. |
280 | */ | 280 | */ |
281 | static int | 281 | static int ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t size) |
282 | ext4_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 | */ |
361 | static int | 352 | static int |
362 | ext4_xattr_inode_get(struct inode *inode, unsigned long ea_ino, void *buffer, | 353 | ext4_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 { |