All of lore.kernel.org
 help / color / mirror / Atom feed
* [tipc-discussion] [net v2 1/1] tipc: fix memory leak caused by tipc_buf_append()
@ 2020-10-26 10:43 Tung Nguyen
  2020-10-26 18:54 ` Jakub Kicinski
  2020-10-27 18:21 ` Cong Wang
  0 siblings, 2 replies; 4+ messages in thread
From: Tung Nguyen @ 2020-10-26 10:43 UTC (permalink / raw)
  To: davem, netdev, tipc-discussion

Commit ed42989eab57 ("fix the skb_unshare() in tipc_buf_append()")
replaced skb_unshare() with skb_copy() to not reduce the data reference
counter of the original skb intentionally. This is not the correct
way to handle the cloned skb because it causes memory leak in 2
following cases:
 1/ Sending multicast messages via broadcast link
  The original skb list is cloned to the local skb list for local
  destination. After that, the data reference counter of each skb
  in the original list has the value of 2. This causes each skb not
  to be freed after receiving ACK:
  tipc_link_advance_transmq()
  {
   ...
   /* release skb */
   __skb_unlink(skb, &l->transmq);
   kfree_skb(skb); <-- memory exists after being freed
  }

 2/ Sending multicast messages via replicast link
  Similar to the above case, each skb cannot be freed after purging
  the skb list:
  tipc_mcast_xmit()
  {
   ...
   __skb_queue_purge(pkts); <-- memory exists after being freed
  }

This commit fixes this issue by using skb_unshare() instead. Besides,
to avoid use-after-free error reported by KASAN, the pointer to the
fragment is set to NULL before calling skb_unshare() to make sure that
the original skb is not freed after freeing the fragment 2 times in
case skb_unshare() returns NULL.

