From: Greg Kroah-Hartman Date: Mon, 30 Dec 2024 15:11:03 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v6.1.123~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0871d70ec44724754a85188d0a7b3ca5773db4f9;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: ipv6-prevent-possible-uaf-in-ip6_xmit.patch skb_expand_head-adjust-skb-truesize-incorrectly.patch --- diff --git a/queue-5.4/ipv6-prevent-possible-uaf-in-ip6_xmit.patch b/queue-5.4/ipv6-prevent-possible-uaf-in-ip6_xmit.patch new file mode 100644 index 00000000000..55858e8f02a --- /dev/null +++ b/queue-5.4/ipv6-prevent-possible-uaf-in-ip6_xmit.patch @@ -0,0 +1,43 @@ +From 2d5ff7e339d04622d8282661df36151906d0e1c7 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 20 Aug 2024 16:08:59 +0000 +Subject: ipv6: prevent possible UAF in ip6_xmit() + +From: Eric Dumazet + +commit 2d5ff7e339d04622d8282661df36151906d0e1c7 upstream. + +If skb_expand_head() returns NULL, skb has been freed +and the associated dst/idev could also have been freed. + +We must use rcu_read_lock() to prevent a possible UAF. + +Fixes: 0c9f227bee11 ("ipv6: use skb_expand_head in ip6_xmit") +Signed-off-by: Eric Dumazet +Cc: Vasily Averin +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20240820160859.3786976-4-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_output.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -271,11 +271,15 @@ int ip6_xmit(const struct sock *sk, stru + head_room += opt->opt_nflen + opt->opt_flen; + + if (unlikely(head_room > skb_headroom(skb))) { ++ /* Make sure idev stays alive */ ++ rcu_read_lock(); + skb = skb_expand_head(skb, head_room); + if (!skb) { + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); ++ rcu_read_unlock(); + return -ENOBUFS; + } ++ rcu_read_unlock(); + } + + if (opt) { diff --git a/queue-5.4/series b/queue-5.4/series index 910b531ed5d..9947a8e7431 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -57,3 +57,5 @@ ipv6-fix-possible-uaf-in-ip6_finish_output2.patch bpf-fix-recursive-lock-when-verdict-program-return-s.patch tracing-constify-string-literal-data-member-in-struct-trace_event_call.patch btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch +skb_expand_head-adjust-skb-truesize-incorrectly.patch +ipv6-prevent-possible-uaf-in-ip6_xmit.patch diff --git a/queue-5.4/skb_expand_head-adjust-skb-truesize-incorrectly.patch b/queue-5.4/skb_expand_head-adjust-skb-truesize-incorrectly.patch new file mode 100644 index 00000000000..fba40128d8b --- /dev/null +++ b/queue-5.4/skb_expand_head-adjust-skb-truesize-incorrectly.patch @@ -0,0 +1,95 @@ +From 7f678def99d29c520418607509bb19c7fc96a6db Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Fri, 22 Oct 2021 13:28:37 +0300 +Subject: skb_expand_head() adjust skb->truesize incorrectly + +From: Vasily Averin + +commit 7f678def99d29c520418607509bb19c7fc96a6db upstream. + +Christoph Paasch reports [1] about incorrect skb->truesize +after skb_expand_head() call in ip6_xmit. +This may happen because of two reasons: +- skb_set_owner_w() for newly cloned skb is called too early, +before pskb_expand_head() where truesize is adjusted for (!skb-sk) case. +- pskb_expand_head() does not adjust truesize in (skb->sk) case. +In this case sk->sk_wmem_alloc should be adjusted too. + +[1] https://lkml.org/lkml/2021/8/20/1082 + +Fixes: f1260ff15a71 ("skbuff: introduce skb_expand_head()") +Fixes: 2d85a1b31dde ("ipv6: ip6_finish_output2: set sk into newly allocated nskb") +Reported-by: Christoph Paasch +Signed-off-by: Vasily Averin +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/644330dd-477e-0462-83bf-9f514c41edd1@virtuozzo.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/core/skbuff.c | 36 +++++++++++++++++++++++------------- + 1 file changed, 23 insertions(+), 13 deletions(-) + create mode 100644 net/core/sock_destructor.h + +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -77,6 +77,7 @@ + #include + + #include "datagram.h" ++#include "sock_destructor.h" + + struct kmem_cache *skbuff_head_cache __ro_after_init; + static struct kmem_cache *skbuff_fclone_cache __ro_after_init; +@@ -1741,30 +1742,39 @@ EXPORT_SYMBOL(skb_realloc_headroom); + struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom) + { + int delta = headroom - skb_headroom(skb); ++ int osize = skb_end_offset(skb); ++ struct sock *sk = skb->sk; + + 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)) { ++ delta = SKB_DATA_ALIGN(delta); ++ /* pskb_expand_head() might crash, if skb is shared. */ ++ if (skb_shared(skb) || !is_skb_wmem(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); +- } ++ if (unlikely(!nskb)) ++ goto fail; ++ ++ if (sk) ++ skb_set_owner_w(nskb, sk); ++ consume_skb(skb); + skb = nskb; + } +- if (skb && +- pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { +- kfree_skb(skb); +- skb = NULL; ++ if (pskb_expand_head(skb, delta, 0, GFP_ATOMIC)) ++ goto fail; ++ ++ if (sk && is_skb_wmem(skb)) { ++ delta = skb_end_offset(skb) - osize; ++ refcount_add(delta, &sk->sk_wmem_alloc); ++ skb->truesize += delta; + } + return skb; ++ ++fail: ++ kfree_skb(skb); ++ return NULL; + } + EXPORT_SYMBOL(skb_expand_head); +