All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Wang <jasowang@redhat.com>
To: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>,
	"David S. Miller" <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>,
	virtualization@lists.linux-foundation.org,
	Ido Schimmel <idosch@nvidia.com>,
	netdev@vger.kernel.org
Subject: Re: [PATCH net-next] virtio-net: fix use-after-free in skb_gro_receive
Date: Fri, 23 Apr 2021 12:33:09 +0800	[thread overview]
Message-ID: <b2f5cab7-18dd-2817-7423-e84ea1907bf3@redhat.com> (raw)
In-Reply-To: <1619151585.3098595-1-xuanzhuo@linux.alibaba.com>


在 2021/4/23 下午12:19, Xuan Zhuo 写道:
> On Fri, 23 Apr 2021 12:08:34 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2021/4/22 下午11:16, Xuan Zhuo 写道:
>>> When "headroom" > 0, the actual allocated memory space is the entire
>>> page, so the address of the page should be used when passing it to
>>> build_skb().
>>>
>>> BUG: KASAN: use-after-free in skb_gro_receive (net/core/skbuff.c:4260)
>>> Write of size 16 at addr ffff88811619fffc by task kworker/u9:0/534
>>> CPU: 2 PID: 534 Comm: kworker/u9:0 Not tainted 5.12.0-rc7-custom-16372-gb150be05b806 #3382
>>> Hardware name: QEMU MSN2700, BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
>>> Workqueue: xprtiod xs_stream_data_receive_workfn [sunrpc]
>>> Call Trace:
>>>    <IRQ>
>>> dump_stack (lib/dump_stack.c:122)
>>> print_address_description.constprop.0 (mm/kasan/report.c:233)
>>> kasan_report.cold (mm/kasan/report.c:400 mm/kasan/report.c:416)
>>> skb_gro_receive (net/core/skbuff.c:4260)
>>> tcp_gro_receive (net/ipv4/tcp_offload.c:266 (discriminator 1))
>>> tcp4_gro_receive (net/ipv4/tcp_offload.c:316)
>>> inet_gro_receive (net/ipv4/af_inet.c:1545 (discriminator 2))
>>> dev_gro_receive (net/core/dev.c:6075)
>>> napi_gro_receive (net/core/dev.c:6168 net/core/dev.c:6198)
>>> receive_buf (drivers/net/virtio_net.c:1151) virtio_net
>>> virtnet_poll (drivers/net/virtio_net.c:1415 drivers/net/virtio_net.c:1519) virtio_net
>>> __napi_poll (net/core/dev.c:6964)
>>> net_rx_action (net/core/dev.c:7033 net/core/dev.c:7118)
>>> __do_softirq (./arch/x86/include/asm/jump_label.h:25 ./include/linux/jump_label.h:200 ./include/trace/events/irq.h:142 kernel/softirq.c:346)
>>> irq_exit_rcu (kernel/softirq.c:221 kernel/softirq.c:422 kernel/softirq.c:434)
>>> common_interrupt (arch/x86/kernel/irq.c:240 (discriminator 14))
>>> </IRQ>
>>>
>>> Fixes: fb32856b16ad ("virtio-net: page_to_skb() use build_skb when there's sufficient tailroom")
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> Reported-by: Ido Schimmel <idosch@nvidia.com>
>>> Tested-by: Ido Schimmel <idosch@nvidia.com>
>>> ---
>>
>> Acked-by: Jason Wang <jasowang@redhat.com>
>>
>> The codes became hard to read, I think we can try to do some cleanups on
>> top to make it easier to read.
>>
>> Thanks
> Yes, this piece of code needs to be sorted out. Especially the big and mergeable
> scenarios should be handled separately. Remove the mergeable code from this
> function, and mergeable uses a new function alone.


Right, another thing is that we may consider to relax the checking of 
len < GOOD_COPY_LEN.

Our QE still see low PPS compared with the code before 3226b158e67c 
("net: avoid 32 x truesize under-estimation for tiny skbs").

Thanks


