* FAILED: patch "[PATCH] ksmbd: restore DACL size on check_add_overflow() to avoid" failed to apply to 6.1-stable tree
@ 2026-07-29 13:55 gregkh
2026-08-08 17:14 ` [PATCH 6.1.y 1/3] ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow Sasha Levin
0 siblings, 1 reply; 4+ messages in thread
From: gregkh @ 2026-07-29 13:55 UTC (permalink / raw)
To: guanwentao, linkinjeon, stfrench; +Cc: stable
The patch below does not apply to the 6.1-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 <stable@vger.kernel.org>.
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-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x bbf0a8e931204ecdab494a88d43b0a24a04285c5
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026072937-broadcast-renewal-0307@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From bbf0a8e931204ecdab494a88d43b0a24a04285c5 Mon Sep 17 00:00:00 2001
From: Wentao Guan <guanwentao@uniontech.com>
Date: Fri, 3 Jul 2026 11:22:09 +0900
Subject: [PATCH] ksmbd: restore DACL size on check_add_overflow() to avoid
malformed ACL
check_add_overflow() unconditionally writes the truncated sum into *d
even on overflow, per its contract in include/linux/overflow.h.
The four check_add_overflow() guards in set_posix_acl_entries_dacl()
and set_ntacl_dacl() break out of the ACE-building loops on overflow,
but the truncated *size is then consumed downstream at the end of
set_ntacl_dacl():
pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
This produces an on-wire NT ACL whose pndacl->size under-reports the
bytes actually written by the preceding fill_ace_for_sid()/memcpy()
calls, yielding a malformed ACL that can trigger out-of-bounds reads
when re-parsed by clients or ksmbd itself.
Restore *size to its pre-addition value on each overflow branch (via
`*size -= ace_sz` / `size -= nt_ace_size`) so that after the break,
*size once again holds the cumulative size of the successfully-written
ACEs. The committed ACL is then truncated-but-self-consistent rather
than malformed.
The ksmbd DACL builders are the only check_add_overflow() sites found
where an overflow path breaks out of a loop and the destination value
is consumed afterward. The other nearby break-style cases either
return -EINVAL on overflow (transport_ipc.c) or break without
consuming the overflowed destination value afterward (buildid.c).
Fixes: 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16 DACL size overflow")
Assisted-by: atomcode:glm-5.2
Assisted-by: Codex:gpt-5.5
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index d28289188e44..f285b4f24a5b 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -663,6 +663,7 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -677,6 +678,7 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
0x03, pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -722,6 +724,7 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -765,8 +768,10 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
goto next_ace;
memcpy((char *)pndace + size, ntace, nt_ace_size);
- if (check_add_overflow(size, nt_ace_size, &size))
+ if (check_add_overflow(size, nt_ace_size, &size)) {
+ size -= nt_ace_size;
break;
+ }
num_aces++;
next_ace:
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 6.1.y 1/3] ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow
2026-07-29 13:55 FAILED: patch "[PATCH] ksmbd: restore DACL size on check_add_overflow() to avoid" failed to apply to 6.1-stable tree gregkh
@ 2026-08-08 17:14 ` Sasha Levin
2026-08-08 17:14 ` [PATCH 6.1.y 2/3] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl Sasha Levin
2026-08-08 17:14 ` [PATCH 6.1.y 3/3] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL Sasha Levin
0 siblings, 2 replies; 4+ messages in thread
From: Sasha Levin @ 2026-08-08 17:14 UTC (permalink / raw)
To: stable; +Cc: Ferry Meng, Namjae Jeon, Steve French, Sasha Levin
From: Ferry Meng <mengferry@linux.alibaba.com>
[ Upstream commit af92ee994cc7f7e83a41c2025f32257a2f82a7ef ]
Commit 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16
DACL size overflow") added check_add_overflow() guards that break out
of the ACE-building loops in set_posix_acl_entries_dacl() when the
accumulated DACL size would wrap past 65535.
However, each iteration allocates a struct smb_sid via kmalloc_obj()
at the top of the loop and relies on the kfree(sid) call at the end
of the loop body (the 'pass_same_sid' label in the first loop, and
the explicit kfree at the tail of the second loop) to release it.
The newly introduced 'break' statements bypass those kfree() calls,
leaking the sid buffer every time an overflow is detected.
A malicious or malformed file with enough POSIX ACL entries to trip
the overflow check will leak one or more struct smb_sid allocations
on every request that touches the file's DACL, providing a trivial
kernel memory exhaustion vector.
Free sid before breaking out of the loops to plug the leak.
Fixes: 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16 DACL size overflow")
Cc: stable@vger.kernel.org
Signed-off-by: Ferry Meng <mengferry@linux.alibaba.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: bbf0a8e93120 ("ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/smbacl.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index 47c6b509cf21d..3a250ddb1a2a9 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -643,8 +643,10 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
ntace = (struct smb_ace *)((char *)pndace + *size);
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
pace->e_perm, 0777);
- if (check_add_overflow(*size, ace_sz, size))
+ if (check_add_overflow(*size, ace_sz, size)) {
+ kfree(sid);
break;
+ }
(*num_aces)++;
if (pace->e_tag == ACL_USER)
ntace->access_req |=
@@ -655,8 +657,10 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
ntace = (struct smb_ace *)((char *)pndace + *size);
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
0x03, pace->e_perm, 0777);
- if (check_add_overflow(*size, ace_sz, size))
+ if (check_add_overflow(*size, ace_sz, size)) {
+ kfree(sid);
break;
+ }
(*num_aces)++;
if (pace->e_tag == ACL_USER)
ntace->access_req |=
@@ -698,8 +702,10 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
ntace = (struct smb_ace *)((char *)pndace + *size);
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
pace->e_perm, 0777);
- if (check_add_overflow(*size, ace_sz, size))
+ if (check_add_overflow(*size, ace_sz, size)) {
+ kfree(sid);
break;
+ }
(*num_aces)++;
if (pace->e_tag == ACL_USER)
ntace->access_req |=
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 6.1.y 2/3] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl
2026-08-08 17:14 ` [PATCH 6.1.y 1/3] ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow Sasha Levin
@ 2026-08-08 17:14 ` Sasha Levin
2026-08-08 17:14 ` [PATCH 6.1.y 3/3] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-08-08 17:14 UTC (permalink / raw)
To: stable; +Cc: Haofeng Li, ChenXiaoSong, Namjae Jeon, Steve French, Sasha Levin
From: Haofeng Li <lihaofeng@kylinos.cn>
[ Upstream commit 47f0b34f6bc98ed85bfdc293e8f3e432ec24958d ]
set_ntacl_dacl() copies each ACE from the attacker-controlled stored
security descriptor verbatim into the response DACL without checking
sid.num_subauth. The ACE bytes (including an unchecked num_subauth)
originate from an authenticated SMB2_SET_INFO(SecInfo=DACL) that is
stored raw via ksmbd_vfs_set_sd_xattr(); parse_dacl() rejects a bad ACE
with `break` rather than an error, so parse_sec_desc() still returns
success and the malformed SD reaches the xattr intact.
On a subsequent SMB2_QUERY_INFO(SecInfo=DACL) for an inode carrying a
POSIX access ACL, build_sec_desc() -> set_ntacl_dacl() ->
set_posix_acl_entries_dacl() walks the copied ACEs and reads
ntace->sid.sub_auth[ntace->sid.num_subauth - 1]
with num_subauth taken straight from the stored SD. Since sub_auth[]
is fixed at SID_MAX_SUB_AUTHORITIES (15), a crafted num_subauth (e.g.
255) drives an out-of-bounds heap read of ~1 KB with an offset fully
controlled by an authenticated client.
The sibling functions already gate this field:
parse_dacl() -- num_subauth == 0 || > SID_MAX_SUB_AUTHORITIES
parse_sid() -- num_subauth > SID_MAX_SUB_AUTHORITIES
smb_copy_sid() -- min_t(u8, num_subauth, SID_MAX_SUB_AUTHORITIES)
set_ntacl_dacl() is the lone inconsistent path that omits the check.
Add the same num_subauth validation in set_ntacl_dacl() before copying
the ACE, matching the gate already enforced by parse_dacl().
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Suggested-by: Namjae Jeon <linkinjeon@kernel.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: bbf0a8e93120 ("ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/smbacl.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index 3a250ddb1a2a9..45c9b980418e8 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -740,12 +740,18 @@ static void set_ntacl_dacl(struct user_namespace *user_ns,
if (nt_ace_size > aces_size)
break;
+ if (ntace->sid.num_subauth == 0 ||
+ ntace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES)
+ goto next_ace;
+
memcpy((char *)pndace + size, ntace, nt_ace_size);
if (check_add_overflow(size, nt_ace_size, &size))
break;
+ num_aces++;
+
+next_ace:
aces_size -= nt_ace_size;
ntace = (struct smb_ace *)((char *)ntace + nt_ace_size);
- num_aces++;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 6.1.y 3/3] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL
2026-08-08 17:14 ` [PATCH 6.1.y 1/3] ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow Sasha Levin
2026-08-08 17:14 ` [PATCH 6.1.y 2/3] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl Sasha Levin
@ 2026-08-08 17:14 ` Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-08-08 17:14 UTC (permalink / raw)
To: stable; +Cc: Wentao Guan, Namjae Jeon, Steve French, Sasha Levin
From: Wentao Guan <guanwentao@uniontech.com>
[ Upstream commit bbf0a8e931204ecdab494a88d43b0a24a04285c5 ]
check_add_overflow() unconditionally writes the truncated sum into *d
even on overflow, per its contract in include/linux/overflow.h.
The four check_add_overflow() guards in set_posix_acl_entries_dacl()
and set_ntacl_dacl() break out of the ACE-building loops on overflow,
but the truncated *size is then consumed downstream at the end of
set_ntacl_dacl():
pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
This produces an on-wire NT ACL whose pndacl->size under-reports the
bytes actually written by the preceding fill_ace_for_sid()/memcpy()
calls, yielding a malformed ACL that can trigger out-of-bounds reads
when re-parsed by clients or ksmbd itself.
Restore *size to its pre-addition value on each overflow branch (via
`*size -= ace_sz` / `size -= nt_ace_size`) so that after the break,
*size once again holds the cumulative size of the successfully-written
ACEs. The committed ACL is then truncated-but-self-consistent rather
than malformed.
The ksmbd DACL builders are the only check_add_overflow() sites found
where an overflow path breaks out of a loop and the destination value
is consumed afterward. The other nearby break-style cases either
return -EINVAL on overflow (transport_ipc.c) or break without
consuming the overflowed destination value afterward (buildid.c).
Fixes: 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16 DACL size overflow")
Assisted-by: atomcode:glm-5.2
Assisted-by: Codex:gpt-5.5
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/smbacl.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index 45c9b980418e8..2b2d8fbaa392e 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -644,6 +644,7 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -658,6 +659,7 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
0x03, pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -703,6 +705,7 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -745,8 +748,10 @@ static void set_ntacl_dacl(struct user_namespace *user_ns,
goto next_ace;
memcpy((char *)pndace + size, ntace, nt_ace_size);
- if (check_add_overflow(size, nt_ace_size, &size))
+ if (check_add_overflow(size, nt_ace_size, &size)) {
+ size -= nt_ace_size;
break;
+ }
num_aces++;
next_ace:
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-08 17:14 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 13:55 FAILED: patch "[PATCH] ksmbd: restore DACL size on check_add_overflow() to avoid" failed to apply to 6.1-stable tree gregkh
2026-08-08 17:14 ` [PATCH 6.1.y 1/3] ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow Sasha Levin
2026-08-08 17:14 ` [PATCH 6.1.y 2/3] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl Sasha Levin
2026-08-08 17:14 ` [PATCH 6.1.y 3/3] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox