]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 30 Dec 2024 15:11:03 +0000 (16:11 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 30 Dec 2024 15:11:03 +0000 (16:11 +0100)
added patches:
ipv6-prevent-possible-uaf-in-ip6_xmit.patch
skb_expand_head-adjust-skb-truesize-incorrectly.patch

queue-5.4/ipv6-prevent-possible-uaf-in-ip6_xmit.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/skb_expand_head-adjust-skb-truesize-incorrectly.patch [new file with mode: 0644]

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 (file)
index 0000000..55858e8
--- /dev/null
@@ -0,0 +1,43 @@
+From 2d5ff7e339d04622d8282661df36151906d0e1c7 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 20 Aug 2024 16:08:59 +0000
+Subject: ipv6: prevent possible UAF in ip6_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+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 <edumazet@google.com>
+Cc: Vasily Averin <vasily.averin@linux.dev>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://patch.msgid.link/20240820160859.3786976-4-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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) {
index 910b531ed5d736d7862d3e1e7976eac6d2e224a9..9947a8e743129736d9d019f7caf65910426e9584 100644 (file)
@@ -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 (file)
index 0000000..fba4012
--- /dev/null
@@ -0,0 +1,95 @@
+From 7f678def99d29c520418607509bb19c7fc96a6db Mon Sep 17 00:00:00 2001
+From: Vasily Averin <vvs@virtuozzo.com>
+Date: Fri, 22 Oct 2021 13:28:37 +0300
+Subject: skb_expand_head() adjust skb->truesize incorrectly
+
+From: Vasily Averin <vvs@virtuozzo.com>
+
+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 <christoph.paasch@gmail.com>
+Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/644330dd-477e-0462-83bf-9f514c41edd1@virtuozzo.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <linux/indirect_call_wrapper.h>
+ #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);