mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ksmbd: fix SMB2 CREATE response buffer overflow
smb2_allocate_rsp_buf() uses the MAX_CIFS_SMALL_BUFFER_SIZE (448-byte) buffer for a single SMB2_CREATE response. That buffer also holds a 4-byte length field, which only leaves 444 bytes for the SMB2 body. The AAPL response made this buffer too small. After8f1b796ff1, a request with AAPL response contexts may need at least 456 bytes. In the 456-byte case, create_aapl_rsp_buf() is appended last, clears 128 bytes, and writes 12 bytes past the allocation. KASAN reports: BUG: KASAN: slab-out-of-bounds in create_aapl_rsp_buf+0x31/0x6e0 Write of size 128 at addr ffff88800370954c by task kworker/0:0/9 ... create_aapl_rsp_buf+0x31/0x6e0 smb2_open+0x58f9/0xef10 ... smb2_allocate_rsp_buf+0x19d/0x370 ... The buggy address is located 332 bytes inside of allocated 448-byte region [ffff888003709400, ffff8880037095c0) Reserve enough space for any fixed CREATE response KSMBD can build. Store the required allocation size in the per-dialect values table. This keeps the small buffer for other commands and avoids using the max transaction buffer for every CREATE. Fixes:8f1b796ff1("ksmbd: add AAPL kAAPL_SERVER_QUERY create context support") Assisted-by: Codex:gpt-5 Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
00aee99cf5
commit
713c31a3a2
|
|
@ -40,6 +40,7 @@ struct smb_version_values {
|
|||
size_t create_disk_id_size;
|
||||
size_t create_posix_size;
|
||||
size_t create_aapl_size;
|
||||
size_t create_rsp_size;
|
||||
};
|
||||
|
||||
static inline unsigned int get_rfc1002_len(void *buf)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,35 @@
|
|||
#include "server.h"
|
||||
#include "stats.h"
|
||||
|
||||
/*
|
||||
* work->response_sz includes the RFC1002 length field while smb_get_msg()
|
||||
* skips over it. Durable v1 and v2 response contexts are mutually exclusive,
|
||||
* and POSIX CREATE contexts are only negotiated for SMB3.1.1.
|
||||
*/
|
||||
#define SMB2_CREATE_RSP_SIZE(lease_size, durable_size) \
|
||||
(sizeof(__be32) + offsetof(struct smb2_create_rsp, Buffer) + \
|
||||
(lease_size) + (durable_size) + \
|
||||
sizeof(struct create_mxac_rsp) + \
|
||||
sizeof(struct create_disk_id_rsp) + \
|
||||
AAPL_RSP_MAX_SIZE)
|
||||
|
||||
#define SMB21_CREATE_RSP_SIZE \
|
||||
SMB2_CREATE_RSP_SIZE(sizeof(struct create_lease), \
|
||||
sizeof(struct create_durable_rsp))
|
||||
|
||||
#define SMB3_CREATE_DURABLE_RSP_SIZE \
|
||||
((sizeof(struct create_durable_rsp) > \
|
||||
sizeof(struct create_durable_rsp_v2)) ? \
|
||||
sizeof(struct create_durable_rsp) : \
|
||||
sizeof(struct create_durable_rsp_v2))
|
||||
|
||||
#define SMB3_CREATE_RSP_SIZE \
|
||||
SMB2_CREATE_RSP_SIZE(sizeof(struct create_lease_v2), \
|
||||
SMB3_CREATE_DURABLE_RSP_SIZE)
|
||||
|
||||
#define SMB311_CREATE_RSP_SIZE \
|
||||
(SMB3_CREATE_RSP_SIZE + sizeof(struct create_posix_rsp))
|
||||
|
||||
static struct smb_version_values smb21_server_values = {
|
||||
.version_string = SMB21_VERSION_STRING,
|
||||
.protocol_id = SMB21_PROT_ID,
|
||||
|
|
@ -38,6 +67,7 @@ static struct smb_version_values smb21_server_values = {
|
|||
.create_disk_id_size = sizeof(struct create_disk_id_rsp),
|
||||
.create_posix_size = sizeof(struct create_posix_rsp),
|
||||
.create_aapl_size = AAPL_RSP_MAX_SIZE,
|
||||
.create_rsp_size = SMB21_CREATE_RSP_SIZE,
|
||||
};
|
||||
|
||||
static struct smb_version_values smb30_server_values = {
|
||||
|
|
@ -66,6 +96,7 @@ static struct smb_version_values smb30_server_values = {
|
|||
.create_disk_id_size = sizeof(struct create_disk_id_rsp),
|
||||
.create_posix_size = sizeof(struct create_posix_rsp),
|
||||
.create_aapl_size = AAPL_RSP_MAX_SIZE,
|
||||
.create_rsp_size = SMB3_CREATE_RSP_SIZE,
|
||||
};
|
||||
|
||||
static struct smb_version_values smb302_server_values = {
|
||||
|
|
@ -94,6 +125,7 @@ static struct smb_version_values smb302_server_values = {
|
|||
.create_disk_id_size = sizeof(struct create_disk_id_rsp),
|
||||
.create_posix_size = sizeof(struct create_posix_rsp),
|
||||
.create_aapl_size = AAPL_RSP_MAX_SIZE,
|
||||
.create_rsp_size = SMB3_CREATE_RSP_SIZE,
|
||||
};
|
||||
|
||||
static struct smb_version_values smb311_server_values = {
|
||||
|
|
@ -122,6 +154,7 @@ static struct smb_version_values smb311_server_values = {
|
|||
.create_disk_id_size = sizeof(struct create_disk_id_rsp),
|
||||
.create_posix_size = sizeof(struct create_posix_rsp),
|
||||
.create_aapl_size = AAPL_RSP_MAX_SIZE,
|
||||
.create_rsp_size = SMB311_CREATE_RSP_SIZE,
|
||||
};
|
||||
|
||||
static struct smb_version_ops smb2_0_server_ops = {
|
||||
|
|
|
|||
|
|
@ -855,14 +855,18 @@ static void smb2_update_lock_sequence(struct ksmbd_work *work,
|
|||
int smb2_allocate_rsp_buf(struct ksmbd_work *work)
|
||||
{
|
||||
struct smb2_hdr *hdr = smb_get_msg(work->request_buf);
|
||||
struct smb_version_values *vals = work->conn->vals;
|
||||
size_t small_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
|
||||
size_t large_sz = small_sz + work->conn->vals->max_trans_size;
|
||||
size_t large_sz = small_sz + vals->max_trans_size;
|
||||
size_t sz = small_sz;
|
||||
int cmd = le16_to_cpu(hdr->Command);
|
||||
|
||||
if (cmd == SMB2_IOCTL_HE || cmd == SMB2_QUERY_DIRECTORY_HE)
|
||||
sz = large_sz;
|
||||
|
||||
if (cmd == SMB2_CREATE_HE)
|
||||
sz = max_t(size_t, sz, vals->create_rsp_size);
|
||||
|
||||
if (cmd == SMB2_QUERY_INFO_HE) {
|
||||
struct smb2_query_info_req *req;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user