[LTS 9.2] smb (cifs): CVE-2026-46195, CVE-2026-46139, CVE-2026-43350, CVE-2026-31709; net: CVE-2026-31419#1380
[LTS 9.2] smb (cifs): CVE-2026-46195, CVE-2026-46139, CVE-2026-43350, CVE-2026-31709; net: CVE-2026-31419#1380pvts-mat wants to merge 5 commits into
Conversation
c6530c1 to
a30f15a
Compare
|
Could you rebase to the latest 9.2 |
jira VULN-181412 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 includes changes from ce7a381 ("net: bonding: add broadcast_neighbor option for 802.3ad"), which was not backported to LTS 9.2 either. 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-183468 cve CVE-2026-31709 commit-author Michael Bommarito <michael.bommarito@gmail.com> commit 0a8cf16 upstream-diff Used linux-5.15.y backport b8603d9ae6c9087662b098619996bc4a8064319d for a clean pick. Compared to the upstream: 1. Structs `cifs_{acl,ace,sid}' underwent renaming to `smb_{acl,ace,sid}' in 7f599d8, 251b93a, 09bedaf. Additionally the `__le32 num_aces' field of `smb_acl' was split into `__le16 num_aces' and `__le16 reserved' in 62e7dd0. These changes were taken into account in the body of `validate_dacl()' function. 2. No removal of validation code fragments in `parse_dacl()'. In the upstream those were put into place by aa2a739 and eeb827f, not backported to LTS 9.2. In both versions they ultimately landed in the `validate_dacl()' function in this fix. 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 b8603d9ae6c9087662b098619996bc4a8064319d) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
jira VULN-184957 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-188853 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-188328 cve CVE-2026-46195 commit-author Michael Bommarito <michael.bommarito@gmail.com> commit f98b481 upstream-diff Used linux-5.15.y backport 5de2665e913a10ad70aaeecf736b97276e83d995 for the clean pick 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 5de2665e913a10ad70aaeecf736b97276e83d995) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
a30f15a to
257e7e7
Compare
|
🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/28201943999 |
🔍 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
@@ -5155,16 +5155,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))
================================================================================
* DELTA DIFFERENCES - code changes that differ between the patches *
================================================================================
--- b/fs/cifs/cifsacl.c
+++ b/fs/smb/client/cifsacl.c
@@ -753,78 +753,6 @@
}
#endif
-static int validate_dacl(struct cifs_acl *pdacl, char *end_of_acl)
-{
- int i, ace_hdr_size, ace_size, min_ace_size;
- u16 dacl_size;
- u32 num_aces;
- char *acl_base, *end_of_dacl;
- struct cifs_ace *pace;
-
- if (!pdacl)
- return 0;
-
- if (end_of_acl < (char *)pdacl + sizeof(struct cifs_acl)) {
- cifs_dbg(VFS, "ACL too small to parse DACL\n");
- return -EINVAL;
- }
-
- dacl_size = le16_to_cpu(pdacl->size);
- if (dacl_size < sizeof(struct cifs_acl) ||
- end_of_acl < (char *)pdacl + dacl_size) {
- cifs_dbg(VFS, "ACL too small to parse DACL\n");
- return -EINVAL;
- }
-
- num_aces = le32_to_cpu(pdacl->num_aces);
- if (!num_aces)
- return 0;
-
- ace_hdr_size = offsetof(struct cifs_ace, sid) +
- offsetof(struct cifs_sid, sub_auth);
- min_ace_size = ace_hdr_size + sizeof(__le32);
- if (num_aces > (dacl_size - sizeof(struct cifs_acl)) / min_ace_size) {
- cifs_dbg(VFS, "ACL too small to parse DACL\n");
- return -EINVAL;
- }
-
- end_of_dacl = (char *)pdacl + dacl_size;
- acl_base = (char *)pdacl;
- ace_size = sizeof(struct cifs_acl);
-
- for (i = 0; i < num_aces; ++i) {
- if (end_of_dacl - acl_base < ace_size) {
- cifs_dbg(VFS, "ACL too small to parse ACE\n");
- return -EINVAL;
- }
-
- pace = (struct cifs_ace *)(acl_base + ace_size);
- acl_base = (char *)pace;
-
- if (end_of_dacl - acl_base < ace_hdr_size ||
- pace->sid.num_subauth == 0 ||
- pace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES) {
- cifs_dbg(VFS, "ACL too small to parse ACE\n");
- return -EINVAL;
- }
-
- ace_size = ace_hdr_size + sizeof(__le32) * pace->sid.num_subauth;
- if (end_of_dacl - acl_base < ace_size ||
- le16_to_cpu(pace->size) < ace_size) {
- cifs_dbg(VFS, "ACL too small to parse ACE\n");
- return -EINVAL;
- }
-
- ace_size = le16_to_cpu(pace->size);
- if (end_of_dacl - acl_base < ace_size) {
- cifs_dbg(VFS, "ACL too small to parse ACE\n");
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
struct cifs_fattr *fattr, bool mode_from_special_sid)
@@ -844,7 +772,9 @@
return;
}
- if (validate_dacl(pdacl, end_of_acl))
+ /* validate that we do not go past end of acl */
+ if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
+ cifs_dbg(VFS, "ACL too small to parse DACL\n");
return;
cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
################################################################################
! REJECTED PATCH2 HUNKS - could not be compared; manual review needed !
################################################################################
--- b/fs/cifs/cifsacl.c
+++ b/fs/smb/client/cifsacl.c
@@ -758,6 +758,77 @@
}
#endif
+static int validate_dacl(struct smb_acl *pdacl, char *end_of_acl)
+{
+ int i, ace_hdr_size, ace_size, min_ace_size;
+ u16 dacl_size, num_aces;
+ char *acl_base, *end_of_dacl;
+ struct smb_ace *pace;
+
+ if (!pdacl)
+ return 0;
+
+ if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl)) {
+ cifs_dbg(VFS, "ACL too small to parse DACL\n");
+ return -EINVAL;
+ }
+
+ dacl_size = le16_to_cpu(pdacl->size);
+ if (dacl_size < sizeof(struct smb_acl) ||
+ end_of_acl < (char *)pdacl + dacl_size) {
+ cifs_dbg(VFS, "ACL too small to parse DACL\n");
+ return -EINVAL;
+ }
+
+ num_aces = le16_to_cpu(pdacl->num_aces);
+ if (!num_aces)
+ return 0;
+
+ ace_hdr_size = offsetof(struct smb_ace, sid) +
+ offsetof(struct smb_sid, sub_auth);
+ min_ace_size = ace_hdr_size + sizeof(__le32);
+ if (num_aces > (dacl_size - sizeof(struct smb_acl)) / min_ace_size) {
+ cifs_dbg(VFS, "ACL too small to parse DACL\n");
+ return -EINVAL;
+ }
+
+ end_of_dacl = (char *)pdacl + dacl_size;
+ acl_base = (char *)pdacl;
+ ace_size = sizeof(struct smb_acl);
+
+ for (i = 0; i < num_aces; ++i) {
+ if (end_of_dacl - acl_base < ace_size) {
+ cifs_dbg(VFS, "ACL too small to parse ACE\n");
+ return -EINVAL;
+ }
+
+ pace = (struct smb_ace *)(acl_base + ace_size);
+ acl_base = (char *)pace;
+
+ if (end_of_dacl - acl_base < ace_hdr_size ||
+ pace->sid.num_subauth == 0 ||
+ pace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES) {
+ cifs_dbg(VFS, "ACL too small to parse ACE\n");
+ return -EINVAL;
+ }
+
+ ace_size = ace_hdr_size + sizeof(__le32) * pace->sid.num_subauth;
+ if (end_of_dacl - acl_base < ace_size ||
+ le16_to_cpu(pace->size) < ace_size) {
+ cifs_dbg(VFS, "ACL too small to parse ACE\n");
+ return -EINVAL;
+ }
+
+ ace_size = le16_to_cpu(pace->size);
+ if (end_of_dacl - acl_base < ace_size) {
+ cifs_dbg(VFS, "ACL too small to parse ACE\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
struct smb_sid *pownersid, struct smb_sid *pgrpsid,
struct cifs_fattr *fattr, bool mode_from_special_sid)
@@ -765,7 +836,7 @@
int i;
u16 num_aces = 0;
int acl_size;
- char *acl_base;
+ char *acl_base, *end_of_dacl;
struct smb_ace **ppace;
/* BB need to add parm so we can store the SID BB */
@@ -777,10 +848,7 @@
return;
}
- /* validate that we do not go past end of acl */
- if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) ||
- end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
- cifs_dbg(VFS, "ACL too small to parse DACL\n");
+ if (validate_dacl(pdacl, end_of_acl))
return;
}
@@ -800,11 +868,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;
@@ -808,9 +871,6 @@
return;
for (i = 0; i < num_aces; ++i) {
- if (end_of_acl - acl_base < acl_size)
- break;
-
ppace[i] = (struct smb_ace *) (acl_base + acl_size);
acl_base = (char *)ppace[i];
acl_size = offsetof(struct smb_ace, sid) +
@@ -812,18 +872,6 @@
break;
ppace[i] = (struct smb_ace *) (acl_base + acl_size);
- acl_base = (char *)ppace[i];
- acl_size = offsetof(struct smb_ace, sid) +
- offsetof(struct smb_sid, sub_auth);
-
- if (end_of_acl - acl_base < acl_size ||
- ppace[i]->sid.num_subauth == 0 ||
- ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
- (end_of_acl - acl_base <
- acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
- (le16_to_cpu(ppace[i]->size) <
- acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth))
- break;
#ifdef CONFIG_CIFS_DEBUG2
dump_ace(ppace[i], end_of_acl);
@@ -870,6 +918,7 @@
(void *)ppace[i],
sizeof(struct smb_ace)); */
+ acl_base = (char *)ppace[i];
acl_size = le16_to_cpu(ppace[i]->size);
}
@@ -1293,10 +1342,9 @@
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
- if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
- cifs_dbg(VFS, "Server returned illegal ACL size\n");
- return -EINVAL;
- }
+ rc = validate_dacl(dacl_ptr, end_of_acl);
+ if (rc)
+ return rc;
}
owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
@@ -1662,6 +1710,12 @@
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
+ rc = validate_dacl(dacl_ptr, (char *)pntsd + secdesclen);
+ if (rc) {
+ kfree(pntsd);
+ cifs_put_tlink(tlink);
+ return rc;
+ }
if (mode_from_sid)
nsecdesclen +=
le16_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace);
================================================================================
* CONTEXT DIFFERENCES - surrounding code differences between the patches *
================================================================================
--- b/fs/cifs/cifsacl.c
+++ b/fs/smb/client/cifsacl.c
@@ -752,4 +752,4 @@
-static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
+static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
+ struct smb_sid *pownersid, struct smb_sid *pgrpsid,
struct cifs_fattr *fattr, bool mode_from_special_sid)
@@ -756,7 +756,7 @@
int i;
- int num_aces = 0;
+ u16 num_aces = 0;
int acl_size;
char *acl_base;
- struct cifs_ace **ppace;
+ struct smb_ace **ppace;
/* BB need to add parm so we can store the SID BB */
@@ -763,11 +763,12 @@
return;
}
/* validate that we do not go past end of acl */
- if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
+ if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) ||
+ end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
cifs_dbg(VFS, "ACL too small to parse DACL\n");
return;
}
cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
@@ -777,3 +778,24 @@
acl_base = (char *)pdacl;
- acl_size = sizeof(struct cifs_acl);
+ acl_size = sizeof(struct smb_acl);
+
+ 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;
+
+ for (i = 0; i < num_aces; ++i) {
+ if (end_of_acl - acl_base < acl_size)
+ break;
+
+ ppace[i] = (struct smb_ace *) (acl_base + acl_size);
+ acl_base = (char *)ppace[i];
+ acl_size = offsetof(struct smb_ace, sid) +
+ offsetof(struct smb_sid, sub_auth);
@@ -1261,10 +1292,10 @@
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
cifs_dbg(VFS, "Server returned illegal ACL size\n");
return -EINVAL;
}
}
- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
@@ -1626,6 +1661,6 @@
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
if (mode_from_sid)
nsecdesclen +=
- le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct cifs_ace);
+ le16_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace);
================================================================================
* DELTA DIFFERENCES - code changes that differ between the patches *
================================================================================
--- b/fs/cifs/cifsacl.c
+++ b/fs/smb/client/cifsacl.c
@@ -1256,13 +1256,13 @@
static bool dacl_offset_valid(unsigned int acl_len, __u32 dacloffset)
{
- if (acl_len < sizeof(struct cifs_acl))
+ if (acl_len < sizeof(struct smb_acl))
return false;
- if (dacloffset < sizeof(struct cifs_ntsd))
+ if (dacloffset < sizeof(struct smb_ntsd))
return false;
- return dacloffset <= acl_len - sizeof(struct cifs_acl);
+ return dacloffset <= acl_len - sizeof(struct smb_acl);
}
@@ -1285,6 +1285,7 @@
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
dacloffset = le32_to_cpu(pntsd->dacloffset);
+ dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
cifs_dbg(NOISY, "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),
le32_to_cpu(pntsd->gsidoffset),
@@ -1321,7 +1322,7 @@
return -EINVAL;
}
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
group_sid_ptr, fattr, get_mode_from_special_sid);
} else {
################################################################################
! REJECTED PATCH2 HUNKS - could not be compared; manual review needed !
################################################################################
--- b/fs/cifs/cifsacl.c
+++ b/fs/smb/client/cifsacl.c
@@ -1295,7 +1306,6 @@
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);
cifs_dbg(NOISY, "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),
le32_to_cpu(pntsd->gsidoffset),
@@ -1360,6 +1377,11 @@
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
+ if (!dacl_offset_valid(secdesclen, dacloffset)) {
+ cifs_dbg(VFS, "Server returned illegal DACL offset\n");
+ return -EINVAL;
+ }
+
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
rc = validate_dacl(dacl_ptr, end_of_acl);
if (rc)
@@ -1728,6 +1750,12 @@
nsecdesclen = sizeof(struct smb_ntsd) + (sizeof(struct smb_sid) * 2);
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
+ if (!dacl_offset_valid(secdesclen, dacloffset)) {
+ cifs_dbg(VFS, "Server returned illegal DACL offset\n");
+ rc = -EINVAL;
+ goto id_mode_to_cifs_acl_exit;
+ }
+
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
rc = validate_dacl(dacl_ptr, (char *)pntsd + secdesclen);
if (rc) {
================================================================================
* CONTEXT DIFFERENCES - surrounding code differences between the patches *
================================================================================
--- b/fs/cifs/cifsacl.c
+++ b/fs/smb/client/cifsacl.c
@@ -1271,7 +1281,7 @@
- group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ group_sid_ptr = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
dacloffset = le32_to_cpu(pntsd->dacloffset);
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
cifs_dbg(NOISY, "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),
le32_to_cpu(pntsd->gsidoffset),
@@ -1333,5 +1343,5 @@
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
rc = validate_dacl(dacl_ptr, end_of_acl);
if (rc)
@@ -1693,6 +1703,6 @@
- nsecdesclen = sizeof(struct cifs_ntsd) + (sizeof(struct cifs_sid) * 2);
+ nsecdesclen = sizeof(struct smb_ntsd) + (sizeof(struct smb_sid) * 2);
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
rc = validate_dacl(dacl_ptr, (char *)pntsd + secdesclen);
if (rc) {This is an automated interdiff check for backported commits. |
JIRA PR Check Results5 commit(s) with issues found: Commit
|
|
❌ Validation checks completed with issues View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/28201943999 |
[LTS 9.2]
Commits
CVE-2026-46195
See CVE-2026-31709 section for the discussion of the differences between
linux-5.15.yandkernel-mainline.CVE-2026-46139
CVE-2026-43350
CVE-2026-31709
LTS 9.2
cifsmodule is on roughly the same level feature-and-bugfix-wise as Linux stable 5.15. The differences between the upstream fix and 5.15 backport stem from the evolution of the core data structures - mostly just renaming and moving around the codebase, although there is one change to thesmb_aclfielfs as well.Compare
ciqlts9_2:kernel-src-tree/fs/cifs/cifsacl.h
Lines 77 to 81 in 4f58c44
kernel-src-tree/fs/cifs/cifsacl.h
Lines 114 to 120 in 4f58c44
kernel-src-tree/fs/cifs/cifsacl.h
Lines 67 to 72 in 4f58c44
with upstream:
kernel-src-tree/fs/smb/common/smbacl.h
Lines 107 to 112 in 0a8cf16
kernel-src-tree/fs/smb/common/smbacl.h
Lines 114 to 120 in 0a8cf16
kernel-src-tree/fs/smb/common/smbacl.h
Lines 97 to 102 in 0a8cf16
The data structures timeline can be summarized in the following table (from oldest):
CVE-2026-31419
kABI check: passed
Boot test: passed
boot-test.log
Kselftests: passed relative
Reference
kselftests–ciqlts9_2–run1.log
Patch
kselftests–ciqlts9_2-CVE-batch-37–run1.log
kselftests–ciqlts9_2-CVE-batch-37–run2.log
Comparison
The tests results for the reference and the patch are the same.
full-test-results-comparison.log