From 645b2d9755939d7bc29fc8fa4fb5c9761a1508d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 30 Jan 2025 14:43:29 -0800 Subject: [PATCH] bpf: define READ_ONCE and WRITE_ONCE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are convenience macros which do (const|volatile) cast for atomic operations. I've run into a case where two 32-bit writes get optimized by the compiler into a single 64-bit write, which then fails verification. WRITE_ONCE() avoids that by virtue of the volatile annotation. Technically I think the same thing could happen on read, so add READ_ONCE too. Test: N/A Signed-off-by: Maciej Żenczykowski Change-Id: Iade089aab3522916bd7b431d4064f89a21bc78b0 --- bpf/headers/include/bpf_helpers.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bpf/headers/include/bpf_helpers.h b/bpf/headers/include/bpf_helpers.h index 67de6330aa..6a0e5a868d 100644 --- a/bpf/headers/include/bpf_helpers.h +++ b/bpf/headers/include/bpf_helpers.h @@ -419,6 +419,22 @@ static void (*bpf_ringbuf_submit_unsafe)(const void* data, __u64 flags) = (void* DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, \ DEFAULT_BPF_MAP_UID, gid, 0660) +// idea from Linux include/linux/compiler_types.h (eBPF is always a 64-bit arch) +#define NATIVE_WORD(t) ((sizeof(t) == 1) || (sizeof(t) == 2) || (sizeof(t) == 4) || (sizeof(t) == 8)) + +// simplified from Linux include/asm-generic/rwonce.h +#define READ_ONCE(x) \ + ({ \ + _Static_assert(NATIVE_WORD(x), "READ_ONCE requires a native word size"); \ + (*(const volatile typeof(x) *)&(x)) \ + }) + +#define WRITE_ONCE(x, value) \ + do { \ + _Static_assert(NATIVE_WORD(x), "WRITE_ONCE requires a native word size"); \ + *(volatile typeof(x) *)&(x) = (value); \ + } while (0) + // LLVM eBPF builtins: they directly generate BPF_LD_ABS/BPF_LD_IND (skb may be ignored?) unsigned long long load_byte(void* skb, unsigned long long off) asm("llvm.bpf.load.byte"); unsigned long long load_half(void* skb, unsigned long long off) asm("llvm.bpf.load.half");