From: Sasha Levin Date: Sat, 28 Dec 2024 23:39:31 +0000 (-0500) Subject: Fixes for 5.10 X-Git-Tag: v6.1.123~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=95cbf4ad8820965ba0f580e0ebd0a70082af8d6d;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/bpf-check-validity-of-link-type-in-bpf_link_show_fdi.patch b/queue-5.10/bpf-check-validity-of-link-type-in-bpf_link_show_fdi.patch new file mode 100644 index 00000000000..de6fc7ccf7d --- /dev/null +++ b/queue-5.10/bpf-check-validity-of-link-type-in-bpf_link_show_fdi.patch @@ -0,0 +1,60 @@ +From 2450c201d8434f95f15516984c449ffd70aca2bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Dec 2024 14:04:35 +0800 +Subject: bpf: Check validity of link->type in bpf_link_show_fdinfo() + +From: Hou Tao + +commit 8421d4c8762bd022cb491f2f0f7019ef51b4f0a7 upstream. + +If a newly-added link type doesn't invoke BPF_LINK_TYPE(), accessing +bpf_link_type_strs[link->type] may result in an out-of-bounds access. + +To spot such missed invocations early in the future, checking the +validity of link->type in bpf_link_show_fdinfo() and emitting a warning +when such invocations are missed. + +Signed-off-by: Hou Tao +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20241024013558.1135167-3-houtao@huaweicloud.com +[ shung-hsi.yu: break up existing seq_printf() call since commit 68b04864ca42 + ("bpf: Create links for BPF struct_ops maps.") is not present ] +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Sasha Levin +--- + kernel/bpf/syscall.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index fbe7f8e2b022..b5d9bba73834 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -2427,16 +2427,21 @@ static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp) + { + const struct bpf_link *link = filp->private_data; + const struct bpf_prog *prog = link->prog; ++ enum bpf_link_type type = link->type; + char prog_tag[sizeof(prog->tag) * 2 + 1] = { }; + ++ if (type < ARRAY_SIZE(bpf_link_type_strs) && bpf_link_type_strs[type]) { ++ seq_printf(m, "link_type:\t%s\n", bpf_link_type_strs[type]); ++ } else { ++ WARN_ONCE(1, "missing BPF_LINK_TYPE(...) for link type %u\n", type); ++ seq_printf(m, "link_type:\t<%u>\n", type); ++ } ++ seq_printf(m, "link_id:\t%u\n", link->id); ++ + bin2hex(prog_tag, prog->tag, sizeof(prog->tag)); + seq_printf(m, +- "link_type:\t%s\n" +- "link_id:\t%u\n" + "prog_tag:\t%s\n" + "prog_id:\t%u\n", +- bpf_link_type_strs[link->type], +- link->id, + prog_tag, + prog->aux->id); + if (link->ops->show_fdinfo) +-- +2.39.5 + diff --git a/queue-5.10/ipv6-fix-possible-uaf-in-ip6_finish_output2.patch b/queue-5.10/ipv6-fix-possible-uaf-in-ip6_finish_output2.patch new file mode 100644 index 00000000000..9f4cc40477d --- /dev/null +++ b/queue-5.10/ipv6-fix-possible-uaf-in-ip6_finish_output2.patch @@ -0,0 +1,52 @@ +From c4385716fd13bf7c5fa96dab92028f4298c2d47f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 21:16:24 -0800 +Subject: ipv6: fix possible UAF in ip6_finish_output2() + +From: Eric Dumazet + +[ Upstream commit e891b36de161fcd96f12ff83667473e5067b9037 ] + +If skb_expand_head() returns NULL, skb has been freed +and associated dst/idev could also have been freed. + +We need to hold rcu_read_lock() to make sure the dst and +associated idev are alive. + +Fixes: 5796015fa968 ("ipv6: allocate enough headroom in ip6_finish_output2()") +Signed-off-by: Eric Dumazet +Cc: Vasily Averin +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20240820160859.3786976-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +(cherry picked from commit e891b36de161fcd96f12ff83667473e5067b9037) +Signed-off-by: Harshvardhan Jha +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_output.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index a8475848d038..48f926157ef8 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -69,11 +69,15 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + + /* Be paranoid, rather than too clever. */ + if (unlikely(hh_len > skb_headroom(skb)) && dev->header_ops) { ++ /* Make sure idev stays alive */ ++ rcu_read_lock(); + skb = skb_expand_head(skb, hh_len); + if (!skb) { + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); ++ rcu_read_unlock(); + return -ENOMEM; + } ++ rcu_read_unlock(); + } + + hdr = ipv6_hdr(skb); +-- +2.39.5 + diff --git a/queue-5.10/ipv6-use-skb_expand_head-in-ip6_finish_output2.patch b/queue-5.10/ipv6-use-skb_expand_head-in-ip6_finish_output2.patch new file mode 100644 index 00000000000..1037dabf997 --- /dev/null +++ b/queue-5.10/ipv6-use-skb_expand_head-in-ip6_finish_output2.patch @@ -0,0 +1,130 @@ +From 1a90731ec228f67086bdf801481bbc36936e0b4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 21:16:22 -0800 +Subject: ipv6: use skb_expand_head in ip6_finish_output2 + +From: Vasily Averin + +[ Upstream commit e415ed3a4b8b246ee5e9d109ff5153efcf96b9f2 ] + +Unlike skb_realloc_headroom, new helper skb_expand_head does not allocate +a new skb if possible. + +Additionally this patch replaces commonly used dereferencing with variables. + +Signed-off-by: Vasily Averin +Signed-off-by: David S. Miller +(cherry picked from commit e415ed3a4b8b246ee5e9d109ff5153efcf96b9f2) +Signed-off-by: Harshvardhan Jha +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_output.c | 51 ++++++++++++++----------------------------- + 1 file changed, 16 insertions(+), 35 deletions(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 26d8105981e9..7806963b4539 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -60,46 +60,29 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + { + struct dst_entry *dst = skb_dst(skb); + struct net_device *dev = dst->dev; ++ struct inet6_dev *idev = ip6_dst_idev(dst); + unsigned int hh_len = LL_RESERVED_SPACE(dev); +- int delta = hh_len - skb_headroom(skb); +- const struct in6_addr *nexthop; ++ const struct in6_addr *daddr, *nexthop; ++ struct ipv6hdr *hdr; + struct neighbour *neigh; + int ret; + + /* Be paranoid, rather than too clever. */ +- if (unlikely(delta > 0) && dev->header_ops) { +- /* pskb_expand_head() might crash, if skb is shared */ +- if (skb_shared(skb)) { +- struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); +- +- if (likely(nskb)) { +- if (skb->sk) +- skb_set_owner_w(nskb, skb->sk); +- consume_skb(skb); +- } else { +- kfree_skb(skb); +- } +- skb = nskb; +- } +- if (skb && +- pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { +- kfree_skb(skb); +- skb = NULL; +- } ++ if (unlikely(hh_len > skb_headroom(skb)) && dev->header_ops) { ++ skb = skb_expand_head(skb, hh_len); + if (!skb) { +- IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS); ++ IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); + return -ENOMEM; + } + } + +- if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { +- struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); +- ++ hdr = ipv6_hdr(skb); ++ daddr = &hdr->daddr; ++ if (ipv6_addr_is_multicast(daddr)) { + if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(sk) && + ((mroute6_is_socket(net, skb) && + !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || +- ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, +- &ipv6_hdr(skb)->saddr))) { ++ ipv6_chk_mcast_addr(dev, daddr, &hdr->saddr))) { + struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); + + /* Do not check for IFF_ALLMULTI; multicast routing +@@ -110,7 +93,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + net, sk, newskb, NULL, newskb->dev, + dev_loopback_xmit); + +- if (ipv6_hdr(skb)->hop_limit == 0) { ++ if (hdr->hop_limit == 0) { + IP6_INC_STATS(net, idev, + IPSTATS_MIB_OUTDISCARDS); + kfree_skb(skb); +@@ -119,9 +102,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + } + + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, skb->len); +- +- if (IPV6_ADDR_MC_SCOPE(&ipv6_hdr(skb)->daddr) <= +- IPV6_ADDR_SCOPE_NODELOCAL && ++ if (IPV6_ADDR_MC_SCOPE(daddr) <= IPV6_ADDR_SCOPE_NODELOCAL && + !(dev->flags & IFF_LOOPBACK)) { + kfree_skb(skb); + return 0; +@@ -136,10 +117,10 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + } + + rcu_read_lock_bh(); +- nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr); +- neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); ++ nexthop = rt6_nexthop((struct rt6_info *)dst, daddr); ++ neigh = __ipv6_neigh_lookup_noref(dev, nexthop); + if (unlikely(!neigh)) +- neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false); ++ neigh = __neigh_create(&nd_tbl, nexthop, dev, false); + if (!IS_ERR(neigh)) { + sock_confirm_neigh(skb, neigh); + ret = neigh_output(neigh, skb, false); +@@ -148,7 +129,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + } + rcu_read_unlock_bh(); + +- IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); ++ IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES); + kfree_skb(skb); + return -EINVAL; + } +-- +2.39.5 + diff --git a/queue-5.10/ipv6-use-skb_expand_head-in-ip6_xmit.patch b/queue-5.10/ipv6-use-skb_expand_head-in-ip6_xmit.patch new file mode 100644 index 00000000000..5d7de0a4e44 --- /dev/null +++ b/queue-5.10/ipv6-use-skb_expand_head-in-ip6_xmit.patch @@ -0,0 +1,98 @@ +From f9042eb743dcd072a62a22fcf4cd71304b3176f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 21:16:23 -0800 +Subject: ipv6: use skb_expand_head in ip6_xmit + +From: Vasily Averin + +[ Upstream commit 0c9f227bee11910a49e1d159abe102d06e3745d5 ] + +Unlike skb_realloc_headroom, new helper skb_expand_head +does not allocate a new skb if possible. + +Additionally this patch replaces commonly used dereferencing with variables. + +Signed-off-by: Vasily Averin +Signed-off-by: David S. Miller +(cherry picked from commit 0c9f227bee11910a49e1d159abe102d06e3745d5) +Signed-off-by: Harshvardhan Jha +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_output.c | 27 +++++++++++---------------- + 1 file changed, 11 insertions(+), 16 deletions(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 7806963b4539..a8475848d038 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -254,6 +254,8 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, + const struct ipv6_pinfo *np = inet6_sk(sk); + struct in6_addr *first_hop = &fl6->daddr; + struct dst_entry *dst = skb_dst(skb); ++ struct net_device *dev = dst->dev; ++ struct inet6_dev *idev = ip6_dst_idev(dst); + unsigned int head_room; + struct ipv6hdr *hdr; + u8 proto = fl6->flowi6_proto; +@@ -261,22 +263,16 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, + int hlimit = -1; + u32 mtu; + +- head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev); ++ head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dev); + if (opt) + head_room += opt->opt_nflen + opt->opt_flen; + +- if (unlikely(skb_headroom(skb) < head_room)) { +- struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); +- if (!skb2) { +- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), +- IPSTATS_MIB_OUTDISCARDS); +- kfree_skb(skb); ++ if (unlikely(head_room > skb_headroom(skb))) { ++ skb = skb_expand_head(skb, head_room); ++ if (!skb) { ++ IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); + return -ENOBUFS; + } +- if (skb->sk) +- skb_set_owner_w(skb2, skb->sk); +- consume_skb(skb); +- skb = skb2; + } + + if (opt) { +@@ -318,8 +314,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, + + mtu = dst_mtu(dst); + if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) { +- IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), +- IPSTATS_MIB_OUT, skb->len); ++ IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); + + /* if egress device is enslaved to an L3 master device pass the + * skb to its handler for processing +@@ -332,17 +327,17 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, + * we promote our socket to non const + */ + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, +- net, (struct sock *)sk, skb, NULL, dst->dev, ++ net, (struct sock *)sk, skb, NULL, dev, + dst_output); + } + +- skb->dev = dst->dev; ++ skb->dev = dev; + /* ipv6_local_error() does not require socket lock, + * we promote our socket to non const + */ + ipv6_local_error((struct sock *)sk, EMSGSIZE, fl6, mtu); + +- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); ++ IP6_INC_STATS(net, idev, IPSTATS_MIB_FRAGFAILS); + kfree_skb(skb); + return -EMSGSIZE; + } +-- +2.39.5 + diff --git a/queue-5.10/mips-probe-toolchain-support-of-msym32.patch b/queue-5.10/mips-probe-toolchain-support-of-msym32.patch new file mode 100644 index 00000000000..393d3f03202 --- /dev/null +++ b/queue-5.10/mips-probe-toolchain-support-of-msym32.patch @@ -0,0 +1,38 @@ +From f98f5c3de0d2365a4e0063275abe8ea0e8c4abeb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 14:09:18 +0800 +Subject: MIPS: Probe toolchain support of -msym32 + +From: Jiaxun Yang + +[ Upstream commit 18ca63a2e23c5e170d2d7552b64b1f5ad019cd9b ] + +msym32 is not supported by LLVM toolchain. +Workaround by probe toolchain support of msym32 for KBUILD_SYM32 +feature. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1544 +Signed-off-by: Jiaxun Yang +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: WangYuli +Signed-off-by: Sasha Levin +--- + arch/mips/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/mips/Makefile b/arch/mips/Makefile +index acab8018ab44..289fb4b88d0e 100644 +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -272,7 +272,7 @@ drivers-$(CONFIG_PCI) += arch/mips/pci/ + ifdef CONFIG_64BIT + ifndef KBUILD_SYM32 + ifeq ($(shell expr $(load-y) \< 0xffffffff80000000), 0) +- KBUILD_SYM32 = y ++ KBUILD_SYM32 = $(call cc-option-yn, -msym32) + endif + endif + +-- +2.39.5 + diff --git a/queue-5.10/series b/queue-5.10/series index f43659329d9..8373322e439 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -65,3 +65,9 @@ platform-x86-asus-nb-wmi-ignore-unknown-event-0xcf.patch scsi-mpt3sas-diag-reset-when-doorbell-in-use-bit-is-.patch scsi-storvsc-do-not-flag-maintenance_in-return-of-sr.patch virtio-blk-don-t-keep-queue-frozen-during-system-sus.patch +mips-probe-toolchain-support-of-msym32.patch +skbuff-introduce-skb_expand_head.patch +ipv6-use-skb_expand_head-in-ip6_finish_output2.patch +ipv6-use-skb_expand_head-in-ip6_xmit.patch +ipv6-fix-possible-uaf-in-ip6_finish_output2.patch +bpf-check-validity-of-link-type-in-bpf_link_show_fdi.patch diff --git a/queue-5.10/skbuff-introduce-skb_expand_head.patch b/queue-5.10/skbuff-introduce-skb_expand_head.patch new file mode 100644 index 00000000000..f2cba7b7d1d --- /dev/null +++ b/queue-5.10/skbuff-introduce-skb_expand_head.patch @@ -0,0 +1,94 @@ +From 804c67eb0b72c6906181767deaa9fc0963a1ae5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 21:16:21 -0800 +Subject: skbuff: introduce skb_expand_head() + +From: Vasily Averin + +[ Upstream commit f1260ff15a71b8fc122b2c9abd8a7abffb6e0168 ] + +Like skb_realloc_headroom(), new helper increases headroom of specified skb. +Unlike skb_realloc_headroom(), it does not allocate a new skb if possible; +copies skb->sk on new skb when as needed and frees original skb in case +of failures. + +This helps to simplify ip[6]_finish_output2() and a few other similar cases. + +Signed-off-by: Vasily Averin +Signed-off-by: David S. Miller +(cherry picked from commit f1260ff15a71b8fc122b2c9abd8a7abffb6e0168) +Signed-off-by: Harshvardhan Jha +Signed-off-by: Sasha Levin +--- + include/linux/skbuff.h | 1 + + net/core/skbuff.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 31ae4b74d435..3248e4aeec03 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1166,6 +1166,7 @@ static inline struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, + int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask); + struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, + unsigned int headroom); ++struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom); + struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom, + int newtailroom, gfp_t priority); + int __must_check skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg, +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index b0c2d6f01800..fa3ea287d6ec 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -1732,6 +1732,48 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) + } + EXPORT_SYMBOL(skb_realloc_headroom); + ++/** ++ * skb_expand_head - reallocate header of &sk_buff ++ * @skb: buffer to reallocate ++ * @headroom: needed headroom ++ * ++ * Unlike skb_realloc_headroom, this one does not allocate a new skb ++ * if possible; copies skb->sk to new skb as needed ++ * and frees original skb in case of failures. ++ * ++ * It expect increased headroom and generates warning otherwise. ++ */ ++ ++struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom) ++{ ++ int delta = headroom - skb_headroom(skb); ++ ++ if (WARN_ONCE(delta <= 0, ++ "%s is expecting an increase in the headroom", __func__)) ++ return skb; ++ ++ /* pskb_expand_head() might crash, if skb is shared */ ++ if (skb_shared(skb)) { ++ struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); ++ ++ if (likely(nskb)) { ++ if (skb->sk) ++ skb_set_owner_w(nskb, skb->sk); ++ consume_skb(skb); ++ } else { ++ kfree_skb(skb); ++ } ++ skb = nskb; ++ } ++ if (skb && ++ pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { ++ kfree_skb(skb); ++ skb = NULL; ++ } ++ return skb; ++} ++EXPORT_SYMBOL(skb_expand_head); ++ + /** + * skb_copy_expand - copy and expand sk_buff + * @skb: buffer to copy +-- +2.39.5 +