1// SPDX-License-Identifier: GPL-2.0 2 3#include "vmlinux.h" 4 5#include "bpf_misc.h" 6 7#include <bpf/bpf_endian.h> 8#include <bpf/bpf_tracing.h> 9#include <bpf/bpf_helpers.h> 10 11SEC("netfilter") 12__description("netfilter invalid context access, size too short") 13__failure __msg("invalid bpf_context access") 14__naked void with_invalid_ctx_access_test1(void) 15{ 16 asm volatile (" \ 17 r2 = *(u8*)(r1 + %[__bpf_nf_ctx_state]); \ 18 r0 = 0; \ 19 exit; \ 20" : 21 : __imm_const(__bpf_nf_ctx_state, offsetof(struct bpf_nf_ctx, state)) 22 : __clobber_all); 23} 24 25SEC("netfilter") 26__description("netfilter invalid context access, size too short") 27__failure __msg("invalid bpf_context access") 28__naked void with_invalid_ctx_access_test2(void) 29{ 30 asm volatile (" \ 31 r2 = *(u16*)(r1 + %[__bpf_nf_ctx_skb]); \ 32 r0 = 0; \ 33 exit; \ 34" : 35 : __imm_const(__bpf_nf_ctx_skb, offsetof(struct bpf_nf_ctx, skb)) 36 : __clobber_all); 37} 38 39SEC("netfilter") 40__description("netfilter invalid context access, past end of ctx") 41__failure __msg("invalid bpf_context access") 42__naked void with_invalid_ctx_access_test3(void) 43{ 44 asm volatile (" \ 45 r2 = *(u64*)(r1 + %[__bpf_nf_ctx_size]); \ 46 r0 = 0; \ 47 exit; \ 48" : 49 : __imm_const(__bpf_nf_ctx_size, sizeof(struct bpf_nf_ctx)) 50 : __clobber_all); 51} 52 53SEC("netfilter") 54__description("netfilter invalid context, write") 55__failure __msg("invalid bpf_context access") 56__naked void with_invalid_ctx_access_test4(void) 57{ 58 asm volatile (" \ 59 r2 = r1; \ 60 *(u64*)(r2 + 0) = r1; \ 61 r0 = 1; \ 62 exit; \ 63" : 64 : __imm_const(__bpf_nf_ctx_skb, offsetof(struct bpf_nf_ctx, skb)) 65 : __clobber_all); 66} 67 68#define NF_DROP 0 69#define NF_ACCEPT 1 70 71SEC("netfilter") 72__description("netfilter valid context read and invalid write") 73__failure __msg("only read is supported") 74int with_invalid_ctx_access_test5(struct bpf_nf_ctx *ctx) 75{ 76 struct nf_hook_state *state = (void *)ctx->state; 77 78 state->sk = NULL; 79 return NF_ACCEPT; 80} 81 82extern int bpf_dynptr_from_skb(struct sk_buff *skb, __u64 flags, 83 struct bpf_dynptr *ptr__uninit) __ksym; 84extern void *bpf_dynptr_slice(const struct bpf_dynptr *ptr, uint32_t offset, 85 void *buffer, uint32_t buffer__sz) __ksym; 86 87SEC("netfilter") 88__description("netfilter test prog with skb and state read access") 89__success __failure_unpriv 90__retval(0) 91int with_valid_ctx_access_test6(struct bpf_nf_ctx *ctx) 92{ 93 const struct nf_hook_state *state = ctx->state; 94 struct sk_buff *skb = ctx->skb; 95 const struct iphdr *iph; 96 const struct tcphdr *th; 97 u8 buffer_iph[20] = {}; 98 u8 buffer_th[40] = {}; 99 struct bpf_dynptr ptr; 100 uint8_t ihl; 101 102 if (skb->len <= 20 || bpf_dynptr_from_skb(skb, 0, &ptr)) 103 return NF_ACCEPT; 104 105 iph = bpf_dynptr_slice(&ptr, 0, buffer_iph, sizeof(buffer_iph)); 106 if (!iph) 107 return NF_ACCEPT; 108 109 if (state->pf != 2) 110 return NF_ACCEPT; 111 112 ihl = iph->ihl << 2; 113 114 th = bpf_dynptr_slice(&ptr, ihl, buffer_th, sizeof(buffer_th)); 115 if (!th) 116 return NF_ACCEPT; 117 118 return th->dest == bpf_htons(22) ? NF_ACCEPT : NF_DROP; 119} 120 121char _license[] SEC("license") = "GPL"; 122