#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include "../../../include/linux/filter.h"
#include "bpf_misc.h"
char _license[] SEC("license") = "GPL";
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1);
__type(key, int);
__type(value, long long);
} map SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(value, __u64);
} array_map_8b SEC(".maps");
const char snprintf_u64_fmt[] = "%llu";
SEC("socket")
__log_level(2)
__msg("0: (79) r1 = *(u64 *)(r10 -8) ; use: fp0-8")
__msg("1: (79) r2 = *(u64 *)(r10 -24) ; use: fp0-24")
__msg("2: (7b) *(u64 *)(r10 -8) = r1 ; def: fp0-8")
__naked void simple_read_simple_write(void)
{
asm volatile (
"r1 = *(u64 *)(r10 - 8);"
"r2 = *(u64 *)(r10 - 24);"
"*(u64 *)(r10 - 8) = r1;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("2: (79) r0 = *(u64 *)(r10 -8) ; use: fp0-8")
__msg("6: (79) r0 = *(u64 *)(r10 -16) ; use: fp0-16")
__naked void read_write_join(void)
{
asm volatile (
"call %[bpf_get_prandom_u32];"
"if r0 > 42 goto 1f;"
"r0 = *(u64 *)(r10 - 8);"
"*(u64 *)(r10 - 32) = r0;"
"*(u64 *)(r10 - 40) = r0;"
"exit;"
"1:"
"r0 = *(u64 *)(r10 - 16);"
"*(u64 *)(r10 - 32) = r0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("stack use/def subprog#0 must_write_not_same_slot (d0,cs0):")
__msg("6: (7b) *(u64 *)(r2 +0) = r0{{$}}")
__msg("Live regs before insn:")
__naked void must_write_not_same_slot(void)
{
asm volatile (
"call %[bpf_get_prandom_u32];"
"r1 = -8;"
"if r0 > 42 goto 1f;"
"r1 = -16;"
"1:"
"r2 = r10;"
"r2 += r1;"
"*(u64 *)(r2 + 0) = r0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("0: (7a) *(u64 *)(r10 -8) = 0 ; def: fp0-8")
__msg("5: (85) call bpf_map_lookup_elem#1 ; use: fp0-8h")
__naked void must_write_not_same_type(void)
{
asm volatile (
"*(u64*)(r10 - 8) = 0;"
"r2 = r10;"
"r2 += -8;"
"r1 = %[map] ll;"
"call %[bpf_map_lookup_elem];"
"if r0 != 0 goto 1f;"
"r0 = r10;"
"r0 += -16;"
"1:"
"*(u64 *)(r0 + 0) = 42;"
"exit;"
:
: __imm(bpf_get_prandom_u32),
__imm(bpf_map_lookup_elem),
__imm_addr(map)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("stack use/def subprog#0 caller_stack_write (d0,cs0):")
__msg("2: (85) call pc+1{{$}}")
__msg("stack use/def subprog#1 write_first_param (d1,cs2):")
__msg("4: (7a) *(u64 *)(r1 +0) = 7 ; def: fp0-8")
__naked void caller_stack_write(void)
{
asm volatile (
"r1 = r10;"
"r1 += -8;"
"call write_first_param;"
"exit;"
::: __clobber_all);
}
static __used __naked void write_first_param(void)
{
asm volatile (
"*(u64 *)(r1 + 0) = 7;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("stack use/def subprog#0 caller_stack_read (d0,cs0):")
__msg("2: (85) call pc+{{.*}} ; use: fp0-8{{$}}")
__msg("5: (85) call pc+{{.*}} ; use: fp0-16{{$}}")
__msg("stack use/def subprog#1 read_first_param (d1,cs2):")
__msg("7: (79) r0 = *(u64 *)(r1 +0) ; use: fp0-8{{$}}")
__msg("8: (95) exit")
__msg("stack use/def subprog#1 read_first_param (d1,cs5):")
__msg("7: (79) r0 = *(u64 *)(r1 +0) ; use: fp0-16{{$}}")
__msg("8: (95) exit")
__naked void caller_stack_read(void)
{
asm volatile (
"r1 = r10;"
"r1 += -8;"
"call read_first_param;"
"r1 = r10;"
"r1 += -16;"
"call read_first_param;"
"exit;"
::: __clobber_all);
}
static __used __naked void read_first_param(void)
{
asm volatile (
"r0 = *(u64 *)(r1 + 0);"
"exit;"
::: __clobber_all);
}
SEC("socket")
__success
__naked void arg_track_join_convergence(void)
{
asm volatile (
"r1 = 1;"
"r2 = 2;"
"call arg_track_join_convergence_subprog;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void arg_track_join_convergence_subprog(void)
{
asm volatile (
"if r1 == 0 goto 1f;"
"r0 = r1;"
"goto 2f;"
"1:"
"r0 = r2;"
"2:"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__log_level(2)
__msg("4: (7b) *(u64 *)(r10 -8) = r0 ; def: fp0-8")
__msg("7: (85) call pc+{{.*}} ; use: fp0-8")
__msg("9: (79) r0 = *(u64 *)(r1 +0) ; use: fp0-8")
__msg("10: (b7) r0 = 0{{$}}")
__msg("11: (05) goto pc+0{{$}}")
__msg("12: (95) exit")
__msg("12: safe")
__naked void caller_stack_pruning(void)
{
asm volatile (
"call %[bpf_get_prandom_u32];"
"if r0 == 42 goto 1f;"
"r0 = %[map] ll;"
"1:"
"*(u64 *)(r10 - 8) = r0;"
"r1 = r10;"
"r1 += -8;"
"call read_first_param2;"
"exit;"
:
: __imm(bpf_get_prandom_u32),
__imm_addr(map)
: __clobber_all);
}
static __used __naked void read_first_param2(void)
{
asm volatile (
"r0 = *(u64 *)(r1 + 0);"
"r0 = 0;"
"goto +0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure
__msg("R1 type=scalar expected=map_ptr")
__naked void caller_stack_pruning_callback(void)
{
asm volatile (
"r0 = %[map] ll;"
"*(u64 *)(r10 - 8) = r0;"
"r1 = 2;"
"r2 = loop_cb ll;"
"r3 = r10;"
"r3 += -8;"
"r4 = 0;"
"call %[bpf_loop];"
"r0 = 42;"
"exit;"
:
: __imm(bpf_get_prandom_u32),
__imm(bpf_loop),
__imm_addr(map)
: __clobber_all);
}
static __used __naked void loop_cb(void)
{
asm volatile (
"r6 = r2;"
"r1 = *(u64 *)(r6 + 0);"
"*(u64*)(r10 - 8) = 7;"
"r2 = r10;"
"r2 += -8;"
"call %[bpf_map_lookup_elem];"
"*(u64 *)(r6 + 0) = 0;"
"r0 = 0;"
"exit;"
:
: __imm(bpf_map_lookup_elem),
__imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__naked void syzbot_postorder_bug1(void)
{
asm volatile (
"r0 = 0;"
"if r0 != 0 goto -1;"
"exit;"
::: __clobber_all);
}
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(value, __u32);
} map_array SEC(".maps");
SEC("socket")
__failure __msg("invalid read from stack R2 off=-1024 size=8")
__flag(BPF_F_TEST_STATE_FREQ)
__naked unsigned long caller_stack_write_tail_call(void)
{
asm volatile (
"r6 = r1;"
"*(u64 *)(r10 - 8) = -8;"
"call %[bpf_get_prandom_u32];"
"if r0 != 42 goto 1f;"
"goto 2f;"
"1:"
"*(u64 *)(r10 - 8) = -1024;"
"2:"
"r1 = r6;"
"r2 = r10;"
"r2 += -8;"
"call write_tail_call;"
"r1 = *(u64 *)(r10 - 8);"
"r2 = r10;"
"r2 += r1;"
"r0 = *(u64 *)(r2 + 0);"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
static __used __naked unsigned long write_tail_call(void)
{
asm volatile (
"r6 = r2;"
"r2 = %[map_array] ll;"
"r3 = 0;"
"call %[bpf_tail_call];"
"*(u64 *)(r6 + 0) = -16;"
"r0 = 0;"
"exit;"
:
: __imm(bpf_tail_call),
__imm_addr(map_array)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("6: (85) call pc+{{.*}} ; use: fp0-24 fp0-32{{$}}")
__naked void subprog_precise_stack_access(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u64 *)(r10 - 16) = 0;"
"*(u64 *)(r10 - 24) = 0;"
"*(u64 *)(r10 - 32) = 0;"
"r1 = r10;"
"r1 += -32;"
"call precise_read_two;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void precise_read_two(void)
{
asm volatile (
"r0 = *(u64 *)(r1 + 0);"
"r2 = *(u64 *)(r1 + 8);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("6: (85) call pc+{{.*}} ; use: fp0-32{{$}}")
__naked void subprog_multilevel_conservative(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u64 *)(r10 - 16) = 0;"
"*(u64 *)(r10 - 24) = 0;"
"*(u64 *)(r10 - 32) = 0;"
"r1 = r10;"
"r1 += -32;"
"call forward_to_inner;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void forward_to_inner(void)
{
asm volatile (
"call inner_callee;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void inner_callee(void)
{
asm volatile (
"r0 = *(u64 *)(r1 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__log_level(2)
__success
__msg(" 7: (85) call pc+{{.*}} ; use: fp0-8")
__msg(" 8: {{.*}} (b7)")
__naked void callee_consumed_caller_stack(void)
{
asm volatile (
"call %[bpf_get_prandom_u32];"
"if r0 == 42 goto 1f;"
"r0 = %[map] ll;"
"1:"
"*(u64 *)(r10 - 8) = r0;"
"r1 = r10;"
"r1 += -8;"
"call consume_and_call_inner;"
"r0 = 0;"
"exit;"
:
: __imm(bpf_get_prandom_u32),
__imm_addr(map)
: __clobber_all);
}
static __used __naked void consume_and_call_inner(void)
{
asm volatile (
"r0 = *(u64 *)(r1 + 0);"
"call do_nothing2;"
"r0 = 0;"
"goto +0;"
"r0 = 0;"
"goto +0;"
"r0 = 0;"
"goto +0;"
"r0 = 0;"
"goto +0;"
"exit;"
::: __clobber_all);
}
static __used __naked void do_nothing2(void)
{
asm volatile (
"r0 = 0;"
"r0 = 0;"
"r0 = 0;"
"r0 = 0;"
"r0 = 0;"
"r0 = 0;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R0 invalid mem access 'map_value_or_null'")
__naked void stack_zero_to_misc_unsound_array_lookup(void)
{
asm volatile (
"*(u32 *)(r10 - 4) = 0;"
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto l_nonconst%=;"
"goto l_lookup%=;"
"l_nonconst%=:"
"*(u8 *)(r10 - 4) = r0;"
"l_lookup%=:"
"r2 = r10;"
"r2 += -4;"
"r1 = %[array_map_8b] ll;"
"call %[bpf_map_lookup_elem];"
"r0 = *(u64 *)(r0 + 0);"
"exit;"
:
: __imm(bpf_get_prandom_u32),
__imm(bpf_map_lookup_elem),
__imm_addr(array_map_8b)
: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R0 invalid mem access 'map_value_or_null'")
__naked void subprog_stack_zero_to_misc_unsound(void)
{
asm volatile (
"*(u32 *)(r10 - 4) = 0;"
"r1 = r10;"
"r1 += -4;"
"call maybe_clobber_key;"
"r2 = r10;"
"r2 += -4;"
"r1 = %[array_map_8b] ll;"
"call %[bpf_map_lookup_elem];"
"r0 = *(u64 *)(r0 + 0);"
"exit;"
:
: __imm(bpf_map_lookup_elem),
__imm_addr(array_map_8b)
: __clobber_all);
}
static __used __naked void maybe_clobber_key(void)
{
asm volatile (
"r6 = r1;"
"call %[bpf_get_prandom_u32];"
"if r0 == 0 goto 1f;"
"*(u8 *)(r6 + 0) = r0;"
"1:"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__log_level(2)
__success
__msg("6: safe")
__naked void spill_reload_inflates_stack_liveness(void)
{
asm volatile (
"*(u64 *)(r10 - 24) = r1;"
"*(u64 *)(r10 - 16) = r1;"
"*(u64 *)(r10 - 8) = 0;"
"r1 = r10;"
"r1 += -24;"
"call modifier2;"
"r1 = r10;"
"r1 += -24;"
"call spill_reload_reader2;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void modifier2(void)
{
asm volatile (
"r6 = r1;"
"call %[bpf_get_prandom_u32];"
"if r0 == 0 goto 1f;"
"*(u64 *)(r6 + 8) = r0;"
"r0 = 0;"
"exit;"
"1:"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
static __used __naked void spill_reload_reader2(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = r1;"
"call %[bpf_get_prandom_u32];"
"r1 = *(u64 *)(r10 - 8);"
"r0 = *(u64 *)(r1 + 16);"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
void __kfunc_btf_root(void)
{
bpf_iter_num_new(0, 0, 0);
bpf_iter_num_next(0);
bpf_iter_num_destroy(0);
}
SEC("socket")
__success __log_level(2)
__msg(" 6: (85) call bpf_iter_num_new{{.*}} ; def: fp0-24{{$}}")
__msg(" 9: (85) call bpf_iter_num_next{{.*}} ; use: fp0-24{{$}}")
__msg("14: (85) call bpf_iter_num_destroy{{.*}} ; use: fp0-24{{$}}")
__naked void kfunc_iter_stack_liveness(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u64 *)(r10 - 16) = 0;"
"r1 = r10;"
"r1 += -24;"
"r2 = 0;"
"r3 = 10;"
"call %[bpf_iter_num_new];"
"1:"
"r1 = r10;"
"r1 += -24;"
"call %[bpf_iter_num_next];"
"if r0 == 0 goto 2f;"
"goto 1b;"
"2:"
"r1 = r10;"
"r1 += -24;"
"call %[bpf_iter_num_destroy];"
"r0 = 0;"
"exit;"
:: __imm(bpf_iter_num_new),
__imm(bpf_iter_num_next),
__imm(bpf_iter_num_destroy)
: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R0 invalid mem access 'scalar'")
__naked void spill_ptr_liveness_type_confusion(void)
{
asm volatile (
"r1 = %[map] ll;"
"*(u32 *)(r10 - 32) = 0;"
"r2 = r10;"
"r2 += -32;"
"call %[bpf_map_lookup_elem];"
"if r0 == 0 goto l_exit%=;"
"r6 = r0;"
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto l_scalar%=;"
"*(u64 *)(r10 - 8) = r6;"
"goto l_merge%=;"
"l_scalar%=:"
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"l_merge%=:"
"r1 = r10;"
"r1 += -8;"
"*(u64 *)(r10 - 16) = r1;"
"goto +0;"
"goto +0;"
"goto +0;"
"r1 = *(u64 *)(r10 - 16);"
"r0 = *(u64 *)(r1 + 0);"
"r0 = *(u64 *)(r0 + 0);"
"exit;"
"l_exit%=:"
"r0 = 0;"
"exit;"
:
: __imm(bpf_map_lookup_elem),
__imm(bpf_get_prandom_u32),
__imm_addr(map)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("1: (62) *(u32 *)(r10 -8) = 0 ; def: fp0-8h")
__naked void four_byte_write_kills_slot(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u32 *)(r10 - 8) = 0;"
"r0 = *(u64 *)(r10 - 8);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("0: (62) *(u32 *)(r10 -8) = 0 ; def: fp0-8h")
__msg("2: (61) r0 = *(u32 *)(r10 -4) ; use: fp0-4h")
__naked void dead_half_spi_write(void)
{
asm volatile (
"*(u32 *)(r10 - 8) = 0;"
"*(u32 *)(r10 - 4) = 0;"
"r0 = *(u32 *)(r10 - 4);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("1: (61) r0 = *(u32 *)(r10 -8) ; use: fp0-8h")
__naked void four_byte_read_upper_half(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"r0 = *(u32 *)(r10 - 8);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("0: (7a) *(u64 *)(r10 -8) = 0 ; def: fp0-8")
__msg("1: (6a) *(u16 *)(r10 -4) = 0{{$}}")
__msg("2: (61) r0 = *(u32 *)(r10 -4) ; use: fp0-4h")
__naked void two_byte_write_no_kill(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u16 *)(r10 - 4) = 0;"
"r0 = *(u32 *)(r10 - 4);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("0: (7a) *(u64 *)(r10 -8) = 0 ; def: fp0-8")
__msg("1: (72) *(u8 *)(r10 -4) = 0")
__msg("2: (61) r0 = *(u32 *)(r10 -4) ; use: fp0-4h")
__naked void one_byte_write_no_kill(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u8 *)(r10 - 4) = 0;"
"r0 = *(u32 *)(r10 - 4);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("1: (79) r0 = *(u64 *)(r10 -264) ; use: fp0-264")
__naked void high_stack_second_bitmask_word(void)
{
asm volatile (
"*(u64 *)(r10 - 264) = 0;"
"r0 = *(u64 *)(r10 - 264);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("0: (62) *(u32 *)(r10 -8) = 0 ; def: fp0-8h")
__msg("1: (62) *(u32 *)(r10 -4) = 0 ; def: fp0-4h")
__naked void two_four_byte_writes_kill_full_spi(void)
{
asm volatile (
"*(u32 *)(r10 - 8) = 0;"
"*(u32 *)(r10 - 4) = 0;"
"r0 = *(u64 *)(r10 - 8);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("1: (55) if r0 != 0x0 goto pc+2")
__msg("2: (7a) *(u64 *)(r10 -8) = 0 ; def: fp0-8")
__msg("3: (05) goto pc+1")
__msg("4: (62) *(u32 *)(r10 -4) = 0 ; def: fp0-4h")
__msg("5: (61) r0 = *(u32 *)(r10 -4) ; use: fp0-4h")
__naked void both_branches_kill_slot(void)
{
asm volatile (
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto 1f;"
"*(u64 *)(r10 - 8) = 0;"
"goto 2f;"
"1:"
"*(u32 *)(r10 - 4) = 0;"
"2:"
"r0 = *(u32 *)(r10 - 4);"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R0 invalid mem access 'map_value_or_null'")
__naked void half_spi_clean_preserves_stack_zero(void)
{
asm volatile (
"*(u32 *)(r10 - 4) = 0;"
"*(u32 *)(r10 - 8) = 0;"
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto l_nonconst%=;"
"goto l_lookup%=;"
"l_nonconst%=:"
"*(u8 *)(r10 - 4) = r0;"
"l_lookup%=:"
"r2 = r10;"
"r2 += -4;"
"r1 = %[array_map_8b] ll;"
"call %[bpf_map_lookup_elem];"
"r0 = *(u64 *)(r0 + 0);"
"exit;"
:
: __imm(bpf_get_prandom_u32),
__imm(bpf_map_lookup_elem),
__imm_addr(array_map_8b)
: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__success
__log_level(2)
__msg("6: safe")
__naked void dead_spill_at_merge_enables_pruning(void)
{
asm volatile (
"call %[bpf_get_prandom_u32];"
"r6 = 7;"
"if r0 != 0 goto l_skip%=;"
"*(u64 *)(r10 - 8) = r6;"
"call %[bpf_get_prandom_u32];"
"r6 = *(u64 *)(r10 - 8);"
"l_skip%=:"
"r0 = r6;"
"exit;"
:
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R1 invalid mem access 'scalar'")
__naked void fp_add_loses_precision_kills_liveness(void)
{
asm volatile (
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto l_pathB%=;"
"r1 = 0;"
"*(u64 *)(r10 - 8) = r1;"
"goto l_merge%=;"
"l_pathB%=:"
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"l_merge%=:"
"r6 = r10;"
"r6 += -24;"
"r6 += 8;"
"r7 = 0;"
"*(u64 *)(r6 + 0) = r7;"
"r2 = *(u64 *)(r10 - 8);"
"if r2 == 42 goto l_danger%=;"
"r0 = 0;"
"exit;"
"l_danger%=:"
"r1 = 0;"
"r0 = *(u64 *)(r1 + 0);"
"exit;"
:
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R1 invalid mem access 'scalar'")
__naked void fp_spill_loses_precision_kills_liveness(void)
{
asm volatile (
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto l_pathB%=;"
"r1 = 0;"
"*(u64 *)(r10 - 8) = r1;"
"goto l_merge%=;"
"l_pathB%=:"
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"l_merge%=:"
"r6 = r10;"
"r6 += -64;"
"*(u64 *)(r10 - 160) = r6;"
"r6 = *(u64 *)(r10 - 160);"
"r7 = 0;"
"*(u64 *)(r6 + 0) = r7;"
"r2 = *(u64 *)(r10 - 8);"
"if r2 == 42 goto l_danger%=;"
"r0 = *(u64 *)(r10 - 56);"
"exit;"
"l_danger%=:"
"r1 = 0;"
"r0 = *(u64 *)(r1 + 0);"
"exit;"
:
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("1: (7b) *(u64 *)(r10 -8) = r1 ; def: fp0-8")
__msg("4: (85) call pc+2{{$}}")
__msg("5: (79) r0 = *(u64 *)(r10 -8) ; use: fp0-8")
__naked void conditional_stx_in_subprog(void)
{
asm volatile (
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r1 += -8;"
"call cond_writer;"
"r0 = *(u64 *)(r10 - 8);"
"exit;"
::: __clobber_all);
}
static __used __naked void cond_writer(void)
{
asm volatile (
"r6 = r1;"
"call %[bpf_get_prandom_u32];"
"if r0 == 0 goto 1f;"
"*(u64 *)(r6 + 0) = r0;"
"1:"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("4: (85) call pc+{{.*}} ; use: fp0-16")
__msg("7: (85) call pc+{{.*}} ; use: fp0-32")
__naked void multiple_callsites_different_offsets(void)
{
asm volatile (
"*(u64 *)(r10 - 16) = 0;"
"*(u64 *)(r10 - 32) = 0;"
"r1 = r10;"
"r1 += -16;"
"call read_first_param;"
"r1 = r10;"
"r1 += -32;"
"call read_first_param;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("6: (85) call pc+{{.*}} ; use: fp0-32")
__naked void nested_fp_passthrough(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u64 *)(r10 - 16) = 0;"
"*(u64 *)(r10 - 24) = 0;"
"*(u64 *)(r10 - 32) = 0;"
"r1 = r10;"
"r1 += -32;"
"call outer_forwarder;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void outer_forwarder(void)
{
asm volatile (
"call inner_reader;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void inner_reader(void)
{
asm volatile (
"r0 = *(u64 *)(r1 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("2: .12345.... (85) call pc+")
__naked void callee_must_write_before_read(void)
{
asm volatile (
"r1 = r10;"
"r1 += -8;"
"call write_then_read;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void write_then_read(void)
{
asm volatile (
"r6 = r1;"
"r7 = 99;"
"*(u64 *)(r6 + 0) = r7;"
"r0 = *(u64 *)(r6 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("3: (85) call pc+{{.*}} ; use: fp0-8")
__msg("7: (85) call pc+{{.*}} ; use: fp0-8")
__naked void return_site_liveness_bleeding(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"r1 = r10;"
"r1 += -8;"
"call read_first_param;"
"r0 = *(u64 *)(r10 - 8);"
"r1 = r10;"
"r1 += -8;"
"call read_first_param;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("9: (85) call bpf_loop#181 ; use: fp0-16")
__naked void callback_conditional_read_beyond_ctx(void)
{
asm volatile (
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = 2;"
"r2 = cb_cond_read ll;"
"r3 = r10;"
"r3 += -8;"
"r4 = 0;"
"call %[bpf_loop];"
"r0 = 0;"
"exit;"
:: __imm(bpf_loop)
: __clobber_all);
}
static __used __naked void cb_cond_read(void)
{
asm volatile (
"r6 = r2;"
"call %[bpf_get_prandom_u32];"
"if r0 == 0 goto 1f;"
"r0 = *(u64 *)(r6 - 8);"
"1:"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("14: (7b) *(u64 *)(r6 -8) = r7 ; def: fp0-16")
__msg("15: (79) r0 = *(u64 *)(r6 -8) ; use: fp0-16")
__naked void callback_write_before_read_kills(void)
{
asm volatile (
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = 2;"
"r2 = cb_write_read ll;"
"r3 = r10;"
"r3 += -8;"
"r4 = 0;"
"call %[bpf_loop];"
"r0 = 0;"
"exit;"
:: __imm(bpf_loop)
: __clobber_all);
}
static __used __naked void cb_write_read(void)
{
asm volatile (
"r6 = r2;"
"r7 = 99;"
"*(u64 *)(r6 - 8) = r7;"
"r0 = *(u64 *)(r6 - 8);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("9: (85) call bpf_loop#181 ; use: fp0-16")
__naked void callback_conditional_write_preserves(void)
{
asm volatile (
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = 2;"
"r2 = cb_cond_write_read ll;"
"r3 = r10;"
"r3 += -8;"
"r4 = 0;"
"call %[bpf_loop];"
"r0 = 0;"
"exit;"
:: __imm(bpf_loop)
: __clobber_all);
}
static __used __naked void cb_cond_write_read(void)
{
asm volatile (
"r6 = r2;"
"call %[bpf_get_prandom_u32];"
"if r0 == 0 goto 1f;"
"*(u64 *)(r6 - 8) = r0;"
"1:"
"r0 = *(u64 *)(r6 - 8);"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg(" 8: (85) call bpf_loop{{.*}} ; use: fp0-8")
__msg("15: (85) call bpf_loop{{.*}} ; use: fp0-24")
__naked void callback_two_calls_different_ctx(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u64 *)(r10 - 24) = 0;"
"r1 = 1;"
"r2 = cb_read_ctx ll;"
"r3 = r10;"
"r3 += -8;"
"r4 = 0;"
"call %[bpf_loop];"
"r1 = 1;"
"r2 = cb_read_ctx ll;"
"r3 = r10;"
"r3 += -24;"
"r4 = 0;"
"call %[bpf_loop];"
"r0 = 0;"
"exit;"
:: __imm(bpf_loop)
: __clobber_all);
}
static __used __naked void cb_read_ctx(void)
{
asm volatile (
"r0 = *(u64 *)(r2 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R0 invalid mem access 'scalar'")
__naked void transitive_parent_stack_read_unsound(void)
{
asm volatile (
"r1 = %[map] ll;"
"*(u32 *)(r10 - 32) = 0;"
"r2 = r10;"
"r2 += -32;"
"call %[bpf_map_lookup_elem];"
"if r0 == 0 goto l_exit%=;"
"r6 = r0;"
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto l_scalar%=;"
"*(u64 *)(r10 - 8) = r6;"
"goto l_merge%=;"
"l_scalar%=:"
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"l_merge%=:"
"r1 = r10;"
"r1 += -8;"
"call mid_fwd;"
"r0 = 0;"
"exit;"
"l_exit%=:"
"r0 = 0;"
"exit;"
:
: __imm(bpf_map_lookup_elem),
__imm(bpf_get_prandom_u32),
__imm_addr(map)
: __clobber_all);
}
static __used __naked void mid_fwd(void)
{
asm volatile (
"call grandchild_deref;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void grandchild_deref(void)
{
asm volatile (
"goto +0;"
"goto +0;"
"r0 = *(u64 *)(r1 + 0);"
"r0 = *(u64 *)(r0 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("14: (79) r1 = *(u64 *)(r10 -8) // r6=fp0-8 r7=fp1-16 fp-8=fp1-16 fp-16=fp0-8")
__msg("15: (79) r0 = *(u64 *)(r1 +0) // r1=fp1-16 r6=fp0-8 r7=fp1-16 fp-8=fp1-16 fp-16=fp0-8")
__msg("stack use/def subprog#1 mid_two_fp_threshold (d1,cs2):")
__msg("14: (79) r1 = *(u64 *)(r10 -8) ; use: fp1-8")
__msg("15: (79) r0 = *(u64 *)(r1 +0) ; use: fp1-16")
__naked void two_fp_clear_stack_threshold(void)
{
asm volatile (
"r1 = r10;"
"r1 += -8;"
"call mid_two_fp_threshold;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void mid_two_fp_threshold(void)
{
asm volatile (
"r6 = r1;"
"r7 = r10;"
"r7 += -16;"
"*(u64 *)(r10 - 8) = r7;"
"*(u64 *)(r10 - 16) = r6;"
"r1 = r10;"
"r1 += -8;"
"r2 = r6;"
"call inner_nop_fptest;"
"r1 = *(u64 *)(r10 - 8);"
"r0 = *(u64 *)(r1 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void inner_nop_fptest(void)
{
asm volatile (
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("13: (79) r1 = *(u64 *)(r10 -8) // r6=fp0-8 r7=fp1-16 fp-8=fp1-16 fp-16=fp0-8")
__msg("14: (79) r0 = *(u64 *)(r1 +0) // r1=fp1-16 r6=fp0-8 r7=fp1-16 fp-8=fp1-16 fp-16=fp0-8")
__msg("stack use/def subprog#1 mid_one_fp_threshold (d1,cs2):")
__msg("13: (79) r1 = *(u64 *)(r10 -8) ; use: fp1-8")
__msg("14: (79) r0 = *(u64 *)(r1 +0) ; use: fp1-16")
__naked void one_fp_clear_stack_threshold(void)
{
asm volatile (
"r1 = r10;"
"r1 += -8;"
"call mid_one_fp_threshold;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void mid_one_fp_threshold(void)
{
asm volatile (
"r6 = r1;"
"r7 = r10;"
"r7 += -16;"
"*(u64 *)(r10 - 8) = r7;"
"*(u64 *)(r10 - 16) = r6;"
"r1 = r10;"
"r1 += -8;"
"call inner_nop_fptest;"
"r1 = *(u64 *)(r10 - 8);"
"r0 = *(u64 *)(r1 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R0 invalid mem access 'map_value_or_null'")
__naked void helper_parent_stack_read_unsound(void)
{
asm volatile (
"*(u32 *)(r10 - 4) = 0;"
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto l_clobber%=;"
"goto l_merge%=;"
"l_clobber%=:"
"*(u8 *)(r10 - 4) = r0;"
"l_merge%=:"
"r1 = r10;"
"r1 += -4;"
"call fwd_parent_key_to_helper;"
"r0 = 0;"
"exit;"
:
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
static __used __naked void fwd_parent_key_to_helper(void)
{
asm volatile (
"goto +0;"
"r2 = r1;"
"r1 = %[array_map_8b] ll;"
"call %[bpf_map_lookup_elem];"
"r0 = *(u64 *)(r0 + 0);"
"r0 = 0;"
"exit;"
:
: __imm(bpf_map_lookup_elem),
__imm_addr(array_map_8b)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("call bpf_snprintf{{.*}} ; use: fp1-8..-512 fp0-8")
__naked void helper_arg_fallback_keeps_scanning(void)
{
asm volatile (
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r1 += -8;"
"call helper_snprintf_parent_after_local_fallback;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void helper_snprintf_parent_after_local_fallback(void)
{
asm volatile (
"r6 = r1;"
"call %[bpf_get_prandom_u32];"
"r0 &= 8;"
"r1 = r10;"
"r1 += -16;"
"r1 += r0;"
"r2 = 8;"
"r3 = %[snprintf_u64_fmt] ll;"
"r4 = r6;"
"r5 = 8;"
"call %[bpf_snprintf];"
"r0 = 0;"
"exit;"
:
: __imm(bpf_get_prandom_u32),
__imm(bpf_snprintf),
__imm_addr(snprintf_u64_fmt)
: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__failure __msg("R0 invalid mem access 'scalar'")
__naked void propagate_callee_ancestor_chain(void)
{
asm volatile (
"r1 = %[map] ll;"
"*(u32 *)(r10 - 32) = 0;"
"r2 = r10;"
"r2 += -32;"
"call %[bpf_map_lookup_elem];"
"if r0 == 0 goto l_exit%=;"
"r6 = r0;"
"call %[bpf_get_prandom_u32];"
"if r0 != 0 goto l_scalar%=;"
"*(u64 *)(r10 - 8) = r6;"
"goto l_merge%=;"
"l_scalar%=:"
"r1 = 42;"
"*(u64 *)(r10 - 8) = r1;"
"l_merge%=:"
"r1 = 99;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = r10;"
"r1 += -8;"
"r2 = r10;"
"r2 += -16;"
"call mid_seq_touch;"
"r0 = 0;"
"exit;"
"l_exit%=:"
"r0 = 0;"
"exit;"
:
: __imm(bpf_map_lookup_elem),
__imm(bpf_get_prandom_u32),
__imm_addr(map)
: __clobber_all);
}
static __used __naked void mid_seq_touch(void)
{
asm volatile (
"r6 = r1;"
"r0 = *(u64 *)(r2 + 0);"
"call nop_callee;"
"r1 = r6;"
"call deref_ancestor;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void nop_callee(void)
{
asm volatile (
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void deref_ancestor(void)
{
asm volatile (
"r0 = *(u64 *)(r1 + 0);"
"r0 = *(u64 *)(r0 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__flag(BPF_F_TEST_STATE_FREQ)
__success
__naked void spilled_fp_cross_frame_deref(void)
{
asm volatile (
"r1 = %[map] ll;"
"*(u32 *)(r10 - 32) = 0;"
"r2 = r10;"
"r2 += -32;"
"call %[bpf_map_lookup_elem];"
"if r0 == 0 goto l_exit%=;"
"*(u64 *)(r10 - 24) = r0;"
"r1 = r10;"
"r1 += -24;"
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r1 += -8;"
"call mid_fwd_spilled_ptr;"
"r0 = 0;"
"exit;"
"l_exit%=:"
"r0 = 0;"
"exit;"
:
: __imm(bpf_map_lookup_elem),
__imm_addr(map)
: __clobber_all);
}
static __used __naked void mid_fwd_spilled_ptr(void)
{
asm volatile (
"call load_ptr_deref_grandchild;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void load_ptr_deref_grandchild(void)
{
asm volatile (
"r2 = *(u64 *)(r1 + 0);"
"r0 = *(u64 *)(r2 + 0);"
"r0 = *(u64 *)(r0 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("14: (85) call pc+2 r1: fp0-16")
__msg("17: (79) r0 = *(u64 *)(r1 +0) // r1=fp0-16")
__msg("14: (85) call pc+2 r1: fp0-8")
__msg("17: (79) r0 = *(u64 *)(r1 +0) // r1=fp0-8")
__msg("5: (85) call pc+{{.*}} ; use: fp0-8 fp0-16")
__naked void test_merge_nonlocal_live(void)
{
asm volatile (
"r1 = 0;"
"*(u64 *)(r10 - 8) = r1;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = r10;"
"r1 += -8;"
"call merge_wrapper_a;"
"r1 = r10;"
"r1 += -16;"
"call merge_wrapper_b;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void merge_wrapper_a(void)
{
asm volatile (
"call merge_shared_mid;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void merge_wrapper_b(void)
{
asm volatile (
"call merge_shared_mid;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void merge_shared_mid(void)
{
asm volatile (
"call merge_leaf_read;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void merge_leaf_read(void)
{
asm volatile (
"r0 = *(u64 *)(r1 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("call bpf_loop#181 ; use: fp2-8..-512 fp1-8..-512 fp0-8..-512")
__naked void bpf_loop_two_callbacks(void)
{
asm volatile (
"r1 = 0;"
"*(u64 *)(r10 - 8) = r1;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = r10;"
"r1 += -8;"
"call dyn_wrapper_a;"
"r1 = r10;"
"r1 += -16;"
"call dyn_wrapper_b;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void dyn_wrapper_a(void)
{
asm volatile (
"call mid_dynamic_cb;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void dyn_wrapper_b(void)
{
asm volatile (
"call mid_dynamic_cb;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void mid_dynamic_cb(void)
{
asm volatile (
"r6 = r1;"
"call %[bpf_get_prandom_u32];"
"if r0 == 0 goto 1f;"
"r2 = dyn_cb_a ll;"
"goto 2f;"
"1:"
"r2 = dyn_cb_b ll;"
"2:"
"r1 = 1;"
"r3 = r6;"
"r4 = 0;"
"call %[bpf_loop];"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32),
__imm(bpf_loop)
: __clobber_all);
}
static __used __naked void dyn_cb_a(void)
{
asm volatile (
"r0 = *(u64 *)(r2 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void dyn_cb_b(void)
{
asm volatile (
"r0 = *(u64 *)(r2 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__msg("10: (79) r0 = *(u64 *)(r10 -8) // r0=fp0-8|fp0+0")
__naked void stack_or_non_stack_write(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"r2 = r10;"
"r2 += -4;"
"r1 = %[map] ll;"
"call %[bpf_map_lookup_elem];"
"if r0 != 0 goto 1f;"
"r0 = r10;"
"r0 += -8;"
"1:"
"*(u64 *)(r0 + 0) = 7;"
"r0 = *(u64 *)(r10 - 8);"
"exit;"
:
: __imm(bpf_map_lookup_elem),
__imm_addr(map)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__flag(BPF_F_TEST_STATE_FREQ)
__msg("subprog#2 write_first_read_second:")
__msg("17: (7a) *(u64 *)(r1 +0) = 42{{$}}")
__msg("18: (79) r0 = *(u64 *)(r2 +0) // r1=fp0-8 r2=fp0-16{{$}}")
__msg("stack use/def subprog#2 write_first_read_second (d2,cs15):")
__msg("17: (7a) *(u64 *)(r1 +0) = 42{{$}}")
__msg("18: (79) r0 = *(u64 *)(r2 +0) ; use: fp0-8 fp0-16")
__naked void shared_instance_must_write_overwrite(void)
{
asm volatile (
"r1 = 1;"
"*(u64 *)(r10 - 8) = r1;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = r10;"
"r1 += -8;"
"r2 = r10;"
"r2 += -16;"
"call forwarding_rw;"
"r1 = r10;"
"r1 += -16;"
"r2 = r10;"
"r2 += -8;"
"call forwarding_rw;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
static __used __naked void forwarding_rw(void)
{
asm volatile (
"call write_first_read_second;"
"exit;"
::: __clobber_all);
}
static __used __naked void write_first_read_second(void)
{
asm volatile (
"*(u64 *)(r1 + 0) = 42;"
"r0 = *(u64 *)(r2 + 0);"
"exit;"
::: __clobber_all);
}
SEC("socket")
__success
__naked void stale_must_write_cross_callsite(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"*(u32 *)(r10 - 16) = 0;"
"r1 = %[map] ll;"
"r2 = r10;"
"r2 += -16;"
"call %[bpf_map_lookup_elem];"
"if r0 == 0 goto 1f;"
"r1 = r0;"
"r2 = r10;"
"r2 += -8;"
"call fwd_to_stale_wr;"
"r1 = r10;"
"r1 += -8;"
"r2 = r1;"
"call fwd_to_stale_wr;"
"1:"
"r0 = 0;"
"exit;"
:: __imm_addr(map),
__imm(bpf_map_lookup_elem)
: __clobber_all);
}
static __used __naked void fwd_to_stale_wr(void)
{
asm volatile (
"call stale_wr_leaf;"
"exit;"
::: __clobber_all);
}
static __used __naked void stale_wr_leaf(void)
{
asm volatile (
"*(u64 *)(r1 + 0) = 42;"
"r0 = *(u64 *)(r2 + 0);"
"exit;"
::: __clobber_all);
}
#ifdef CAN_USE_LOAD_ACQ_STORE_REL
SEC("socket")
__log_level(2)
__success
__msg("*(u64 *)(r0 +0) = 42 ; def: fp0-16")
__naked void load_acquire_dont_clear_dst(void)
{
asm volatile (
"r0 = r10;"
"r0 += -16;"
"*(u64 *)(r0 + 0) = r0;"
".8byte %[load_acquire_insn];"
"r0 = *(u64 *)(r10 - 16);"
"*(u64 *)(r0 + 0) = 42;"
"r0 = 0;"
"exit;"
:
: __imm_insn(load_acquire_insn,
BPF_ATOMIC_OP(BPF_DW, BPF_LOAD_ACQ, BPF_REG_0, BPF_REG_0, 0))
: __clobber_all);
}
#endif
SEC("socket")
__success
__naked void imprecise_fill_loses_cross_frame(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = 0;"
"r1 = r10;"
"r1 += -8;"
"call imprecise_fill_cross_frame;"
"exit;"
::: __clobber_all);
}
static __used __naked void imprecise_fill_cross_frame(void)
{
asm volatile (
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r2 = -8;"
"r1 += r2;"
"r1 = *(u64 *)(r1 + 0);"
"r0 = *(u64 *)(r1 + 0);"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("20: (79) r0 = *(u64 *)(r10 -16)")
__msg("21: (79) r0 = *(u64 *)(r0 +0) ; use: fp0-24 fp0-32")
__naked void spill_join_with_multi_off(void)
{
asm volatile (
"*(u64 *)(r10 - 24) = 0;"
"*(u64 *)(r10 - 32) = 0;"
"r1 = r10;"
"r1 += -24;"
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r1 += -32;"
"*(u64 *)(r10 - 16) = r1;"
"call %[bpf_get_prandom_u32];"
"if r0 == 0 goto 1f;"
"r1 = r10;"
"r1 += -8;"
"goto 2f;"
"1:"
"r1 = r10;"
"r1 += -16;"
"2:"
"r2 = r10;"
"r2 += -24;"
"*(u64 *)(r1 + 0) = r2;"
"r0 = *(u64 *)(r10 - 8);"
"r0 = *(u64 *)(r0 + 0);"
"r0 = *(u64 *)(r10 - 16);"
"r0 = *(u64 *)(r0 + 0);"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("15: (79) r0 = *(u64 *)(r0 +0) ; use: fp0-24 fp0-32")
__naked void spill_join_with_imprecise_off(void)
{
asm volatile (
"*(u64 *)(r10 - 24) = 0;"
"*(u64 *)(r10 - 32) = 0;"
"r1 = r10;"
"r1 += -24;"
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r1 += -32;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = r10;"
"r2 = -8;"
"r1 += r2;"
"r3 = r10;"
"r3 += -24;"
"*(u64 *)(r1 + 0) = r3;"
"r0 = *(u64 *)(r10 - 16);"
"r0 = *(u64 *)(r0 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__failure
__msg("15: (7a) *(u64 *)(r1 +0) = 0 fp-8: fp0-24 -> fp0-24|fp0+0 fp-16: fp0-32 -> fp0-32|fp0+0")
__msg("17: (79) r0 = *(u64 *)(r0 +0) ; use: fp0-32")
__naked void st_imm_join_with_multi_off(void)
{
asm volatile (
"*(u64 *)(r10 - 24) = 0;"
"*(u64 *)(r10 - 32) = 0;"
"r1 = r10;"
"r1 += -24;"
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r1 += -32;"
"*(u64 *)(r10 - 16) = r1;"
"call %[bpf_get_prandom_u32];"
"if r0 == 0 goto 1f;"
"r1 = r10;"
"r1 += -8;"
"goto 2f;"
"1:"
"r1 = r10;"
"r1 += -16;"
"2:"
"*(u64 *)(r1 + 0) = 0;"
"r0 = *(u64 *)(r10 - 16);"
"r0 = *(u64 *)(r0 + 0);"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("5: (7a) *(u64 *)(r1 +0) = 0 fp-8: fp0-16 -> _{{$}}")
__naked void st_imm_join_with_single_off(void)
{
asm volatile (
"r2 = r10;"
"r2 += -16;"
"*(u64 *)(r10 - 8) = r2;"
"r1 = r10;"
"r1 += -8;"
"*(u64 *)(r1 + 0) = 0;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("13: (79) r0 = *(u64 *)(r0 +0) ; use: fp0-32")
__naked void st_imm_join_with_imprecise_off(void)
{
asm volatile (
"*(u64 *)(r10 - 24) = 0;"
"*(u64 *)(r10 - 32) = 0;"
"r1 = r10;"
"r1 += -24;"
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r1 += -32;"
"*(u64 *)(r10 - 16) = r1;"
"r1 = r10;"
"r2 = -8;"
"r1 += r2;"
"*(u64 *)(r1 + 0) = 0;"
"r0 = *(u64 *)(r10 - 16);"
"r0 = *(u64 *)(r0 + 0);"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
SEC("socket")
__log_level(2)
__success
__msg("26: (79) r0 = *(u64 *)(r10 -8) // r1=IMP3 r6=fp0-24 r7=fp1-16 fp-8=fp1-16|fp1+0")
__naked void imprecise_dst_spill_join(void)
{
asm volatile (
"*(u64 *)(r10 - 24) = 0;"
"*(u32 *)(r10 - 32) = 0;"
"r1 = %[map] ll;"
"r2 = r10;"
"r2 += -32;"
"call %[bpf_map_lookup_elem];"
"if r0 == 0 goto 1f;"
"r1 = r10;"
"r1 += -24;"
"r2 = r0;"
"call imprecise_dst_spill_join_sub;"
"1:"
"r0 = 0;"
"exit;"
:: __imm_addr(map),
__imm(bpf_map_lookup_elem)
: __clobber_all);
}
static __used __naked void imprecise_dst_spill_join_sub(void)
{
asm volatile (
"r6 = r1;"
"r8 = r2;"
"*(u64 *)(r10 - 16) = 0;"
"r7 = r10;"
"r7 += -16;"
"*(u64 *)(r10 - 8) = r7;"
"call %[bpf_get_prandom_u32];"
"r1 = r6;"
"if r0 == 0 goto 1f;"
"r1 = r10;"
"r1 += -8;"
"1:"
"*(u64 *)(r1 + 0) = r8;"
"r0 = *(u64 *)(r10 - 8);"
"*(u64 *)(r0 + 0) = 42;"
"r0 = 0;"
"exit;"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}