root/tools/testing/selftests/bpf/progs/verifier_ringbuf.c
// SPDX-License-Identifier: GPL-2.0
/* Converted from tools/testing/selftests/bpf/verifier/ringbuf.c */

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include "bpf_misc.h"

struct {
        __uint(type, BPF_MAP_TYPE_RINGBUF);
        __uint(max_entries, 4096);
} map_ringbuf SEC(".maps");

SEC("socket")
__description("ringbuf: invalid reservation offset 1")
__failure __msg("R1 must have zero offset when passed to release func")
__failure_unpriv
__naked void ringbuf_invalid_reservation_offset_1(void)
{
        asm volatile ("                                 \
        /* reserve 8 byte ringbuf memory */             \
        r1 = 0;                                         \
        *(u64*)(r10 - 8) = r1;                          \
        r1 = %[map_ringbuf] ll;                         \
        r2 = 8;                                         \
        r3 = 0;                                         \
        call %[bpf_ringbuf_reserve];                    \
        /* store a pointer to the reserved memory in R6 */\
        r6 = r0;                                        \
        /* check whether the reservation was successful */\
        if r0 == 0 goto l0_%=;                          \
        /* spill R6(mem) into the stack */              \
        *(u64*)(r10 - 8) = r6;                          \
        /* fill it back in R7 */                        \
        r7 = *(u64*)(r10 - 8);                          \
        /* should be able to access *(R7) = 0 */        \
        r1 = 0;                                         \
        *(u64*)(r7 + 0) = r1;                           \
        /* submit the reserved ringbuf memory */        \
        r1 = r7;                                        \
        /* add invalid offset to reserved ringbuf memory */\
        r1 += 0xcafe;                                   \
        r2 = 0;                                         \
        call %[bpf_ringbuf_submit];                     \
l0_%=:  r0 = 0;                                         \
        exit;                                           \
"       :
        : __imm(bpf_ringbuf_reserve),
          __imm(bpf_ringbuf_submit),
          __imm_addr(map_ringbuf)
        : __clobber_all);
}

SEC("socket")
__description("ringbuf: invalid reservation offset 2")
__failure __msg("R7 min value is outside of the allowed memory range")
__failure_unpriv
__naked void ringbuf_invalid_reservation_offset_2(void)
{
        asm volatile ("                                 \
        /* reserve 8 byte ringbuf memory */             \
        r1 = 0;                                         \
        *(u64*)(r10 - 8) = r1;                          \
        r1 = %[map_ringbuf] ll;                         \
        r2 = 8;                                         \
        r3 = 0;                                         \
        call %[bpf_ringbuf_reserve];                    \
        /* store a pointer to the reserved memory in R6 */\
        r6 = r0;                                        \
        /* check whether the reservation was successful */\
        if r0 == 0 goto l0_%=;                          \
        /* spill R6(mem) into the stack */              \
        *(u64*)(r10 - 8) = r6;                          \
        /* fill it back in R7 */                        \
        r7 = *(u64*)(r10 - 8);                          \
        /* add invalid offset to reserved ringbuf memory */\
        r7 += 0xcafe;                                   \
        /* should be able to access *(R7) = 0 */        \
        r1 = 0;                                         \
        *(u64*)(r7 + 0) = r1;                           \
        /* submit the reserved ringbuf memory */        \
        r1 = r7;                                        \
        r2 = 0;                                         \
        call %[bpf_ringbuf_submit];                     \
l0_%=:  r0 = 0;                                         \
        exit;                                           \
"       :
        : __imm(bpf_ringbuf_reserve),
          __imm(bpf_ringbuf_submit),
          __imm_addr(map_ringbuf)
        : __clobber_all);
}

SEC("xdp")
__description("ringbuf: check passing rb mem to helpers")
__success __retval(0)
__naked void passing_rb_mem_to_helpers(void)
{
        asm volatile ("                                 \
        r6 = r1;                                        \
        /* reserve 8 byte ringbuf memory */             \
        r1 = 0;                                         \
        *(u64*)(r10 - 8) = r1;                          \
        r1 = %[map_ringbuf] ll;                         \
        r2 = 8;                                         \
        r3 = 0;                                         \
        call %[bpf_ringbuf_reserve];                    \
        r7 = r0;                                        \
        /* check whether the reservation was successful */\
        if r0 != 0 goto l0_%=;                          \
        exit;                                           \
l0_%=:  /* pass allocated ring buffer memory to fib lookup */\
        r1 = r6;                                        \
        r2 = r0;                                        \
        r3 = 8;                                         \
        r4 = 0;                                         \
        call %[bpf_fib_lookup];                         \
        /* submit the ringbuf memory */                 \
        r1 = r7;                                        \
        r2 = 0;                                         \
        call %[bpf_ringbuf_submit];                     \
        r0 = 0;                                         \
        exit;                                           \
"       :
        : __imm(bpf_fib_lookup),
          __imm(bpf_ringbuf_reserve),
          __imm(bpf_ringbuf_submit),
          __imm_addr(map_ringbuf)
        : __clobber_all);
}

char _license[] SEC("license") = "GPL";