Skip to content

Commit d6a6aa8

Browse files
mjbommarsmfrench
authored andcommitted
ksmbd: validate response sizes in ipc_validate_msg()
ipc_validate_msg() computes the expected message size for each response type by adding (or multiplying) attacker-controlled fields from the daemon response to a fixed struct size in unsigned int arithmetic. Three cases can overflow: KSMBD_EVENT_RPC_REQUEST: msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz; KSMBD_EVENT_SHARE_CONFIG_REQUEST: msg_sz = sizeof(struct ksmbd_share_config_response) + resp->payload_sz; KSMBD_EVENT_LOGIN_REQUEST_EXT: msg_sz = sizeof(struct ksmbd_login_response_ext) + resp->ngroups * sizeof(gid_t); resp->payload_sz is __u32 and resp->ngroups is __s32. Each addition can wrap in unsigned int; the multiplication by sizeof(gid_t) mixes signed and size_t, so a negative ngroups is converted to SIZE_MAX before the multiply. A wrapped value of msg_sz that happens to equal entry->msg_sz bypasses the size check on the next line, and downstream consumers (smb2pdu.c:6742 memcpy using rpc_resp->payload_sz, kmemdup in ksmbd_alloc_user using resp_ext->ngroups) then trust the unverified length. Use check_add_overflow() on the RPC_REQUEST and SHARE_CONFIG_REQUEST paths to detect integer overflow without constraining functional payload size; userspace ksmbd-tools grows NDR responses in 4096-byte chunks for calls like NetShareEnumAll, so a hard transport cap is unworkable on the response side. For LOGIN_REQUEST_EXT, reject resp->ngroups outside the signed [0, NGROUPS_MAX] range up front and report the error from ipc_validate_msg() so it fires at the IPC boundary; with that bound the subsequent multiplication and addition stay well below UINT_MAX. The now-redundant ngroups check and pr_err in ksmbd_alloc_user() are removed. This is the response-side analogue of aab98e2 ("ksmbd: fix integer overflows on 32 bit systems"), which hardened the request side. Fixes: 0626e66 ("cifsd: add server handler for central processing and tranport layers") Fixes: a77e0e0 ("ksmbd: add support for supplementary groups") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-6 Assisted-by: Codex:gpt-5-4 Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 6551300 commit d6a6aa8

2 files changed

Lines changed: 13 additions & 9 deletions

File tree

fs/smb/server/mgmt/user_config.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,6 @@ struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp,
5656
goto err_free;
5757

5858
if (resp_ext) {
59-
if (resp_ext->ngroups > NGROUPS_MAX) {
60-
pr_err("ngroups(%u) from login response exceeds max groups(%d)\n",
61-
resp_ext->ngroups, NGROUPS_MAX);
62-
goto err_free;
63-
}
64-
6559
user->sgid = kmemdup(resp_ext->____payload,
6660
resp_ext->ngroups * sizeof(gid_t),
6761
KSMBD_DEFAULT_GFP);

fs/smb/server/transport_ipc.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <net/genetlink.h>
1414
#include <linux/socket.h>
1515
#include <linux/workqueue.h>
16+
#include <linux/overflow.h>
1617

1718
#include "vfs_cache.h"
1819
#include "transport_ipc.h"
@@ -496,7 +497,9 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
496497
{
497498
struct ksmbd_rpc_command *resp = entry->response;
498499

499-
msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;
500+
if (check_add_overflow(sizeof(struct ksmbd_rpc_command),
501+
resp->payload_sz, &msg_sz))
502+
return -EINVAL;
500503
break;
501504
}
502505
case KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST:
@@ -515,8 +518,9 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
515518
if (resp->payload_sz < resp->veto_list_sz)
516519
return -EINVAL;
517520

518-
msg_sz = sizeof(struct ksmbd_share_config_response) +
519-
resp->payload_sz;
521+
if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
522+
resp->payload_sz, &msg_sz))
523+
return -EINVAL;
520524
}
521525
break;
522526
}
@@ -525,6 +529,12 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
525529
struct ksmbd_login_response_ext *resp = entry->response;
526530

527531
if (resp->ngroups) {
532+
if (resp->ngroups < 0 ||
533+
resp->ngroups > NGROUPS_MAX) {
534+
pr_err("ngroups(%d) from login response exceeds max groups(%d)\n",
535+
resp->ngroups, NGROUPS_MAX);
536+
return -EINVAL;
537+
}
528538
msg_sz = sizeof(struct ksmbd_login_response_ext) +
529539
resp->ngroups * sizeof(gid_t);
530540
}

0 commit comments

Comments
 (0)