diff mbox series

[net] tipc: use skb_unshare() instead in tipc_buf_append()

Message ID 0fcddb2bab6bde5632dcd4889961ebce1ec8bb8f.1599997051.git.lucien.xin@gmail.com
State New
Headers show
Series [net] tipc: use skb_unshare() instead in tipc_buf_append() | expand

Commit Message

Xin Long Sept. 13, 2020, 11:37 a.m. UTC
In tipc_buf_append() it may change skb's frag_list, and it causes
problems when this skb is cloned. skb_unclone() doesn't really
make this skb's flag_list available to change.

Shuang Li has reported an use-after-free issue because of this
when creating quite a few macvlan dev over the same dev, where
the broadcast packets will be cloned and go up to the stack:

 [ ] BUG: KASAN: use-after-free in pskb_expand_head+0x86d/0xea0
 [ ] Call Trace:
 [ ]  dump_stack+0x7c/0xb0
 [ ]  print_address_description.constprop.7+0x1a/0x220
 [ ]  kasan_report.cold.10+0x37/0x7c
 [ ]  check_memory_region+0x183/0x1e0
 [ ]  pskb_expand_head+0x86d/0xea0
 [ ]  process_backlog+0x1df/0x660
 [ ]  net_rx_action+0x3b4/0xc90
 [ ]
 [ ] Allocated by task 1786:
 [ ]  kmem_cache_alloc+0xbf/0x220
 [ ]  skb_clone+0x10a/0x300
 [ ]  macvlan_broadcast+0x2f6/0x590 [macvlan]
 [ ]  macvlan_process_broadcast+0x37c/0x516 [macvlan]
 [ ]  process_one_work+0x66a/0x1060
 [ ]  worker_thread+0x87/0xb10
 [ ]
 [ ] Freed by task 3253:
 [ ]  kmem_cache_free+0x82/0x2a0
 [ ]  skb_release_data+0x2c3/0x6e0
 [ ]  kfree_skb+0x78/0x1d0
 [ ]  tipc_recvmsg+0x3be/0xa40 [tipc]

So fix it by using skb_unshare() instead, which would create a new
skb for the cloned frag and it'll be safe to change its frag_list.
The similar things were also done in sctp_make_reassembled_event(),
which is using skb_copy().

Reported-by: Shuang Li <shuali@redhat.com>
Fixes: 37e22164a8a3 ("tipc: rename and move message reassembly function")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
 net/tipc/msg.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Comments

David Miller Sept. 14, 2020, 11:41 p.m. UTC | #1
From: Xin Long <lucien.xin@gmail.com>

Date: Sun, 13 Sep 2020 19:37:31 +0800

> In tipc_buf_append() it may change skb's frag_list, and it causes

> problems when this skb is cloned. skb_unclone() doesn't really

> make this skb's flag_list available to change.

> 

> Shuang Li has reported an use-after-free issue because of this

> when creating quite a few macvlan dev over the same dev, where

> the broadcast packets will be cloned and go up to the stack:

  ...
> So fix it by using skb_unshare() instead, which would create a new

> skb for the cloned frag and it'll be safe to change its frag_list.

> The similar things were also done in sctp_make_reassembled_event(),

> which is using skb_copy().

> 

> Reported-by: Shuang Li <shuali@redhat.com>

> Fixes: 37e22164a8a3 ("tipc: rename and move message reassembly function")

> Signed-off-by: Xin Long <lucien.xin@gmail.com>


Applied and queued up for -stable, thanks.
diff mbox series

Patch

diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 848fae6..52e93ba 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -150,7 +150,8 @@  int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
 	if (fragid == FIRST_FRAGMENT) {
 		if (unlikely(head))
 			goto err;
-		if (unlikely(skb_unclone(frag, GFP_ATOMIC)))
+		frag = skb_unshare(frag, GFP_ATOMIC);
+		if (unlikely(!frag))
 			goto err;
 		head = *headbuf = frag;
 		*buf = NULL;