[PATCH 1/2] Fix possible UDF data corruption

From: Jan Kara
Date: Thu May 24 2007 - 12:48:25 EST


Hi Andrew,

attached patch fixes possible data corruption in UDF - this bug was actually
introduced by one of my fixes :-( and should (if possible) go to Linus before
2.6.22 is out (that's why I'm diffing against Linus's tree and not the
latest changes in -mm tree)... Thanks.

Honza

--
Jan Kara <jack@xxxxxxx>
SuSE CR Labs
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@xxxxxxx>

diff -rupX /home/jack/.kerndiffexclude linux-2.6.22-rc2/fs/udf/inode.c linux-2.6.22-rc2-1-udf_data_corruption/fs/udf/inode.c
--- linux-2.6.22-rc2/fs/udf/inode.c 2007-05-24 18:00:05.000000000 +0200
+++ linux-2.6.22-rc2-1-udf_data_corruption/fs/udf/inode.c 2007-05-24 18:16:36.000000000 +0200
@@ -460,8 +460,8 @@ static struct buffer_head * inode_getblk
kernel_long_ad laarr[EXTENT_MERGE_SIZE];
struct extent_position prev_epos, cur_epos, next_epos;
int count = 0, startnum = 0, endnum = 0;
- uint32_t elen = 0;
- kernel_lb_addr eloc;
+ uint32_t elen = 0, tmpelen;
+ kernel_lb_addr eloc, tmpeloc;
int c = 1;
loff_t lbcount = 0, b_off = 0;
uint32_t newblocknum, newblock;
@@ -520,8 +520,12 @@ static struct buffer_head * inode_getblk

b_off -= lbcount;
offset = b_off >> inode->i_sb->s_blocksize_bits;
- /* Move into indirect extent if we are at a pointer to it */
- udf_next_aext(inode, &prev_epos, &eloc, &elen, 0);
+ /*
+ * Move prev_epos and cur_epos into indirect extent if we are at
+ * the pointer to it
+ */
+ udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0);
+ udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0);

/* if the extent is allocated and recorded, return the block
if the extent is not a multiple of the blocksize, round up */