Skip to content

Commit 40144e4

Browse files
jankaradjwong
authored andcommitted
xfs: Fix stale data exposure when readahead races with hole punch
Hole puching currently evicts pages from page cache and then goes on to remove blocks from the inode. This happens under both XFS_IOLOCK_EXCL and XFS_MMAPLOCK_EXCL which provides appropriate serialization with racing reads or page faults. However there is currently nothing that prevents readahead triggered by fadvise() or madvise() from racing with the hole punch and instantiating page cache page after hole punching has evicted page cache in xfs_flush_unmap_range() but before it has removed blocks from the inode. This page cache page will be mapping soon to be freed block and that can lead to returning stale data to userspace or even filesystem corruption. Fix the problem by protecting handling of readahead requests by XFS_IOLOCK_SHARED similarly as we protect reads. CC: [email protected] Link: https://lore.kernel.org/linux-fsdevel/CAOQ4uxjQNmxqmtA_VbYW0Su9rKRk2zobJmahcyeaEVOFKVQ5dw@mail.gmail.com/ Reported-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]>
1 parent cf1ea05 commit 40144e4

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

fs/xfs/xfs_file.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/falloc.h>
2929
#include <linux/backing-dev.h>
3030
#include <linux/mman.h>
31+
#include <linux/fadvise.h>
3132

3233
static const struct vm_operations_struct xfs_file_vm_ops;
3334

@@ -933,6 +934,30 @@ xfs_file_fallocate(
933934
return error;
934935
}
935936

937+
STATIC int
938+
xfs_file_fadvise(
939+
struct file *file,
940+
loff_t start,
941+
loff_t end,
942+
int advice)
943+
{
944+
struct xfs_inode *ip = XFS_I(file_inode(file));
945+
int ret;
946+
int lockflags = 0;
947+
948+
/*
949+
* Operations creating pages in page cache need protection from hole
950+
* punching and similar ops
951+
*/
952+
if (advice == POSIX_FADV_WILLNEED) {
953+
lockflags = XFS_IOLOCK_SHARED;
954+
xfs_ilock(ip, lockflags);
955+
}
956+
ret = generic_fadvise(file, start, end, advice);
957+
if (lockflags)
958+
xfs_iunlock(ip, lockflags);
959+
return ret;
960+
}
936961

937962
STATIC loff_t
938963
xfs_file_remap_range(
@@ -1232,6 +1257,7 @@ const struct file_operations xfs_file_operations = {
12321257
.fsync = xfs_file_fsync,
12331258
.get_unmapped_area = thp_get_unmapped_area,
12341259
.fallocate = xfs_file_fallocate,
1260+
.fadvise = xfs_file_fadvise,
12351261
.remap_file_range = xfs_file_remap_range,
12361262
};
12371263

0 commit comments

Comments
 (0)