From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> mainline inclusion from mainline-v7.1-rc1 commit 53370cf9090777774e07fd9a8ebce67c6cc333ab category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14354 CVE: CVE-2026-31611 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- ksmbd: require 3 sub-authorities before reading sub_auth[2] parse_dacl() compares each ACE SID against sid_unix_NFS_mode and on match reads sid.sub_auth[2] as the file mode. If sid_unix_NFS_mode is the prefix S-1-5-88-3 with num_subauth = 2 then compare_sids() compares only min(num_subauth, 2) sub-authorities so a client SID with num_subauth = 2 and sub_auth = {88, 3} will match. If num_subauth = 2 and the ACE is placed at the very end of the security descriptor, sub_auth[2] will be 4 bytes past end_of_acl. The out-of-band bytes will then be masked to the low 9 bits and applied as the file's POSIX mode, probably not something that is good to have happen. Fix this up by forcing the SID to actually carry a third sub-authority before reading it at all. Cc: Namjae Jeon <linkinjeon@kernel.org> Cc: Steve French <smfrench@gmail.com> Cc: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: Tom Talpey <tom@talpey.com> Cc: linux-cifs@vger.kernel.org Cc: <stable@kernel.org> Assisted-by: gregkh_clanker_t1000 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> Conflicts: fs/smb/server/smbacl.c fs/ksmbd/smbacl.c [File Path Difference] Signed-off-by: Li Lingfeng <lilingfeng3@huawei.com> --- fs/ksmbd/smbacl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c index 3368a4e73773..859b88f0de88 100644 --- a/fs/ksmbd/smbacl.c +++ b/fs/ksmbd/smbacl.c @@ -439,7 +439,8 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, ppace[i]->access_req = smb_map_generic_desired_access(ppace[i]->access_req); - if (!(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) { + if (ppace[i]->sid.num_subauth >= 3 && + !(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) { fattr->cf_mode = le32_to_cpu(ppace[i]->sid.sub_auth[2]); break; -- 2.52.0