diff options
6 files changed, 509 insertions, 0 deletions
diff --git a/queue-6.6/bpf-fix-l4-csum-update-on-ipv6-in-checksum_complete.patch b/queue-6.6/bpf-fix-l4-csum-update-on-ipv6-in-checksum_complete.patch new file mode 100644 index 00000000000..77916c20b5b --- /dev/null +++ b/queue-6.6/bpf-fix-l4-csum-update-on-ipv6-in-checksum_complete.patch @@ -0,0 +1,129 @@ +From ead7f9b8de65632ef8060b84b0c55049a33cfea1 Mon Sep 17 00:00:00 2001 +From: Paul Chaignon <paul.chaignon@gmail.com> +Date: Thu, 29 May 2025 12:28:35 +0200 +Subject: bpf: Fix L4 csum update on IPv6 in CHECKSUM_COMPLETE + +From: Paul Chaignon <paul.chaignon@gmail.com> + +commit ead7f9b8de65632ef8060b84b0c55049a33cfea1 upstream. + +In Cilium, we use bpf_csum_diff + bpf_l4_csum_replace to, among other +things, update the L4 checksum after reverse SNATing IPv6 packets. That +use case is however not currently supported and leads to invalid +skb->csum values in some cases. This patch adds support for IPv6 address +changes in bpf_l4_csum_update via a new flag. + +When calling bpf_l4_csum_replace in Cilium, it ends up calling +inet_proto_csum_replace_by_diff: + + 1: void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb, + 2: __wsum diff, bool pseudohdr) + 3: { + 4: if (skb->ip_summed != CHECKSUM_PARTIAL) { + 5: csum_replace_by_diff(sum, diff); + 6: if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) + 7: skb->csum = ~csum_sub(diff, skb->csum); + 8: } else if (pseudohdr) { + 9: *sum = ~csum_fold(csum_add(diff, csum_unfold(*sum))); + 10: } + 11: } + +The bug happens when we're in the CHECKSUM_COMPLETE state. We've just +updated one of the IPv6 addresses. The helper now updates the L4 header +checksum on line 5. Next, it updates skb->csum on line 7. It shouldn't. + +For an IPv6 packet, the updates of the IPv6 address and of the L4 +checksum will cancel each other. The checksums are set such that +computing a checksum over the packet including its checksum will result +in a sum of 0. So the same is true here when we update the L4 checksum +on line 5. We'll update it as to cancel the previous IPv6 address +update. Hence skb->csum should remain untouched in this case. + +The same bug doesn't affect IPv4 packets because, in that case, three +fields are updated: the IPv4 address, the IP checksum, and the L4 +checksum. The change to the IPv4 address and one of the checksums still +cancel each other in skb->csum, but we're left with one checksum update +and should therefore update skb->csum accordingly. That's exactly what +inet_proto_csum_replace_by_diff does. + +This special case for IPv6 L4 checksums is also described atop +inet_proto_csum_replace16, the function we should be using in this case. + +This patch introduces a new bpf_l4_csum_replace flag, BPF_F_IPV6, +to indicate that we're updating the L4 checksum of an IPv6 packet. When +the flag is set, inet_proto_csum_replace_by_diff will skip the +skb->csum update. + +Fixes: 7d672345ed295 ("bpf: add generic bpf_csum_diff helper") +Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com> +Acked-by: Daniel Borkmann <daniel@iogearbox.net> +Link: https://patch.msgid.link/96a6bc3a443e6f0b21ff7b7834000e17fb549e05.1748509484.git.paul.chaignon@gmail.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + include/uapi/linux/bpf.h | 2 ++ + net/core/filter.c | 5 +++-- + tools/include/uapi/linux/bpf.h | 2 ++ + 3 files changed, 7 insertions(+), 2 deletions(-) + +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -1913,6 +1913,7 @@ union bpf_attr { + * for updates resulting in a null checksum the value is set to + * **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates + * the checksum is to be computed against a pseudo-header. ++ * Flag **BPF_F_IPV6** should be set for IPv6 packets. + * + * This helper works in combination with **bpf_csum_diff**\ (), + * which does not update the checksum in-place, but offers more +@@ -5920,6 +5921,7 @@ enum { + BPF_F_PSEUDO_HDR = (1ULL << 4), + BPF_F_MARK_MANGLED_0 = (1ULL << 5), + BPF_F_MARK_ENFORCE = (1ULL << 6), ++ BPF_F_IPV6 = (1ULL << 7), + }; + + /* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */ +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -1968,10 +1968,11 @@ BPF_CALL_5(bpf_l4_csum_replace, struct s + bool is_pseudo = flags & BPF_F_PSEUDO_HDR; + bool is_mmzero = flags & BPF_F_MARK_MANGLED_0; + bool do_mforce = flags & BPF_F_MARK_ENFORCE; ++ bool is_ipv6 = flags & BPF_F_IPV6; + __sum16 *ptr; + + if (unlikely(flags & ~(BPF_F_MARK_MANGLED_0 | BPF_F_MARK_ENFORCE | +- BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK))) ++ BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK | BPF_F_IPV6))) + return -EINVAL; + if (unlikely(offset > 0xffff || offset & 1)) + return -EFAULT; +@@ -1987,7 +1988,7 @@ BPF_CALL_5(bpf_l4_csum_replace, struct s + if (unlikely(from != 0)) + return -EINVAL; + +- inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo, false); ++ inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo, is_ipv6); + break; + case 2: + inet_proto_csum_replace2(ptr, skb, from, to, is_pseudo); +--- a/tools/include/uapi/linux/bpf.h ++++ b/tools/include/uapi/linux/bpf.h +@@ -1913,6 +1913,7 @@ union bpf_attr { + * for updates resulting in a null checksum the value is set to + * **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates + * the checksum is to be computed against a pseudo-header. ++ * Flag **BPF_F_IPV6** should be set for IPv6 packets. + * + * This helper works in combination with **bpf_csum_diff**\ (), + * which does not update the checksum in-place, but offers more +@@ -5920,6 +5921,7 @@ enum { + BPF_F_PSEUDO_HDR = (1ULL << 4), + BPF_F_MARK_MANGLED_0 = (1ULL << 5), + BPF_F_MARK_ENFORCE = (1ULL << 6), ++ BPF_F_IPV6 = (1ULL << 7), + }; + + /* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */ diff --git a/queue-6.6/erofs-remove-unused-trace-event-erofs_destroy_inode.patch b/queue-6.6/erofs-remove-unused-trace-event-erofs_destroy_inode.patch new file mode 100644 index 00000000000..2836d5202e9 --- /dev/null +++ b/queue-6.6/erofs-remove-unused-trace-event-erofs_destroy_inode.patch @@ -0,0 +1,51 @@ +From 30b58444807c93bffeaba7d776110f2a909d2f9a Mon Sep 17 00:00:00 2001 +From: Gao Xiang <hsiangkao@linux.alibaba.com> +Date: Tue, 17 Jun 2025 13:40:56 +0800 +Subject: erofs: remove unused trace event erofs_destroy_inode + +From: Gao Xiang <hsiangkao@linux.alibaba.com> + +commit 30b58444807c93bffeaba7d776110f2a909d2f9a upstream. + +The trace event `erofs_destroy_inode` was added but remains unused. This +unused event contributes approximately 5KB to the kernel module size. + +Reported-by: Steven Rostedt <rostedt@goodmis.org> +Closes: https://lore.kernel.org/r/20250612224906.15000244@batman.local.home +Fixes: 13f06f48f7bf ("staging: erofs: support tracepoint") +Cc: stable@vger.kernel.org +Reviewed-by: Hongbo Li <lihongbo22@huawei.com> +Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com> +Link: https://lore.kernel.org/r/20250617054056.3232365-1-hsiangkao@linux.alibaba.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + include/trace/events/erofs.h | 18 ------------------ + 1 file changed, 18 deletions(-) + +--- a/include/trace/events/erofs.h ++++ b/include/trace/events/erofs.h +@@ -237,24 +237,6 @@ DEFINE_EVENT(erofs__map_blocks_exit, z_e + TP_ARGS(inode, map, flags, ret) + ); + +-TRACE_EVENT(erofs_destroy_inode, +- TP_PROTO(struct inode *inode), +- +- TP_ARGS(inode), +- +- TP_STRUCT__entry( +- __field( dev_t, dev ) +- __field( erofs_nid_t, nid ) +- ), +- +- TP_fast_assign( +- __entry->dev = inode->i_sb->s_dev; +- __entry->nid = EROFS_I(inode)->nid; +- ), +- +- TP_printk("dev = (%d,%d), nid = %llu", show_dev_nid(__entry)) +-); +- + #endif /* _TRACE_EROFS_H */ + + /* This part must be outside protection */ diff --git a/queue-6.6/mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch b/queue-6.6/mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch new file mode 100644 index 00000000000..b28a98b6497 --- /dev/null +++ b/queue-6.6/mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch @@ -0,0 +1,100 @@ +From be6e843fc51a584672dfd9c4a6a24c8cb81d5fb7 Mon Sep 17 00:00:00 2001 +From: Gavin Guo <gavinguo@igalia.com> +Date: Mon, 21 Apr 2025 19:35:36 +0800 +Subject: mm/huge_memory: fix dereferencing invalid pmd migration entry + +From: Gavin Guo <gavinguo@igalia.com> + +commit be6e843fc51a584672dfd9c4a6a24c8cb81d5fb7 upstream. + +When migrating a THP, concurrent access to the PMD migration entry during +a deferred split scan can lead to an invalid address access, as +illustrated below. To prevent this invalid access, it is necessary to +check the PMD migration entry and return early. In this context, there is +no need to use pmd_to_swp_entry and pfn_swap_entry_to_page to verify the +equality of the target folio. Since the PMD migration entry is locked, it +cannot be served as the target. + +Mailing list discussion and explanation from Hugh Dickins: "An anon_vma +lookup points to a location which may contain the folio of interest, but +might instead contain another folio: and weeding out those other folios is +precisely what the "folio != pmd_folio((*pmd)" check (and the "risk of +replacing the wrong folio" comment a few lines above it) is for." + +BUG: unable to handle page fault for address: ffffea60001db008 +CPU: 0 UID: 0 PID: 2199114 Comm: tee Not tainted 6.14.0+ #4 NONE +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +RIP: 0010:split_huge_pmd_locked+0x3b5/0x2b60 +Call Trace: +<TASK> +try_to_migrate_one+0x28c/0x3730 +rmap_walk_anon+0x4f6/0x770 +unmap_folio+0x196/0x1f0 +split_huge_page_to_list_to_order+0x9f6/0x1560 +deferred_split_scan+0xac5/0x12a0 +shrinker_debugfs_scan_write+0x376/0x470 +full_proxy_write+0x15c/0x220 +vfs_write+0x2fc/0xcb0 +ksys_write+0x146/0x250 +do_syscall_64+0x6a/0x120 +entry_SYSCALL_64_after_hwframe+0x76/0x7e + +The bug is found by syzkaller on an internal kernel, then confirmed on +upstream. + +Link: https://lkml.kernel.org/r/20250421113536.3682201-1-gavinguo@igalia.com +Link: https://lore.kernel.org/all/20250414072737.1698513-1-gavinguo@igalia.com/ +Link: https://lore.kernel.org/all/20250418085802.2973519-1-gavinguo@igalia.com/ +Fixes: 84c3fc4e9c56 ("mm: thp: check pmd migration entry in common path") +Signed-off-by: Gavin Guo <gavinguo@igalia.com> +Acked-by: David Hildenbrand <david@redhat.com> +Acked-by: Hugh Dickins <hughd@google.com> +Acked-by: Zi Yan <ziy@nvidia.com> +Reviewed-by: Gavin Shan <gshan@redhat.com> +Cc: Florent Revest <revest@google.com> +Cc: Matthew Wilcox (Oracle) <willy@infradead.org> +Cc: Miaohe Lin <linmiaohe@huawei.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +[gavin: backport the migration checking logic to __split_huge_pmd] +Signed-off-by: Gavin Guo <gavinguo@igalia.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + mm/huge_memory.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2260,12 +2260,14 @@ void __split_huge_pmd(struct vm_area_str + { + spinlock_t *ptl; + struct mmu_notifier_range range; ++ bool pmd_migration; + + mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma->vm_mm, + address & HPAGE_PMD_MASK, + (address & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE); + mmu_notifier_invalidate_range_start(&range); + ptl = pmd_lock(vma->vm_mm, pmd); ++ pmd_migration = is_pmd_migration_entry(*pmd); + + /* + * If caller asks to setup a migration entry, we need a folio to check +@@ -2274,13 +2276,12 @@ void __split_huge_pmd(struct vm_area_str + VM_BUG_ON(freeze && !folio); + VM_WARN_ON_ONCE(folio && !folio_test_locked(folio)); + +- if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd) || +- is_pmd_migration_entry(*pmd)) { ++ if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd) || pmd_migration) { + /* +- * It's safe to call pmd_page when folio is set because it's +- * guaranteed that pmd is present. ++ * Do not apply pmd_folio() to a migration entry; and folio lock ++ * guarantees that it must be of the wrong folio anyway. + */ +- if (folio && folio != page_folio(pmd_page(*pmd))) ++ if (folio && (pmd_migration || folio != page_folio(pmd_page(*pmd)))) + goto out; + __split_huge_pmd_locked(vma, pmd, range.start, freeze); + } diff --git a/queue-6.6/net-fix-checksum-update-for-ila-adj-transport.patch b/queue-6.6/net-fix-checksum-update-for-ila-adj-transport.patch new file mode 100644 index 00000000000..12ceede381e --- /dev/null +++ b/queue-6.6/net-fix-checksum-update-for-ila-adj-transport.patch @@ -0,0 +1,157 @@ +From 6043b794c7668c19dabc4a93c75b924a19474d59 Mon Sep 17 00:00:00 2001 +From: Paul Chaignon <paul.chaignon@gmail.com> +Date: Thu, 29 May 2025 12:28:05 +0200 +Subject: net: Fix checksum update for ILA adj-transport + +From: Paul Chaignon <paul.chaignon@gmail.com> + +commit 6043b794c7668c19dabc4a93c75b924a19474d59 upstream. + +During ILA address translations, the L4 checksums can be handled in +different ways. One of them, adj-transport, consist in parsing the +transport layer and updating any found checksum. This logic relies on +inet_proto_csum_replace_by_diff and produces an incorrect skb->csum when +in state CHECKSUM_COMPLETE. + +This bug can be reproduced with a simple ILA to SIR mapping, assuming +packets are received with CHECKSUM_COMPLETE: + + $ ip a show dev eth0 + 14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 + link/ether 62:ae:35:9e:0f:8d brd ff:ff:ff:ff:ff:ff link-netnsid 0 + inet6 3333:0:0:1::c078/64 scope global + valid_lft forever preferred_lft forever + inet6 fd00:10:244:1::c078/128 scope global nodad + valid_lft forever preferred_lft forever + inet6 fe80::60ae:35ff:fe9e:f8d/64 scope link proto kernel_ll + valid_lft forever preferred_lft forever + $ ip ila add loc_match fd00:10:244:1 loc 3333:0:0:1 \ + csum-mode adj-transport ident-type luid dev eth0 + +Then I hit [fd00:10:244:1::c078]:8000 with a server listening only on +[3333:0:0:1::c078]:8000. With the bug, the SYN packet is dropped with +SKB_DROP_REASON_TCP_CSUM after inet_proto_csum_replace_by_diff changed +skb->csum. The translation and drop are visible on pwru [1] traces: + + IFACE TUPLE FUNC + eth0:9 [fd00:10:244:3::3d8]:51420->[fd00:10:244:1::c078]:8000(tcp) ipv6_rcv + eth0:9 [fd00:10:244:3::3d8]:51420->[fd00:10:244:1::c078]:8000(tcp) ip6_rcv_core + eth0:9 [fd00:10:244:3::3d8]:51420->[fd00:10:244:1::c078]:8000(tcp) nf_hook_slow + eth0:9 [fd00:10:244:3::3d8]:51420->[fd00:10:244:1::c078]:8000(tcp) inet_proto_csum_replace_by_diff + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) tcp_v6_early_demux + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) ip6_route_input + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) ip6_input + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) ip6_input_finish + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) ip6_protocol_deliver_rcu + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) raw6_local_deliver + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) ipv6_raw_deliver + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) tcp_v6_rcv + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) __skb_checksum_complete + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) kfree_skb_reason(SKB_DROP_REASON_TCP_CSUM) + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) skb_release_head_state + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) skb_release_data + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) skb_free_head + eth0:9 [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp) kfree_skbmem + +This is happening because inet_proto_csum_replace_by_diff is updating +skb->csum when it shouldn't. The L4 checksum is updated such that it +"cancels" the IPv6 address change in terms of checksum computation, so +the impact on skb->csum is null. + +Note this would be different for an IPv4 packet since three fields +would be updated: the IPv4 address, the IP checksum, and the L4 +checksum. Two would cancel each other and skb->csum would still need +to be updated to take the L4 checksum change into account. + +This patch fixes it by passing an ipv6 flag to +inet_proto_csum_replace_by_diff, to skip the skb->csum update if we're +in the IPv6 case. Note the behavior of the only other user of +inet_proto_csum_replace_by_diff, the BPF subsystem, is left as is in +this patch and fixed in the subsequent patch. + +With the fix, using the reproduction from above, I can confirm +skb->csum is not touched by inet_proto_csum_replace_by_diff and the TCP +SYN proceeds to the application after the ILA translation. + +Link: https://github.com/cilium/pwru [1] +Fixes: 65d7ab8de582 ("net: Identifier Locator Addressing module") +Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com> +Acked-by: Daniel Borkmann <daniel@iogearbox.net> +Link: https://patch.msgid.link/b5539869e3550d46068504feb02d37653d939c0b.1748509484.git.paul.chaignon@gmail.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + include/net/checksum.h | 2 +- + net/core/filter.c | 2 +- + net/core/utils.c | 4 ++-- + net/ipv6/ila/ila_common.c | 6 +++--- + 4 files changed, 7 insertions(+), 7 deletions(-) + +--- a/include/net/checksum.h ++++ b/include/net/checksum.h +@@ -158,7 +158,7 @@ void inet_proto_csum_replace16(__sum16 * + const __be32 *from, const __be32 *to, + bool pseudohdr); + void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb, +- __wsum diff, bool pseudohdr); ++ __wsum diff, bool pseudohdr, bool ipv6); + + static __always_inline + void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb, +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -1987,7 +1987,7 @@ BPF_CALL_5(bpf_l4_csum_replace, struct s + if (unlikely(from != 0)) + return -EINVAL; + +- inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo); ++ inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo, false); + break; + case 2: + inet_proto_csum_replace2(ptr, skb, from, to, is_pseudo); +--- a/net/core/utils.c ++++ b/net/core/utils.c +@@ -473,11 +473,11 @@ void inet_proto_csum_replace16(__sum16 * + EXPORT_SYMBOL(inet_proto_csum_replace16); + + void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb, +- __wsum diff, bool pseudohdr) ++ __wsum diff, bool pseudohdr, bool ipv6) + { + if (skb->ip_summed != CHECKSUM_PARTIAL) { + csum_replace_by_diff(sum, diff); +- if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) ++ if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr && !ipv6) + skb->csum = ~csum_sub(diff, skb->csum); + } else if (pseudohdr) { + *sum = ~csum_fold(csum_add(diff, csum_unfold(*sum))); +--- a/net/ipv6/ila/ila_common.c ++++ b/net/ipv6/ila/ila_common.c +@@ -86,7 +86,7 @@ static void ila_csum_adjust_transport(st + + diff = get_csum_diff(ip6h, p); + inet_proto_csum_replace_by_diff(&th->check, skb, +- diff, true); ++ diff, true, true); + } + break; + case NEXTHDR_UDP: +@@ -97,7 +97,7 @@ static void ila_csum_adjust_transport(st + if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { + diff = get_csum_diff(ip6h, p); + inet_proto_csum_replace_by_diff(&uh->check, skb, +- diff, true); ++ diff, true, true); + if (!uh->check) + uh->check = CSUM_MANGLED_0; + } +@@ -111,7 +111,7 @@ static void ila_csum_adjust_transport(st + + diff = get_csum_diff(ip6h, p); + inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb, +- diff, true); ++ diff, true, true); + } + break; + } diff --git a/queue-6.6/series b/queue-6.6/series index a2021f61693..aaa356d1d63 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -236,3 +236,8 @@ alsa-hda-intel-add-thinkpad-e15-to-pm-deny-list.patch alsa-hda-realtek-enable-headset-mic-on-latitude-5420-rugged.patch iio-accel-fxls8962af-fix-temperature-calculation.patch mm-hugetlb-unshare-page-tables-during-vma-split-not-before.patch +mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch +net-fix-checksum-update-for-ila-adj-transport.patch +bpf-fix-l4-csum-update-on-ipv6-in-checksum_complete.patch +erofs-remove-unused-trace-event-erofs_destroy_inode.patch +sunrpc-handle-svc_garbage-during-svc-auth-processing-as-auth-error.patch diff --git a/queue-6.6/sunrpc-handle-svc_garbage-during-svc-auth-processing-as-auth-error.patch b/queue-6.6/sunrpc-handle-svc_garbage-during-svc-auth-processing-as-auth-error.patch new file mode 100644 index 00000000000..27b72cfa55e --- /dev/null +++ b/queue-6.6/sunrpc-handle-svc_garbage-during-svc-auth-processing-as-auth-error.patch @@ -0,0 +1,67 @@ +From 94d10a4dba0bc482f2b01e39f06d5513d0f75742 Mon Sep 17 00:00:00 2001 +From: Jeff Layton <jlayton@kernel.org> +Date: Thu, 19 Jun 2025 06:01:55 -0400 +Subject: sunrpc: handle SVC_GARBAGE during svc auth processing as auth error + +From: Jeff Layton <jlayton@kernel.org> + +commit 94d10a4dba0bc482f2b01e39f06d5513d0f75742 upstream. + +tianshuo han reported a remotely-triggerable crash if the client sends a +kernel RPC server a specially crafted packet. If decoding the RPC reply +fails in such a way that SVC_GARBAGE is returned without setting the +rq_accept_statp pointer, then that pointer can be dereferenced and a +value stored there. + +If it's the first time the thread has processed an RPC, then that +pointer will be set to NULL and the kernel will crash. In other cases, +it could create a memory scribble. + +The server sunrpc code treats a SVC_GARBAGE return from svc_authenticate +or pg_authenticate as if it should send a GARBAGE_ARGS reply. RFC 5531 +says that if authentication fails that the RPC should be rejected +instead with a status of AUTH_ERR. + +Handle a SVC_GARBAGE return as an AUTH_ERROR, with a reason of +AUTH_BADCRED instead of returning GARBAGE_ARGS in that case. This +sidesteps the whole problem of touching the rpc_accept_statp pointer in +this situation and avoids the crash. + +Cc: stable@kernel.org +Fixes: 29cd2927fb91 ("SUNRPC: Fix encoding of accepted but unsuccessful RPC replies") +Reported-by: tianshuo han <hantianshuo233@gmail.com> +Reviewed-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + net/sunrpc/svc.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -1344,7 +1344,8 @@ svc_process_common(struct svc_rqst *rqst + case SVC_OK: + break; + case SVC_GARBAGE: +- goto err_garbage_args; ++ rqstp->rq_auth_stat = rpc_autherr_badcred; ++ goto err_bad_auth; + case SVC_SYSERR: + goto err_system_err; + case SVC_DENIED: +@@ -1485,14 +1486,6 @@ err_bad_proc: + *rqstp->rq_accept_statp = rpc_proc_unavail; + goto sendit; + +-err_garbage_args: +- svc_printk(rqstp, "failed to decode RPC header\n"); +- +- if (serv->sv_stats) +- serv->sv_stats->rpcbadfmt++; +- *rqstp->rq_accept_statp = rpc_garbage_args; +- goto sendit; +- + err_system_err: + if (serv->sv_stats) + serv->sv_stats->rpcbadfmt++; |