public inbox for linux-cifs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] ksmbd: harden IPC response arithmetic and ACE walk
@ 2026-04-14 19:15 Michael Bommarito
  2026-04-14 19:15 ` [PATCH 1/3] ksmbd: cap response sizes in ipc_validate_msg() Michael Bommarito
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Michael Bommarito @ 2026-04-14 19:15 UTC (permalink / raw)
  To: linux-cifs, Namjae Jeon, Steve French
  Cc: Sergey Senozhatsky, Tom Talpey, stable

Hi,

Three ksmbd patches: two hardening fixes for the kernel <-> mountd
IPC arithmetic, plus one authenticated OOB-read fix in the DACL
ACE walker.  All three reproduced under UML + KASAN on v7.0-rc7.
Patch 3 reproduces end-to-end over loopback SMB2 from a guest
client against UML ksmbd + ksmbd.mountd:

  pre-fix:
    BUG: KASAN: slab-out-of-bounds in compare_sids+0x2b1/0x440
     compare_sids
     smb_check_perm_dacl+0x4fe/0x11a0
     smb2_open+0x4eb2/0xad50
     handle_ksmbd_work+0x3d3/0x1140
    "The buggy address is located 4 bytes to the right of
    allocated 32-byte region" with the allocation trace pointing
    at ndr_decode_v4_ntacl() reading the stored xattr.
  post-fix:
    CREATE returns STATUS_ACCESS_DENIED; no KASAN splat; granted
    bits stay at 0 because the tightened bound rejects ace_size=4
    before compare_sids is called.

Patches 1 and 2 reproduced with in-kernel synthetic triggers that
hand ipc_validate_msg() a response with a wrap-matching size:

  patch 1 (RPC_REQUEST payload_sz):
    pre-fix  returns 0 (u32 wrap bypass)
    post-fix returns -EINVAL (payload_sz > KSMBD_IPC_MAX_PAYLOAD)

  patch 1 + 2 (LOGIN_REQUEST_EXT ngroups=-1):
    pre-fix  returns 0 (signed->size_t wrap matches msg_sz)
    post-fix returns -EINVAL (explicit ngroups<0 gate)

Same threat model as the earlier hardening commits aab98e2dbd64
("ksmbd: fix integer overflows on 32 bit systems") and 6f40e50ceb99
("ksmbd: transport_ipc: validate payload size before reading
handle"): the kernel should not trust arithmetic on attacker-
controlled fields even when those fields come from a cooperating
root daemon or an authenticated client writing an xattr.

Patch 1/3 caps the attacker-controlled fields in ipc_validate_msg()
against the existing KSMBD_IPC_MAX_PAYLOAD / NGROUPS_MAX bounds
before they feed the size-computation arithmetic.  Three cases:

  - KSMBD_EVENT_RPC_REQUEST: sizeof(struct) + resp->payload_sz
    (__u32) can wrap in unsigned int; downstream consumer at
    smb2pdu.c:6742 uses rpc_resp->payload_sz for a memcpy.  Cap
    payload_sz against KSMBD_IPC_MAX_PAYLOAD, matching the
    request-side cap in aab98e2dbd64.
  - KSMBD_EVENT_SHARE_CONFIG_REQUEST: sizeof(struct) +
    resp->payload_sz same class; same cap.
  - KSMBD_EVENT_LOGIN_REQUEST_EXT: resp->ngroups is __s32 signed,
    so the existing > NGROUPS_MAX comparison at user_config.c:59
    misses negative values, and the mul sizeof(gid_t) mixes signed
    and size_t in a surprising way.  Reject ngroups outside the
    signed [0, NGROUPS_MAX] range up front.

Patch 2/3 fixes user_config.c so ksmbd_alloc_user() also rejects
negative ngroups explicitly, independent of ipc_validate_msg.

Patch 3/3 tightens bounds checking in smb_check_perm_dacl()'s two
ACE-walk loops.  Today they only require the 4-byte ACE header to
fit in the remaining DACL buffer; an attacker-declared ace->size
of 4 passes both guards, after which the loop reads access_req
(offset 4) and ace->sid (offset 8+) past the real buffer.
parse_sec_desc() already performs an equivalent check; this patch
brings smb_check_perm_dacl() up to the same bar.

Practical exploitation of patches 1-2 is narrow: the wrap-bypass
requires ksmbd.mountd to send a response crafted around the wrapped
size while preserving consistent field values, and the downstream
kvmalloc almost always fails for u32-wrap sizes.  Patch 3 is
reachable post-auth by any client that can SET an ACL and then
OPEN the affected file.

The patch 3 exploit chain is authenticated but otherwise untrusted:
guest session -> TREE_CONNECT -> CREATE evil.dat -> SET_INFO with a
crafted security descriptor (one ACE with size=4) -> close -> re-open
the file, which triggers smb_check_perm_dacl() in smb2_open().  The
malformed SD is accepted by SET_INFO without validation on the write
side; parsing happens on the next open.

Instrumentation, triggers, client, and both console logs are
available on request.

Michael Bommarito (3):
  ksmbd: cap response sizes in ipc_validate_msg()
  ksmbd: reject negative ngroups in ksmbd_alloc_user()
  ksmbd: require minimum ACE size in smb_check_perm_dacl()

 fs/smb/server/mgmt/user_config.c |  2 +-
 fs/smb/server/smbacl.c           | 17 +++++++++++++----
 fs/smb/server/transport_ipc.c    | 42 +++++++++++++++++++++++++++++-----
 3 files changed, 49 insertions(+), 12 deletions(-)

--
2.53.0

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-04-16  0:07 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-14 19:15 [PATCH 0/3] ksmbd: harden IPC response arithmetic and ACE walk Michael Bommarito
2026-04-14 19:15 ` [PATCH 1/3] ksmbd: cap response sizes in ipc_validate_msg() Michael Bommarito
2026-04-15  2:00   ` Namjae Jeon
2026-04-15  2:35     ` Michael Bommarito
2026-04-15  4:22       ` Namjae Jeon
2026-04-14 19:15 ` [PATCH 2/3] ksmbd: reject negative ngroups in ksmbd_alloc_user() Michael Bommarito
2026-04-15  2:05   ` Namjae Jeon
2026-04-15  2:35     ` Michael Bommarito
2026-04-15  4:31       ` Namjae Jeon
2026-04-14 19:15 ` [PATCH 3/3] ksmbd: require minimum ACE size in smb_check_perm_dacl() Michael Bommarito
2026-04-15 11:24 ` [PATCH v2 0/2] ksmbd: harden ipc_validate_msg() and smb_check_perm_dacl() Michael Bommarito
2026-04-15 11:25   ` [PATCH v2 1/2] ksmbd: validate response sizes in ipc_validate_msg() Michael Bommarito
2026-04-15 11:25   ` [PATCH v2 2/2] ksmbd: require minimum ACE size in smb_check_perm_dacl() Michael Bommarito
2026-04-16  0:07   ` [PATCH v2 0/2] ksmbd: harden ipc_validate_msg() and smb_check_perm_dacl() Namjae Jeon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox