Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: add global subprog annotation tests

Add test cases to validate semantics of global subprog argument
annotations:
- non-null pointers;
- context argument;
- const dynptr passing;
- packet pointers (data, metadata, end).

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20231215011334.2307144-10-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
0a0ffcac aae9c25d

+95 -4
+95 -4
tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ 3 3 4 - #include <stdbool.h> 5 - #include <errno.h> 6 - #include <string.h> 7 - #include <linux/bpf.h> 4 + #include <vmlinux.h> 8 5 #include <bpf/bpf_helpers.h> 9 6 #include "bpf_misc.h" 7 + #include "xdp_metadata.h" 8 + #include "bpf_kfuncs.h" 10 9 11 10 int arr[1]; 12 11 int unkn_idx; ··· 95 96 int x = 0; 96 97 97 98 return global_unsupp(&x); 99 + } 100 + 101 + long stack[128]; 102 + 103 + __weak int subprog_nullable_ptr_bad(int *p) 104 + { 105 + return (*p) * 2; /* bad, missing null check */ 106 + } 107 + 108 + SEC("?raw_tp") 109 + __failure __log_level(2) 110 + __msg("invalid mem access 'mem_or_null'") 111 + int arg_tag_nullable_ptr_fail(void *ctx) 112 + { 113 + int x = 42; 114 + 115 + return subprog_nullable_ptr_bad(&x); 116 + } 117 + 118 + __noinline __weak int subprog_nonnull_ptr_good(int *p1 __arg_nonnull, int *p2 __arg_nonnull) 119 + { 120 + return (*p1) * (*p2); /* good, no need for NULL checks */ 121 + } 122 + 123 + int x = 47; 124 + 125 + SEC("?raw_tp") 126 + __success __log_level(2) 127 + int arg_tag_nonnull_ptr_good(void *ctx) 128 + { 129 + int y = 74; 130 + 131 + return subprog_nonnull_ptr_good(&x, &y); 132 + } 133 + 134 + /* this global subprog can be now called from many types of entry progs, each 135 + * with different context type 136 + */ 137 + __weak int subprog_ctx_tag(void *ctx __arg_ctx) 138 + { 139 + return bpf_get_stack(ctx, stack, sizeof(stack), 0); 140 + } 141 + 142 + SEC("?raw_tp") 143 + __success __log_level(2) 144 + int arg_tag_ctx_raw_tp(void *ctx) 145 + { 146 + return subprog_ctx_tag(ctx); 147 + } 148 + 149 + SEC("?tp") 150 + __success __log_level(2) 151 + int arg_tag_ctx_tp(void *ctx) 152 + { 153 + return subprog_ctx_tag(ctx); 154 + } 155 + 156 + SEC("?kprobe") 157 + __success __log_level(2) 158 + int arg_tag_ctx_kprobe(void *ctx) 159 + { 160 + return subprog_ctx_tag(ctx); 161 + } 162 + 163 + __weak int subprog_dynptr(struct bpf_dynptr *dptr) 164 + { 165 + long *d, t, buf[1] = {}; 166 + 167 + d = bpf_dynptr_data(dptr, 0, sizeof(long)); 168 + if (!d) 169 + return 0; 170 + 171 + t = *d + 1; 172 + 173 + d = bpf_dynptr_slice(dptr, 0, &buf, sizeof(long)); 174 + if (!d) 175 + return t; 176 + 177 + t = *d + 2; 178 + 179 + return t; 180 + } 181 + 182 + SEC("?xdp") 183 + __success __log_level(2) 184 + int arg_tag_dynptr(struct xdp_md *ctx) 185 + { 186 + struct bpf_dynptr dptr; 187 + 188 + bpf_dynptr_from_xdp(ctx, 0, &dptr); 189 + 190 + return subprog_dynptr(&dptr); 98 191 } 99 192 100 193 char _license[] SEC("license") = "GPL";