* [PATCH net v1] net: Fix tuntap uninitialized value
@ 2025-03-27 13:41 Jiayuan Chen
2025-03-27 21:08 ` Willem de Bruijn
0 siblings, 1 reply; 5+ messages in thread
From: Jiayuan Chen @ 2025-03-27 13:41 UTC (permalink / raw)
To: netdev
Cc: willemdebruijn.kernel, jasowang, andrew+netdev, davem, edumazet,
kuba, pabeni, ast, daniel, hawk, john.fastabend, linux-kernel,
Jiayuan Chen, syzbot+0e6ddb1ef80986bdfe64
Then tun/tap allocates an skb, it additionally allocates a prepad size
(usually equal to NET_SKB_PAD) but leaves it uninitialized.
bpf_xdp_adjust_head() may move skb->data forward, which may lead to an
issue.
Since the linear address is likely to be allocated from kmem_cache, it's
unlikely to trigger a KMSAN warning. We need some tricks, such as forcing
kmem_cache_shrink in __do_kmalloc_node, to reproduce the issue and trigger
a KMSAN warning.
Reported-by: syzbot+0e6ddb1ef80986bdfe64@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/00000000000067f65105edbd295d@google.com/T/
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
drivers/net/tun.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index f75f912a0225..111f83668b5e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1463,6 +1463,7 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
if (!skb)
return ERR_PTR(err);
+ memset(skb->data, 0, prepad);
skb_reserve(skb, prepad);
skb_put(skb, linear);
skb->data_len = len - linear;
@@ -1621,6 +1622,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
return ERR_PTR(-ENOMEM);
buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset;
+ memset(buf, 0, pad);
copied = copy_page_from_iter(alloc_frag->page,
alloc_frag->offset + pad,
len, from);
--
2.47.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net v1] net: Fix tuntap uninitialized value
2025-03-27 13:41 [PATCH net v1] net: Fix tuntap uninitialized value Jiayuan Chen
@ 2025-03-27 21:08 ` Willem de Bruijn
2025-03-28 9:15 ` Jiayuan Chen
0 siblings, 1 reply; 5+ messages in thread
From: Willem de Bruijn @ 2025-03-27 21:08 UTC (permalink / raw)
To: Jiayuan Chen, netdev
Cc: willemdebruijn.kernel, jasowang, andrew+netdev, davem, edumazet,
kuba, pabeni, ast, daniel, hawk, john.fastabend, linux-kernel,
Jiayuan Chen, syzbot+0e6ddb1ef80986bdfe64, bpf
Jiayuan Chen wrote:
> Then tun/tap allocates an skb, it additionally allocates a prepad size
> (usually equal to NET_SKB_PAD) but leaves it uninitialized.
>
> bpf_xdp_adjust_head() may move skb->data forward, which may lead to an
> issue.
>
> Since the linear address is likely to be allocated from kmem_cache, it's
> unlikely to trigger a KMSAN warning. We need some tricks, such as forcing
> kmem_cache_shrink in __do_kmalloc_node, to reproduce the issue and trigger
> a KMSAN warning.
>
> Reported-by: syzbot+0e6ddb1ef80986bdfe64@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/00000000000067f65105edbd295d@google.com/T/
> Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
> ---
> drivers/net/tun.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index f75f912a0225..111f83668b5e 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -1463,6 +1463,7 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
> if (!skb)
> return ERR_PTR(err);
>
> + memset(skb->data, 0, prepad);
> skb_reserve(skb, prepad);
> skb_put(skb, linear);
> skb->data_len = len - linear;
Is this specific to the tun device?
This happens in generic (skb) xdp.
The stackdump shows a napi poll call stack
bpf_prog_run_generic_xdp+0x13ff/0x1a30 net/core/dev.c:4782
netif_receive_generic_xdp+0x639/0x910 net/core/dev.c:4845
do_xdp_generic net/core/dev.c:4904 [inline]
__netif_receive_skb_core+0x290f/0x6360 net/core/dev.c:5310
__netif_receive_skb_one_core net/core/dev.c:5487 [inline]
__netif_receive_skb+0xc8/0x5d0 net/core/dev.c:5603
process_backlog+0x45a/0x890 net/core/dev.c:5931
Since this is syzbot, the skb will have come from a tun device,
seemingly with IFF_NAPI, and maybe IFF_NAPI_FRAGS.
But relevant to bpf_xdp_adjust_head is how the xdp metadata
was setup with xdp_prepare_buff, which here is called from
bpf_prog_run_generic_xdp:
/* The XDP program wants to see the packet starting at the MAC
* header.
*/
mac_len = skb->data - skb_mac_header(skb);
hard_start = skb->data - skb_headroom(skb);
/* SKB "head" area always have tailroom for skb_shared_info */
frame_sz = (void *)skb_end_pointer(skb) - hard_start;
frame_sz += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
rxqueue = netif_get_rxqueue(skb);
xdp_init_buff(xdp, frame_sz, &rxqueue->xdp_rxq);
xdp_prepare_buff(xdp, hard_start, skb_headroom(skb) - mac_len,
skb_headlen(skb) + mac_len, true);
> @@ -1621,6 +1622,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
> return ERR_PTR(-ENOMEM);
>
> buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset;
> + memset(buf, 0, pad);
> copied = copy_page_from_iter(alloc_frag->page,
> alloc_frag->offset + pad,
> len, from);
> --
> 2.47.1
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net v1] net: Fix tuntap uninitialized value
2025-03-27 21:08 ` Willem de Bruijn
@ 2025-03-28 9:15 ` Jiayuan Chen
2025-03-28 11:39 ` Jakub Kicinski
0 siblings, 1 reply; 5+ messages in thread
From: Jiayuan Chen @ 2025-03-28 9:15 UTC (permalink / raw)
To: Willem de Bruijn, netdev
Cc: willemdebruijn.kernel, jasowang, andrew+netdev, davem, edumazet,
kuba, pabeni, ast, daniel, hawk, john.fastabend, linux-kernel,
syzbot+0e6ddb1ef80986bdfe64, bpf, martin.lau, eddyz87, song,
kpsingh, jolsa
March 28, 2025 at 05:08, "Willem de Bruijn" <willemdebruijn.kernel@gmail.com> wrote:
>
> Jiayuan Chen wrote:
>
> >
> > Then tun/tap allocates an skb, it additionally allocates a prepad size
> > (usually equal to NET_SKB_PAD) but leaves it uninitialized.
> > bpf_xdp_adjust_head() may move skb->data forward, which may lead to an
> > issue.
> > Since the linear address is likely to be allocated from kmem_cache, it's
> > unlikely to trigger a KMSAN warning. We need some tricks, such as forcing
> > kmem_cache_shrink in __do_kmalloc_node, to reproduce the issue and trigger
> > a KMSAN warning.
> >
> > Reported-by: syzbot+0e6ddb1ef80986bdfe64@syzkaller.appspotmail.com
> > Closes: https://lore.kernel.org/all/00000000000067f65105edbd295d@google.com/T/
> > Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
> >
> > ---
> >
> > drivers/net/tun.c | 2 ++
> >
> > 1 file changed, 2 insertions(+)
> >
> >
> >
> > diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> >
> > index f75f912a0225..111f83668b5e 100644
> >
> > --- a/drivers/net/tun.c
> >
> > +++ b/drivers/net/tun.c
> >
> > @@ -1463,6 +1463,7 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
> >
> > if (!skb)
> >
> > return ERR_PTR(err);
> >
> >
> >
> > + memset(skb->data, 0, prepad);
> >
> > skb_reserve(skb, prepad);
> >
> > skb_put(skb, linear);
> >
> > skb->data_len = len - linear;
> >
>
> Is this specific to the tun device?
>
> This happens in generic (skb) xdp.
>
> The stackdump shows a napi poll call stack
>
> bpf_prog_run_generic_xdp+0x13ff/0x1a30 net/core/dev.c:4782
>
> netif_receive_generic_xdp+0x639/0x910 net/core/dev.c:4845
>
> do_xdp_generic net/core/dev.c:4904 [inline]
>
> __netif_receive_skb_core+0x290f/0x6360 net/core/dev.c:5310
>
> __netif_receive_skb_one_core net/core/dev.c:5487 [inline]
>
> __netif_receive_skb+0xc8/0x5d0 net/core/dev.c:5603
>
> process_backlog+0x45a/0x890 net/core/dev.c:5931
>
> Since this is syzbot, the skb will have come from a tun device,
>
> seemingly with IFF_NAPI, and maybe IFF_NAPI_FRAGS.
>
> But relevant to bpf_xdp_adjust_head is how the xdp metadata
>
Thanks.
I'm wondering if we can directly perform a memset in bpf_xdp_adjust_head
when users execute an expand header (offset < 0).
Although the main purpose of bpf_xdp_adjust_head is to write new headers,
it's possible that some users might be doing this to read lower-layer
headers, in which case memset would be inappropriate.
However, I found that when expanding headers, it also involves copying
data meta forward, which would overwrite padding memory, so maybe I'm
overthinking this?
In general, since bpf_xdp_adjust_head can access skb->head, it exposes a
minimum of XDP_PACKET_HEADROOM (256) uninitialized bytes to users, and
I'm not entirely clear if there are any security implications.
diff --git a/net/core/filter.c b/net/core/filter.c
index 2ec162dd83c4..51f3f0d9b4bb 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3947,6 +3947,8 @@ BPF_CALL_2(bpf_xdp_adjust_head, struct xdp_buff *, xdp, int, offset)
if (metalen)
memmove(xdp->data_meta + offset,
xdp->data_meta, metalen);
+ if (offset < 0)
+ memset(data, 0, -offset);
xdp->data_meta += offset;
xdp->data = data;
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net v1] net: Fix tuntap uninitialized value
2025-03-28 9:15 ` Jiayuan Chen
@ 2025-03-28 11:39 ` Jakub Kicinski
2025-03-31 11:47 ` Lei Yang
0 siblings, 1 reply; 5+ messages in thread
From: Jakub Kicinski @ 2025-03-28 11:39 UTC (permalink / raw)
To: Jiayuan Chen
Cc: Willem de Bruijn, netdev, jasowang, andrew+netdev, davem,
edumazet, pabeni, ast, daniel, hawk, john.fastabend, linux-kernel,
syzbot+0e6ddb1ef80986bdfe64, bpf, martin.lau, eddyz87, song,
kpsingh, jolsa
On Fri, 28 Mar 2025 09:15:53 +0000 Jiayuan Chen wrote:
> I'm wondering if we can directly perform a memset in bpf_xdp_adjust_head
> when users execute an expand header (offset < 0).
Same situation happens in bpf_xdp_adjust_meta(), but I'm pretty
sure this was discussed and considered too high cost for XDP.
Could you find the old discussions and double check the arguments
made back then? Opinions may have changed but let's make sure we're
not missing anything. And performance numbers would be good to have
since the main reason this isn't done today was perf.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net v1] net: Fix tuntap uninitialized value
2025-03-28 11:39 ` Jakub Kicinski
@ 2025-03-31 11:47 ` Lei Yang
0 siblings, 0 replies; 5+ messages in thread
From: Lei Yang @ 2025-03-31 11:47 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Jiayuan Chen, Willem de Bruijn, netdev, jasowang, andrew+netdev,
davem, edumazet, pabeni, ast, daniel, hawk, john.fastabend,
linux-kernel, syzbot+0e6ddb1ef80986bdfe64, bpf, martin.lau,
eddyz87, song, kpsingh, jolsa
QE tested this patch with virtio-net regression tests, everything works fine.
Tested-by: Lei Yang <leiyang@redhat.com>
On Fri, Mar 28, 2025 at 7:39 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Fri, 28 Mar 2025 09:15:53 +0000 Jiayuan Chen wrote:
> > I'm wondering if we can directly perform a memset in bpf_xdp_adjust_head
> > when users execute an expand header (offset < 0).
>
> Same situation happens in bpf_xdp_adjust_meta(), but I'm pretty
> sure this was discussed and considered too high cost for XDP.
> Could you find the old discussions and double check the arguments
> made back then? Opinions may have changed but let's make sure we're
> not missing anything. And performance numbers would be good to have
> since the main reason this isn't done today was perf.
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-03-31 11:47 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-27 13:41 [PATCH net v1] net: Fix tuntap uninitialized value Jiayuan Chen
2025-03-27 21:08 ` Willem de Bruijn
2025-03-28 9:15 ` Jiayuan Chen
2025-03-28 11:39 ` Jakub Kicinski
2025-03-31 11:47 ` Lei Yang
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).