diff mbox series

[bpf-next] bpf: Make sure internal and UAPI bpf_redirect flags don't overlap

Message ID 20240920125625.59465-1-toke@redhat.com (mailing list archive)
State Accepted
Commit 09d88791c7cd888d5195c84733caf9183dcfbd16
Delegated to: BPF
Headers show
Series [bpf-next] bpf: Make sure internal and UAPI bpf_redirect flags don't overlap | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 226 this patch: 226
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 19 of 19 maintainers
netdev/build_clang success Errors and warnings before: 291 this patch: 291
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 Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 6867 this patch: 6867
netdev/checkpatch warning CHECK: Please use a blank line after function/struct/union/enum declarations WARNING: line length of 90 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 6 this patch: 6
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-8 success Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-15 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18

Commit Message

Toke Høiland-Jørgensen Sept. 20, 2024, 12:56 p.m. UTC
The bpf_redirect_info is shared between the SKB and XDP redirect paths,
and the two paths use the same numeric flag values in the ri->flags
field (specifically, BPF_F_BROADCAST == BPF_F_NEXTHOP). This means that
if skb bpf_redirect_neigh() is used with a non-NULL params argument and,
subsequently, an XDP redirect is performed using the same
bpf_redirect_info struct, the XDP path will get confused and end up
crashing, which syzbot managed to trigger.

With the stack-allocated bpf_redirect_info, the structure is no longer
shared between the SKB and XDP paths, so the crash doesn't happen
anymore. However, different code paths using identically-numbered flag
values in the same struct field still seems like a bit of a mess, so
this patch cleans that up by moving the flag definitions together and
redefining the three flags in BPF_F_REDIRECT_INTERNAL to not overlap
with the flags used for XDP. It also adds a BUILD_BUG_ON() check to make
sure the overlap is not re-introduced by mistake.

Fixes: e624d4ed4aa8 ("xdp: Extend xdp_redirect_map with broadcast support")
Reported-by: syzbot+cca39e6e84a367a7e6f6@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=cca39e6e84a367a7e6f6
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
 include/uapi/linux/bpf.h | 14 ++++++--------
 net/core/filter.c        |  8 +++++---
 2 files changed, 11 insertions(+), 11 deletions(-)

Comments

Daniel Borkmann Oct. 1, 2024, 7:49 p.m. UTC | #1
On 9/20/24 2:56 PM, Toke Høiland-Jørgensen wrote:
> The bpf_redirect_info is shared between the SKB and XDP redirect paths,
> and the two paths use the same numeric flag values in the ri->flags
> field (specifically, BPF_F_BROADCAST == BPF_F_NEXTHOP). This means that
> if skb bpf_redirect_neigh() is used with a non-NULL params argument and,
> subsequently, an XDP redirect is performed using the same
> bpf_redirect_info struct, the XDP path will get confused and end up
> crashing, which syzbot managed to trigger.
>
> With the stack-allocated bpf_redirect_info, the structure is no longer
> shared between the SKB and XDP paths, so the crash doesn't happen
> anymore. However, different code paths using identically-numbered flag
> values in the same struct field still seems like a bit of a mess, so
> this patch cleans that up by moving the flag definitions together and
> redefining the three flags in BPF_F_REDIRECT_INTERNAL to not overlap
> with the flags used for XDP. It also adds a BUILD_BUG_ON() check to make
> sure the overlap is not re-introduced by mistake.
>
> Fixes: e624d4ed4aa8 ("xdp: Extend xdp_redirect_map with broadcast support")
> Reported-by: syzbot+cca39e6e84a367a7e6f6@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=cca39e6e84a367a7e6f6
> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
> ---
>   include/uapi/linux/bpf.h | 14 ++++++--------
>   net/core/filter.c        |  8 +++++---
>   2 files changed, 11 insertions(+), 11 deletions(-)
Lgtm, applied, thanks! I also added a tools header sync.I took this into 
bpf tree, so that stable can pick it up.
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index c3a5728db115..0c6154272ab3 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -6047,11 +6047,6 @@ enum {
>   	BPF_F_MARK_ENFORCE		= (1ULL << 6),
>   };
>   
> -/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
> -enum {
> -	BPF_F_INGRESS			= (1ULL << 0),
> -};
> -
>   /* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
>   enum {
>   	BPF_F_TUNINFO_IPV6		= (1ULL << 0),
> @@ -6198,11 +6193,14 @@ enum {
>   	BPF_F_BPRM_SECUREEXEC	= (1ULL << 0),
>   };
>   
> -/* Flags for bpf_redirect_map helper */
> +/* Flags for bpf_redirect and bpf_redirect_map helpers */
>   enum {
> -	BPF_F_BROADCAST		= (1ULL << 3),
> -	BPF_F_EXCLUDE_INGRESS	= (1ULL << 4),
> +	BPF_F_INGRESS		= (1ULL << 0), /* used for skb path */
> +	BPF_F_BROADCAST		= (1ULL << 3), /* used for XDP path */
> +	BPF_F_EXCLUDE_INGRESS	= (1ULL << 4), /* used for XDP path */
>   };
> +#define BPF_F_REDIRECT_ALL_FLAGS (BPF_F_INGRESS | BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS)
> +
>   
Also fixed up extra newline.

Thanks,
Daniel
patchwork-bot+netdevbpf@kernel.org Oct. 1, 2024, 7:50 p.m. UTC | #2
Hello:

