// SPDX-License-Identifier: GPL-2.0 /* Bounds checks for PTR_TO_FLOW_KEYS pointer arithmetic. */ #include "vmlinux.h" #include #include "bpf_misc.h" /* sizeof(struct bpf_flow_keys) is well under 4096, so +0x1000 is OOB. */ SEC("flow_dissector") __description("flow_keys: in-bounds constant pointer arithmetic accepted") __success __naked void flow_keys_const_inbounds(void) { asm volatile (" \ r1 = *(u64 *)(r1 + %[flow_keys]); \ r1 += 8; \ r0 = *(u64 *)(r1 + 0); \ r0 = 0; \ exit; \ " : : __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys)) : __clobber_all); } SEC("flow_dissector") __description("flow_keys: OOB via constant pointer arithmetic rejected") __failure __msg("invalid access to flow keys off=4096 size=8") __naked void flow_keys_const_oob_read(void) { asm volatile (" \ r1 = *(u64 *)(r1 + %[flow_keys]); \ r1 += 4096; \ r0 = *(u64 *)(r1 + 0); \ r0 = 0; \ exit; \ " : : __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys)) : __clobber_all); } SEC("flow_dissector") __description("flow_keys: OOB write via constant pointer arithmetic rejected") __failure __msg("invalid access to flow keys off=4096 size=8") __naked void flow_keys_const_oob_write(void) { asm volatile (" \ r1 = *(u64 *)(r1 + %[flow_keys]); \ r1 += 4096; \ r2 = 0; \ *(u64 *)(r1 + 0) = r2; \ r0 = 0; \ exit; \ " : : __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys)) : __clobber_all); } /* Equivalent OOB expressed directly in insn->off; this form was always * rejected and is kept to show both forms now share one diagnostic. */ SEC("flow_dissector") __description("flow_keys: OOB via insn->off rejected") __failure __msg("invalid access to flow keys off=4096 size=8") __naked void flow_keys_insn_off_oob(void) { asm volatile (" \ r1 = *(u64 *)(r1 + %[flow_keys]); \ r0 = *(u64 *)(r1 + 4096); \ r0 = 0; \ exit; \ " : : __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys)) : __clobber_all); } SEC("flow_dissector") __description("flow_keys: variable pointer arithmetic rejected") __failure __msg("R1 pointer arithmetic on flow_keys prohibited") __naked void flow_keys_var_read(void) { asm volatile (" \ r6 = r1; \ call %[bpf_get_prandom_u32]; \ r0 &= 0xFFFF; \ r1 = *(u64 *)(r6 + %[flow_keys]); \ r1 += r0; \ r0 = *(u64 *)(r1 + 0); \ r0 = 0; \ exit; \ " : : __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys)), __imm(bpf_get_prandom_u32) : __clobber_all); } char _license[] SEC("license") = "GPL";