diff options
author | Jan Kara <jack@suse.cz> | 2007-06-01 03:46:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-01 11:18:27 -0400 |
commit | 85d71244f02583886dc20a60df2d4657d42116b4 (patch) | |
tree | 9140675832d488f40f5a4b230ff7c651a598dbf4 /fs/udf | |
parent | 296baae254c2e9ead4da5bfa57ecec86750331c7 (diff) |
Fix possible UDF data corruption
update_next_aext() could possibly rewrite values in elen and eloc, possibly
leading to data corruption when rewriting a file. Use temporary variables
instead. Also advance cur_epos as it can also point to an indirect extent
pointer.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/udf')
-rw-r--r-- | fs/udf/inode.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index c8461551e108..1f0129405cf4 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -460,8 +460,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
460 | kernel_long_ad laarr[EXTENT_MERGE_SIZE]; | 460 | kernel_long_ad laarr[EXTENT_MERGE_SIZE]; |
461 | struct extent_position prev_epos, cur_epos, next_epos; | 461 | struct extent_position prev_epos, cur_epos, next_epos; |
462 | int count = 0, startnum = 0, endnum = 0; | 462 | int count = 0, startnum = 0, endnum = 0; |
463 | uint32_t elen = 0; | 463 | uint32_t elen = 0, tmpelen; |
464 | kernel_lb_addr eloc; | 464 | kernel_lb_addr eloc, tmpeloc; |
465 | int c = 1; | 465 | int c = 1; |
466 | loff_t lbcount = 0, b_off = 0; | 466 | loff_t lbcount = 0, b_off = 0; |
467 | uint32_t newblocknum, newblock; | 467 | uint32_t newblocknum, newblock; |
@@ -520,8 +520,12 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block, | |||
520 | 520 | ||
521 | b_off -= lbcount; | 521 | b_off -= lbcount; |
522 | offset = b_off >> inode->i_sb->s_blocksize_bits; | 522 | offset = b_off >> inode->i_sb->s_blocksize_bits; |
523 | /* Move into indirect extent if we are at a pointer to it */ | 523 | /* |
524 | udf_next_aext(inode, &prev_epos, &eloc, &elen, 0); | 524 | * Move prev_epos and cur_epos into indirect extent if we are at |
525 | * the pointer to it | ||
526 | */ | ||
527 | udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0); | ||
528 | udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0); | ||
525 | 529 | ||
526 | /* if the extent is allocated and recorded, return the block | 530 | /* if the extent is allocated and recorded, return the block |
527 | if the extent is not a multiple of the blocksize, round up */ | 531 | if the extent is not a multiple of the blocksize, round up */ |