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 8 SEC("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; \ 20 l0_%=: 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 28 SEC("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; \ 40 l0_%=: 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 48 SEC("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; \ 60 l0_%=: 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 68 SEC("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); \ 80 l0_%=: 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 88 SEC("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); \ 100 l0_%=: 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 108 SEC("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); \ 120 l0_%=: 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 128 SEC("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); \ 143 l0_%=: 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 151 SEC("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 173 SEC("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 187 SEC("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 201 SEC("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 215 SEC("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 234 char _license[] SEC("license") = "GPL"; 235