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 11 SEC("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 25 SEC("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 39 SEC("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 53 SEC("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 71 SEC("netfilter") 72 __description("netfilter valid context read and invalid write") 73 __failure __msg("only read is supported") 74 int 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 82 SEC("netfilter") 83 __description("netfilter test prog with skb and state read access") 84 __success __failure_unpriv 85 __retval(0) 86 int with_valid_ctx_access_test6(struct bpf_nf_ctx *ctx) 87 { 88 struct __sk_buff *skb = (struct __sk_buff *)ctx->skb; 89 const struct nf_hook_state *state = ctx->state; 90 const struct iphdr *iph; 91 const struct tcphdr *th; 92 u8 buffer_iph[20] = {}; 93 u8 buffer_th[40] = {}; 94 struct bpf_dynptr ptr; 95 uint8_t ihl; 96 97 if (ctx->skb->len <= 20 || bpf_dynptr_from_skb(skb, 0, &ptr)) 98 return NF_ACCEPT; 99 100 iph = bpf_dynptr_slice(&ptr, 0, buffer_iph, sizeof(buffer_iph)); 101 if (!iph) 102 return NF_ACCEPT; 103 104 if (state->pf != 2) 105 return NF_ACCEPT; 106 107 ihl = iph->ihl << 2; 108 109 th = bpf_dynptr_slice(&ptr, ihl, buffer_th, sizeof(buffer_th)); 110 if (!th) 111 return NF_ACCEPT; 112 113 return th->dest == bpf_htons(22) ? NF_ACCEPT : NF_DROP; 114 } 115 116 char _license[] SEC("license") = "GPL"; 117