]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 30 May 2021 14:19:18 +0000 (16:19 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 30 May 2021 14:19:18 +0000 (16:19 +0200)
added patches:
revert-net-tipc-fix-a-double-free-in-tipc_sk_mcast_rcv.patch
tipc-skb_linearize-the-head-skb-when-reassembling-msgs.patch

queue-4.4/revert-net-tipc-fix-a-double-free-in-tipc_sk_mcast_rcv.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/tipc-skb_linearize-the-head-skb-when-reassembling-msgs.patch [new file with mode: 0644]

diff --git a/queue-4.4/revert-net-tipc-fix-a-double-free-in-tipc_sk_mcast_rcv.patch b/queue-4.4/revert-net-tipc-fix-a-double-free-in-tipc_sk_mcast_rcv.patch
new file mode 100644 (file)
index 0000000..5281895
--- /dev/null
@@ -0,0 +1,36 @@
+From 75016891357a628d2b8acc09e2b9b2576c18d318 Mon Sep 17 00:00:00 2001
+From: Hoang Le <hoang.h.le@dektech.com.au>
+Date: Fri, 14 May 2021 08:23:03 +0700
+Subject: Revert "net:tipc: Fix a double free in tipc_sk_mcast_rcv"
+
+From: Hoang Le <hoang.h.le@dektech.com.au>
+
+commit 75016891357a628d2b8acc09e2b9b2576c18d318 upstream.
+
+This reverts commit 6bf24dc0cc0cc43b29ba344b66d78590e687e046.
+Above fix is not correct and caused memory leak issue.
+
+Fixes: 6bf24dc0cc0c ("net:tipc: Fix a double free in tipc_sk_mcast_rcv")
+Acked-by: Jon Maloy <jmaloy@redhat.com>
+Acked-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>
+Signed-off-by: Hoang Le <hoang.h.le@dektech.com.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tipc/socket.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -763,7 +763,10 @@ void tipc_sk_mcast_rcv(struct net *net,
+               spin_lock_bh(&inputq->lock);
+               if (skb_peek(arrvq) == skb) {
+                       skb_queue_splice_tail_init(&tmpq, inputq);
+-                      __skb_dequeue(arrvq);
++                      /* Decrease the skb's refcnt as increasing in the
++                       * function tipc_skb_peek
++                       */
++                      kfree_skb(__skb_dequeue(arrvq));
+               }
+               spin_unlock_bh(&inputq->lock);
+               __skb_queue_purge(&tmpq);
index 1357adba21a25bfa93e56747600319bc8e74ca58..b9edf08587cb04dec1815f9a0b31f9a2fe534429 100644 (file)
@@ -24,3 +24,5 @@ nfs-fix-an-incorrect-limit-in-filelayout_decode_layout.patch
 nfs-don-t-corrupt-the-value-of-pg_bytes_written-in-nfs_do_recoalesce.patch
 nfsv4-fix-v4.0-v4.1-seek_data-return-enotsupp-when-set-nfs_v4_2-config.patch
 net-mlx4-fix-eeprom-dump-support.patch
+revert-net-tipc-fix-a-double-free-in-tipc_sk_mcast_rcv.patch
+tipc-skb_linearize-the-head-skb-when-reassembling-msgs.patch
diff --git a/queue-4.4/tipc-skb_linearize-the-head-skb-when-reassembling-msgs.patch b/queue-4.4/tipc-skb_linearize-the-head-skb-when-reassembling-msgs.patch
new file mode 100644 (file)
index 0000000..37d578f
--- /dev/null
@@ -0,0 +1,95 @@
+From b7df21cf1b79ab7026f545e7bf837bd5750ac026 Mon Sep 17 00:00:00 2001
+From: Xin Long <lucien.xin@gmail.com>
+Date: Sat, 8 May 2021 03:57:03 +0800
+Subject: tipc: skb_linearize the head skb when reassembling msgs
+
+From: Xin Long <lucien.xin@gmail.com>
+
+commit b7df21cf1b79ab7026f545e7bf837bd5750ac026 upstream.
+
+It's not a good idea to append the frag skb to a skb's frag_list if
+the frag_list already has skbs from elsewhere, such as this skb was
+created by pskb_copy() where the frag_list was cloned (all the skbs
+in it were skb_get'ed) and shared by multiple skbs.
+
+However, the new appended frag skb should have been only seen by the
+current skb. Otherwise, it will cause use after free crashes as this
+appended frag skb are seen by multiple skbs but it only got skb_get
+called once.
+
+The same thing happens with a skb updated by pskb_may_pull() with a
+skb_cloned skb. Li Shuang has reported quite a few crashes caused
+by this when doing testing over macvlan devices:
+
+  [] kernel BUG at net/core/skbuff.c:1970!
+  [] Call Trace:
+  []  skb_clone+0x4d/0xb0
+  []  macvlan_broadcast+0xd8/0x160 [macvlan]
+  []  macvlan_process_broadcast+0x148/0x150 [macvlan]
+  []  process_one_work+0x1a7/0x360
+  []  worker_thread+0x30/0x390
+
+  [] kernel BUG at mm/usercopy.c:102!
+  [] Call Trace:
+  []  __check_heap_object+0xd3/0x100
+  []  __check_object_size+0xff/0x16b
+  []  simple_copy_to_iter+0x1c/0x30
+  []  __skb_datagram_iter+0x7d/0x310
+  []  __skb_datagram_iter+0x2a5/0x310
+  []  skb_copy_datagram_iter+0x3b/0x90
+  []  tipc_recvmsg+0x14a/0x3a0 [tipc]
+  []  ____sys_recvmsg+0x91/0x150
+  []  ___sys_recvmsg+0x7b/0xc0
+
+  [] kernel BUG at mm/slub.c:305!
+  [] Call Trace:
+  []  <IRQ>
+  []  kmem_cache_free+0x3ff/0x400
+  []  __netif_receive_skb_core+0x12c/0xc40
+  []  ? kmem_cache_alloc+0x12e/0x270
+  []  netif_receive_skb_internal+0x3d/0xb0
+  []  ? get_rx_page_info+0x8e/0xa0 [be2net]
+  []  be_poll+0x6ef/0xd00 [be2net]
+  []  ? irq_exit+0x4f/0x100
+  []  net_rx_action+0x149/0x3b0
+
+  ...
+
+This patch is to fix it by linearizing the head skb if it has frag_list
+set in tipc_buf_append(). Note that we choose to do this before calling
+skb_unshare(), as __skb_linearize() will avoid skb_copy(). Also, we can
+not just drop the frag_list either as the early time.
+
+Fixes: 45c8b7b175ce ("tipc: allow non-linear first fragment buffer")
+Reported-by: Li Shuang <shuali@redhat.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Jon Maloy <jmaloy@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tipc/msg.c |    9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+--- a/net/tipc/msg.c
++++ b/net/tipc/msg.c
+@@ -139,18 +139,13 @@ int tipc_buf_append(struct sk_buff **hea
+               if (unlikely(head))
+                       goto err;
+               *buf = NULL;
++              if (skb_has_frag_list(frag) && __skb_linearize(frag))
++                      goto err;
+               frag = skb_unshare(frag, GFP_ATOMIC);
+               if (unlikely(!frag))
+                       goto err;
+               head = *headbuf = frag;
+               TIPC_SKB_CB(head)->tail = NULL;
+-              if (skb_is_nonlinear(head)) {
+-                      skb_walk_frags(head, tail) {
+-                              TIPC_SKB_CB(head)->tail = tail;
+-                      }
+-              } else {
+-                      skb_frag_list_init(head);
+-              }
+               return 0;
+       }