[PATCH] ksmbd: validate COPYCHUNK source and target ranges

Alon Shakevsky via B4 Relay posted 1 patch 3 weeks, 4 days ago
fs/smb/server/vfs.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
[PATCH] ksmbd: validate COPYCHUNK source and target ranges
Posted by Alon Shakevsky via B4 Relay 3 weeks, 4 days ago
From: Alon Shakevsky <shakevsky@berkeley.edu>

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: 8482150a0743 ("ksmbd: support copychunk for alternate data streams")
Assisted-by: Antiproof:GPT-5.6-Sol
Signed-off-by: Alon Shakevsky <shakevsky@berkeley.edu>
---
 fs/smb/server/vfs.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
index 35123550a5535..3a6f3139c6f52 100644
--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -2009,6 +2009,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,
@@ -2044,6 +2049,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;
@@ -2136,7 +2145,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) {

---
base-commit: e53a23f960a10bf85ed2c9dbe0c1fc7d09c077ae
change-id: 20260901-review-ksmbd-copychunk-offsets-v2-062681dd948e

Best regards,
--  
Alon Shakevsky <shakevsky@berkeley.edu>
Re: [PATCH] ksmbd: validate COPYCHUNK source and target ranges
Posted by Namjae Jeon 3 weeks, 3 days ago
On Tue, Sep 1, 2026 at 9:05 AM Alon Shakevsky via B4 Relay
<devnull+shakevsky.berkeley.edu@kernel.org> wrote:
>
> From: Alon Shakevsky <shakevsky@berkeley.edu>
>
> 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: 8482150a0743 ("ksmbd: support copychunk for alternate data streams")
> Assisted-by: Antiproof:GPT-5.6-Sol
> Signed-off-by: Alon Shakevsky <shakevsky@berkeley.edu>
Applied it to #ksmbd-for-next.
Thanks!