Loading...
Note: File does not exist in v6.8.
1// SPDX-License-Identifier: GPL-2.0
2
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__success
78int test_sched_act(struct __sk_buff *skb)
79{
80 test_sockmap_mutate(skb->sk);
81 return 0;
82}
83
84SEC("classifier")
85__success
86int test_sched_cls(struct __sk_buff *skb)
87{
88 test_sockmap_mutate(skb->sk);
89 return 0;
90}
91
92SEC("flow_dissector")
93__success
94int 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__success
110int 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__success
134int test_sk_lookup(struct bpf_sk_lookup *ctx)
135{
136 test_sockmap_mutate(ctx->sk);
137 return 0;
138}
139
140SEC("sk_reuseport")
141__success
142int test_sk_reuseport(struct sk_reuseport_md *ctx)
143{
144 test_sockmap_mutate(ctx->sk);
145 return 0;
146}
147
148SEC("socket")
149__success
150int test_socket_filter(struct __sk_buff *skb)
151{
152 test_sockmap_mutate(skb->sk);
153 return 0;
154}
155
156SEC("sockops")
157__success
158int 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__success
174int 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__success
183int test_xdp(struct xdp_md *ctx __always_unused)
184{
185 test_sockmap_lookup_and_mutate();
186 return XDP_PASS;
187}