Fixes: ed42989eab57 ("fix the skb_unshare() in tipc_buf_append()")
Acked-by: Jon Maloy <jmaloy@redhat.com>
Reported-by: Thang Hoang Ngo <thang.h.ngo@dektech.com.au>
Signed-off-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>
---
 net/tipc/msg.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 2a78aa701572..32c79c59052b 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -150,12 +150,11 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
 	if (fragid == FIRST_FRAGMENT) {
 		if (unlikely(head))
 			goto err;
-		if (skb_cloned(frag))
-			frag = skb_copy(frag, GFP_ATOMIC);
+		*buf = NULL;
+		frag = skb_unshare(frag, GFP_ATOMIC);
 		if (unlikely(!frag))
 			goto err;
 		head = *headbuf = frag;
-		*buf = NULL;
 		TIPC_SKB_CB(head)->tail = NULL;
 		if (skb_is_nonlinear(head)) {
 			skb_walk_frags(head, tail) {
-- 
2.17.1


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

* Re: [tipc-discussion] [net v2 1/1] tipc: fix memory leak caused by tipc_buf_append()
  2020-10-26 10:43 [tipc-discussion] [net v2 1/1] tipc: fix memory leak caused by tipc_buf_append() Tung Nguyen
@ 2020-10-26 18:54 ` Jakub Kicinski
  2020-10-27 18:21 ` Cong Wang
  1 sibling, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2020-10-26 18:54 UTC (permalink / raw)
  To: Tung Nguyen; +Cc: davem, netdev, tipc-discussion

On Mon, 26 Oct 2020 17:43:33 +0700 Tung Nguyen wrote:
> Commit ed42989eab57 ("fix the skb_unshare() in tipc_buf_append()")
> replaced skb_unshare() with skb_copy() to not reduce the data reference
> counter of the original skb intentionally. This is not the correct
> way to handle the cloned skb because it causes memory leak in 2
> following cases:
>  1/ Sending multicast messages via broadcast link
>   The original skb list is cloned to the local skb list for local
>   destination. After that, the data reference counter of each skb
>   in the original list has the value of 2. This causes each skb not
>   to be freed after receiving ACK:
>   tipc_link_advance_transmq()
>   {
>    ...
>    /* release skb */
>    __skb_unlink(skb, &l->transmq);
>    kfree_skb(skb); <-- memory exists after being freed
>   }
> 
>  2/ Sending multicast messages via replicast link
>   Similar to the above case, each skb cannot be freed after purging
>   the skb list:
>   tipc_mcast_xmit()
>   {
>    ...
>    __skb_queue_purge(pkts); <-- memory exists after being freed
>   }
> 
> This commit fixes this issue by using skb_unshare() instead. Besides,
> to avoid use-after-free error reported by KASAN, the pointer to the
> fragment is set to NULL before calling skb_unshare() to make sure that
> the original skb is not freed after freeing the fragment 2 times in
> case skb_unshare() returns NULL.
> 
> Fixes: ed42989eab57 ("fix the skb_unshare() in tipc_buf_append()")
> Acked-by: Jon Maloy <jmaloy@redhat.com>
> Reported-by: Thang Hoang Ngo <thang.h.ngo@dektech.com.au>
> Signed-off-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>

Fixes tag: Fixes: ed42989eab57 ("fix the skb_unshare() in tipc_buf_append()")
Has these problem(s):
	- Subject does not match target commit subject
	  Just use
		git log -1 --format='Fixes: %h ("%s")'

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

* Re: [tipc-discussion] [net v2 1/1] tipc: fix memory leak caused by tipc_buf_append()
  2020-10-26 10:43 [tipc-discussion] [net v2 1/1] tipc: fix memory leak caused by tipc_buf_append() Tung Nguyen
  2020-10-26 18:54 ` Jakub Kicinski
@ 2020-10-27 18:21 ` Cong Wang
  2020-10-27 18:49   ` Cong Wang
  1 sibling, 1 reply; 4+ messages in thread
From: Cong Wang @ 2020-10-27 18:21 UTC (permalink / raw)
  To: Tung Nguyen
  Cc: David Miller, Linux Kernel Network Developers, tipc-discussion

On Mon, Oct 26, 2020 at 3:46 AM Tung Nguyen
<tung.q.nguyen@dektech.com.au> wrote:
>
> Commit ed42989eab57 ("fix the skb_unshare() in tipc_buf_append()")
> replaced skb_unshare() with skb_copy() to not reduce the data reference
> counter of the original skb intentionally. This is not the correct
> way to handle the cloned skb because it causes memory leak in 2
> following cases:
>  1/ Sending multicast messages via broadcast link
>   The original skb list is cloned to the local skb list for local
>   destination. After that, the data reference counter of each skb
>   in the original list has the value of 2. This causes each skb not
>   to be freed after receiving ACK:

Interesting, I can not immediately see how tipc_link_advance_transmq()
clones the skb. You point out how it is freed but not cloned.

It looks really odd to see the skb is held by some caller, then expected
to be released by the unshare in tipc_buf_append(). IMHO, the refcnt
should be released where it is held.

Can you be more specific here?

Thanks.

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

* Re: [tipc-discussion] [net v2 1/1] tipc: fix memory leak caused by tipc_buf_append()
  2020-10-27 18:21 ` Cong Wang
@ 2020-10-27 18:49   ` Cong Wang
  0 siblings, 0 replies; 4+ messages in thread
From: Cong Wang @ 2020-10-27 18:49 UTC (permalink / raw)
  To: Tung Nguyen
  Cc: David Miller, Linux Kernel Network Developers, tipc-discussion

On Tue, Oct 27, 2020 at 11:21 AM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> On Mon, Oct 26, 2020 at 3:46 AM Tung Nguyen
> <tung.q.nguyen@dektech.com.au> wrote:
> >
> > Commit ed42989eab57 ("fix the skb_unshare() in tipc_buf_append()")
> > replaced skb_unshare() with skb_copy() to not reduce the data reference
> > counter of the original skb intentionally. This is not the correct
> > way to handle the cloned skb because it causes memory leak in 2
> > following cases:
> >  1/ Sending multicast messages via broadcast link
> >   The original skb list is cloned to the local skb list for local
> >   destination. After that, the data reference counter of each skb
> >   in the original list has the value of 2. This causes each skb not
> >   to be freed after receiving ACK:
>
> Interesting, I can not immediately see how tipc_link_advance_transmq()
> clones the skb. You point out how it is freed but not cloned.
>
> It looks really odd to see the skb is held by some caller, then expected
> to be released by the unshare in tipc_buf_append(). IMHO, the refcnt
> should be released where it is held.

More importantly, prior to Xin Long's change of skb_unshare(),
skb_unclone() was used, which does not touch the skb refcnt either.
So, why does it rely on skb_unshare() to release this refcnt now?

Thanks.

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

end of thread, other threads:[~2020-10-27 18:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-26 10:43 [tipc-discussion] [net v2 1/1] tipc: fix memory leak caused by tipc_buf_append() Tung Nguyen
2020-10-26 18:54 ` Jakub Kicinski
2020-10-27 18:21 ` Cong Wang
2020-10-27 18:49   ` Cong Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.