>
> Thanks.
>
>>
>>>    drivers/net/virtio_net.c | 12 +++++++++---
>>>    1 file changed, 9 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>>> index 74d2d49264f3..7fda2ae4c40f 100644
>>> --- a/drivers/net/virtio_net.c
>>> +++ b/drivers/net/virtio_net.c
>>> @@ -387,7 +387,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
>>>    	unsigned int copy, hdr_len, hdr_padded_len;
>>>    	struct page *page_to_free = NULL;
>>>    	int tailroom, shinfo_size;
>>> -	char *p, *hdr_p;
>>> +	char *p, *hdr_p, *buf;
>>>
>>>    	p = page_address(page) + offset;
>>>    	hdr_p = p;
>>> @@ -403,11 +403,15 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
>>>    	 * space are aligned.
>>>    	 */
>>>    	if (headroom) {
>>> -		/* The actual allocated space size is PAGE_SIZE. */
>>> +		/* Buffers with headroom use PAGE_SIZE as alloc size,
>>> +		 * see add_recvbuf_mergeable() + get_mergeable_buf_len()
>>> +		 */
>>>    		truesize = PAGE_SIZE;
>>>    		tailroom = truesize - len - offset;
>>> +		buf = page_address(page);
>>>    	} else {
>>>    		tailroom = truesize - len;
>>> +		buf = p;
>>>    	}
>>>
>>>    	len -= hdr_len;
>>> @@ -416,11 +420,13 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
>>>
>>>    	shinfo_size = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
>>>
>>> +	/* copy small packet so we can reuse these pages */
>>>    	if (!NET_IP_ALIGN && len > GOOD_COPY_LEN && tailroom >= shinfo_size) {
>>> -		skb = build_skb(p, truesize);
>>> +		skb = build_skb(buf, truesize);
>>>    		if (unlikely(!skb))
>>>    			return NULL;
>>>
>>> +		skb_reserve(skb, p - buf);
>>>    		skb_put(skb, len);
>>>    		goto ok;
>>>    	}


WARNING: multiple messages have this Message-ID (diff)
From: Jason Wang <jasowang@redhat.com>
To: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>,
	Ido Schimmel <idosch@nvidia.com>,
	virtualization@lists.linux-foundation.org,
	netdev@vger.kernel.org, Jakub Kicinski <kuba@kernel.org>,
	"David S. Miller" <davem@davemloft.net>
Subject: Re: [PATCH net-next] virtio-net: fix use-after-free in skb_gro_receive
Date: Fri, 23 Apr 2021 12:33:09 +0800	[thread overview]
Message-ID: <b2f5cab7-18dd-2817-7423-e84ea1907bf3@redhat.com> (raw)
In-Reply-To: <1619151585.3098595-1-xuanzhuo@linux.alibaba.com>


在 2021/4/23 下午12:19, Xuan Zhuo 写道:
> On Fri, 23 Apr 2021 12:08:34 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2021/4/22 下午11:16, Xuan Zhuo 写道:
>>> When "headroom" > 0, the actual allocated memory space is the entire
>>> page, so the address of the page should be used when passing it to
>>> build_skb().
>>>
>>> BUG: KASAN: use-after-free in skb_gro_receive (net/core/skbuff.c:4260)
>>> Write of size 16 at addr ffff88811619fffc by task kworker/u9:0/534
>>> CPU: 2 PID: 534 Comm: kworker/u9:0 Not tainted 5.12.0-rc7-custom-16372-gb150be05b806 #3382
>>> Hardware name: QEMU MSN2700, BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
>>> Workqueue: xprtiod xs_stream_data_receive_workfn [sunrpc]
>>> Call Trace:
>>>    <IRQ>
>>> dump_stack (lib/dump_stack.c:122)
>>> print_address_description.constprop.0 (mm/kasan/report.c:233)
>>> kasan_report.cold (mm/kasan/report.c:400 mm/kasan/report.c:416)
>>> skb_gro_receive (net/core/skbuff.c:4260)
>>> tcp_gro_receive (net/ipv4/tcp_offload.c:266 (discriminator 1))
>>> tcp4_gro_receive (net/ipv4/tcp_offload.c:316)
>>> inet_gro_receive (net/ipv4/af_inet.c:1545 (discriminator 2))
>>> dev_gro_receive (net/core/dev.c:6075)
>>> napi_gro_receive (net/core/dev.c:6168 net/core/dev.c:6198)
>>> receive_buf (drivers/net/virtio_net.c:1151) virtio_net
>>> virtnet_poll (drivers/net/virtio_net.c:1415 drivers/net/virtio_net.c:1519) virtio_net
>>> __napi_poll (net/core/dev.c:6964)
>>> net_rx_action (net/core/dev.c:7033 net/core/dev.c:7118)
>>> __do_softirq (./arch/x86/include/asm/jump_label.h:25 ./include/linux/jump_label.h:200 ./include/trace/events/irq.h:142 kernel/softirq.c:346)
>>> irq_exit_rcu (kernel/softirq.c:221 kernel/softirq.c:422 kernel/softirq.c:434)
>>> common_interrupt (arch/x86/kernel/irq.c:240 (discriminator 14))
>>> </IRQ>
>>>
>>> Fixes: fb32856b16ad ("virtio-net: page_to_skb() use build_skb when there's sufficient tailroom")
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> Reported-by: Ido Schimmel <idosch@nvidia.com>
>>> Tested-by: Ido Schimmel <idosch@nvidia.com>
>>> ---
>>
>> Acked-by: Jason Wang <jasowang@redhat.com>
>>
>> The codes became hard to read, I think we can try to do some cleanups on
>> top to make it easier to read.
>>
>> Thanks
> Yes, this piece of code needs to be sorted out. Especially the big and mergeable
> scenarios should be handled separately. Remove the mergeable code from this
> function, and mergeable uses a new function alone.


