netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch net] tipc: fix the skb_unshare() in tipc_buf_append()
@ 2020-10-08  4:12 Cong Wang
  2020-10-08  8:45 ` Xin Long
  2020-10-10  1:26 ` Jakub Kicinski
  0 siblings, 2 replies; 5+ messages in thread
From: Cong Wang @ 2020-10-08  4:12 UTC (permalink / raw)
  To: netdev
  Cc: Cong Wang, syzbot+e96a7ba46281824cc46a, Xin Long, Jon Maloy, Ying Xue

skb_unshare() drops a reference count on the old skb unconditionally,
so in the failure case, we end up freeing the skb twice here.
And because the skb is allocated in fclone and cloned by caller
tipc_msg_reassemble(), the consequence is actually freeing the
original skb too, thus triggered the UAF by syzbot.

Fix this by replacing this skb_unshare() with skb_cloned()+skb_copy().

Fixes: ff48b6222e65 ("tipc: use skb_unshare() instead in tipc_buf_append()")
Reported-and-tested-by: syzbot+e96a7ba46281824cc46a@syzkaller.appspotmail.com
Cc: Xin Long <lucien.xin@gmail.com>
Cc: Jon Maloy <jmaloy@redhat.com>
Cc: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/tipc/msg.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 52e93ba4d8e2..681224401871 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;
-		frag = skb_unshare(frag, GFP_ATOMIC);
+		if (skb_cloned(frag))
+			frag = skb_copy(frag, GFP_ATOMIC);
 		if (unlikely(!frag))
 			goto err;
 		head = *headbuf = frag;
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Patch net] tipc: fix the skb_unshare() in tipc_buf_append()
  2020-10-08  4:12 [Patch net] tipc: fix the skb_unshare() in tipc_buf_append() Cong Wang
@ 2020-10-08  8:45 ` Xin Long
  2020-10-08 17:44   ` Cong Wang
  2020-10-10  1:26 ` Jakub Kicinski
  1 sibling, 1 reply; 5+ messages in thread
From: Xin Long @ 2020-10-08  8:45 UTC (permalink / raw)
  To: Cong Wang; +Cc: network dev, syzbot, Jon Maloy, Ying Xue

On Thu, Oct 8, 2020 at 12:12 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> skb_unshare() drops a reference count on the old skb unconditionally,
> so in the failure case, we end up freeing the skb twice here.
> And because the skb is allocated in fclone and cloned by caller
> tipc_msg_reassemble(), the consequence is actually freeing the
> original skb too, thus triggered the UAF by syzbot.
Do you mean:
                frag = skb_clone(skb, GFP_ATOMIC);
frag = skb_unshare(frag) will free the 'skb' too?

>
> Fix this by replacing this skb_unshare() with skb_cloned()+skb_copy().
>
> Fixes: ff48b6222e65 ("tipc: use skb_unshare() instead in tipc_buf_append()")
> Reported-and-tested-by: syzbot+e96a7ba46281824cc46a@syzkaller.appspotmail.com
> Cc: Xin Long <lucien.xin@gmail.com>
> Cc: Jon Maloy <jmaloy@redhat.com>
> Cc: Ying Xue <ying.xue@windriver.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> ---
>  net/tipc/msg.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/tipc/msg.c b/net/tipc/msg.c
> index 52e93ba4d8e2..681224401871 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;
> -               frag = skb_unshare(frag, GFP_ATOMIC);
> +               if (skb_cloned(frag))
> +                       frag = skb_copy(frag, GFP_ATOMIC);
>                 if (unlikely(!frag))
>                         goto err;
>                 head = *headbuf = frag;
> --
> 2.28.0
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch net] tipc: fix the skb_unshare() in tipc_buf_append()
  2020-10-08  8:45 ` Xin Long
@ 2020-10-08 17:44   ` Cong Wang
  2020-10-09  3:07     ` Xin Long
  0 siblings, 1 reply; 5+ messages in thread
From: Cong Wang @ 2020-10-08 17:44 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev, syzbot, Jon Maloy, Ying Xue

On Thu, Oct 8, 2020 at 1:45 AM Xin Long <lucien.xin@gmail.com> wrote:
>
> On Thu, Oct 8, 2020 at 12:12 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
> >
> > skb_unshare() drops a reference count on the old skb unconditionally,
> > so in the failure case, we end up freeing the skb twice here.
> > And because the skb is allocated in fclone and cloned by caller
> > tipc_msg_reassemble(), the consequence is actually freeing the
> > original skb too, thus triggered the UAF by syzbot.
> Do you mean:
>                 frag = skb_clone(skb, GFP_ATOMIC);
> frag = skb_unshare(frag) will free the 'skb' too?

