diff mbox series

[v2,net] bpf: do not return NET_XMIT_xxx values on bpf_redirect

Message ID ZLdY6JkWRccunvu0@debian.debian (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [v2,net] bpf: do not return NET_XMIT_xxx values on bpf_redirect | 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: 1368 this patch: 1368
netdev/cc_maintainers success CCed 17 of 17 maintainers
netdev/build_clang success Errors and warnings before: 1365 this patch: 1365
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: 1391 this patch: 1391
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 9 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Yan Zhai July 19, 2023, 3:30 a.m. UTC
skb_do_redirect handles returns error code from both rx and tx path. The
tx path codes are special, e.g. NET_XMIT_CN: they are non-negative, and
can conflict with LWTUNNEL_XMIT_xxx values. Directly returning such code
can cause unexpected behavior. We found at least one bug that will panic
the kernel through KASAN report when we are redirecting packets to a
down or carrier-down device at lwt xmit hook:

https://gist.github.com/zhaiyan920/8fbac245b261fe316a7ef04c9b1eba48

Above bug is hit because NET_XMIT_CN is returned by noop_qdisc of the
down device, and it propagates from dev_queue_xmit all way to the lwt
logic. The result is skb that has been freed by the qdisc continues to
neighbor subsystem and triggers the bug.

This change converts the tx code to proper errors that lwt can consume.

Suggested-by: Stanislav Fomichev <sdf@google.com>
Reported-by: Jordan Griege <jgriege@cloudflare.com>
Signed-off-by: Yan Zhai <yan@cloudflare.com>
---
v2: coding style fix; sent to netdev instead of bpf for bug fixing.

---
 net/core/filter.c | 3 +++
 1 file changed, 3 insertions(+)

Comments

Alexei Starovoitov July 19, 2023, 3:42 a.m. UTC | #1
On Tue, Jul 18, 2023 at 8:30 PM Yan Zhai <yan@cloudflare.com> wrote:
>
> skb_do_redirect handles returns error code from both rx and tx path. The
> tx path codes are special, e.g. NET_XMIT_CN: they are non-negative, and
> can conflict with LWTUNNEL_XMIT_xxx values. Directly returning such code
> can cause unexpected behavior. We found at least one bug that will panic
> the kernel through KASAN report when we are redirecting packets to a
> down or carrier-down device at lwt xmit hook:
>
> https://gist.github.com/zhaiyan920/8fbac245b261fe316a7ef04c9b1eba48
>
> Above bug is hit because NET_XMIT_CN is returned by noop_qdisc of the
> down device, and it propagates from dev_queue_xmit all way to the lwt
> logic. The result is skb that has been freed by the qdisc continues to
> neighbor subsystem and triggers the bug.

I'm struggling to parse the above paragraph.
Where bpf prog is installed?
Is this lwt bpf prog that returns BPF_REDIRECT ?
that redirects to netdev with noop_qdisc ?
What is the topology?

Please add a selftest to make sure we don't regress.

Also pls mark your patch as [PATCH v3 bpf] when you respin.

> This change converts the tx code to proper errors that lwt can consume.
>
> Suggested-by: Stanislav Fomichev <sdf@google.com>
> Reported-by: Jordan Griege <jgriege@cloudflare.com>
> Signed-off-by: Yan Zhai <yan@cloudflare.com>
> ---
> v2: coding style fix; sent to netdev instead of bpf for bug fixing.
>
> ---
>  net/core/filter.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 06ba0e56e369..8738c7a4701d 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -2129,6 +2129,9 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
>         ret = dev_queue_xmit(skb);
>         dev_xmit_recursion_dec();
>
> +       if (unlikely(ret > 0))
> +               ret = net_xmit_errno(ret);
> +
>         return ret;
>  }
>
> --
> 2.30.2
>
Yan Zhai July 20, 2023, 2:48 a.m. UTC | #2
On Tue, Jul 18, 2023 at 10:42 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Tue, Jul 18, 2023 at 8:30 PM Yan Zhai <yan@cloudflare.com> wrote:
> >
> > skb_do_redirect handles returns error code from both rx and tx path. The
> > tx path codes are special, e.g. NET_XMIT_CN: they are non-negative, and
> > can conflict with LWTUNNEL_XMIT_xxx values. Directly returning such code
> > can cause unexpected behavior. We found at least one bug that will panic
> > the kernel through KASAN report when we are redirecting packets to a
> > down or carrier-down device at lwt xmit hook:
> >
> > https://gist.github.com/zhaiyan920/8fbac245b261fe316a7ef04c9b1eba48
> >
> > Above bug is hit because NET_XMIT_CN is returned by noop_qdisc of the
> > down device, and it propagates from dev_queue_xmit all way to the lwt
> > logic. The result is skb that has been freed by the qdisc continues to
> > neighbor subsystem and triggers the bug.
>
> I'm struggling to parse the above paragraph.
> Where bpf prog is installed?
> Is this lwt bpf prog that returns BPF_REDIRECT ?
> that redirects to netdev with noop_qdisc ?
> What is the topology?
>
Sorry for the confusion. Mentioning noop_qdisc is an explanation of
what happened. The actual trigger is simple: install a bpf program on
lwt route at xmit hook. It bpf_redirect packets to a device FOO. If
FOO is down or carrier-down, redirected packets will crash the kernel.

> Please add a selftest to make sure we don't regress.
>
> Also pls mark your patch as [PATCH v3 bpf] when you respin.
>
Ack

> > This change converts the tx code to proper errors that lwt can consume.
> >
> > Suggested-by: Stanislav Fomichev <sdf@google.com>
> > Reported-by: Jordan Griege <jgriege@cloudflare.com>
> > Signed-off-by: Yan Zhai <yan@cloudflare.com>
> > ---
> > v2: coding style fix; sent to netdev instead of bpf for bug fixing.
> >
> > ---
> >  net/core/filter.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/net/core/filter.c b/net/core/filter.c
> > index 06ba0e56e369..8738c7a4701d 100644
> > --- a/net/core/filter.c
> > +++ b/net/core/filter.c
> > @@ -2129,6 +2129,9 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
> >         ret = dev_queue_xmit(skb);
> >         dev_xmit_recursion_dec();
> >
> > +       if (unlikely(ret > 0))
> > +               ret = net_xmit_errno(ret);
> > +
> >         return ret;
> >  }
> >
> > --
> > 2.30.2
> >
diff mbox series

Patch

diff --git a/net/core/filter.c b/net/core/filter.c
index 06ba0e56e369..8738c7a4701d 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2129,6 +2129,9 @@  static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
 	ret = dev_queue_xmit(skb);
 	dev_xmit_recursion_dec();
 
+	if (unlikely(ret > 0))
+		ret = net_xmit_errno(ret);
+
 	return ret;
 }