[net,v2] virtio/vsock: fix leaks due to missing skb owner

Message ID 20230327-vsock-fix-leak-v2-1-f6619972dee0@bytedance.com
State New
Headers
Series [net,v2] virtio/vsock: fix leaks due to missing skb owner |

Commit Message

Bobby Eshleman March 28, 2023, 4:29 p.m. UTC
  This patch sets the skb owner in the recv and send path for virtio.

For the send path, this solves the leak caused when
virtio_transport_purge_skbs() finds skb->sk is always NULL and therefore
never matches it with the current socket. Setting the owner upon
allocation fixes this.

For the recv path, this ensures correctness of accounting and also
correct transfer of ownership in vsock_loopback (when skbs are sent from
one socket and received by another).

Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")
Signed-off-by: Bobby Eshleman <bobby.eshleman@bytedance.com>
Reported-by: Cong Wang <xiyou.wangcong@gmail.com>
Link: https://lore.kernel.org/all/ZCCbATwov4U+GBUv@pop-os.localdomain/
---
Changes in v2:
- virtio/vsock: add skb_set_owner_r to recv_pkt()
- Link to v1: https://lore.kernel.org/r/20230327-vsock-fix-leak-v1-1-3fede367105f@bytedance.com
---
 net/vmw_vsock/virtio_transport_common.c | 5 +++++
 1 file changed, 5 insertions(+)


---
base-commit: e5b42483ccce50d5b957f474fd332afd4ef0c27b
change-id: 20230327-vsock-fix-leak-b1cef1582aa8

Best regards,
  

Comments

Bobby Eshleman March 18, 2023, 5:50 p.m. UTC | #1
On Wed, Mar 29, 2023 at 09:16:19AM +0200, Stefano Garzarella wrote:
> On Tue, Mar 28, 2023 at 04:29:09PM +0000, Bobby Eshleman wrote:
> > This patch sets the skb owner in the recv and send path for virtio.
> > 
> > For the send path, this solves the leak caused when
> > virtio_transport_purge_skbs() finds skb->sk is always NULL and therefore
> > never matches it with the current socket. Setting the owner upon
> > allocation fixes this.
> > 
> > For the recv path, this ensures correctness of accounting and also
> > correct transfer of ownership in vsock_loopback (when skbs are sent from
> > one socket and received by another).
> > 
> > Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")
> > Signed-off-by: Bobby Eshleman <bobby.eshleman@bytedance.com>
> > Reported-by: Cong Wang <xiyou.wangcong@gmail.com>
> > Link: https://lore.kernel.org/all/ZCCbATwov4U+GBUv@pop-os.localdomain/
> > ---
> > Changes in v2:
> > - virtio/vsock: add skb_set_owner_r to recv_pkt()
> > - Link to v1: https://lore.kernel.org/r/20230327-vsock-fix-leak-v1-1-3fede367105f@bytedance.com
> > ---
> > net/vmw_vsock/virtio_transport_common.c | 5 +++++
> > 1 file changed, 5 insertions(+)
> > 
> > diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> > index 957cdc01c8e8..900e5dca05f5 100644
> > --- a/net/vmw_vsock/virtio_transport_common.c
> > +++ b/net/vmw_vsock/virtio_transport_common.c
> > @@ -94,6 +94,9 @@ virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
> > 					 info->op,
> > 					 info->flags);
> > 
> > +	if (info->vsk)
> > +		skb_set_owner_w(skb, sk_vsock(info->vsk));
> > +
> > 	return skb;
> > 
> > out:
> > @@ -1294,6 +1297,8 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
> > 		goto free_pkt;
> > 	}
> > 
> > +	skb_set_owner_r(skb, sk);
> > +
> > 	vsk = vsock_sk(sk);
> > 
> > 	lock_sock(sk);
> 
> Can you explain why we are using skb_set_owner_w/skb_set_owner_r?
> 
> I'm a little concerned about 2 things:
> - skb_set_owner_r() documentation says: "Stream and sequenced
>   protocols can't normally use this as they need to fit buffers in
>   and play with them."
> - they increment sk_wmem_alloc and sk_rmem_alloc that we never used
>   (IIRC)
> 
> For the long run, I think we should manage memory better, and using
> socket accounting makes sense to me, but since we now have a different
> system (which we have been carrying around since the introduction of
> vsock), I think this change is a bit risky, especially as a fix.
> 
> So my suggestion is to use skb_set_owner_sk_safe() for now, unless I
> missed something about why to use skb_set_owner_w/skb_set_owner_r.
> 

