mirror of
https://github.com/torvalds/linux.git
synced 2026-09-11 20:13:02 +02:00
ksmbd: validate COPYCHUNK source and target ranges
ksmbd_vfs_copy_file_ranges() rejects negative source offsets in the
copy loop, but it does not validate target offsets. It also calculates
lock and overlap endpoints before ensuring that either range fits within
MAX_LFS_FILESIZE.
When the target is an alternate data stream, the buffered path passes a
negative target offset to ksmbd_vfs_stream_write(). Let n be Length and
let -d be TargetOffset, where 0 < d < n <= XATTR_SIZE_MAX. For an empty
stream, the writer allocates n - d bytes, then copies n bytes starting d
bytes before the allocation. An authenticated SMB client can control d
and the source data, overwrite kernel heap memory, and crash the host.
Validate both ranges before lock, overlap, or I/O calculations.
Fixes: 8482150a07 ("ksmbd: support copychunk for alternate data streams")
Assisted-by: Antiproof:GPT-5.6-Sol
Signed-off-by: Alon Shakevsky <shakevsky@berkeley.edu>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
0e75389962
commit
0480cee8cc
|
|
@ -2007,6 +2007,11 @@ static ssize_t ksmbd_vfs_copy_file_range_buffered(struct ksmbd_work *work,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool ksmbd_vfs_copy_range_valid(loff_t offset, size_t len)
|
||||
{
|
||||
return offset >= 0 && (loff_t)len <= MAX_LFS_FILESIZE - offset;
|
||||
}
|
||||
|
||||
int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
|
||||
struct ksmbd_file *src_fp,
|
||||
struct ksmbd_file *dst_fp,
|
||||
|
|
@ -2042,6 +2047,10 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
|
|||
dst_off = le64_to_cpu(chunks[i].TargetOffset);
|
||||
len = le32_to_cpu(chunks[i].Length);
|
||||
|
||||
if (!ksmbd_vfs_copy_range_valid(src_off, len) ||
|
||||
!ksmbd_vfs_copy_range_valid(dst_off, len))
|
||||
return -E2BIG;
|
||||
|
||||
if (check_lock_range(src_fp->filp, src_off,
|
||||
src_off + len - 1, READ))
|
||||
return -EAGAIN;
|
||||
|
|
@ -2134,7 +2143,8 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
|
|||
len = le32_to_cpu(chunks[i].Length);
|
||||
copy_len = len;
|
||||
|
||||
if (src_off < 0)
|
||||
if (!ksmbd_vfs_copy_range_valid(src_off, len) ||
|
||||
!ksmbd_vfs_copy_range_valid(dst_off, len))
|
||||
return -E2BIG;
|
||||
|
||||
if (src_off > src_file_size || len > src_file_size - src_off) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user