Right, another thing is that we may consider to relax the checking of 
len < GOOD_COPY_LEN.

Our QE still see low PPS compared with the code before 3226b158e67c 
("net: avoid 32 x truesize under-estimation for tiny skbs").

Thanks


>
> Thanks.
>
>>
>>>    drivers/net/virtio_net.c | 12 +++++++++---
>>>    1 file changed, 9 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>>> index 74d2d49264f3..7fda2ae4c40f 100644
>>> --- a/drivers/net/virtio_net.c
>>> +++ b/drivers/net/virtio_net.c
>>> @@ -387,7 +387,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
>>>    	unsigned int copy, hdr_len, hdr_padded_len;
>>>    	struct page *page_to_free = NULL;
>>>    	int tailroom, shinfo_size;
>>> -	char *p, *hdr_p;
>>> +	char *p, *hdr_p, *buf;
>>>
>>>    	p = page_address(page) + offset;
>>>    	hdr_p = p;
>>> @@ -403,11 +403,15 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
>>>    	 * space are aligned.
>>>    	 */
>>>    	if (headroom) {
>>> -		/* The actual allocated space size is PAGE_SIZE. */
>>> +		/* Buffers with headroom use PAGE_SIZE as alloc size,
>>> +		 * see add_recvbuf_mergeable() + get_mergeable_buf_len()
>>> +		 */
>>>    		truesize = PAGE_SIZE;
>>>    		tailroom = truesize - len - offset;
>>> +		buf = page_address(page);
>>>    	} else {
>>>    		tailroom = truesize - len;
>>> +		buf = p;
>>>    	}
>>>
>>>    	len -= hdr_len;
>>> @@ -416,11 +420,13 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
>>>
>>>    	shinfo_size = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
>>>
>>> +	/* copy small packet so we can reuse these pages */
>>>    	if (!NET_IP_ALIGN && len > GOOD_COPY_LEN && tailroom >= shinfo_size) {
>>> -		skb = build_skb(p, truesize);
>>> +		skb = build_skb(buf, truesize);
>>>    		if (unlikely(!skb))
>>>    			return NULL;
>>>
>>> +		skb_reserve(skb, p - buf);
>>>    		skb_put(skb, len);
>>>    		goto ok;
>>>    	}

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

       reply	other threads:[~2021-04-23  4:33 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1619151585.3098595-1-xuanzhuo@linux.alibaba.com>
2021-04-23  4:33 ` Jason Wang [this message]
2021-04-23  4:33   ` [PATCH net-next] virtio-net: fix use-after-free in skb_gro_receive Jason Wang
2021-05-03  8:00   ` Michael S. Tsirkin
2021-05-03  8:00     ` Michael S. Tsirkin
     [not found] <1620030574.9881887-1-xuanzhuo@linux.alibaba.com>
2021-05-06  3:23 ` Jason Wang
2021-05-06  3:23   ` Jason Wang
2021-04-22 15:16 Xuan Zhuo
2021-04-23  4:08 ` Jason Wang
2021-04-23  4:08   ` Jason Wang
2021-04-23 20:20 ` patchwork-bot+netdevbpf
2021-05-03  7:59 ` Michael S. Tsirkin
2021-05-03  7:59   ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b2f5cab7-18dd-2817-7423-e84ea1907bf3@redhat.com \
    --to=jasowang@redhat.com \
    --cc=davem@davemloft.net \
    --cc=idosch@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=virtualization@lists.linux-foundation.org \
    --cc=xuanzhuo@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.