FILE
verifier_store_release.c
File preview with syntax highlighting.
linux-6.19.14/tools/testing/selftests/bpf/progs/verifier_store_release.c
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (c) 2025 Google LLC. */ 3 4#include <linux/bpf.h> 5#include <bpf/bpf_helpers.h> 6#include "../../../include/linux/filter.h" 7#include "bpf_misc.h" 8 9#ifdef CAN_USE_LOAD_ACQ_STORE_REL 10 11SEC("socket") 12__description("store-release, 8-bit") 13__success __success_unpriv __retval(0) 14__naked void store_release_8(void) 15{ 16 asm volatile ( 17 "r0 = 0;" 18 "w1 = 0x12;" 19 ".8byte %[store_release_insn];" // store_release((u8 *)(r10 - 1), w1); 20 "w2 = *(u8 *)(r10 - 1);" 21 "if r2 == r1 goto 1f;" 22 "r0 = 1;" 23"1:" 24 "exit;" 25 : 26 : __imm_insn(store_release_insn, 27 BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -1)) 28 : __clobber_all); 29} 30 31SEC("socket") 32__description("store-release, 16-bit") 33__success __success_unpriv __retval(0) 34__naked void store_release_16(void) 35{ 36 asm volatile ( 37 "r0 = 0;" 38 "w1 = 0x1234;" 39 ".8byte %[store_release_insn];" // store_release((u16 *)(r10 - 2), w1); 40 "w2 = *(u16 *)(r10 - 2);" 41 "if r2 == r1 goto 1f;" 42 "r0 = 1;" 43"1:" 44 "exit;" 45 : 46 : __imm_insn(store_release_insn, 47 BPF_ATOMIC_OP(BPF_H, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -2)) 48 : __clobber_all); 49} 50 51SEC("socket") 52__description("store-release, 32-bit") 53__success __success_unpriv __retval(0) 54__naked void store_release_32(void) 55{ 56 asm volatile ( 57 "r0 = 0;" 58 "w1 = 0x12345678;" 59 ".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 4), w1); 60 "w2 = *(u32 *)(r10 - 4);" 61 "if r2 == r1 goto 1f;" 62 "r0 = 1;" 63"1:" 64 "exit;" 65 : 66 : __imm_insn(store_release_insn, 67 BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -4)) 68 : __clobber_all); 69} 70 71SEC("socket") 72__description("store-release, 64-bit") 73__success __success_unpriv __retval(0) 74__naked void store_release_64(void) 75{ 76 asm volatile ( 77 "r0 = 0;" 78 "r1 = 0x1234567890abcdef ll;" 79 ".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1); 80 "r2 = *(u64 *)(r10 - 8);" 81 "if r2 == r1 goto 1f;" 82 "r0 = 1;" 83"1:" 84 "exit;" 85 : 86 : __imm_insn(store_release_insn, 87 BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8)) 88 : __clobber_all); 89} 90 91SEC("socket") 92__description("store-release with uninitialized src_reg") 93__failure __failure_unpriv __msg("R2 !read_ok") 94__naked void store_release_with_uninitialized_src_reg(void) 95{ 96 asm volatile ( 97 ".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r2); 98 "exit;" 99 : 100 : __imm_insn(store_release_insn, 101 BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_2, -8)) 102 : __clobber_all); 103} 104 105SEC("socket") 106__description("store-release with uninitialized dst_reg") 107__failure __failure_unpriv __msg("R2 !read_ok") 108__naked void store_release_with_uninitialized_dst_reg(void) 109{ 110 asm volatile ( 111 "r1 = 0;" 112 ".8byte %[store_release_insn];" // store_release((u64 *)(r2 - 8), r1); 113 "exit;" 114 : 115 : __imm_insn(store_release_insn, 116 BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_2, BPF_REG_1, -8)) 117 : __clobber_all); 118} 119 120SEC("socket") 121__description("store-release with non-pointer dst_reg") 122__failure __failure_unpriv __msg("R1 invalid mem access 'scalar'") 123__naked void store_release_with_non_pointer_dst_reg(void) 124{ 125 asm volatile ( 126 "r1 = 0;" 127 ".8byte %[store_release_insn];" // store_release((u64 *)(r1 + 0), r1); 128 "exit;" 129 : 130 : __imm_insn(store_release_insn, 131 BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_1, BPF_REG_1, 0)) 132 : __clobber_all); 133} 134 135SEC("socket") 136__description("misaligned store-release") 137__failure __failure_unpriv __msg("misaligned stack access off") 138__flag(BPF_F_ANY_ALIGNMENT) 139__naked void store_release_misaligned(void) 140{ 141 asm volatile ( 142 "w0 = 0;" 143 ".8byte %[store_release_insn];" // store_release((u32 *)(r10 - 5), w0); 144 "exit;" 145 : 146 : __imm_insn(store_release_insn, 147 BPF_ATOMIC_OP(BPF_W, BPF_STORE_REL, BPF_REG_10, BPF_REG_0, -5)) 148 : __clobber_all); 149} 150 151SEC("socket") 152__description("store-release to ctx pointer") 153__failure __failure_unpriv __msg("BPF_ATOMIC stores into R1 ctx is not allowed") 154__naked void store_release_to_ctx_pointer(void) 155{ 156 asm volatile ( 157 "w0 = 0;" 158 // store_release((u8 *)(r1 + offsetof(struct __sk_buff, cb[0])), w0); 159 ".8byte %[store_release_insn];" 160 "exit;" 161 : 162 : __imm_insn(store_release_insn, 163 BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_1, BPF_REG_0, 164 offsetof(struct __sk_buff, cb[0]))) 165 : __clobber_all); 166} 167 168SEC("xdp") 169__description("store-release to pkt pointer") 170__failure __msg("BPF_ATOMIC stores into R2 pkt is not allowed") 171__naked void store_release_to_pkt_pointer(void) 172{ 173 asm volatile ( 174 "w0 = 0;" 175 "r2 = *(u32 *)(r1 + %[xdp_md_data]);" 176 "r3 = *(u32 *)(r1 + %[xdp_md_data_end]);" 177 "r1 = r2;" 178 "r1 += 8;" 179 "if r1 >= r3 goto l0_%=;" 180 ".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0); 181"l0_%=: r0 = 0;" 182 "exit;" 183 : 184 : __imm_const(xdp_md_data, offsetof(struct xdp_md, data)), 185 __imm_const(xdp_md_data_end, offsetof(struct xdp_md, data_end)), 186 __imm_insn(store_release_insn, 187 BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0)) 188 : __clobber_all); 189} 190 191SEC("flow_dissector") 192__description("store-release to flow_keys pointer") 193__failure __msg("BPF_ATOMIC stores into R2 flow_keys is not allowed") 194__naked void store_release_to_flow_keys_pointer(void) 195{ 196 asm volatile ( 197 "w0 = 0;" 198 "r2 = *(u64 *)(r1 + %[__sk_buff_flow_keys]);" 199 ".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0); 200 "exit;" 201 : 202 : __imm_const(__sk_buff_flow_keys, 203 offsetof(struct __sk_buff, flow_keys)), 204 __imm_insn(store_release_insn, 205 BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0)) 206 : __clobber_all); 207} 208 209SEC("sk_reuseport") 210__description("store-release to sock pointer") 211__failure __msg("R2 cannot write into sock") 212__naked void store_release_to_sock_pointer(void) 213{ 214 asm volatile ( 215 "w0 = 0;" 216 "r2 = *(u64 *)(r1 + %[sk_reuseport_md_sk]);" 217 ".8byte %[store_release_insn];" // store_release((u8 *)(r2 + 0), w0); 218 "exit;" 219 : 220 : __imm_const(sk_reuseport_md_sk, offsetof(struct sk_reuseport_md, sk)), 221 __imm_insn(store_release_insn, 222 BPF_ATOMIC_OP(BPF_B, BPF_STORE_REL, BPF_REG_2, BPF_REG_0, 0)) 223 : __clobber_all); 224} 225 226SEC("socket") 227__description("store-release, leak pointer to stack") 228__success __success_unpriv __retval(0) 229__naked void store_release_leak_pointer_to_stack(void) 230{ 231 asm volatile ( 232 ".8byte %[store_release_insn];" // store_release((u64 *)(r10 - 8), r1); 233 "r0 = 0;" 234 "exit;" 235 : 236 : __imm_insn(store_release_insn, 237 BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_10, BPF_REG_1, -8)) 238 : __clobber_all); 239} 240 241struct { 242 __uint(type, BPF_MAP_TYPE_HASH); 243 __uint(max_entries, 1); 244 __type(key, long long); 245 __type(value, long long); 246} map_hash_8b SEC(".maps"); 247 248SEC("socket") 249__description("store-release, leak pointer to map") 250__success __retval(0) 251__failure_unpriv __msg_unpriv("R6 leaks addr into map") 252__naked void store_release_leak_pointer_to_map(void) 253{ 254 asm volatile ( 255 "r6 = r1;" 256 "r1 = %[map_hash_8b] ll;" 257 "r2 = 0;" 258 "*(u64 *)(r10 - 8) = r2;" 259 "r2 = r10;" 260 "r2 += -8;" 261 "call %[bpf_map_lookup_elem];" 262 "if r0 == 0 goto l0_%=;" 263 ".8byte %[store_release_insn];" // store_release((u64 *)(r0 + 0), r6); 264"l0_%=:" 265 "r0 = 0;" 266 "exit;" 267 : 268 : __imm_addr(map_hash_8b), 269 __imm(bpf_map_lookup_elem), 270 __imm_insn(store_release_insn, 271 BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, BPF_REG_0, BPF_REG_6, 0)) 272 : __clobber_all); 273} 274 275SEC("socket") 276__description("store-release with invalid register R15") 277__failure __failure_unpriv __msg("R15 is invalid") 278__naked void store_release_with_invalid_reg(void) 279{ 280 asm volatile ( 281 ".8byte %[store_release_insn];" // store_release((u64 *)(r15 + 0), r1); 282 "exit;" 283 : 284 : __imm_insn(store_release_insn, 285 BPF_ATOMIC_OP(BPF_DW, BPF_STORE_REL, 15 /* invalid reg */, BPF_REG_1, 0)) 286 : __clobber_all); 287} 288 289#else /* CAN_USE_LOAD_ACQ_STORE_REL */ 290 291SEC("socket") 292__description("Clang version < 18, ENABLE_ATOMICS_TESTS not defined, and/or JIT doesn't support store-release, use a dummy test") 293__success 294int dummy_test(void) 295{ 296 return 0; 297} 298 299#endif /* CAN_USE_LOAD_ACQ_STORE_REL */ 300 301char _license[] SEC("license") = "GPL";
~/
Read-only file preview.