I think that makes sense. I was honestly unaware of
skb_set_owner_sk_safe(), but given the reasons you stated and after
reading its code, I agree it is a better fit in light of vsock's
different accounting scheme.

I'll switch it over in v3.

Best,
Bobby
  
Stefano Garzarella March 29, 2023, 7:16 a.m. UTC | #2
On Tue, Mar 28, 2023 at 04:29:09PM +0000, Bobby Eshleman wrote:
>This patch sets the skb owner in the recv and send path for virtio.
>
>For the send path, this solves the leak caused when
>virtio_transport_purge_skbs() finds skb->sk is always NULL and therefore
>never matches it with the current socket. Setting the owner upon
>allocation fixes this.
>
>For the recv path, this ensures correctness of accounting and also
>correct transfer of ownership in vsock_loopback (when skbs are sent from
>one socket and received by another).
>
>Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")
>Signed-off-by: Bobby Eshleman <bobby.eshleman@bytedance.com>
>Reported-by: Cong Wang <xiyou.wangcong@gmail.com>
>Link: https://lore.kernel.org/all/ZCCbATwov4U+GBUv@pop-os.localdomain/
>---
>Changes in v2:
>- virtio/vsock: add skb_set_owner_r to recv_pkt()
>- Link to v1: https://lore.kernel.org/r/20230327-vsock-fix-leak-v1-1-3fede367105f@bytedance.com
>---
> net/vmw_vsock/virtio_transport_common.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
>diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
>index 957cdc01c8e8..900e5dca05f5 100644
>--- a/net/vmw_vsock/virtio_transport_common.c
>+++ b/net/vmw_vsock/virtio_transport_common.c
>@@ -94,6 +94,9 @@ virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
> 					 info->op,
> 					 info->flags);
>
>+	if (info->vsk)
>+		skb_set_owner_w(skb, sk_vsock(info->vsk));
>+
> 	return skb;
>
> out:
>@@ -1294,6 +1297,8 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
> 		goto free_pkt;
> 	}
>
>+	skb_set_owner_r(skb, sk);
>+
> 	vsk = vsock_sk(sk);
>
> 	lock_sock(sk);

Can you explain why we are using skb_set_owner_w/skb_set_owner_r?

I'm a little concerned about 2 things:
- skb_set_owner_r() documentation says: "Stream and sequenced
   protocols can't normally use this as they need to fit buffers in
   and play with them."
- they increment sk_wmem_alloc and sk_rmem_alloc that we never used
   (IIRC)

For the long run, I think we should manage memory better, and using
socket accounting makes sense to me, but since we now have a different
system (which we have been carrying around since the introduction of
vsock), I think this change is a bit risky, especially as a fix.

So my suggestion is to use skb_set_owner_sk_safe() for now, unless I
missed something about why to use skb_set_owner_w/skb_set_owner_r.

Thanks,
Stefano
  

Patch

diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index 957cdc01c8e8..900e5dca05f5 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -94,6 +94,9 @@  virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
 					 info->op,
 					 info->flags);
 
+	if (info->vsk)
+		skb_set_owner_w(skb, sk_vsock(info->vsk));
+
 	return skb;
 
 out:
@@ -1294,6 +1297,8 @@  void virtio_transport_recv_pkt(struct virtio_transport *t,
 		goto free_pkt;
 	}
 
+	skb_set_owner_r(skb, sk);
+
 	vsk = vsock_sk(sk);
 
 	lock_sock(sk);