mirror of
https://github.com/torvalds/linux.git
synced 2026-10-10 04:18:03 +02:00
ksmbd: validate SMB2 write offsets
An SMB2 WRITE request with a negative offset returns -EINVAL directly from smb2_write(). This bypasses the common error response path, leaving the client waiting until the request times out. ksmbd also allows nonempty writes at or beyond MAXFILESIZE as defined by [MS-FSA]. Writes beyond the limit must fail with STATUS_INVALID_PARAMETER. Writes ending at the limit fail with STATUS_DISK_FULL, while a zero-length write remains valid. Route negative offsets through the common error path and validate the end offset of nonempty writes against MAXFILESIZE. This fixes smb2.rw.invalid. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
7019a11f79
commit
df35438ba9
|
|
@ -64,6 +64,9 @@ static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
|
|||
/* Windows reports automatic write-time updates at roughly 15 ms resolution. */
|
||||
#define KSMBD_WRITE_TIME_RESOLUTION (15ULL * 10000)
|
||||
|
||||
/* MAXFILESIZE in [MS-FSA] 2.1.5.3 Server Requests a Write. */
|
||||
#define SMB2_MAX_FILE_SIZE 0xfffffff0000ULL
|
||||
|
||||
/**
|
||||
* check_session_id() - check for valid session id in smb header
|
||||
* @conn: connection instance
|
||||
|
|
@ -7685,8 +7688,10 @@ int smb2_write(struct ksmbd_work *work)
|
|||
}
|
||||
|
||||
offset = le64_to_cpu(req->Offset);
|
||||
if (offset < 0)
|
||||
return -EINVAL;
|
||||
if (offset < 0) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
length = le32_to_cpu(req->Length);
|
||||
|
||||
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
|
||||
|
|
@ -7700,6 +7705,19 @@ int smb2_write(struct ksmbd_work *work)
|
|||
length = le32_to_cpu(req->RemainingBytes);
|
||||
}
|
||||
|
||||
if (length) {
|
||||
u64 end = (u64)offset + length;
|
||||
|
||||
if (end > SMB2_MAX_FILE_SIZE) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (end == SMB2_MAX_FILE_SIZE) {
|
||||
err = -EFBIG;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_rdma_channel == true) {
|
||||
unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user