diff mbox series

[net] virtio_net: bugfix overflow inside xdp_linearize_page()

Message ID 20230413121937.46135-1-xuanzhuo@linux.alibaba.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net] virtio_net: bugfix overflow inside xdp_linearize_page() | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/fixes_present fail Series targets non-next tree, but doesn't contain any Fixes tags
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 18 this patch: 18
netdev/cc_maintainers success CCed 13 of 13 maintainers
netdev/build_clang success Errors and warnings before: 18 this patch: 18
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 18 this patch: 18
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 21 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Xuan Zhuo April 13, 2023, 12:19 p.m. UTC
Here we copy the data from the original buf to the new page. But we
not check that it may be overflow.

As long as the size received(including vnethdr) is greater than 3840
(PAGE_SIZE -VIRTIO_XDP_HEADROOM). Then the memcpy will overflow.

And this is completely possible, as long as the MTU is large, such
as 4096. In our test environment, this will cause crash. Since crash is
caused by the written memory, it is meaningless, so I do not include it.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

Comments

Jason Wang April 14, 2023, 5:40 a.m. UTC | #1
On Thu, Apr 13, 2023 at 8:19 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
>
> Here we copy the data from the original buf to the new page. But we
> not check that it may be overflow.
>
> As long as the size received(including vnethdr) is greater than 3840
> (PAGE_SIZE -VIRTIO_XDP_HEADROOM). Then the memcpy will overflow.
>
> And this is completely possible, as long as the MTU is large, such
> as 4096. In our test environment, this will cause crash. Since crash is
> caused by the written memory, it is meaningless, so I do not include it.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>

Missing fixes tag?

Other than this,

Acked-by: Jason Wang <jasowang@redhat.com>

Thanks

> ---
>  drivers/net/virtio_net.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 2396c28c0122..ea1bd4bb326d 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -814,8 +814,13 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
>                                        int page_off,
>                                        unsigned int *len)
>  {
> -       struct page *page = alloc_page(GFP_ATOMIC);
> +       int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
> +       struct page *page;
> +
> +       if (page_off + *len + tailroom > PAGE_SIZE)
> +               return NULL;
>
> +       page = alloc_page(GFP_ATOMIC);
>         if (!page)
>                 return NULL;
>
> @@ -823,7 +828,6 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
>         page_off += *len;
>
>         while (--*num_buf) {
> -               int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
>                 unsigned int buflen;
>                 void *buf;
>                 int off;
> --
> 2.32.0.3.g01195cf9f
>
Xuan Zhuo April 14, 2023, 5:59 a.m. UTC | #2
On Fri, 14 Apr 2023 13:40:32 +0800, Jason Wang <jasowang@redhat.com> wrote:
> On Thu, Apr 13, 2023 at 8:19 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> >
> > Here we copy the data from the original buf to the new page. But we
> > not check that it may be overflow.
> >
> > As long as the size received(including vnethdr) is greater than 3840
> > (PAGE_SIZE -VIRTIO_XDP_HEADROOM). Then the memcpy will overflow.
> >
> > And this is completely possible, as long as the MTU is large, such
> > as 4096. In our test environment, this will cause crash. Since crash is
> > caused by the written memory, it is meaningless, so I do not include it.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>
> Missing fixes tag?
>
> Other than this,
>
> Acked-by: Jason Wang <jasowang@redhat.com>

Sorry, miss this.

Thanks.



>
> Thanks
>
> > ---
> >  drivers/net/virtio_net.c | 8 ++++++--
> >  1 file changed, 6 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 2396c28c0122..ea1bd4bb326d 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -814,8 +814,13 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
> >                                        int page_off,
> >                                        unsigned int *len)
> >  {
> > -       struct page *page = alloc_page(GFP_ATOMIC);
> > +       int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
> > +       struct page *page;
> > +
> > +       if (page_off + *len + tailroom > PAGE_SIZE)
> > +               return NULL;
> >
> > +       page = alloc_page(GFP_ATOMIC);
> >         if (!page)
> >                 return NULL;
> >
> > @@ -823,7 +828,6 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
> >         page_off += *len;
> >
> >         while (--*num_buf) {
> > -               int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
> >                 unsigned int buflen;
> >                 void *buf;
> >                 int off;
> > --
> > 2.32.0.3.g01195cf9f
> >
>
diff mbox series

Patch

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 2396c28c0122..ea1bd4bb326d 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -814,8 +814,13 @@  static struct page *xdp_linearize_page(struct receive_queue *rq,
 				       int page_off,
 				       unsigned int *len)
 {
-	struct page *page = alloc_page(GFP_ATOMIC);
+	int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+	struct page *page;
+
+	if (page_off + *len + tailroom > PAGE_SIZE)
+		return NULL;
 
+	page = alloc_page(GFP_ATOMIC);
 	if (!page)
 		return NULL;
 
@@ -823,7 +828,6 @@  static struct page *xdp_linearize_page(struct receive_queue *rq,
 	page_off += *len;
 
 	while (--*num_buf) {
-		int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 		unsigned int buflen;
 		void *buf;
 		int off;