[LTS 9.6] smb (cifs): CVE-2026-46195, CVE-2026-46139, CVE-2026-43350, CVE-2026-31709; net: CVE-2026-31419#1379
[LTS 9.6] smb (cifs): CVE-2026-46195, CVE-2026-46139, CVE-2026-43350, CVE-2026-31709; net: CVE-2026-31419#1379pvts-mat wants to merge 7 commits into
Conversation
b2ff89c to
fc129af
Compare
|
could you rebase to the latest 9.6 head? |
jira VULN-181414 cve CVE-2026-31419 commit-author Xiang Mei <xmei5@asu.edu> commit 2884bf7 upstream-diff Used linux-6.12.y backport 3453882 for a clean pick. That commit partially mixes in the ce7a381 ("net: bonding: add broadcast_neighbor option for 802.3ad") which was not backported to LTS 9.6 neither bond_xmit_broadcast() reuses the original skb for the last slave (determined by bond_is_last_slave()) and clones it for others. Concurrent slave enslave/release can mutate the slave list during RCU-protected iteration, changing which slave is "last" mid-loop. This causes the original skb to be double-consumed (double-freed). Replace the racy bond_is_last_slave() check with a simple index comparison (i + 1 == slaves_count) against the pre-snapshot slave count taken via READ_ONCE() before the loop. This preserves the zero-copy optimization for the last slave while making the "last" determination stable against concurrent list mutations. The UAF can trigger the following crash: ================================================================== BUG: KASAN: slab-use-after-free in skb_clone Read of size 8 at addr ffff888100ef8d40 by task exploit/147 CPU: 1 UID: 0 PID: 147 Comm: exploit Not tainted 7.0.0-rc3+ ctrliq#4 PREEMPTLAZY Call Trace: <TASK> dump_stack_lvl (lib/dump_stack.c:123) print_report (mm/kasan/report.c:379 mm/kasan/report.c:482) kasan_report (mm/kasan/report.c:597) skb_clone (include/linux/skbuff.h:1724 include/linux/skbuff.h:1792 include/linux/skbuff.h:3396 net/core/skbuff.c:2108) bond_xmit_broadcast (drivers/net/bonding/bond_main.c:5334) bond_start_xmit (drivers/net/bonding/bond_main.c:5567 drivers/net/bonding/bond_main.c:5593) dev_hard_start_xmit (include/linux/netdevice.h:5325 include/linux/netdevice.h:5334 net/core/dev.c:3871 net/core/dev.c:3887) __dev_queue_xmit (include/linux/netdevice.h:3601 net/core/dev.c:4838) ip6_finish_output2 (include/net/neighbour.h:540 include/net/neighbour.h:554 net/ipv6/ip6_output.c:136) ip6_finish_output (net/ipv6/ip6_output.c:208 net/ipv6/ip6_output.c:219) ip6_output (net/ipv6/ip6_output.c:250) ip6_send_skb (net/ipv6/ip6_output.c:1985) udp_v6_send_skb (net/ipv6/udp.c:1442) udpv6_sendmsg (net/ipv6/udp.c:1733) __sys_sendto (net/socket.c:730 net/socket.c:742 net/socket.c:2206) __x64_sys_sendto (net/socket.c:2209) do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) </TASK> Allocated by task 147: Freed by task 147: The buggy address belongs to the object at ffff888100ef8c80 which belongs to the cache skbuff_head_cache of size 224 The buggy address is located 192 bytes inside of freed 224-byte region [ffff888100ef8c80, ffff888100ef8d60) Memory state around the buggy address: ffff888100ef8c00: fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc ffff888100ef8c80: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff888100ef8d00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc ^ ffff888100ef8d80: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb ffff888100ef8e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== Fixes: 4e5bd03 ("net: bonding: fix bond_xmit_broadcast return value error bug") Reported-by: Weiming Shi <bestswngs@gmail.com> Signed-off-by: Xiang Mei <xmei5@asu.edu> Link: https://patch.msgid.link/20260326075553.3960562-1-xmei5@asu.edu Signed-off-by: Paolo Abeni <pabeni@redhat.com> (cherry picked from commit 3453882) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
jira VULN-183470 cve-pre CVE-2026-31709 commit-author Namjae Jeon <linkinjeon@kernel.org> commit aa2a739 parse_dcal() validate num_aces to allocate ace array. f (num_aces > ULONG_MAX / sizeof(struct smb_ace *)) It is an incorrect validation that we can create an array of size ULONG_MAX. smb_acl has ->size field to calculate actual number of aces in response buffer size. Use this to check invalid num_aces. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit aa2a739) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
jira VULN-183470 cve-pre CVE-2026-31709 commit-author Namjae Jeon <linkinjeon@kernel.org> commit eeb827f cifs.ko is missing validation check when accessing smb_aces. This patch add validation check for the fields in smb_aces. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit eeb827f) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
jira VULN-183470 cve CVE-2026-31709 commit-author Michael Bommarito <michael.bommarito@gmail.com> commit 0a8cf16 upstream-diff Usd linux-6.12.y backport d92f3f0 for the clean pick build_sec_desc() and id_mode_to_cifs_acl() derive a DACL pointer from a server-supplied dacloffset and then use the incoming ACL to rebuild the chmod/chown security descriptor. The original fix only checked that the struct smb_acl header fits before reading dacl_ptr->size or dacl_ptr->num_aces. That avoids the immediate header-field OOB read, but the rewrite helpers still walk ACEs based on pdacl->num_aces with no structural validation of the incoming DACL body. A malicious server can return a truncated DACL that still contains a header, claims one or more ACEs, and then drive replace_sids_and_copy_aces() or set_chmod_dacl() past the validated extent while they compare or copy attacker-controlled ACEs. Factor the DACL structural checks into validate_dacl(), extend them to validate each ACE against the DACL bounds, and use the shared validator before the chmod/chown rebuild paths. parse_dacl() reuses the same validator so the read-side parser and write-side rewrite paths agree on what constitutes a well-formed incoming DACL. Fixes: bc3e9dd ("cifs: Change SIDs in ACEs while transferring file ownership.") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-6 Assisted-by: Codex:gpt-5-4 Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit d92f3f0) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
jira VULN-184959 cve CVE-2026-43350 commit-author Michael Bommarito <michael.bommarito@gmail.com> commit 2757ad3 parse_dacl() treats an ACE SID matching sid_unix_NFS_mode as an NFS mode SID and reads sid.sub_auth[2] to recover the mode bits. That assumes the ACE carries three subauthorities, but compare_sids() only compares min(a, b) subauthorities. A malicious server can return an ACE with num_subauth = 2 and sub_auth[] = {88, 3}, which still matches sid_unix_NFS_mode and then drives the sub_auth[2] read four bytes past the end of the ACE. Require num_subauth >= 3 before treating the ACE as an NFS mode SID. This keeps the fix local to the special-SID mode path without changing compare_sids() semantics for the rest of cifsacl. Fixes: e2f8fbf ("cifs: get mode bits from special sid on stat") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit 2757ad3) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
jira VULN-188852 cve CVE-2026-46139 commit-author Bjoern Doebel <doebel@amazon.de> commit 5e489c6 Commit 62e7dd0 ("smb: common: change the data type of num_aces to le16") split struct smb_acl's __le32 num_aces field into __le16 num_aces and __le16 reserved. The reserved field corresponds to Sbz2 in the MS-DTYP ACL wire format, which must be zero [1]. When building an ACL descriptor in build_sec_desc(), we are using a kmalloc()'ed descriptor buffer and writing the fields explicitly using le16() writes now. This never writes to the 2 byte reserved field, leaving it as uninitialized heap data. When the reserved field happens to contain non-zero slab garbage, Samba rejects the security descriptor with "ndr_pull_security_descriptor failed: Range Error", causing chmod to fail with EINVAL. Change kmalloc() to kzalloc() to ensure the entire buffer is zero-initialized. Fixes: 62e7dd0 ("smb: common: change the data type of num_aces to le16") Cc: stable@vger.kernel.org Signed-off-by: Bjoern Doebel <doebel@amazon.de> Assisted-by: Kiro:claude-opus-4.6 [1] https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/20233ed8-a6c6-4097-aafa-dd545ed24428 Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit 5e489c6) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
jira VULN-188330 cve CVE-2026-46195 commit-author Michael Bommarito <michael.bommarito@gmail.com> commit f98b481 parse_sec_desc(), build_sec_desc(), and the chown path in id_mode_to_cifs_acl() all add the server-supplied dacloffset to pntsd before proving a DACL header fits inside the returned security descriptor. On 32-bit builds a malicious server can return dacloffset near U32_MAX, wrap the derived DACL pointer below end_of_acl, and then slip past the later pointer-based bounds checks. build_sec_desc() and id_mode_to_cifs_acl() can then dereference DACL fields from the wrapped pointer in the chmod/chown rewrite paths. Validate dacloffset numerically before building any DACL pointer and reuse the same helper at the three DACL entry points. Fixes: bc3e9dd ("cifs: Change SIDs in ACEs while transferring file ownership.") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit f98b481) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
fc129af to
482e59e
Compare
|
🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/28201918926 |
🔍 Interdiff Analysis
================================================================================
* DELTA DIFFERENCES - code changes that differ between the patches *
================================================================================
--- b/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5320,16 +5320,12 @@
struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct bond_up_slave *slaves;
+ struct slave *slave = NULL;
+ struct list_head *iter;
bool xmit_suc = false;
bool skb_used = false;
- int slaves_count, i;
- slaves = rcu_dereference(bond->all_slaves);
-
- slaves_count = slaves ? READ_ONCE(slaves->count) : 0;
- for (i = 0; i < slaves_count; i++) {
- struct slave *slave = slaves->arr[i];
+ bond_for_each_slave_rcu(bond, slave, iter) {
struct sk_buff *skb2;
if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP))
################################################################################
! REJECTED PATCH2 HUNKS - could not be compared; manual review needed !
################################################################################
--- b/fs/smb/client/cifsacl.c
+++ b/fs/smb/client/cifsacl.c
@@ -868,11 +936,6 @@
if (num_aces > 0) {
umode_t denied_mode = 0;
- if (num_aces > (le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) /
- (offsetof(struct smb_ace, sid) +
- offsetof(struct smb_sid, sub_auth) + sizeof(__le16)))
- return;
-
ppace = kmalloc_objs(struct smb_ace *, num_aces);
if (!ppace)
return;
================================================================================
* CONTEXT DIFFERENCES - surrounding code differences between the patches *
================================================================================
--- b/fs/smb/client/cifsacl.c
+++ b/fs/smb/client/cifsacl.c
@@ -763,5 +763,5 @@
int i;
- int num_aces = 0;
+ u16 num_aces = 0;
int acl_size;
char *acl_base;
struct smb_ace **ppace;
@@ -805,8 +805,7 @@
offsetof(struct smb_sid, sub_auth) + sizeof(__le16)))
return;
- ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *),
- GFP_KERNEL);
+ ppace = kmalloc_objs(struct smb_ace *, num_aces);
if (!ppace)
return;
@@ -1660,6 +1659,6 @@
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
if (mode_from_sid)
nsecdesclen +=
- le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace);
+ le16_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace);This is an automated interdiff check for backported commits. |
JIRA PR Check Results7 commit(s) with issues found: Commit
|
|
❌ Validation checks completed with issues View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/28201918926 |
[LTS 9.6]
All smb-related CVE fixes are changes to a single file
fs/smb/client/cifsacl.c.Commits
CVE-2026-46195
CVE-2026-46139
CVE-2026-43350
CVE-2026-31709
Everything that the two prerequisites added to
parse_daclis later removed by the fixing commit 0a8cf16 so they aren't necessarily needed, but allow for clean cherry picks and simplify backporting.CVE-2026-31419
kABI check: passed
Boot test: passed
boot-test.log
Kselftests: passed relative
Reference
kselftests–ciqlts9_6–run1.log
Patch
kselftests–ciqlts9_6-CVE-batch-38–run1.log
kselftests–ciqlts9_6-CVE-batch-38–run2.log
Comparison
One test reported different status for the patched kernel, but it's not a regression (and not a progression either).
full-test-results-comparison.log