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 11 char _license[] SEC("license") = "GPL"; 12 13 struct sock { 14 } __attribute__((preserve_access_index)); 15 16 struct bpf_iter__sockmap { 17 union { 18 struct sock *sk; 19 }; 20 } __attribute__((preserve_access_index)); 21 22 struct { 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 29 struct { 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 36 enum { CG_OK = 1 }; 37 38 int zero = 0; 39 40 static __always_inline void test_sockmap_delete(void) 41 { 42 bpf_map_delete_elem(&sockmap, &zero); 43 bpf_map_delete_elem(&sockhash, &zero); 44 } 45 46 static __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 54 static __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 64 static __always_inline void test_sockmap_mutate(void *sk) 65 { 66 test_sockmap_delete(); 67 test_sockmap_update(sk); 68 } 69 70 static __always_inline void test_sockmap_lookup_and_mutate(void) 71 { 72 test_sockmap_delete(); 73 test_sockmap_lookup_and_update(); 74 } 75 76 SEC("action") 77 __success 78 int test_sched_act(struct __sk_buff *skb) 79 { 80 test_sockmap_mutate(skb->sk); 81 return 0; 82 } 83 84 SEC("classifier") 85 __success 86 int test_sched_cls(struct __sk_buff *skb) 87 { 88 test_sockmap_mutate(skb->sk); 89 return 0; 90 } 91 92 SEC("flow_dissector") 93 __success 94 int test_flow_dissector_delete(struct __sk_buff *skb __always_unused) 95 { 96 test_sockmap_delete(); 97 return 0; 98 } 99 100 SEC("flow_dissector") 101 __failure __msg("program of this type cannot use helper bpf_sk_release") 102 int 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 108 SEC("iter/sockmap") 109 __success 110 int test_trace_iter(struct bpf_iter__sockmap *ctx) 111 { 112 test_sockmap_mutate(ctx->sk); 113 return 0; 114 } 115 116 SEC("raw_tp/kfree") 117 __failure __msg("cannot update sockmap in this context") 118 int test_raw_tp_delete(const void *ctx __always_unused) 119 { 120 test_sockmap_delete(); 121 return 0; 122 } 123 124 SEC("raw_tp/kfree") 125 __failure __msg("cannot update sockmap in this context") 126 int test_raw_tp_update(const void *ctx __always_unused) 127 { 128 test_sockmap_lookup_and_update(); 129 return 0; 130 } 131 132 SEC("sk_lookup") 133 __success 134 int test_sk_lookup(struct bpf_sk_lookup *ctx) 135 { 136 test_sockmap_mutate(ctx->sk); 137 return 0; 138 } 139 140 SEC("sk_reuseport") 141 __success 142 int test_sk_reuseport(struct sk_reuseport_md *ctx) 143 { 144 test_sockmap_mutate(ctx->sk); 145 return 0; 146 } 147 148 SEC("socket") 149 __success 150 int test_socket_filter(struct __sk_buff *skb) 151 { 152 test_sockmap_mutate(skb->sk); 153 return 0; 154 } 155 156 SEC("sockops") 157 __success 158 int test_sockops_delete(struct bpf_sock_ops *ctx __always_unused) 159 { 160 test_sockmap_delete(); 161 return CG_OK; 162 } 163 164 SEC("sockops") 165 __failure __msg("cannot update sockmap in this context") 166 int test_sockops_update(struct bpf_sock_ops *ctx) 167 { 168 test_sockmap_update(ctx->sk); 169 return CG_OK; 170 } 171 172 SEC("sockops") 173 __success 174 int 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 181 SEC("xdp") 182 __success 183 int test_xdp(struct xdp_md *ctx __always_unused) 184 { 185 test_sockmap_lookup_and_mutate(); 186 return XDP_PASS; 187 } 188
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.