188 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include <linux/bpf.h>4#include <bpf/bpf_helpers.h>5#include <bpf/bpf_tracing.h>6 7#include "bpf_misc.h"8 9#define __always_unused __attribute__((unused))10 11char _license[] SEC("license") = "GPL";12 13struct sock {14} __attribute__((preserve_access_index));15 16struct bpf_iter__sockmap {17 union {18 struct sock *sk;19 };20} __attribute__((preserve_access_index));21 22struct {23 __uint(type, BPF_MAP_TYPE_SOCKHASH);24 __uint(max_entries, 1);25 __type(key, int);26 __type(value, int);27} sockhash SEC(".maps");28 29struct {30 __uint(type, BPF_MAP_TYPE_SOCKMAP);31 __uint(max_entries, 1);32 __type(key, int);33 __type(value, int);34} sockmap SEC(".maps");35 36enum { CG_OK = 1 };37 38int zero = 0;39 40static __always_inline void test_sockmap_delete(void)41{42 bpf_map_delete_elem(&sockmap, &zero);43 bpf_map_delete_elem(&sockhash, &zero);44}45 46static __always_inline void test_sockmap_update(void *sk)47{48 if (sk) {49 bpf_map_update_elem(&sockmap, &zero, sk, BPF_ANY);50 bpf_map_update_elem(&sockhash, &zero, sk, BPF_ANY);51 }52}53 54static __always_inline void test_sockmap_lookup_and_update(void)55{56 struct bpf_sock *sk = bpf_map_lookup_elem(&sockmap, &zero);57 58 if (sk) {59 test_sockmap_update(sk);60 bpf_sk_release(sk);61 }62}63 64static __always_inline void test_sockmap_mutate(void *sk)65{66 test_sockmap_delete();67 test_sockmap_update(sk);68}69 70static __always_inline void test_sockmap_lookup_and_mutate(void)71{72 test_sockmap_delete();73 test_sockmap_lookup_and_update();74}75 76SEC("action")77__success78int test_sched_act(struct __sk_buff *skb)79{80 test_sockmap_mutate(skb->sk);81 return 0;82}83 84SEC("classifier")85__success86int test_sched_cls(struct __sk_buff *skb)87{88 test_sockmap_mutate(skb->sk);89 return 0;90}91 92SEC("flow_dissector")93__success94int test_flow_dissector_delete(struct __sk_buff *skb __always_unused)95{96 test_sockmap_delete();97 return 0;98}99 100SEC("flow_dissector")101__failure __msg("program of this type cannot use helper bpf_sk_release")102int test_flow_dissector_update(struct __sk_buff *skb __always_unused)103{104 test_sockmap_lookup_and_update(); /* no access to skb->sk */105 return 0;106}107 108SEC("iter/sockmap")109__success110int test_trace_iter(struct bpf_iter__sockmap *ctx)111{112 test_sockmap_mutate(ctx->sk);113 return 0;114}115 116SEC("raw_tp/kfree")117__failure __msg("cannot update sockmap in this context")118int test_raw_tp_delete(const void *ctx __always_unused)119{120 test_sockmap_delete();121 return 0;122}123 124SEC("raw_tp/kfree")125__failure __msg("cannot update sockmap in this context")126int test_raw_tp_update(const void *ctx __always_unused)127{128 test_sockmap_lookup_and_update();129 return 0;130}131 132SEC("sk_lookup")133__success134int test_sk_lookup(struct bpf_sk_lookup *ctx)135{136 test_sockmap_mutate(ctx->sk);137 return 0;138}139 140SEC("sk_reuseport")141__success142int test_sk_reuseport(struct sk_reuseport_md *ctx)143{144 test_sockmap_mutate(ctx->sk);145 return 0;146}147 148SEC("socket")149__success150int test_socket_filter(struct __sk_buff *skb)151{152 test_sockmap_mutate(skb->sk);153 return 0;154}155 156SEC("sockops")157__success158int test_sockops_delete(struct bpf_sock_ops *ctx __always_unused)159{160 test_sockmap_delete();161 return CG_OK;162}163 164SEC("sockops")165__failure __msg("cannot update sockmap in this context")166int test_sockops_update(struct bpf_sock_ops *ctx)167{168 test_sockmap_update(ctx->sk);169 return CG_OK;170}171 172SEC("sockops")173__success174int test_sockops_update_dedicated(struct bpf_sock_ops *ctx)175{176 bpf_sock_map_update(ctx, &sockmap, &zero, BPF_ANY);177 bpf_sock_hash_update(ctx, &sockhash, &zero, BPF_ANY);178 return CG_OK;179}180 181SEC("xdp")182__success183int test_xdp(struct xdp_md *ctx __always_unused)184{185 test_sockmap_lookup_and_mutate();186 return XDP_PASS;187}188