FAILED: patch "[PATCH] ksmbd: validate security descriptor offsets before pointer" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 3474e1a304fbf9f7c996b24adcd519e031227a90
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026110319-apple-willow-5e9e@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 3474e1a304fbf9f7c996b24adcd519e031227a90 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <[email protected]>
Date: Sat, 17 Oct 2026 09:44:48 +0900
Subject: [PATCH] ksmbd: validate security descriptor offsets before pointer
arithmetic
parse_sec_desc() constructs SID and DACL pointers by adding untrusted 32-bit offsets to the security descriptor before checking their bounds. The existing checks reject offsets into the descriptor header, but do not reject offsets beyond the descriptor's length.
On a 32-bit kernel, a large offset can wrap the pointer before the descriptor. The end-only checks in parse_sid() and parse_dacl() can then accept it, allowing an authenticated SMB2 SET_INFO request to access memory outside the security descriptor and fault the kernel.
Check each nonzero offset against acl_len before constructing its pointer. Initialize the optional owner and group SID pointers to NULL so an omitted SID remains absent when parsing the DACL.
fs/smb/server/smbacl.c +11 -9
@@ -900,7 +900,7 @@ int parse_sec_desc(const struct mnt_idmap *idmap, struct smb_ntsd *pntsd, int acl_len, struct smb_fattr *fattr) { int rc = 0; -struct smb_sid *owner_sid_ptr, *group_sid_ptr; +struct smb_sid *owner_sid_ptr =NULL , *group_sid_ptr =NULL ;struct smb_acl *dacl_ptr;/* no need for SACL ptr */ char *end_of_acl = ((char *)pntsd) + acl_len;__u32 dacloffset;
@@ -912,12 +912,7 @@ int parse_sec_desc(const struct mnt_idmap *idmap, struct smb_ntsd *pntsd,if (acl_len <sizeof (struct smb_ntsd ))return -EINVAL ; - owner_sid_ptr = (struct smb_sid *)((char *)pntsd + -le32_to_cpu (pntsd->osidoffset)); - group_sid_ptr = (struct smb_sid *)((char *)pntsd + -le32_to_cpu (pntsd->gsidoffset)); dacloffset =le32_to_cpu (pntsd->dacloffset); - dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); ksmbd_debug(SMB, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n", pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
@@ -933,9 +928,12 @@ int parse_sec_desc(const struct mnt_idmap *idmap, struct smb_ntsd *pntsd, pntsd->type =cpu_to_le16 (DACL_PRESENT );if (pntsd->osidoffset) { -if (le32_to_cpu (pntsd->osidoffset) <sizeof (struct smb_ntsd )) +if (le32_to_cpu (pntsd->osidoffset) <sizeof (struct smb_ntsd ) || +le32_to_cpu (pntsd->osidoffset) >= acl_len)return -EINVAL ; + owner_sid_ptr = (struct smb_sid *)((char *)pntsd + +le32_to_cpu (pntsd->osidoffset)); rc =parse_sid (owner_sid_ptr, end_of_acl);if (rc) {pr_err ("%s: Error %d parsing Owner SID\n" , __func__, rc);
@@ -951,9 +949,12 @@ int parse_sec_desc(const struct mnt_idmap *idmap, struct smb_ntsd *pntsd, }if (pntsd->gsidoffset) { -if (le32_to_cpu (pntsd->gsidoffset) <sizeof (struct smb_ntsd )) +if (le32_to_cpu (pntsd->gsidoffset) <sizeof (struct smb_ntsd ) || +le32_to_cpu (pntsd->gsidoffset) >= acl_len)return -EINVAL ; + group_sid_ptr = (struct smb_sid *)((char *)pntsd + +le32_to_cpu (pntsd->gsidoffset)); rc =parse_sid (group_sid_ptr, end_of_acl);if (rc) { pr_err("%s: Error %d mapping Owner SID to gid\n",
@@ -975,9 +976,10 @@ int parse_sec_desc(const struct mnt_idmap *idmap, struct smb_ntsd *pntsd, pntsd->type |=cpu_to_le16 (DACL_PROTECTED );if (dacloffset) { -if (dacloffset <sizeof (struct smb_ntsd )) +if (dacloffset <sizeof (struct smb_ntsd ) || dacloffset >= acl_len)return -EINVAL ; + dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); rc =parse_dacl (idmap, dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, fattr);if (rc)
Re: Backport:FAILED: patch "[PATCH] ksmbd: validate security descriptor offsets before pointer" failed to apply to 5.15-stable tree
From: Namjae Jeon <[email protected]>
[ Upstream commit 3474e1a304fbf9f7c996b24adcd519e031227a90 ]
parse_sec_desc() constructs SID and DACL pointers by adding untrusted 32-bit offsets to the security descriptor before checking their bounds. The existing checks reject offsets into the descriptor header, but do not reject offsets beyond the descriptor's length.
On a 32-bit kernel, a large offset can wrap the pointer before the descriptor. The end-only checks in parse_sid() and parse_dacl() can then accept it, allowing an authenticated SMB2 SET_INFO request to access memory outside the security descriptor and fault the kernel.
Check each nonzero offset against acl_len before constructing its pointer. Initialize the optional owner and group SID pointers to NULL so an omitted SID remains absent when parsing the DACL.
The 5.15 tree keeps this code in fs/ksmbd/smbacl.c and uses a void parse_dacl(). Preserve those interfaces in this backport.
--- fs/ksmbd/smbacl.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
fs/ksmbd/smbacl.c +17 -6
@@ -830,7 +830,7 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, int acl_len, struct smb_fattr *fattr) { int rc = 0; -struct smb_sid *owner_sid_ptr, *group_sid_ptr; +struct smb_sid *owner_sid_ptr =NULL , *group_sid_ptr =NULL ;struct smb_acl *dacl_ptr;/* no need for SACL ptr */ char *end_of_acl = ((char *)pntsd) + acl_len;__u32 dacloffset;
@@ -842,12 +842,7 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,if (acl_len <sizeof (struct smb_ntsd ))return -EINVAL ; - owner_sid_ptr = (struct smb_sid *)((char *)pntsd + -le32_to_cpu (pntsd->osidoffset)); - group_sid_ptr = (struct smb_sid *)((char *)pntsd + -le32_to_cpu (pntsd->gsidoffset)); dacloffset =le32_to_cpu (pntsd->dacloffset); - dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); ksmbd_debug(SMB, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n", pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
@@ -863,6 +858,12 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, pntsd->type =cpu_to_le16 (DACL_PRESENT );if (pntsd->osidoffset) { +if (le32_to_cpu (pntsd->osidoffset) <sizeof (struct smb_ntsd ) || +le32_to_cpu (pntsd->osidoffset) >= acl_len) +return -EINVAL ; + + owner_sid_ptr = (struct smb_sid *)((char *)pntsd + +le32_to_cpu (pntsd->osidoffset)); rc =parse_sid (owner_sid_ptr, end_of_acl);if (rc) {pr_err ("%s: Error %d parsing Owner SID\n" , __func__, rc);
@@ -878,6 +879,12 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, }if (pntsd->gsidoffset) { +if (le32_to_cpu (pntsd->gsidoffset) <sizeof (struct smb_ntsd ) || +le32_to_cpu (pntsd->gsidoffset) >= acl_len) +return -EINVAL ; + + group_sid_ptr = (struct smb_sid *)((char *)pntsd + +le32_to_cpu (pntsd->gsidoffset)); rc =parse_sid (group_sid_ptr, end_of_acl);if (rc) { pr_err("%s: Error %d mapping Owner SID to gid\n",
@@ -899,6 +906,10 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, pntsd->type |=cpu_to_le16 (DACL_PROTECTED );if (dacloffset) { +if (dacloffset <sizeof (struct smb_ntsd ) || dacloffset >= acl_len) +return -EINVAL ; + + dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);parse_dacl (user_ns, dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, fattr); }
--
2.43.0
Re: Fixed Backport:FAILED: patch "[PATCH] ksmbd: validate security descriptor offsets before pointer" failed to apply to 5.15-stable tree
From: Namjae Jeon <[email protected]>
[ Upstream commit 3474e1a304fbf9f7c996b24adcd519e031227a90 ]
parse_sec_desc() constructs SID and DACL pointers by adding untrusted 32-bit offsets to the security descriptor before checking their bounds. The existing checks reject offsets into the descriptor header, but do not reject offsets beyond the descriptor's length.
On a 32-bit kernel, a large offset can wrap the pointer before the descriptor. The end-only checks in parse_sid() and parse_dacl() can then accept it, allowing an authenticated SMB2 SET_INFO request to access memory outside the security descriptor and fault the kernel.
Check each nonzero offset against acl_len before constructing its pointer. Initialize the optional owner and group SID pointers to NULL so an omitted SID remains absent when parsing the DACL.
The 5.15 tree keeps this code in fs/ksmbd/smbacl.c and uses a void parse_dacl(). Preserve those interfaces in this backport.
---
My earlier reply in this thread had its tabs expanded by Outlook. Please disregard that copy.
fs/ksmbd/smbacl.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
fs/ksmbd/smbacl.c +17 -6
@@ -830,7 +830,7 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, int acl_len, struct smb_fattr *fattr) { int rc = 0; -struct smb_sid *owner_sid_ptr, *group_sid_ptr; +struct smb_sid *owner_sid_ptr =NULL , *group_sid_ptr =NULL ;struct smb_acl *dacl_ptr;/* no need for SACL ptr */ char *end_of_acl = ((char *)pntsd) + acl_len;__u32 dacloffset;
@@ -842,12 +842,7 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,if (acl_len <sizeof (struct smb_ntsd ))return -EINVAL ; - owner_sid_ptr = (struct smb_sid *)((char *)pntsd + -le32_to_cpu (pntsd->osidoffset)); - group_sid_ptr = (struct smb_sid *)((char *)pntsd + -le32_to_cpu (pntsd->gsidoffset)); dacloffset =le32_to_cpu (pntsd->dacloffset); - dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); ksmbd_debug(SMB, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n", pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
@@ -863,6 +858,12 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, pntsd->type =cpu_to_le16 (DACL_PRESENT );if (pntsd->osidoffset) { +if (le32_to_cpu (pntsd->osidoffset) <sizeof (struct smb_ntsd ) || +le32_to_cpu (pntsd->osidoffset) >= acl_len) +return -EINVAL ; + + owner_sid_ptr = (struct smb_sid *)((char *)pntsd + +le32_to_cpu (pntsd->osidoffset)); rc =parse_sid (owner_sid_ptr, end_of_acl);if (rc) {pr_err ("%s: Error %d parsing Owner SID\n" , __func__, rc);
@@ -878,6 +879,12 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, }if (pntsd->gsidoffset) { +if (le32_to_cpu (pntsd->gsidoffset) <sizeof (struct smb_ntsd ) || +le32_to_cpu (pntsd->gsidoffset) >= acl_len) +return -EINVAL ; + + group_sid_ptr = (struct smb_sid *)((char *)pntsd + +le32_to_cpu (pntsd->gsidoffset)); rc =parse_sid (group_sid_ptr, end_of_acl);if (rc) { pr_err("%s: Error %d mapping Owner SID to gid\n",
@@ -899,6 +906,10 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, pntsd->type |=cpu_to_le16 (DACL_PROTECTED );if (dacloffset) { +if (dacloffset <sizeof (struct smb_ntsd ) || dacloffset >= acl_len) +return -EINVAL ; + + dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);parse_dacl (user_ns, dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, fattr); }
Signature · 1 line
2.43.0