This patch was applied to bpf/bpf.git (master)
by Daniel Borkmann <daniel@iogearbox.net>:

On Fri, 20 Sep 2024 14:56:24 +0200 you wrote:
> The bpf_redirect_info is shared between the SKB and XDP redirect paths,
> and the two paths use the same numeric flag values in the ri->flags
> field (specifically, BPF_F_BROADCAST == BPF_F_NEXTHOP). This means that
> if skb bpf_redirect_neigh() is used with a non-NULL params argument and,
> subsequently, an XDP redirect is performed using the same
> bpf_redirect_info struct, the XDP path will get confused and end up
> crashing, which syzbot managed to trigger.
> 
> [...]

Here is the summary with links:
  - [bpf-next] bpf: Make sure internal and UAPI bpf_redirect flags don't overlap
    https://git.kernel.org/bpf/bpf/c/09d88791c7cd

You are awesome, thank you!
Toke Høiland-Jørgensen Oct. 2, 2024, 8:35 a.m. UTC | #3
Daniel Borkmann <daniel@iogearbox.net> writes:

> On 9/20/24 2:56 PM, Toke Høiland-Jørgensen wrote:
>> The bpf_redirect_info is shared between the SKB and XDP redirect paths,
>> and the two paths use the same numeric flag values in the ri->flags
>> field (specifically, BPF_F_BROADCAST == BPF_F_NEXTHOP). This means that
>> if skb bpf_redirect_neigh() is used with a non-NULL params argument and,
>> subsequently, an XDP redirect is performed using the same
>> bpf_redirect_info struct, the XDP path will get confused and end up
>> crashing, which syzbot managed to trigger.
>>
>> With the stack-allocated bpf_redirect_info, the structure is no longer
>> shared between the SKB and XDP paths, so the crash doesn't happen
>> anymore. However, different code paths using identically-numbered flag
>> values in the same struct field still seems like a bit of a mess, so
>> this patch cleans that up by moving the flag definitions together and
>> redefining the three flags in BPF_F_REDIRECT_INTERNAL to not overlap
>> with the flags used for XDP. It also adds a BUILD_BUG_ON() check to make
>> sure the overlap is not re-introduced by mistake.
>>
>> Fixes: e624d4ed4aa8 ("xdp: Extend xdp_redirect_map with broadcast support")
>> Reported-by: syzbot+cca39e6e84a367a7e6f6@syzkaller.appspotmail.com
>> Closes: https://syzkaller.appspot.com/bug?extid=cca39e6e84a367a7e6f6
>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>> ---
>>   include/uapi/linux/bpf.h | 14 ++++++--------
>>   net/core/filter.c        |  8 +++++---
>>   2 files changed, 11 insertions(+), 11 deletions(-)
> Lgtm, applied, thanks! I also added a tools header sync.I took this into 
> bpf tree, so that stable can pick it up.

Great! Thanks for the fixups :)

-Toke
diff mbox series

Patch

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c3a5728db115..0c6154272ab3 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -6047,11 +6047,6 @@  enum {
 	BPF_F_MARK_ENFORCE		= (1ULL << 6),
 };
 
-/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
-enum {
-	BPF_F_INGRESS			= (1ULL << 0),
-};
-
 /* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
 enum {
 	BPF_F_TUNINFO_IPV6		= (1ULL << 0),
@@ -6198,11 +6193,14 @@  enum {
 	BPF_F_BPRM_SECUREEXEC	= (1ULL << 0),
 };
 
-/* Flags for bpf_redirect_map helper */
+/* Flags for bpf_redirect and bpf_redirect_map helpers */
 enum {
-	BPF_F_BROADCAST		= (1ULL << 3),
-	BPF_F_EXCLUDE_INGRESS	= (1ULL << 4),
+	BPF_F_INGRESS		= (1ULL << 0), /* used for skb path */
+	BPF_F_BROADCAST		= (1ULL << 3), /* used for XDP path */
+	BPF_F_EXCLUDE_INGRESS	= (1ULL << 4), /* used for XDP path */
 };
+#define BPF_F_REDIRECT_ALL_FLAGS (BPF_F_INGRESS | BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS)
+
 
 #define __bpf_md_ptr(type, name)	\
 union {					\
diff --git a/net/core/filter.c b/net/core/filter.c
index e4a4454df5f9..db99f2b38e06 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2437,9 +2437,9 @@  static int __bpf_redirect_neigh(struct sk_buff *skb, struct net_device *dev,
 
 /* Internal, non-exposed redirect flags. */
 enum {
-	BPF_F_NEIGH	= (1ULL << 1),
-	BPF_F_PEER	= (1ULL << 2),
-	BPF_F_NEXTHOP	= (1ULL << 3),
+	BPF_F_NEIGH	= (1ULL << 16),
+	BPF_F_PEER	= (1ULL << 17),
+	BPF_F_NEXTHOP	= (1ULL << 18),
 #define BPF_F_REDIRECT_INTERNAL	(BPF_F_NEIGH | BPF_F_PEER | BPF_F_NEXTHOP)
 };
 
@@ -2449,6 +2449,8 @@  BPF_CALL_3(bpf_clone_redirect, struct sk_buff *, skb, u32, ifindex, u64, flags)
 	struct sk_buff *clone;
 	int ret;
 
+	BUILD_BUG_ON(BPF_F_REDIRECT_INTERNAL & BPF_F_REDIRECT_ALL_FLAGS);
+
 	if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL)))
 		return -EINVAL;