lwt: fix return values of BPF ops
Subsystems (6)
v6 cover lwt: fix return values of BPF ops
lwt xmit hook does not expect positive return values in function ip_finish_output2 and ip6_finish_output. However, BPF programs can directly return positive statuses such like NET_XMIT_DROP, NET_RX_DROP, and etc to the caller. Such return values would make the kernel continue processing already freed skbs and eventually panic.
This set fixes the return values from BPF ops to unexpected continue processing, checks strictly on the correct continue condition for future proof. In addition, add missing selftests for BPF redirect and reroute cases for BPF-CI.
v5: https://lore.kernel.org/bpf/[email protected]/
v4: https://lore.kernel.org/bpf/[email protected]/T/
v3: https://lore.kernel.org/bpf/[email protected]/
v2: https://lore.kernel.org/netdev/[email protected]/
v1: https://lore.kernel.org/bpf/[email protected]/
changes since v5:
* fix BPF-CI failures due to missing config and busybox ping issue
changes since v4:
* fixed same error on BPF_REROUTE path
* re-implemented selftests under BPF-CI requirement
changes since v3:
* minor change in commit message and changelogs
* tested by Jakub Sitnicki
changes since v2:
* subject name changed
* also covered redirect to ingress case
* added selftests
changes since v1:
* minor code style changes
Yan Zhai (4):
lwt: fix return values of BPF xmit ops
lwt: check LWTUNNEL_XMIT_CONTINUE strictly selftests/bpf: add lwt_xmit tests for BPF_REDIRECT selftests/bpf: add lwt_xmit tests for BPF_REROUTE
include/net/lwtunnel.h | 5 +- net/core/lwt_bpf.c | 7 +- net/ipv4/ip_output.c | 2 +- net/ipv6/ip6_output.c | 2 +- tools/testing/selftests/bpf/config | 2 + .../selftests/bpf/prog_tests/lwt_helpers.h | 139 ++++++++ .../selftests/bpf/prog_tests/lwt_redirect.c | 330 ++++++++++++++++++ .../selftests/bpf/prog_tests/lwt_reroute.c | 262 ++++++++++++++ .../selftests/bpf/progs/test_lwt_redirect.c | 90 +++++ .../selftests/bpf/progs/test_lwt_reroute.c | 36 ++ 10 files changed, 868 insertions(+), 7 deletions(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/lwt_helpers.h create mode 100644 tools/testing/selftests/bpf/prog_tests/lwt_redirect.c create mode 100644 tools/testing/selftests/bpf/prog_tests/lwt_reroute.c create mode 100644 tools/testing/selftests/bpf/progs/test_lwt_redirect.c create mode 100644 tools/testing/selftests/bpf/progs/test_lwt_reroute.c
Signature · 1 line
2.30.2
PATCH v6 1/4 lwt: fix return values of BPF xmit ops
BPF encap ops can return different types of positive values, such like NET_RX_DROP, NET_XMIT_CN, NETDEV_TX_BUSY, and so on, from function skb_do_redirect and bpf_lwt_xmit_reroute. At the xmit hook, such return values would be treated implicitly as LWTUNNEL_XMIT_CONTINUE in ip(6)_finish_output2. When this happens, skbs that have been freed would continue to the neighbor subsystem, causing use-after-free bug and kernel crashes.
To fix the incorrect behavior, skb_do_redirect return values can be simply discarded, the same as tc-egress behavior. On the other hand, bpf_lwt_xmit_reroute returns useful errors to local senders, e.g. PMTU information. Thus convert its return values to avoid the conflict with LWTUNNEL_XMIT_CONTINUE.
---
* v5: discards skb_do_redirect return instead; convert
bpf_lwt_xmit_reroute return; * v4: minor commit message changes * v3: converts skb_do_redirect statuses from both ingress and egress * v2: code style amend --- net/core/lwt_bpf.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
net/core/lwt_bpf.c +3 -4
@@ -60,9 +60,8 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt, ret =BPF_OK ; }else {skb_reset_mac_header (skb); - ret =skb_do_redirect (skb); -if (ret ==0 ) - ret =BPF_REDIRECT ; +skb_do_redirect (skb); + ret =BPF_REDIRECT ; }break ;
@@ -255,7 +254,7 @@ static int bpf_lwt_xmit_reroute(struct sk_buff *skb) err =dst_output (dev_net (skb_dst (skb)->dev), skb->sk, skb);if (unlikely (err)) -return err; +return net_xmit_errno (err);/* ip[6]_finish_output2 understand LWTUNNEL_XMIT_DONE */ return LWTUNNEL_XMIT_DONE ;
Signature · 1 line
2.30.2
PATCH v6 2/4 lwt: check LWTUNNEL_XMIT_CONTINUE strictly
In reply to Yan ZhaiLWTUNNEL_XMIT_CONTINUE is implicitly assumed in ip(6)_finish_output2, such that any positive return value from a xmit hook could cause unexpected continue behavior, despite that related skb may have been freed. This could be error-prone for future xmit hook ops. One of the possible errors is to return statuses of dst_output directly.
To make the code safer, redefine LWTUNNEL_XMIT_CONTINUE value to distinguish from dst_output statuses and check the continue condition explicitly.
--- include/net/lwtunnel.h | 5 ++++- net/ipv4/ip_output.c | 2 +- net/ipv6/ip6_output.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-)
include/net/lwtunnel.h +4 -1
@@ -16,9 +16,12 @@#define LWTUNNEL_STATE_INPUT_REDIRECT BIT(1)#define LWTUNNEL_STATE_XMIT_REDIRECT BIT(2) +/* LWTUNNEL_XMIT_CONTINUE should be distinguishable from dst_output return +* values (NET_XMIT_xxx and NETDEV_TX_xxx in linux/netdevice.h) for safety. +*/ enum {LWTUNNEL_XMIT_DONE , -LWTUNNEL_XMIT_CONTINUE , +LWTUNNEL_XMIT_CONTINUE =0x100 , };
net/ipv4/ip_output.c +1 -1
@@ -216,7 +216,7 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *sif (lwtunnel_xmit_redirect (dst->lwtstate)) {int res =lwtunnel_xmit (skb); -if (res <0 || res ==LWTUNNEL_XMIT_DONE ) +if (res !=LWTUNNEL_XMIT_CONTINUE )return res; }
net/ipv6/ip6_output.c +1 -1
@@ -113,7 +113,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *if (lwtunnel_xmit_redirect (dst->lwtstate)) {int res =lwtunnel_xmit (skb); -if (res <0 || res ==LWTUNNEL_XMIT_DONE ) +if (res !=LWTUNNEL_XMIT_CONTINUE )return res; }
Signature · 1 line
2.30.2
PATCH v6 3/4 selftests/bpf: add lwt_xmit tests for BPF_REDIRECT
In reply to Yan ZhaiThere is no lwt_xmit test case for BPF_REDIRECT yet. Add test cases for both normal and abnormal situations. For abnormal test cases, devices are set down or have its carrier set down. Without proper fixes, BPF_REDIRECT to either ingress or egress of such device would panic the kernel.
---v5->v6: busybox does not support ping mark, redirect via IP address
instead. Add missing kernel test config.
--- tools/testing/selftests/bpf/config | 1 + .../selftests/bpf/prog_tests/lwt_helpers.h | 139 ++++++++ .../selftests/bpf/prog_tests/lwt_redirect.c | 330 ++++++++++++++++++ .../selftests/bpf/progs/test_lwt_redirect.c | 90 +++++ 4 files changed, 560 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/lwt_helpers.h create mode 100644 tools/testing/selftests/bpf/prog_tests/lwt_redirect.c create mode 100644 tools/testing/selftests/bpf/progs/test_lwt_redirect.c
tools/testing/selftests/bpf/config +1 -0
@@ -16,6 +16,7 @@ CONFIG_CRYPTO_USER_API_HASH=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_BTF=y CONFIG_DEBUG_INFO_DWARF4=y +CONFIG_DUMMY=y CONFIG_DYNAMIC_FTRACE=y CONFIG_FPROBE=y CONFIG_FTRACE_SYSCALLS=y
tools/testing/selftests/bpf/prog_tests/lwt_helpers.h new file +139 -0
139 lines not on this page · raw message
tools/testing/selftests/bpf/prog_tests/lwt_redirect.c new file +330 -0
330 lines not on this page · raw message
tools/testing/selftests/bpf/progs/test_lwt_redirect.c new file +90 -0
90 lines not on this page · raw message
Signature · 1 line
2.30.2
PATCH v6 4/4 selftests/bpf: add lwt_xmit tests for BPF_REROUTE
In reply to Yan ZhaiThere is no lwt test case for BPF_REROUTE yet. Add test cases for both normal and abnormal situations. The abnormal situation is set up with an fq qdisc on the reroute target device. Without proper fixes, overflow this qdisc queue limit (to trigger a drop) would panic the kernel.
--- tools/testing/selftests/bpf/config | 1 + .../selftests/bpf/prog_tests/lwt_reroute.c | 262 ++++++++++++++++++ .../selftests/bpf/progs/test_lwt_reroute.c | 36 +++ 3 files changed, 299 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/lwt_reroute.c create mode 100644 tools/testing/selftests/bpf/progs/test_lwt_reroute.c
tools/testing/selftests/bpf/config +1 -0
@@ -60,6 +60,7 @@ CONFIG_NET_IPGRE=y CONFIG_NET_IPGRE_DEMUX=y CONFIG_NET_IPIP=y CONFIG_NET_MPLS_GSO=y +CONFIG_NET_SCH_FQ=y CONFIG_NET_SCH_INGRESS=y CONFIG_NET_SCHED=y CONFIG_NETDEVSIM=y
tools/testing/selftests/bpf/prog_tests/lwt_reroute.c new file +262 -0
262 lines not on this page · raw message
tools/testing/selftests/bpf/progs/test_lwt_reroute.c new file +36 -0
@@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <inttypes.h> +#include <linux/bpf.h> +#include <bpf/bpf_endian.h> +#include <bpf/bpf_helpers.h> +#include <linux/if_ether.h> +#include <linux/ip.h> + +/* This function extracts the last byte of the daddr, and uses it +* as output dev index. +*/ +SEC("lwt_xmit") +int test_lwt_reroute (struct __sk_buff *skb) +{ +struct iphdr *iph =NULL ; +void *start = (void *)(long )skb->data; +void *end = (void *)(long )skb->data_end; + +/* set mark at most once */ +if (skb->mark !=0 ) +return BPF_OK ; + +if (start +sizeof (*iph) > end) +return BPF_DROP ; + + iph = (struct iphdr *)start; + skb->mark =bpf_ntohl (iph->daddr) &0xff ; + +/* do not reroute x.x.x.0 packets */ +if (skb->mark ==0 ) +return BPF_OK ; + +return BPF_LWT_REROUTE ; +} + +char _license[] SEC("license") = "GPL";
Signature · 1 line
2.30.2
Daniel Borkmann
maintainerQuoted 11 lines · Yan Zhai
lwt xmit hook does not expect positive return values in function
ip_finish_output2andip6_finish_output. However, BPF programs can directly return positive statuses such likeNET_XMIT_DROP,NET_RX_DROP, and etc to the caller. Such return values would make the kernel continue processing already freed skbs and eventually panic.This set fixes the return values from BPF ops to unexpected continue processing, checks strictly on the correct continue condition for future proof. In addition, add missing selftests for BPF redirect and reroute cases for BPF-CI.
Quoted 8 lines
v5: https://lore.kernel.org/bpf/[email protected]/
v4: https://lore.kernel.org/bpf/[email protected]/T/
v3: https://lore.kernel.org/bpf/[email protected]/
v2: https://lore.kernel.org/netdev/[email protected]/
v1: https://lore.kernel.org/bpf/[email protected]/changes since v5:
* fix BPF-CI failures due to missing config and busybox ping issue
Series looks good, thanks! Given we're fairly close to merge window and this has been broken for quite some time, I took this into bpf-next.
Thanks,
Daniel
Quoted 19 lines · Daniel Borkmann
Quoted 17 lines · Yan Zhai
lwt xmit hook does not expect positive return values in function
ip_finish_output2andip6_finish_output. However, BPF programs can directly return positive statuses such likeNET_XMIT_DROP,NET_RX_DROP, and etc to the caller. Such return values would make the kernel continue processing already freed skbs and eventually panic.This set fixes the return values from BPF ops to unexpected continue processing, checks strictly on the correct continue condition for future proof. In addition, add missing selftests for BPF redirect and reroute cases for BPF-CI.
v5: https://lore.kernel.org/bpf/[email protected]/
v4: https://lore.kernel.org/bpf/[email protected]/T/
v3: https://lore.kernel.org/bpf/[email protected]/
v2: https://lore.kernel.org/netdev/[email protected]/
v1: https://lore.kernel.org/bpf/[email protected]/
Quoted 6 lines
Quoted 2 lines
changes since v5:
* fix BPF-CI failures due to missing config and busybox ping issueSeries looks good, thanks! Given we're fairly close to merge window and this has been broken for quite some time, I took this into bpf-next.
Thanks Daniel! Can you also queue this up for stable (or guide how I can do it)?
Yan
Quoted 2 lines
Thanks,
Daniel
Daniel Borkmann
maintainerQuoted 20 lines · Yan Zhai
Quoted 19 lines · Daniel Borkmann
Quoted 17 lines · Yan Zhai
lwt xmit hook does not expect positive return values in function
ip_finish_output2andip6_finish_output. However, BPF programs can directly return positive statuses such likeNET_XMIT_DROP,NET_RX_DROP, and etc to the caller. Such return values would make the kernel continue processing already freed skbs and eventually panic.This set fixes the return values from BPF ops to unexpected continue processing, checks strictly on the correct continue condition for future proof. In addition, add missing selftests for BPF redirect and reroute cases for BPF-CI.
v5: https://lore.kernel.org/bpf/[email protected]/
v4: https://lore.kernel.org/bpf/[email protected]/T/
v3: https://lore.kernel.org/bpf/[email protected]/
v2: https://lore.kernel.org/netdev/[email protected]/
v1: https://lore.kernel.org/bpf/[email protected]/
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines
changes since v5:
* fix BPF-CI failures due to missing config and busybox ping issueSeries looks good, thanks! Given we're fairly close to merge window and this has been broken for quite some time, I took this into bpf-next.
Thanks Daniel! Can you also queue this up for stable (or guide how I can do it)?
Given the Fixes tags, it will be picked up automatically once it lands in Linus' tree.
Thanks,
Daniel
Quoted 25 lines · Daniel Borkmann
Quoted 23 lines · Yan Zhai
Quoted 22 lines · Daniel Borkmann
Quoted 19 lines · Yan Zhai
lwt xmit hook does not expect positive return values in function
ip_finish_output2andip6_finish_output. However, BPF programs can directly return positive statuses such likeNET_XMIT_DROP,NET_RX_DROP, and etc to the caller. Such return values would make the kernel continue processing already freed skbs and eventually panic.This set fixes the return values from BPF ops to unexpected continue processing, checks strictly on the correct continue condition for future proof. In addition, add missing selftests for BPF redirect and reroute cases for BPF-CI.
v5: https://lore.kernel.org/bpf/[email protected]/
v4: https://lore.kernel.org/bpf/[email protected]/T/
v3: https://lore.kernel.org/bpf/[email protected]/
v2: https://lore.kernel.org/netdev/[email protected]/
v1: https://lore.kernel.org/bpf/[email protected]/changes since v5:
* fix BPF-CI failures due to missing config and busybox ping issue
Quoted 8 lines
Quoted 4 lines
Quoted 3 lines
Series looks good, thanks! Given we're fairly close to merge window and this has been broken for quite some time, I took this into bpf-next.
Thanks Daniel! Can you also queue this up for stable (or guide how I can do it)?
Given the Fixes tags, it will be picked up automatically once it lands in Linus' tree.
Wonderful. Thank you!
Quoted 2 lines
Thanks,
Daniel