mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 20:53:03 +02:00
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: e2d12e22c5 ("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>
This commit is contained in:
parent
923690d809
commit
a44730dd05
10
mm/shmem.c
10
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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user