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 extern int bpf_dynptr_from_skb(struct sk_buff *skb, __u64 flags, 83 struct bpf_dynptr *ptr__uninit) __ksym; 84 extern void *bpf_dynptr_slice(const struct bpf_dynptr *ptr, uint32_t offset, 85 void *buffer, uint32_t buffer__sz) __ksym; 86 87 SEC("netfilter") 88 __description("netfilter test prog with skb and state read access") 89 __success __failure_unpriv 90 __retval(0) 91 int 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 121 char _license[] SEC("license") = "GPL"; 122