1e8a339b5SAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0 2e8a339b5SAndrii Nakryiko /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ 3e8a339b5SAndrii Nakryiko 40a0ffcacSAndrii Nakryiko #include <vmlinux.h> 5e8a339b5SAndrii Nakryiko #include <bpf/bpf_helpers.h> 6989410cdSAndrii Nakryiko #include <bpf/bpf_tracing.h> 7e8a339b5SAndrii Nakryiko #include "bpf_misc.h" 80a0ffcacSAndrii Nakryiko #include "xdp_metadata.h" 90a0ffcacSAndrii Nakryiko #include "bpf_kfuncs.h" 10e8a339b5SAndrii Nakryiko 11*cd3fc3b9SJose E. Marchesi /* The compiler may be able to detect the access to uninitialized 12*cd3fc3b9SJose E. Marchesi memory in the routines performing out of bound memory accesses and 13*cd3fc3b9SJose E. Marchesi emit warnings about it. This is the case of GCC. */ 14*cd3fc3b9SJose E. Marchesi #if !defined(__clang__) 15*cd3fc3b9SJose E. Marchesi #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 16*cd3fc3b9SJose E. Marchesi #endif 17*cd3fc3b9SJose E. Marchesi 18e8a339b5SAndrii Nakryiko int arr[1]; 19e8a339b5SAndrii Nakryiko int unkn_idx; 20e72c1ccfSAndrii Nakryiko const volatile bool call_dead_subprog = false; 21e8a339b5SAndrii Nakryiko 22e8a339b5SAndrii Nakryiko __noinline long global_bad(void) 23e8a339b5SAndrii Nakryiko { 24e8a339b5SAndrii Nakryiko return arr[unkn_idx]; /* BOOM */ 25e8a339b5SAndrii Nakryiko } 26e8a339b5SAndrii Nakryiko 27e8a339b5SAndrii Nakryiko __noinline long global_good(void) 28e8a339b5SAndrii Nakryiko { 29e8a339b5SAndrii Nakryiko return arr[0]; 30e8a339b5SAndrii Nakryiko } 31e8a339b5SAndrii Nakryiko 32e8a339b5SAndrii Nakryiko __noinline long global_calls_bad(void) 33e8a339b5SAndrii Nakryiko { 34e8a339b5SAndrii Nakryiko return global_good() + global_bad() /* does BOOM indirectly */; 35e8a339b5SAndrii Nakryiko } 36e8a339b5SAndrii Nakryiko 37e8a339b5SAndrii Nakryiko __noinline long global_calls_good_only(void) 38e8a339b5SAndrii Nakryiko { 39e8a339b5SAndrii Nakryiko return global_good(); 40e8a339b5SAndrii Nakryiko } 41e8a339b5SAndrii Nakryiko 42e72c1ccfSAndrii Nakryiko __noinline long global_dead(void) 43e72c1ccfSAndrii Nakryiko { 44e72c1ccfSAndrii Nakryiko return arr[0] * 2; 45e72c1ccfSAndrii Nakryiko } 46e72c1ccfSAndrii Nakryiko 47e8a339b5SAndrii Nakryiko SEC("?raw_tp") 48e8a339b5SAndrii Nakryiko __success __log_level(2) 49e8a339b5SAndrii Nakryiko /* main prog is validated completely first */ 50e8a339b5SAndrii Nakryiko __msg("('global_calls_good_only') is global and assumed valid.") 51e8a339b5SAndrii Nakryiko /* eventually global_good() is transitively validated as well */ 52e8a339b5SAndrii Nakryiko __msg("Validating global_good() func") 53e8a339b5SAndrii Nakryiko __msg("('global_good') is safe for any args that match its prototype") 54e8a339b5SAndrii Nakryiko int chained_global_func_calls_success(void) 55e8a339b5SAndrii Nakryiko { 56e72c1ccfSAndrii Nakryiko int sum = 0; 57e72c1ccfSAndrii Nakryiko 58e72c1ccfSAndrii Nakryiko if (call_dead_subprog) 59e72c1ccfSAndrii Nakryiko sum += global_dead(); 60e72c1ccfSAndrii Nakryiko return global_calls_good_only() + sum; 61e8a339b5SAndrii Nakryiko } 62e8a339b5SAndrii Nakryiko 63e8a339b5SAndrii Nakryiko SEC("?raw_tp") 64e8a339b5SAndrii Nakryiko __failure __log_level(2) 65e8a339b5SAndrii Nakryiko /* main prog validated successfully first */ 66e72c1ccfSAndrii Nakryiko __msg("('global_calls_bad') is global and assumed valid.") 67e8a339b5SAndrii Nakryiko /* eventually we validate global_bad() and fail */ 68e8a339b5SAndrii Nakryiko __msg("Validating global_bad() func") 69e8a339b5SAndrii Nakryiko __msg("math between map_value pointer and register") /* BOOM */ 70e8a339b5SAndrii Nakryiko int chained_global_func_calls_bad(void) 71e8a339b5SAndrii Nakryiko { 72e8a339b5SAndrii Nakryiko return global_calls_bad(); 73e8a339b5SAndrii Nakryiko } 74e8a339b5SAndrii Nakryiko 75e8a339b5SAndrii Nakryiko /* do out of bounds access forcing verifier to fail verification if this 76e8a339b5SAndrii Nakryiko * global func is called 77e8a339b5SAndrii Nakryiko */ 78e8a339b5SAndrii Nakryiko __noinline int global_unsupp(const int *mem) 79e8a339b5SAndrii Nakryiko { 80e8a339b5SAndrii Nakryiko if (!mem) 81e8a339b5SAndrii Nakryiko return 0; 82e8a339b5SAndrii Nakryiko return mem[100]; /* BOOM */ 83e8a339b5SAndrii Nakryiko } 84e8a339b5SAndrii Nakryiko 85e8a339b5SAndrii Nakryiko const volatile bool skip_unsupp_global = true; 86e8a339b5SAndrii Nakryiko 87e8a339b5SAndrii Nakryiko SEC("?raw_tp") 88e8a339b5SAndrii Nakryiko __success 89e8a339b5SAndrii Nakryiko int guarded_unsupp_global_called(void) 90e8a339b5SAndrii Nakryiko { 91e8a339b5SAndrii Nakryiko if (!skip_unsupp_global) 92e8a339b5SAndrii Nakryiko return global_unsupp(NULL); 93e8a339b5SAndrii Nakryiko return 0; 94e8a339b5SAndrii Nakryiko } 95e8a339b5SAndrii Nakryiko 96e8a339b5SAndrii Nakryiko SEC("?raw_tp") 97e8a339b5SAndrii Nakryiko __failure __log_level(2) 98e8a339b5SAndrii Nakryiko __msg("Func#1 ('global_unsupp') is global and assumed valid.") 99e8a339b5SAndrii Nakryiko __msg("Validating global_unsupp() func#1...") 100e8a339b5SAndrii Nakryiko __msg("value is outside of the allowed memory range") 101e8a339b5SAndrii Nakryiko int unguarded_unsupp_global_called(void) 102e8a339b5SAndrii Nakryiko { 103e8a339b5SAndrii Nakryiko int x = 0; 104e8a339b5SAndrii Nakryiko 105e8a339b5SAndrii Nakryiko return global_unsupp(&x); 106e8a339b5SAndrii Nakryiko } 107e8a339b5SAndrii Nakryiko 1080a0ffcacSAndrii Nakryiko long stack[128]; 1090a0ffcacSAndrii Nakryiko 1100a0ffcacSAndrii Nakryiko __weak int subprog_nullable_ptr_bad(int *p) 1110a0ffcacSAndrii Nakryiko { 1120a0ffcacSAndrii Nakryiko return (*p) * 2; /* bad, missing null check */ 1130a0ffcacSAndrii Nakryiko } 1140a0ffcacSAndrii Nakryiko 1150a0ffcacSAndrii Nakryiko SEC("?raw_tp") 1160a0ffcacSAndrii Nakryiko __failure __log_level(2) 1170a0ffcacSAndrii Nakryiko __msg("invalid mem access 'mem_or_null'") 1180a0ffcacSAndrii Nakryiko int arg_tag_nullable_ptr_fail(void *ctx) 1190a0ffcacSAndrii Nakryiko { 1200a0ffcacSAndrii Nakryiko int x = 42; 1210a0ffcacSAndrii Nakryiko 1220a0ffcacSAndrii Nakryiko return subprog_nullable_ptr_bad(&x); 1230a0ffcacSAndrii Nakryiko } 1240a0ffcacSAndrii Nakryiko 12563d5a33fSAndrii Nakryiko typedef struct { 12663d5a33fSAndrii Nakryiko int x; 12763d5a33fSAndrii Nakryiko } user_struct_t; 12863d5a33fSAndrii Nakryiko 12963d5a33fSAndrii Nakryiko __noinline __weak int subprog_user_anon_mem(user_struct_t *t) 13063d5a33fSAndrii Nakryiko { 13163d5a33fSAndrii Nakryiko return t ? t->x : 0; 13263d5a33fSAndrii Nakryiko } 13363d5a33fSAndrii Nakryiko 13463d5a33fSAndrii Nakryiko SEC("?tracepoint") 13563d5a33fSAndrii Nakryiko __failure __log_level(2) 13663d5a33fSAndrii Nakryiko __msg("invalid bpf_context access") 13763d5a33fSAndrii Nakryiko __msg("Caller passes invalid args into func#1 ('subprog_user_anon_mem')") 13863d5a33fSAndrii Nakryiko int anon_user_mem_invalid(void *ctx) 13963d5a33fSAndrii Nakryiko { 14063d5a33fSAndrii Nakryiko /* can't pass PTR_TO_CTX as user memory */ 14163d5a33fSAndrii Nakryiko return subprog_user_anon_mem(ctx); 14263d5a33fSAndrii Nakryiko } 14363d5a33fSAndrii Nakryiko 14463d5a33fSAndrii Nakryiko SEC("?tracepoint") 14563d5a33fSAndrii Nakryiko __success __log_level(2) 14663d5a33fSAndrii Nakryiko __msg("Func#1 ('subprog_user_anon_mem') is safe for any args that match its prototype") 14763d5a33fSAndrii Nakryiko int anon_user_mem_valid(void *ctx) 14863d5a33fSAndrii Nakryiko { 14963d5a33fSAndrii Nakryiko user_struct_t t = { .x = 42 }; 15063d5a33fSAndrii Nakryiko 15163d5a33fSAndrii Nakryiko return subprog_user_anon_mem(&t); 15263d5a33fSAndrii Nakryiko } 15363d5a33fSAndrii Nakryiko 1540a0ffcacSAndrii Nakryiko __noinline __weak int subprog_nonnull_ptr_good(int *p1 __arg_nonnull, int *p2 __arg_nonnull) 1550a0ffcacSAndrii Nakryiko { 1560a0ffcacSAndrii Nakryiko return (*p1) * (*p2); /* good, no need for NULL checks */ 1570a0ffcacSAndrii Nakryiko } 1580a0ffcacSAndrii Nakryiko 1590a0ffcacSAndrii Nakryiko int x = 47; 1600a0ffcacSAndrii Nakryiko 1610a0ffcacSAndrii Nakryiko SEC("?raw_tp") 1620a0ffcacSAndrii Nakryiko __success __log_level(2) 1630a0ffcacSAndrii Nakryiko int arg_tag_nonnull_ptr_good(void *ctx) 1640a0ffcacSAndrii Nakryiko { 1650a0ffcacSAndrii Nakryiko int y = 74; 1660a0ffcacSAndrii Nakryiko 1670a0ffcacSAndrii Nakryiko return subprog_nonnull_ptr_good(&x, &y); 1680a0ffcacSAndrii Nakryiko } 1690a0ffcacSAndrii Nakryiko 1700a0ffcacSAndrii Nakryiko /* this global subprog can be now called from many types of entry progs, each 1710a0ffcacSAndrii Nakryiko * with different context type 1720a0ffcacSAndrii Nakryiko */ 1730a0ffcacSAndrii Nakryiko __weak int subprog_ctx_tag(void *ctx __arg_ctx) 1740a0ffcacSAndrii Nakryiko { 1750a0ffcacSAndrii Nakryiko return bpf_get_stack(ctx, stack, sizeof(stack), 0); 1760a0ffcacSAndrii Nakryiko } 1770a0ffcacSAndrii Nakryiko 178989410cdSAndrii Nakryiko __weak int raw_tp_canonical(struct bpf_raw_tracepoint_args *ctx __arg_ctx) 179989410cdSAndrii Nakryiko { 180989410cdSAndrii Nakryiko return 0; 181989410cdSAndrii Nakryiko } 182989410cdSAndrii Nakryiko 183989410cdSAndrii Nakryiko __weak int raw_tp_u64_array(u64 *ctx __arg_ctx) 184989410cdSAndrii Nakryiko { 185989410cdSAndrii Nakryiko return 0; 186989410cdSAndrii Nakryiko } 187989410cdSAndrii Nakryiko 1880a0ffcacSAndrii Nakryiko SEC("?raw_tp") 1890a0ffcacSAndrii Nakryiko __success __log_level(2) 1900a0ffcacSAndrii Nakryiko int arg_tag_ctx_raw_tp(void *ctx) 1910a0ffcacSAndrii Nakryiko { 192989410cdSAndrii Nakryiko return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx); 193989410cdSAndrii Nakryiko } 194989410cdSAndrii Nakryiko 195989410cdSAndrii Nakryiko SEC("?raw_tp.w") 196989410cdSAndrii Nakryiko __success __log_level(2) 197989410cdSAndrii Nakryiko int arg_tag_ctx_raw_tp_writable(void *ctx) 198989410cdSAndrii Nakryiko { 199989410cdSAndrii Nakryiko return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx); 200989410cdSAndrii Nakryiko } 201989410cdSAndrii Nakryiko 202989410cdSAndrii Nakryiko SEC("?tp_btf/sys_enter") 203989410cdSAndrii Nakryiko __success __log_level(2) 204989410cdSAndrii Nakryiko int arg_tag_ctx_raw_tp_btf(void *ctx) 205989410cdSAndrii Nakryiko { 206989410cdSAndrii Nakryiko return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx); 207989410cdSAndrii Nakryiko } 208989410cdSAndrii Nakryiko 209989410cdSAndrii Nakryiko struct whatever { }; 210989410cdSAndrii Nakryiko 211989410cdSAndrii Nakryiko __weak int tp_whatever(struct whatever *ctx __arg_ctx) 212989410cdSAndrii Nakryiko { 213989410cdSAndrii Nakryiko return 0; 2140a0ffcacSAndrii Nakryiko } 2150a0ffcacSAndrii Nakryiko 2160a0ffcacSAndrii Nakryiko SEC("?tp") 2170a0ffcacSAndrii Nakryiko __success __log_level(2) 2180a0ffcacSAndrii Nakryiko int arg_tag_ctx_tp(void *ctx) 2190a0ffcacSAndrii Nakryiko { 220989410cdSAndrii Nakryiko return subprog_ctx_tag(ctx) + tp_whatever(ctx); 221989410cdSAndrii Nakryiko } 222989410cdSAndrii Nakryiko 223989410cdSAndrii Nakryiko __weak int kprobe_subprog_pt_regs(struct pt_regs *ctx __arg_ctx) 224989410cdSAndrii Nakryiko { 225989410cdSAndrii Nakryiko return 0; 226989410cdSAndrii Nakryiko } 227989410cdSAndrii Nakryiko 228989410cdSAndrii Nakryiko __weak int kprobe_subprog_typedef(bpf_user_pt_regs_t *ctx __arg_ctx) 229989410cdSAndrii Nakryiko { 230989410cdSAndrii Nakryiko return 0; 2310a0ffcacSAndrii Nakryiko } 2320a0ffcacSAndrii Nakryiko 2330a0ffcacSAndrii Nakryiko SEC("?kprobe") 2340a0ffcacSAndrii Nakryiko __success __log_level(2) 2350a0ffcacSAndrii Nakryiko int arg_tag_ctx_kprobe(void *ctx) 2360a0ffcacSAndrii Nakryiko { 237989410cdSAndrii Nakryiko return subprog_ctx_tag(ctx) + 238989410cdSAndrii Nakryiko kprobe_subprog_pt_regs(ctx) + 239989410cdSAndrii Nakryiko kprobe_subprog_typedef(ctx); 240989410cdSAndrii Nakryiko } 241989410cdSAndrii Nakryiko 242989410cdSAndrii Nakryiko __weak int perf_subprog_regs( 243989410cdSAndrii Nakryiko #if defined(bpf_target_riscv) 244989410cdSAndrii Nakryiko struct user_regs_struct *ctx __arg_ctx 245989410cdSAndrii Nakryiko #elif defined(bpf_target_s390) 246989410cdSAndrii Nakryiko /* user_pt_regs typedef is anonymous struct, so only `void *` works */ 247989410cdSAndrii Nakryiko void *ctx __arg_ctx 248989410cdSAndrii Nakryiko #elif defined(bpf_target_loongarch) || defined(bpf_target_arm64) || defined(bpf_target_powerpc) 249989410cdSAndrii Nakryiko struct user_pt_regs *ctx __arg_ctx 250989410cdSAndrii Nakryiko #else 251989410cdSAndrii Nakryiko struct pt_regs *ctx __arg_ctx 252989410cdSAndrii Nakryiko #endif 253989410cdSAndrii Nakryiko ) 254989410cdSAndrii Nakryiko { 255989410cdSAndrii Nakryiko return 0; 256989410cdSAndrii Nakryiko } 257989410cdSAndrii Nakryiko 258989410cdSAndrii Nakryiko __weak int perf_subprog_typedef(bpf_user_pt_regs_t *ctx __arg_ctx) 259989410cdSAndrii Nakryiko { 260989410cdSAndrii Nakryiko return 0; 261989410cdSAndrii Nakryiko } 262989410cdSAndrii Nakryiko 263989410cdSAndrii Nakryiko __weak int perf_subprog_canonical(struct bpf_perf_event_data *ctx __arg_ctx) 264989410cdSAndrii Nakryiko { 265989410cdSAndrii Nakryiko return 0; 266989410cdSAndrii Nakryiko } 267989410cdSAndrii Nakryiko 268989410cdSAndrii Nakryiko SEC("?perf_event") 269989410cdSAndrii Nakryiko __success __log_level(2) 270989410cdSAndrii Nakryiko int arg_tag_ctx_perf(void *ctx) 271989410cdSAndrii Nakryiko { 272989410cdSAndrii Nakryiko return subprog_ctx_tag(ctx) + 273989410cdSAndrii Nakryiko perf_subprog_regs(ctx) + 274989410cdSAndrii Nakryiko perf_subprog_typedef(ctx) + 275989410cdSAndrii Nakryiko perf_subprog_canonical(ctx); 276989410cdSAndrii Nakryiko } 277989410cdSAndrii Nakryiko 278989410cdSAndrii Nakryiko __weak int iter_subprog_void(void *ctx __arg_ctx) 279989410cdSAndrii Nakryiko { 280989410cdSAndrii Nakryiko return 0; 281989410cdSAndrii Nakryiko } 282989410cdSAndrii Nakryiko 283989410cdSAndrii Nakryiko __weak int iter_subprog_typed(struct bpf_iter__task *ctx __arg_ctx) 284989410cdSAndrii Nakryiko { 285989410cdSAndrii Nakryiko return 0; 286989410cdSAndrii Nakryiko } 287989410cdSAndrii Nakryiko 288989410cdSAndrii Nakryiko SEC("?iter/task") 289989410cdSAndrii Nakryiko __success __log_level(2) 290989410cdSAndrii Nakryiko int arg_tag_ctx_iter_task(struct bpf_iter__task *ctx) 291989410cdSAndrii Nakryiko { 292989410cdSAndrii Nakryiko return (iter_subprog_void(ctx) + iter_subprog_typed(ctx)) & 1; 293989410cdSAndrii Nakryiko } 294989410cdSAndrii Nakryiko 295989410cdSAndrii Nakryiko __weak int tracing_subprog_void(void *ctx __arg_ctx) 296989410cdSAndrii Nakryiko { 297989410cdSAndrii Nakryiko return 0; 298989410cdSAndrii Nakryiko } 299989410cdSAndrii Nakryiko 300989410cdSAndrii Nakryiko __weak int tracing_subprog_u64(u64 *ctx __arg_ctx) 301989410cdSAndrii Nakryiko { 302989410cdSAndrii Nakryiko return 0; 303989410cdSAndrii Nakryiko } 304989410cdSAndrii Nakryiko 305989410cdSAndrii Nakryiko int acc; 306989410cdSAndrii Nakryiko 307989410cdSAndrii Nakryiko SEC("?fentry/" SYS_PREFIX "sys_nanosleep") 308989410cdSAndrii Nakryiko __success __log_level(2) 309989410cdSAndrii Nakryiko int BPF_PROG(arg_tag_ctx_fentry) 310989410cdSAndrii Nakryiko { 311989410cdSAndrii Nakryiko acc += tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); 312989410cdSAndrii Nakryiko return 0; 313989410cdSAndrii Nakryiko } 314989410cdSAndrii Nakryiko 315989410cdSAndrii Nakryiko SEC("?fexit/" SYS_PREFIX "sys_nanosleep") 316989410cdSAndrii Nakryiko __success __log_level(2) 317989410cdSAndrii Nakryiko int BPF_PROG(arg_tag_ctx_fexit) 318989410cdSAndrii Nakryiko { 319989410cdSAndrii Nakryiko acc += tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); 320989410cdSAndrii Nakryiko return 0; 321989410cdSAndrii Nakryiko } 322989410cdSAndrii Nakryiko 323989410cdSAndrii Nakryiko SEC("?fmod_ret/" SYS_PREFIX "sys_nanosleep") 324989410cdSAndrii Nakryiko __success __log_level(2) 325989410cdSAndrii Nakryiko int BPF_PROG(arg_tag_ctx_fmod_ret) 326989410cdSAndrii Nakryiko { 327989410cdSAndrii Nakryiko return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); 328989410cdSAndrii Nakryiko } 329989410cdSAndrii Nakryiko 330989410cdSAndrii Nakryiko SEC("?lsm/bpf") 331989410cdSAndrii Nakryiko __success __log_level(2) 332989410cdSAndrii Nakryiko int BPF_PROG(arg_tag_ctx_lsm) 333989410cdSAndrii Nakryiko { 334989410cdSAndrii Nakryiko return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); 335989410cdSAndrii Nakryiko } 336989410cdSAndrii Nakryiko 337989410cdSAndrii Nakryiko SEC("?struct_ops/test_1") 338989410cdSAndrii Nakryiko __success __log_level(2) 339989410cdSAndrii Nakryiko int BPF_PROG(arg_tag_ctx_struct_ops) 340989410cdSAndrii Nakryiko { 341989410cdSAndrii Nakryiko return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); 342989410cdSAndrii Nakryiko } 343989410cdSAndrii Nakryiko 344989410cdSAndrii Nakryiko SEC(".struct_ops") 345989410cdSAndrii Nakryiko struct bpf_dummy_ops dummy_1 = { 346989410cdSAndrii Nakryiko .test_1 = (void *)arg_tag_ctx_struct_ops, 347989410cdSAndrii Nakryiko }; 348989410cdSAndrii Nakryiko 349989410cdSAndrii Nakryiko SEC("?syscall") 350989410cdSAndrii Nakryiko __success __log_level(2) 351989410cdSAndrii Nakryiko int arg_tag_ctx_syscall(void *ctx) 352989410cdSAndrii Nakryiko { 353989410cdSAndrii Nakryiko return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx) + tp_whatever(ctx); 3540a0ffcacSAndrii Nakryiko } 3550a0ffcacSAndrii Nakryiko 3560a0ffcacSAndrii Nakryiko __weak int subprog_dynptr(struct bpf_dynptr *dptr) 3570a0ffcacSAndrii Nakryiko { 3580a0ffcacSAndrii Nakryiko long *d, t, buf[1] = {}; 3590a0ffcacSAndrii Nakryiko 3600a0ffcacSAndrii Nakryiko d = bpf_dynptr_data(dptr, 0, sizeof(long)); 3610a0ffcacSAndrii Nakryiko if (!d) 3620a0ffcacSAndrii Nakryiko return 0; 3630a0ffcacSAndrii Nakryiko 3640a0ffcacSAndrii Nakryiko t = *d + 1; 3650a0ffcacSAndrii Nakryiko 3660a0ffcacSAndrii Nakryiko d = bpf_dynptr_slice(dptr, 0, &buf, sizeof(long)); 3670a0ffcacSAndrii Nakryiko if (!d) 3680a0ffcacSAndrii Nakryiko return t; 3690a0ffcacSAndrii Nakryiko 3700a0ffcacSAndrii Nakryiko t = *d + 2; 3710a0ffcacSAndrii Nakryiko 3720a0ffcacSAndrii Nakryiko return t; 3730a0ffcacSAndrii Nakryiko } 3740a0ffcacSAndrii Nakryiko 3750a0ffcacSAndrii Nakryiko SEC("?xdp") 3760a0ffcacSAndrii Nakryiko __success __log_level(2) 3770a0ffcacSAndrii Nakryiko int arg_tag_dynptr(struct xdp_md *ctx) 3780a0ffcacSAndrii Nakryiko { 3790a0ffcacSAndrii Nakryiko struct bpf_dynptr dptr; 3800a0ffcacSAndrii Nakryiko 3810a0ffcacSAndrii Nakryiko bpf_dynptr_from_xdp(ctx, 0, &dptr); 3820a0ffcacSAndrii Nakryiko 3830a0ffcacSAndrii Nakryiko return subprog_dynptr(&dptr); 3840a0ffcacSAndrii Nakryiko } 3850a0ffcacSAndrii Nakryiko 386e8a339b5SAndrii Nakryiko char _license[] SEC("license") = "GPL"; 387