86 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */3 4#include <vmlinux.h>5#include <bpf/bpf_helpers.h>6#include <bpf/bpf_tracing.h>7#include <bpf/bpf_core_read.h>8#include "../bpf_experimental.h"9#include "bpf_misc.h"10 11struct node_data {12 long key;13 long data;14 struct bpf_rb_node node;15};16 17struct map_value {18 struct node_data __kptr *node;19};20 21struct node_data2 {22 long key[4];23};24 25/* This is necessary so that LLVM generates BTF for node_data struct26 * If it's not included, a fwd reference for node_data will be generated but27 * no struct. Example BTF of "node" field in map_value when not included:28 *29 * [10] PTR '(anon)' type_id=3530 * [34] FWD 'node_data' fwd_kind=struct31 * [35] TYPE_TAG 'kptr_ref' type_id=3432 */33struct node_data *just_here_because_btf_bug;34 35struct {36 __uint(type, BPF_MAP_TYPE_ARRAY);37 __type(key, int);38 __type(value, struct map_value);39 __uint(max_entries, 2);40} some_nodes SEC(".maps");41 42SEC("tc")43__failure __msg("invalid kptr access, R2 type=ptr_node_data2 expected=ptr_node_data")44long stash_rb_nodes(void *ctx)45{46 struct map_value *mapval;47 struct node_data2 *res;48 int idx = 0;49 50 mapval = bpf_map_lookup_elem(&some_nodes, &idx);51 if (!mapval)52 return 1;53 54 res = bpf_obj_new(typeof(*res));55 if (!res)56 return 1;57 res->key[0] = 40;58 59 res = bpf_kptr_xchg(&mapval->node, res);60 if (res)61 bpf_obj_drop(res);62 return 0;63}64 65SEC("tc")66__failure __msg("R1 must have zero offset when passed to release func")67long drop_rb_node_off(void *ctx)68{69 struct map_value *mapval;70 struct node_data *res;71 int idx = 0;72 73 mapval = bpf_map_lookup_elem(&some_nodes, &idx);74 if (!mapval)75 return 1;76 77 res = bpf_obj_new(typeof(*res));78 if (!res)79 return 1;80 /* Try releasing with graph node offset */81 bpf_obj_drop(&res->node);82 return 0;83}84 85char _license[] SEC("license") = "GPL";86