summaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
authorZhiling Zou <zhilinz@nebusec.ai>2026-07-31 11:22:51 +0800
committerAndrew Morton <akpm@linux-foundation.org>2026-08-20 18:24:36 -0700
commit4d231496273a765b081c2f41dd151f430bba14da (patch)
treec76cc1ff74fe7e98dd00ae9840fe97a40a43077f /mm
parent96c3ebe2ae09b9a0bc7446980f3bacbdbf63a940 (diff)
downloadlinux-next-4d231496273a765b081c2f41dd151f430bba14da.tar.gz
linux-next-4d231496273a765b081c2f41dd151f430bba14da.zip
mm: shmem: reject page-aligned fallocate end overflow
shmem_fallocate() validates offset + len with inode_newsize_ok(), but then rounds that end offset up to a page boundary before entering the preallocation loop. For a valid request ending at MAX_LFS_FILESIZE, such as offset = 0 and len = LLONG_MAX, adding PAGE_SIZE - 1 to the validated end can overflow the signed loff_t used for the rounded end calculation. If that wrapped value is then converted into a page index, shmem_fallocate() can enter the folio allocation loop with an invalid range. Use check_add_overflow() when calculating the page-aligned end, and fail before entering the allocation loop if the rounded end cannot be represented. Link: https://lore.kernel.org/1929a466735dcbb9438936ff50b7a4fc2332a8a4.1785377919.git.zhilinz@nebusec.ai Fixes: e2d12e22c59c ("tmpfs: support fallocate preallocation") Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai> Reported-by: Vega <vega@nebusec.ai> Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/shmem.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index 774f4b18ff5c..8ea776e52823 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3617,6 +3617,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
struct shmem_inode_info *info = SHMEM_I(inode);
struct shmem_falloc shmem_falloc;
pgoff_t start, index, end, undo_fallocend;
+ loff_t aligned_end;
int error;
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
@@ -3673,8 +3674,15 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
goto out;
}
+ /* Check for wraparound */
+ if (check_add_overflow(offset + len, (loff_t)PAGE_SIZE - 1,
+ &aligned_end)) {
+ error = -EFBIG;
+ goto out;
+ }
+
start = offset >> PAGE_SHIFT;
- end = (offset + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ end = aligned_end >> PAGE_SHIFT;
/* Try to avoid a swapstorm if len is impossible to satisfy */
if (sbinfo->max_blocks && end - start > sbinfo->max_blocks) {
error = -ENOSPC;