Yes, more precisely, I mean:

new = skb_clone(old)
kfree_skb(new)
kfree_skb(new)

would free 'old' eventually when 'old' is a fast clone. The skb_clone()
sets ->fclone_ref to 2 and returns the clone, whose skb->fclone is
SKB_FCLONE_CLONE. So, the first call of kfree_skbmem() will
just decrease ->fclone_ref by 1, but the second call will trigger
kmem_cache_free() which frees _both_  skb's.

Thanks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch net] tipc: fix the skb_unshare() in tipc_buf_append()
  2020-10-08 17:44   ` Cong Wang
@ 2020-10-09  3:07     ` Xin Long
  0 siblings, 0 replies; 5+ messages in thread
From: Xin Long @ 2020-10-09  3:07 UTC (permalink / raw)
  To: Cong Wang; +Cc: network dev, syzbot, Jon Maloy, Ying Xue

On Fri, Oct 9, 2020 at 1:45 AM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> On Thu, Oct 8, 2020 at 1:45 AM Xin Long <lucien.xin@gmail.com> wrote:
> >
> > On Thu, Oct 8, 2020 at 12:12 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
> > >
> > > skb_unshare() drops a reference count on the old skb unconditionally,
> > > so in the failure case, we end up freeing the skb twice here.
> > > And because the skb is allocated in fclone and cloned by caller
> > > tipc_msg_reassemble(), the consequence is actually freeing the
> > > original skb too, thus triggered the UAF by syzbot.
> > Do you mean:
> >                 frag = skb_clone(skb, GFP_ATOMIC);
> > frag = skb_unshare(frag) will free the 'skb' too?
>
> Yes, more precisely, I mean:
>
> new = skb_clone(old)
> kfree_skb(new)
> kfree_skb(new)
>
> would free 'old' eventually when 'old' is a fast clone. The skb_clone()
> sets ->fclone_ref to 2 and returns the clone, whose skb->fclone is
> SKB_FCLONE_CLONE. So, the first call of kfree_skbmem() will
> just decrease ->fclone_ref by 1, but the second call will trigger
> kmem_cache_free() which frees _both_  skb's.
Thanks. Didn't notice kfree_skb 'buf' on the err path.

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch net] tipc: fix the skb_unshare() in tipc_buf_append()
  2020-10-08  4:12 [Patch net] tipc: fix the skb_unshare() in tipc_buf_append() Cong Wang
  2020-10-08  8:45 ` Xin Long
@ 2020-10-10  1:26 ` Jakub Kicinski
  1 sibling, 0 replies; 5+ messages in thread
From: Jakub Kicinski @ 2020-10-10  1:26 UTC (permalink / raw)
  To: Cong Wang
  Cc: netdev, syzbot+e96a7ba46281824cc46a, Xin Long, Jon Maloy, Ying Xue

On Wed,  7 Oct 2020 21:12:50 -0700 Cong Wang wrote:
> skb_unshare() drops a reference count on the old skb unconditionally,
> so in the failure case, we end up freeing the skb twice here.
> And because the skb is allocated in fclone and cloned by caller
> tipc_msg_reassemble(), the consequence is actually freeing the
> original skb too, thus triggered the UAF by syzbot.
> 
> Fix this by replacing this skb_unshare() with skb_cloned()+skb_copy().
> 
> Fixes: ff48b6222e65 ("tipc: use skb_unshare() instead in tipc_buf_append()")
> Reported-and-tested-by: syzbot+e96a7ba46281824cc46a@syzkaller.appspotmail.com
> Cc: Xin Long <lucien.xin@gmail.com>
> Cc: Jon Maloy <jmaloy@redhat.com>
> Cc: Ying Xue <ying.xue@windriver.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Applied and queued for stable, thank you!

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-10-10  1:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-08  4:12 [Patch net] tipc: fix the skb_unshare() in tipc_buf_append() Cong Wang
2020-10-08  8:45 ` Xin Long
2020-10-08 17:44   ` Cong Wang
2020-10-09  3:07     ` Xin Long
2020-10-10  1:26 ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).