From 79decd88dd3f0d42e7fb0689b1a7853bfa302459 Mon Sep 17 00:00:00 2001 From: Hang Nan <2122295973@qq.com> Date: Mon, 17 Aug 2026 09:52:45 +0900 Subject: [PATCH] ksmbd: bound smb_check_perm_dacl() ACE walks by DACL size smb_check_perm_dacl() validates that the DACL fits inside the NT security descriptor, but then bounds its two ACE walks by the remaining NTSD length (acl_size) rather than the DACL's declared size (pdacl_size). When pdacl->size is smaller than the trailing NTSD buffer, bytes after the declared DACL boundary - still inside the stored security descriptor - are parsed as ACEs during access checks. A crafted DACL can place an access-granting ACE beyond pdacl->size, and the current code accepts it during SMB2_CREATE access validation, while parse_dacl() and smb_inherit_dacl() stop at pdacl_size. Bound both ACE walks by pdacl_size to match the DACL boundary semantics used elsewhere in the server. Validation: - semantic KUnit harness shows the post-boundary ACE is selected before the fix and rejected (EACCES) after it - linux master (7.2-rc6), x86_64 Fixes: 8f0541186e9a ("ksmbd: fix heap-based overflow in set_ntacl_dacl()") Signed-off-by: Hang Nan <2122295973@qq.com> Reviewed-by: ChenXiaoSong Signed-off-by: Namjae Jeon --- fs/smb/server/smbacl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c index b5db6dcfbaa4..8ad2e5a5cca8 100644 --- a/fs/smb/server/smbacl.c +++ b/fs/smb/server/smbacl.c @@ -1494,7 +1494,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, if (*pdaccess & FILE_MAXIMAL_ACCESS_LE) { ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); - aces_size = acl_size - sizeof(struct smb_acl); + aces_size = pdacl_size - sizeof(struct smb_acl); for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) { if (aces_size < offsetof(struct smb_ace, sid) + CIFS_SID_BASE_SIZE) @@ -1551,7 +1551,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, } ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); - aces_size = acl_size - sizeof(struct smb_acl); + aces_size = pdacl_size - sizeof(struct smb_acl); for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) { if (aces_size < offsetof(struct smb_ace, sid) + CIFS_SID_BASE_SIZE)