From: Sasha Levin Date: Tue, 18 Feb 2025 12:30:07 +0000 (-0500) Subject: Fixes for 5.4 X-Git-Tag: v6.1.129~50^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aeb15eeeb3f1c38ddd02d2a7a53b7a516a8a5833;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/arp-use-rcu-protection-in-arp_xmit.patch b/queue-5.4/arp-use-rcu-protection-in-arp_xmit.patch new file mode 100644 index 0000000000..1b48f38e97 --- /dev/null +++ b/queue-5.4/arp-use-rcu-protection-in-arp_xmit.patch @@ -0,0 +1,45 @@ +From 582226d4457e8e7aebf6c3833ca8e0d2d039aedc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:58:36 +0000 +Subject: arp: use RCU protection in arp_xmit() + +From: Eric Dumazet + +[ Upstream commit a42b69f692165ec39db42d595f4f65a4c8f42e44 ] + +arp_xmit() can be called without RTNL or RCU protection. + +Use RCU protection to avoid potential UAF. + +Fixes: 29a26a568038 ("netfilter: Pass struct net into the netfilter hooks") +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250207135841.1948589-5-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/arp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c +index b8fe943ae89d0..9455b96449e5a 100644 +--- a/net/ipv4/arp.c ++++ b/net/ipv4/arp.c +@@ -637,10 +637,12 @@ static int arp_xmit_finish(struct net *net, struct sock *sk, struct sk_buff *skb + */ + void arp_xmit(struct sk_buff *skb) + { ++ rcu_read_lock(); + /* Send it off, maybe filter it using firewalling first. */ + NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, +- dev_net(skb->dev), NULL, skb, NULL, skb->dev, ++ dev_net_rcu(skb->dev), NULL, skb, NULL, skb->dev, + arp_xmit_finish); ++ rcu_read_unlock(); + } + EXPORT_SYMBOL(arp_xmit); + +-- +2.39.5 + diff --git a/queue-5.4/ipv4-use-rcu-protection-in-inet_select_addr.patch b/queue-5.4/ipv4-use-rcu-protection-in-inet_select_addr.patch new file mode 100644 index 0000000000..37dff06ccf --- /dev/null +++ b/queue-5.4/ipv4-use-rcu-protection-in-inet_select_addr.patch @@ -0,0 +1,41 @@ +From dffd10aa1dace313c447d5bf86109032bff4e72c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 15:51:14 +0000 +Subject: ipv4: use RCU protection in inet_select_addr() + +From: Eric Dumazet + +[ Upstream commit 719817cd293e4fa389e1f69c396f3f816ed5aa41 ] + +inet_select_addr() must use RCU protection to make +sure the net structure it reads does not disappear. + +Fixes: c4544c724322 ("[NETNS]: Process inet_select_addr inside a namespace.") +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250205155120.1676781-7-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/devinet.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c +index 9910844c890ba..6855372d57a34 100644 +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -1317,10 +1317,11 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) + __be32 addr = 0; + unsigned char localnet_scope = RT_SCOPE_HOST; + struct in_device *in_dev; +- struct net *net = dev_net(dev); ++ struct net *net; + int master_idx; + + rcu_read_lock(); ++ net = dev_net_rcu(dev); + in_dev = __in_dev_get_rcu(dev); + if (!in_dev) + goto no_in_dev; +-- +2.39.5 + diff --git a/queue-5.4/ipv4-use-rcu-protection-in-rt_is_expired.patch b/queue-5.4/ipv4-use-rcu-protection-in-rt_is_expired.patch new file mode 100644 index 0000000000..957621b8dc --- /dev/null +++ b/queue-5.4/ipv4-use-rcu-protection-in-rt_is_expired.patch @@ -0,0 +1,44 @@ +From fd7f0e49678f7b8c37a9f65aa42382c33e07a0ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 15:51:13 +0000 +Subject: ipv4: use RCU protection in rt_is_expired() + +From: Eric Dumazet + +[ Upstream commit dd205fcc33d92d54eee4d7f21bb073af9bd5ce2b ] + +rt_is_expired() must use RCU protection to make +sure the net structure it reads does not disappear. + +Fixes: e84f84f27647 ("netns: place rt_genid into struct net") +Signed-off-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250205155120.1676781-6-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index f3e77b1e1d4b9..da280a2df4e66 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -423,7 +423,13 @@ static inline int ip_rt_proc_init(void) + + static inline bool rt_is_expired(const struct rtable *rth) + { +- return rth->rt_genid != rt_genid_ipv4(dev_net(rth->dst.dev)); ++ bool res; ++ ++ rcu_read_lock(); ++ res = rth->rt_genid != rt_genid_ipv4(dev_net_rcu(rth->dst.dev)); ++ rcu_read_unlock(); ++ ++ return res; + } + + void rt_cache_flush(struct net *net) +-- +2.39.5 + diff --git a/queue-5.4/ipv6-use-rcu-protection-in-ip6_default_advmss.patch b/queue-5.4/ipv6-use-rcu-protection-in-ip6_default_advmss.patch new file mode 100644 index 0000000000..60e569a097 --- /dev/null +++ b/queue-5.4/ipv6-use-rcu-protection-in-ip6_default_advmss.patch @@ -0,0 +1,49 @@ +From c71fae8b68e472255c64a3b2b9d145b221010f12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 15:51:18 +0000 +Subject: ipv6: use RCU protection in ip6_default_advmss() + +From: Eric Dumazet + +[ Upstream commit 3c8ffcd248da34fc41e52a46e51505900115fc2a ] + +ip6_default_advmss() needs rcu protection to make +sure the net structure it reads does not disappear. + +Fixes: 5578689a4e3c ("[NETNS][IPV6] route6 - make route6 per namespace") +Signed-off-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250205155120.1676781-11-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/route.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 364abcf4b6c14..99908861246d3 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -3090,13 +3090,18 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst) + { + struct net_device *dev = dst->dev; + unsigned int mtu = dst_mtu(dst); +- struct net *net = dev_net(dev); ++ struct net *net; + + mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); + ++ rcu_read_lock(); ++ ++ net = dev_net_rcu(dev); + if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) + mtu = net->ipv6.sysctl.ip6_rt_min_advmss; + ++ rcu_read_unlock(); ++ + /* + * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and + * corresponding MSS is IPV6_MAXPLEN - tcp_header_size. +-- +2.39.5 + diff --git a/queue-5.4/mips-fix-mips_get_syscall_arg-for-o32.patch b/queue-5.4/mips-fix-mips_get_syscall_arg-for-o32.patch new file mode 100644 index 0000000000..ff343fcd8a --- /dev/null +++ b/queue-5.4/mips-fix-mips_get_syscall_arg-for-o32.patch @@ -0,0 +1,132 @@ +From de89111213a3fb4751245214dc4dd590ed153d29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 01:02:09 +0200 +Subject: MIPS: fix mips_get_syscall_arg() for o32 + +From: Dmitry V. Levin + +[ Upstream commit 733a90561ad0a4a74035d2d627098da85d43b592 ] + +This makes ptrace/get_syscall_info selftest pass on mips o32 and +mips64 o32 by fixing the following two test assertions: + +1. get_syscall_info test assertion on mips o32: + # get_syscall_info.c:218:get_syscall_info:Expected exp_args[5] (3134521044) == info.entry.args[4] (4911432) + # get_syscall_info.c:219:get_syscall_info:wait #1: entry stop mismatch + +2. get_syscall_info test assertion on mips64 o32: + # get_syscall_info.c:209:get_syscall_info:Expected exp_args[2] (3134324433) == info.entry.args[1] (18446744072548908753) + # get_syscall_info.c:210:get_syscall_info:wait #1: entry stop mismatch + +The first assertion happens due to mips_get_syscall_arg() trying to access +another task's context but failing to do it properly because get_user() it +calls just peeks at the current task's context. It usually does not crash +because the default user stack always gets assigned the same VMA, but it +is pure luck which mips_get_syscall_arg() wouldn't have if e.g. the stack +was switched (via setcontext(3) or however) or a non-default process's +thread peeked at, and in any case irrelevant data is obtained just as +observed with the test case. + +mips_get_syscall_arg() ought to be using access_remote_vm() instead to +retrieve the other task's stack contents, but given that the data has been +already obtained and saved in `struct pt_regs' it would be an overkill. + +The first assertion is fixed for mips o32 by using struct pt_regs.args +instead of get_user() to obtain syscall arguments. This approach works +due to this piece in arch/mips/kernel/scall32-o32.S: + + /* + * Ok, copy the args from the luser stack to the kernel stack. + */ + + .set push + .set noreorder + .set nomacro + + load_a4: user_lw(t5, 16(t0)) # argument #5 from usp + load_a5: user_lw(t6, 20(t0)) # argument #6 from usp + load_a6: user_lw(t7, 24(t0)) # argument #7 from usp + load_a7: user_lw(t8, 28(t0)) # argument #8 from usp + loads_done: + + sw t5, PT_ARG4(sp) # argument #5 to ksp + sw t6, PT_ARG5(sp) # argument #6 to ksp + sw t7, PT_ARG6(sp) # argument #7 to ksp + sw t8, PT_ARG7(sp) # argument #8 to ksp + .set pop + + .section __ex_table,"a" + PTR_WD load_a4, bad_stack_a4 + PTR_WD load_a5, bad_stack_a5 + PTR_WD load_a6, bad_stack_a6 + PTR_WD load_a7, bad_stack_a7 + .previous + +arch/mips/kernel/scall64-o32.S has analogous code for mips64 o32 that +allows fixing the issue by obtaining syscall arguments from struct +pt_regs.regs[4..11] instead of the erroneous use of get_user(). + +The second assertion is fixed by truncating 64-bit values to 32-bit +syscall arguments. + +Fixes: c0ff3c53d4f9 ("MIPS: Enable HAVE_ARCH_TRACEHOOK.") +Signed-off-by: Dmitry V. Levin +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/include/asm/syscall.h | 32 ++++++++------------------------ + 1 file changed, 8 insertions(+), 24 deletions(-) + +diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h +index ebdf4d910af2f..056aa1b713e23 100644 +--- a/arch/mips/include/asm/syscall.h ++++ b/arch/mips/include/asm/syscall.h +@@ -57,37 +57,21 @@ static inline void mips_syscall_update_nr(struct task_struct *task, + static inline void mips_get_syscall_arg(unsigned long *arg, + struct task_struct *task, struct pt_regs *regs, unsigned int n) + { +- unsigned long usp __maybe_unused = regs->regs[29]; +- ++#ifdef CONFIG_32BIT + switch (n) { + case 0: case 1: case 2: case 3: + *arg = regs->regs[4 + n]; +- +- return; +- +-#ifdef CONFIG_32BIT +- case 4: case 5: case 6: case 7: +- get_user(*arg, (int *)usp + n); + return; +-#endif +- +-#ifdef CONFIG_64BIT + case 4: case 5: case 6: case 7: +-#ifdef CONFIG_MIPS32_O32 +- if (test_tsk_thread_flag(task, TIF_32BIT_REGS)) +- get_user(*arg, (int *)usp + n); +- else +-#endif +- *arg = regs->regs[4 + n]; +- ++ *arg = regs->args[n]; + return; +-#endif +- +- default: +- BUG(); + } +- +- unreachable(); ++#else ++ *arg = regs->regs[4 + n]; ++ if ((IS_ENABLED(CONFIG_MIPS32_O32) && ++ test_tsk_thread_flag(task, TIF_32BIT_REGS))) ++ *arg = (unsigned int)*arg; ++#endif + } + + static inline long syscall_get_error(struct task_struct *task, +-- +2.39.5 + diff --git a/queue-5.4/ndisc-extend-rcu-protection-in-ndisc_send_skb.patch b/queue-5.4/ndisc-extend-rcu-protection-in-ndisc_send_skb.patch new file mode 100644 index 0000000000..22e6069222 --- /dev/null +++ b/queue-5.4/ndisc-extend-rcu-protection-in-ndisc_send_skb.patch @@ -0,0 +1,72 @@ +From 840e6078d39651822a37d65f9eae635486a9c08c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:58:39 +0000 +Subject: ndisc: extend RCU protection in ndisc_send_skb() + +From: Eric Dumazet + +[ Upstream commit ed6ae1f325d3c43966ec1b62ac1459e2b8e45640 ] + +ndisc_send_skb() can be called without RTNL or RCU held. + +Acquire rcu_read_lock() earlier, so that we can use dev_net_rcu() +and avoid a potential UAF. + +Fixes: 1762f7e88eb3 ("[NETNS][IPV6] ndisc - make socket control per namespace") +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250207135841.1948589-8-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ndisc.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index 92e35b3096dba..fe10f1ce167be 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -470,16 +470,20 @@ static void ndisc_send_skb(struct sk_buff *skb, + const struct in6_addr *daddr, + const struct in6_addr *saddr) + { ++ struct icmp6hdr *icmp6h = icmp6_hdr(skb); + struct dst_entry *dst = skb_dst(skb); +- struct net *net = dev_net(skb->dev); +- struct sock *sk = net->ipv6.ndisc_sk; + struct inet6_dev *idev; ++ struct net *net; ++ struct sock *sk; + int err; +- struct icmp6hdr *icmp6h = icmp6_hdr(skb); + u8 type; + + type = icmp6h->icmp6_type; + ++ rcu_read_lock(); ++ ++ net = dev_net_rcu(skb->dev); ++ sk = net->ipv6.ndisc_sk; + if (!dst) { + struct flowi6 fl6; + int oif = skb->dev->ifindex; +@@ -487,6 +491,7 @@ static void ndisc_send_skb(struct sk_buff *skb, + icmpv6_flow_init(sk, &fl6, type, saddr, daddr, oif); + dst = icmp6_dst_alloc(skb->dev, &fl6); + if (IS_ERR(dst)) { ++ rcu_read_unlock(); + kfree_skb(skb); + return; + } +@@ -501,7 +506,6 @@ static void ndisc_send_skb(struct sk_buff *skb, + + ip6_nd_hdr(skb, saddr, daddr, inet6_sk(sk)->hop_limit, skb->len); + +- rcu_read_lock(); + idev = __in6_dev_get(dst->dev); + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); + +-- +2.39.5 + diff --git a/queue-5.4/ndisc-use-rcu-protection-in-ndisc_alloc_skb.patch b/queue-5.4/ndisc-use-rcu-protection-in-ndisc_alloc_skb.patch new file mode 100644 index 0000000000..f344064cc2 --- /dev/null +++ b/queue-5.4/ndisc-use-rcu-protection-in-ndisc_alloc_skb.patch @@ -0,0 +1,59 @@ +From 9fce16c45abb367e32957e93301301b15457e958 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:58:34 +0000 +Subject: ndisc: use RCU protection in ndisc_alloc_skb() + +From: Eric Dumazet + +[ Upstream commit 628e6d18930bbd21f2d4562228afe27694f66da9 ] + +ndisc_alloc_skb() can be called without RTNL or RCU being held. + +Add RCU protection to avoid possible UAF. + +Fixes: de09334b9326 ("ndisc: Introduce ndisc_alloc_skb() helper.") +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250207135841.1948589-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ndisc.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index 3096807caecab..92e35b3096dba 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -416,15 +416,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev, + { + int hlen = LL_RESERVED_SPACE(dev); + int tlen = dev->needed_tailroom; +- struct sock *sk = dev_net(dev)->ipv6.ndisc_sk; + struct sk_buff *skb; + + skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC); +- if (!skb) { +- ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n", +- __func__); ++ if (!skb) + return NULL; +- } + + skb->protocol = htons(ETH_P_IPV6); + skb->dev = dev; +@@ -435,7 +431,9 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev, + /* Manually assign socket ownership as we avoid calling + * sock_alloc_send_pskb() to bypass wmem buffer limits + */ +- skb_set_owner_w(skb, sk); ++ rcu_read_lock(); ++ skb_set_owner_w(skb, dev_net_rcu(dev)->ipv6.ndisc_sk); ++ rcu_read_unlock(); + + return skb; + } +-- +2.39.5 + diff --git a/queue-5.4/neighbour-delete-redundant-judgment-statements.patch b/queue-5.4/neighbour-delete-redundant-judgment-statements.patch new file mode 100644 index 0000000000..c38e8749f4 --- /dev/null +++ b/queue-5.4/neighbour-delete-redundant-judgment-statements.patch @@ -0,0 +1,40 @@ +From efd3665f5511367db84446f7d8a7a69dbd3ee8d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Aug 2024 12:32:45 +0800 +Subject: neighbour: delete redundant judgment statements + +From: Li Zetao + +[ Upstream commit c25bdd2ac8cf7da70a226f1a66cdce7af15ff86f ] + +The initial value of err is -ENOBUFS, and err is guaranteed to be +less than 0 before all goto errout. Therefore, on the error path +of errout, there is no need to repeatedly judge that err is less than 0, +and delete redundant judgments to make the code more concise. + +Signed-off-by: Li Zetao +Reviewed-by: Petr Machata +Signed-off-by: David S. Miller +Stable-dep-of: becbd5850c03 ("neighbour: use RCU protection in __neigh_notify()") +Signed-off-by: Sasha Levin +--- + net/core/neighbour.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 4dfe17f1a76aa..3e007cbadb707 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -3382,8 +3382,7 @@ static void __neigh_notify(struct neighbour *n, int type, int flags, + rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); + return; + errout: +- if (err < 0) +- rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); ++ rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); + } + + void neigh_app_ns(struct neighbour *n) +-- +2.39.5 + diff --git a/queue-5.4/neighbour-use-rcu-protection-in-__neigh_notify.patch b/queue-5.4/neighbour-use-rcu-protection-in-__neigh_notify.patch new file mode 100644 index 0000000000..162deadd16 --- /dev/null +++ b/queue-5.4/neighbour-use-rcu-protection-in-__neigh_notify.patch @@ -0,0 +1,58 @@ +From 4e8e7a9bf2fe77f46bb87ecff1f3c934fb01b09a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:58:35 +0000 +Subject: neighbour: use RCU protection in __neigh_notify() + +From: Eric Dumazet + +[ Upstream commit becbd5850c03ed33b232083dd66c6e38c0c0e569 ] + +__neigh_notify() can be called without RTNL or RCU protection. + +Use RCU protection to avoid potential UAF. + +Fixes: 426b5303eb43 ("[NETNS]: Modify the neighbour table code so it handles multiple network namespaces") +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250207135841.1948589-4-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/neighbour.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 3e007cbadb707..7ef3630ea20d7 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -3364,10 +3364,12 @@ static const struct seq_operations neigh_stat_seq_ops = { + static void __neigh_notify(struct neighbour *n, int type, int flags, + u32 pid) + { +- struct net *net = dev_net(n->dev); + struct sk_buff *skb; + int err = -ENOBUFS; ++ struct net *net; + ++ rcu_read_lock(); ++ net = dev_net_rcu(n->dev); + skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC); + if (skb == NULL) + goto errout; +@@ -3380,9 +3382,11 @@ static void __neigh_notify(struct neighbour *n, int type, int flags, + goto errout; + } + rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); +- return; ++ goto out; + errout: + rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); ++out: ++ rcu_read_unlock(); + } + + void neigh_app_ns(struct neighbour *n) +-- +2.39.5 + diff --git a/queue-5.4/net-add-dev_net_rcu-helper.patch b/queue-5.4/net-add-dev_net_rcu-helper.patch new file mode 100644 index 0000000000..a01b158c29 --- /dev/null +++ b/queue-5.4/net-add-dev_net_rcu-helper.patch @@ -0,0 +1,62 @@ +From 0030b820930df1e30ceaaf76f6683202d475a81c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 15:51:09 +0000 +Subject: net: add dev_net_rcu() helper + +From: Eric Dumazet + +[ Upstream commit 482ad2a4ace2740ca0ff1cbc8f3c7f862f3ab507 ] + +dev->nd_net can change, readers should either +use rcu_read_lock() or RTNL. + +We currently use a generic helper, dev_net() with +no debugging support. We probably have many hidden bugs. + +Add dev_net_rcu() helper for callers using rcu_read_lock() +protection. + +Signed-off-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250205155120.1676781-2-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: dd205fcc33d9 ("ipv4: use RCU protection in rt_is_expired()") +Signed-off-by: Sasha Levin +--- + include/linux/netdevice.h | 6 ++++++ + include/net/net_namespace.h | 2 +- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index a6bb64dccb888..f5c1058f565c8 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2216,6 +2216,12 @@ struct net *dev_net(const struct net_device *dev) + return read_pnet(&dev->nd_net); + } + ++static inline ++struct net *dev_net_rcu(const struct net_device *dev) ++{ ++ return read_pnet_rcu(&dev->nd_net); ++} ++ + static inline + void dev_net_set(struct net_device *dev, struct net *net) + { +diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h +index 6ce0ec2dd2032..334286b57994b 100644 +--- a/include/net/net_namespace.h ++++ b/include/net/net_namespace.h +@@ -330,7 +330,7 @@ static inline struct net *read_pnet(const possible_net_t *pnet) + #endif + } + +-static inline struct net *read_pnet_rcu(possible_net_t *pnet) ++static inline struct net *read_pnet_rcu(const possible_net_t *pnet) + { + #ifdef CONFIG_NET_NS + return rcu_dereference(pnet->net); +-- +2.39.5 + diff --git a/queue-5.4/net-treat-possible_net_t-net-pointer-as-an-rcu-one-a.patch b/queue-5.4/net-treat-possible_net_t-net-pointer-as-an-rcu-one-a.patch new file mode 100644 index 0000000000..b95eb8cec0 --- /dev/null +++ b/queue-5.4/net-treat-possible_net_t-net-pointer-as-an-rcu-one-a.patch @@ -0,0 +1,65 @@ +From 3f10851d99a8620c46bcc7f8a4e00bc313663ace Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Oct 2023 14:10:23 +0200 +Subject: net: treat possible_net_t net pointer as an RCU one and add + read_pnet_rcu() + +From: Jiri Pirko + +[ Upstream commit 2034d90ae41ae93e30d492ebcf1f06f97a9cfba6 ] + +Make the net pointer stored in possible_net_t structure annotated as +an RCU pointer. Change the access helpers to treat it as such. +Introduce read_pnet_rcu() helper to allow caller to dereference +the net pointer under RCU read lock. + +Signed-off-by: Jiri Pirko +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Stable-dep-of: dd205fcc33d9 ("ipv4: use RCU protection in rt_is_expired()") +Signed-off-by: Sasha Levin +--- + include/net/net_namespace.h | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h +index 0d61b452b9082..6ce0ec2dd2032 100644 +--- a/include/net/net_namespace.h ++++ b/include/net/net_namespace.h +@@ -310,21 +310,30 @@ static inline int check_net(const struct net *net) + + typedef struct { + #ifdef CONFIG_NET_NS +- struct net *net; ++ struct net __rcu *net; + #endif + } possible_net_t; + + static inline void write_pnet(possible_net_t *pnet, struct net *net) + { + #ifdef CONFIG_NET_NS +- pnet->net = net; ++ rcu_assign_pointer(pnet->net, net); + #endif + } + + static inline struct net *read_pnet(const possible_net_t *pnet) + { + #ifdef CONFIG_NET_NS +- return pnet->net; ++ return rcu_dereference_protected(pnet->net, true); ++#else ++ return &init_net; ++#endif ++} ++ ++static inline struct net *read_pnet_rcu(possible_net_t *pnet) ++{ ++#ifdef CONFIG_NET_NS ++ return rcu_dereference(pnet->net); + #else + return &init_net; + #endif +-- +2.39.5 + diff --git a/queue-5.4/openvswitch-use-rcu-protection-in-ovs_vport_cmd_fill.patch b/queue-5.4/openvswitch-use-rcu-protection-in-ovs_vport_cmd_fill.patch new file mode 100644 index 0000000000..c31902d05d --- /dev/null +++ b/queue-5.4/openvswitch-use-rcu-protection-in-ovs_vport_cmd_fill.patch @@ -0,0 +1,66 @@ +From 79c150fd1fa76b369bdb6e88ebcf0ba41ecb24b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:58:37 +0000 +Subject: openvswitch: use RCU protection in ovs_vport_cmd_fill_info() + +From: Eric Dumazet + +[ Upstream commit 90b2f49a502fa71090d9f4fe29a2f51fe5dff76d ] + +ovs_vport_cmd_fill_info() can be called without RTNL or RCU. + +Use RCU protection and dev_net_rcu() to avoid potential UAF. + +Fixes: 9354d4520342 ("openvswitch: reliable interface indentification in port dumps") +Signed-off-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250207135841.1948589-6-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/datapath.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c +index 4c537e74b18c7..20a57a3dc2813 100644 +--- a/net/openvswitch/datapath.c ++++ b/net/openvswitch/datapath.c +@@ -1912,6 +1912,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, + { + struct ovs_header *ovs_header; + struct ovs_vport_stats vport_stats; ++ struct net *net_vport; + int err; + + ovs_header = genlmsg_put(skb, portid, seq, &dp_vport_genl_family, +@@ -1928,12 +1929,15 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, + nla_put_u32(skb, OVS_VPORT_ATTR_IFINDEX, vport->dev->ifindex)) + goto nla_put_failure; + +- if (!net_eq(net, dev_net(vport->dev))) { +- int id = peernet2id_alloc(net, dev_net(vport->dev), gfp); ++ rcu_read_lock(); ++ net_vport = dev_net_rcu(vport->dev); ++ if (!net_eq(net, net_vport)) { ++ int id = peernet2id_alloc(net, net_vport, GFP_ATOMIC); + + if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id)) +- goto nla_put_failure; ++ goto nla_put_failure_unlock; + } ++ rcu_read_unlock(); + + ovs_vport_get_stats(vport, &vport_stats); + if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS, +@@ -1951,6 +1955,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, + genlmsg_end(skb, ovs_header); + return 0; + ++nla_put_failure_unlock: ++ rcu_read_unlock(); + nla_put_failure: + err = -EMSGSIZE; + error: +-- +2.39.5 + diff --git a/queue-5.4/series b/queue-5.4/series index 47462e5eb3..9a5d22f987 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -189,3 +189,15 @@ serial-8250-fix-fifo-underflow-on-flush.patch alpha-align-stack-for-page-fault-and-user-unaligned-trap-handlers.patch gpio-stmpe-check-return-value-of-stmpe_reg_read-in-stmpe_gpio_irq_sync_unlock.patch partitions-mac-fix-handling-of-bogus-partition-table.patch +net-treat-possible_net_t-net-pointer-as-an-rcu-one-a.patch +net-add-dev_net_rcu-helper.patch +ipv4-use-rcu-protection-in-rt_is_expired.patch +ipv4-use-rcu-protection-in-inet_select_addr.patch +ipv6-use-rcu-protection-in-ip6_default_advmss.patch +ndisc-use-rcu-protection-in-ndisc_alloc_skb.patch +neighbour-delete-redundant-judgment-statements.patch +neighbour-use-rcu-protection-in-__neigh_notify.patch +arp-use-rcu-protection-in-arp_xmit.patch +openvswitch-use-rcu-protection-in-ovs_vport_cmd_fill.patch +ndisc-extend-rcu-protection-in-ndisc_send_skb.patch +mips-fix-mips_get_syscall_arg-for-o32.patch