1// SPDX-License-Identifier: GPL-2.0 2/* Converted from tools/testing/selftests/bpf/verifier/lwt.c */ 3 4#include <linux/bpf.h> 5#include <bpf/bpf_helpers.h> 6#include "bpf_misc.h" 7 8SEC("lwt_in") 9__description("invalid direct packet write for LWT_IN") 10__failure __msg("cannot write into packet") 11__naked void packet_write_for_lwt_in(void) 12{ 13 asm volatile (" \ 14 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 15 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 16 r0 = r2; \ 17 r0 += 8; \ 18 if r0 > r3 goto l0_%=; \ 19 *(u8*)(r2 + 0) = r2; \ 20l0_%=: r0 = 0; \ 21 exit; \ 22" : 23 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 24 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 25 : __clobber_all); 26} 27 28SEC("lwt_out") 29__description("invalid direct packet write for LWT_OUT") 30__failure __msg("cannot write into packet") 31__naked void packet_write_for_lwt_out(void) 32{ 33 asm volatile (" \ 34 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 35 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 36 r0 = r2; \ 37 r0 += 8; \ 38 if r0 > r3 goto l0_%=; \ 39 *(u8*)(r2 + 0) = r2; \ 40l0_%=: r0 = 0; \ 41 exit; \ 42" : 43 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 44 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 45 : __clobber_all); 46} 47 48SEC("lwt_xmit") 49__description("direct packet write for LWT_XMIT") 50__success __retval(0) 51__naked void packet_write_for_lwt_xmit(void) 52{ 53 asm volatile (" \ 54 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 55 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 56 r0 = r2; \ 57 r0 += 8; \ 58 if r0 > r3 goto l0_%=; \ 59 *(u8*)(r2 + 0) = r2; \ 60l0_%=: r0 = 0; \ 61 exit; \ 62" : 63 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 64 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 65 : __clobber_all); 66} 67 68SEC("lwt_in") 69__description("direct packet read for LWT_IN") 70__success __retval(0) 71__naked void packet_read_for_lwt_in(void) 72{ 73 asm volatile (" \ 74 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 75 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 76 r0 = r2; \ 77 r0 += 8; \ 78 if r0 > r3 goto l0_%=; \ 79 r0 = *(u8*)(r2 + 0); \ 80l0_%=: r0 = 0; \ 81 exit; \ 82" : 83 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 84 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 85 : __clobber_all); 86} 87 88SEC("lwt_out") 89__description("direct packet read for LWT_OUT") 90__success __retval(0) 91__naked void packet_read_for_lwt_out(void) 92{ 93 asm volatile (" \ 94 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 95 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 96 r0 = r2; \ 97 r0 += 8; \ 98 if r0 > r3 goto l0_%=; \ 99 r0 = *(u8*)(r2 + 0); \ 100l0_%=: r0 = 0; \ 101 exit; \ 102" : 103 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 104 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 105 : __clobber_all); 106} 107 108SEC("lwt_xmit") 109__description("direct packet read for LWT_XMIT") 110__success __retval(0) 111__naked void packet_read_for_lwt_xmit(void) 112{ 113 asm volatile (" \ 114 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 115 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 116 r0 = r2; \ 117 r0 += 8; \ 118 if r0 > r3 goto l0_%=; \ 119 r0 = *(u8*)(r2 + 0); \ 120l0_%=: r0 = 0; \ 121 exit; \ 122" : 123 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 124 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 125 : __clobber_all); 126} 127 128SEC("lwt_xmit") 129__description("overlapping checks for direct packet access") 130__success __retval(0) 131__naked void checks_for_direct_packet_access(void) 132{ 133 asm volatile (" \ 134 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 135 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 136 r0 = r2; \ 137 r0 += 8; \ 138 if r0 > r3 goto l0_%=; \ 139 r1 = r2; \ 140 r1 += 6; \ 141 if r1 > r3 goto l0_%=; \ 142 r0 = *(u16*)(r2 + 6); \ 143l0_%=: r0 = 0; \ 144 exit; \ 145" : 146 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 147 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 148 : __clobber_all); 149} 150 151SEC("lwt_xmit") 152__description("make headroom for LWT_XMIT") 153__success __retval(0) 154__naked void make_headroom_for_lwt_xmit(void) 155{ 156 asm volatile (" \ 157 r6 = r1; \ 158 r2 = 34; \ 159 r3 = 0; \ 160 call %[bpf_skb_change_head]; \ 161 /* split for s390 to succeed */ \ 162 r1 = r6; \ 163 r2 = 42; \ 164 r3 = 0; \ 165 call %[bpf_skb_change_head]; \ 166 r0 = 0; \ 167 exit; \ 168" : 169 : __imm(bpf_skb_change_head) 170 : __clobber_all); 171} 172 173SEC("socket") 174__description("invalid access of tc_classid for LWT_IN") 175__failure __msg("invalid bpf_context access") 176__failure_unpriv 177__naked void tc_classid_for_lwt_in(void) 178{ 179 asm volatile (" \ 180 r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \ 181 exit; \ 182" : 183 : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid)) 184 : __clobber_all); 185} 186 187SEC("socket") 188__description("invalid access of tc_classid for LWT_OUT") 189__failure __msg("invalid bpf_context access") 190__failure_unpriv 191__naked void tc_classid_for_lwt_out(void) 192{ 193 asm volatile (" \ 194 r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \ 195 exit; \ 196" : 197 : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid)) 198 : __clobber_all); 199} 200 201SEC("socket") 202__description("invalid access of tc_classid for LWT_XMIT") 203__failure __msg("invalid bpf_context access") 204__failure_unpriv 205__naked void tc_classid_for_lwt_xmit(void) 206{ 207 asm volatile (" \ 208 r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]); \ 209 exit; \ 210" : 211 : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid)) 212 : __clobber_all); 213} 214 215SEC("lwt_in") 216__description("check skb->tc_classid half load not permitted for lwt prog") 217__failure __msg("invalid bpf_context access") 218__naked void not_permitted_for_lwt_prog(void) 219{ 220 asm volatile ( 221 "r0 = 0;" 222#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 223 "r0 = *(u16*)(r1 + %[__sk_buff_tc_classid]);" 224#else 225 "r0 = *(u16*)(r1 + %[__imm_0]);" 226#endif 227 "exit;" 228 : 229 : __imm_const(__imm_0, offsetof(struct __sk_buff, tc_classid) + 2), 230 __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid)) 231 : __clobber_all); 232} 233 234char _license[] SEC("license") = "GPL"; 235