summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2023-01-23 16:18:47 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-03-11 18:39:57 +0300
commitbacfce056ea694ad023ce577950abde515de0599 (patch)
treef22c1c083ba4e3d9cfdd84a80e50efdc88e4bba5 /fs
parenta44ec34b90440ada190924f5908b97026504fdcd (diff)
downloadlinux-bacfce056ea694ad023ce577950abde515de0599.tar.xz
udf: Fix file corruption when appending just after end of preallocated extent
commit 36ec52ea038b18a53e198116ef7d7e70c87db046 upstream. When we append new block just after the end of preallocated extent, the code in inode_getblk() wrongly determined we're going to use the preallocated extent which resulted in adding block into a wrong logical offset in the file. Sequence like this manifests it: xfs_io -f -c "pwrite 0x2cacf 0xd122" -c "truncate 0x2dd6f" \ -c "pwrite 0x27fd9 0x69a9" -c "pwrite 0x32981 0x7244" <file> The code that determined the use of preallocated extent is actually stale because udf_do_extend_file() does not create preallocation anymore so after calling that function we are sure there's no usable preallocation. Just remove the faulty condition. CC: stable@vger.kernel.org Fixes: 16d055656814 ("udf: Discard preallocation before extending file with a hole") Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/udf/inode.c24
1 files changed, 11 insertions, 13 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 71acce2c0b6a..81876284a83c 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -804,19 +804,17 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
c = 0;
offset = 0;
count += ret;
- /* We are not covered by a preallocated extent? */
- if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) !=
- EXT_NOT_RECORDED_ALLOCATED) {
- /* Is there any real extent? - otherwise we overwrite
- * the fake one... */
- if (count)
- c = !c;
- laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
- inode->i_sb->s_blocksize;
- memset(&laarr[c].extLocation, 0x00,
- sizeof(struct kernel_lb_addr));
- count++;
- }
+ /*
+ * Is there any real extent? - otherwise we overwrite the fake
+ * one...
+ */
+ if (count)
+ c = !c;
+ laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
+ inode->i_sb->s_blocksize;
+ memset(&laarr[c].extLocation, 0x00,
+ sizeof(struct kernel_lb_addr));
+ count++;
endnum = c + 1;
lastblock = 1;
} else {