1// SPDX-License-Identifier: GPL-2.0 2/* Converted from tools/testing/selftests/bpf/verifier/runtime_jit.c */ 3 4#include <linux/bpf.h> 5#include <bpf/bpf_helpers.h> 6#include "bpf_misc.h" 7 8void dummy_prog_42_socket(void); 9void dummy_prog_24_socket(void); 10void dummy_prog_loop1_socket(void); 11void dummy_prog_loop2_socket(void); 12 13struct { 14 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 15 __uint(max_entries, 4); 16 __uint(key_size, sizeof(int)); 17 __array(values, void (void)); 18} map_prog1_socket SEC(".maps") = { 19 .values = { 20 [0] = (void *)&dummy_prog_42_socket, 21 [1] = (void *)&dummy_prog_loop1_socket, 22 [2] = (void *)&dummy_prog_24_socket, 23 }, 24}; 25 26struct { 27 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 28 __uint(max_entries, 8); 29 __uint(key_size, sizeof(int)); 30 __array(values, void (void)); 31} map_prog2_socket SEC(".maps") = { 32 .values = { 33 [1] = (void *)&dummy_prog_loop2_socket, 34 [2] = (void *)&dummy_prog_24_socket, 35 [7] = (void *)&dummy_prog_42_socket, 36 }, 37}; 38 39SEC("socket") 40__auxiliary __auxiliary_unpriv 41__naked void dummy_prog_42_socket(void) 42{ 43 asm volatile ("r0 = 42; exit;"); 44} 45 46SEC("socket") 47__auxiliary __auxiliary_unpriv 48__naked void dummy_prog_24_socket(void) 49{ 50 asm volatile ("r0 = 24; exit;"); 51} 52 53SEC("socket") 54__auxiliary __auxiliary_unpriv 55__naked void dummy_prog_loop1_socket(void) 56{ 57 asm volatile (" \ 58 r3 = 1; \ 59 r2 = %[map_prog1_socket] ll; \ 60 call %[bpf_tail_call]; \ 61 r0 = 41; \ 62 exit; \ 63" : 64 : __imm(bpf_tail_call), 65 __imm_addr(map_prog1_socket) 66 : __clobber_all); 67} 68 69SEC("socket") 70__auxiliary __auxiliary_unpriv 71__naked void dummy_prog_loop2_socket(void) 72{ 73 asm volatile (" \ 74 r3 = 1; \ 75 r2 = %[map_prog2_socket] ll; \ 76 call %[bpf_tail_call]; \ 77 r0 = 41; \ 78 exit; \ 79" : 80 : __imm(bpf_tail_call), 81 __imm_addr(map_prog2_socket) 82 : __clobber_all); 83} 84 85SEC("socket") 86__description("runtime/jit: tail_call within bounds, prog once") 87__success __success_unpriv __retval(42) 88__naked void call_within_bounds_prog_once(void) 89{ 90 asm volatile (" \ 91 r3 = 0; \ 92 r2 = %[map_prog1_socket] ll; \ 93 call %[bpf_tail_call]; \ 94 r0 = 1; \ 95 exit; \ 96" : 97 : __imm(bpf_tail_call), 98 __imm_addr(map_prog1_socket) 99 : __clobber_all); 100} 101 102SEC("socket") 103__description("runtime/jit: tail_call within bounds, prog loop") 104__success __success_unpriv __retval(41) 105__naked void call_within_bounds_prog_loop(void) 106{ 107 asm volatile (" \ 108 r3 = 1; \ 109 r2 = %[map_prog1_socket] ll; \ 110 call %[bpf_tail_call]; \ 111 r0 = 1; \ 112 exit; \ 113" : 114 : __imm(bpf_tail_call), 115 __imm_addr(map_prog1_socket) 116 : __clobber_all); 117} 118 119SEC("socket") 120__description("runtime/jit: tail_call within bounds, no prog") 121__success __success_unpriv __retval(1) 122__naked void call_within_bounds_no_prog(void) 123{ 124 asm volatile (" \ 125 r3 = 3; \ 126 r2 = %[map_prog1_socket] ll; \ 127 call %[bpf_tail_call]; \ 128 r0 = 1; \ 129 exit; \ 130" : 131 : __imm(bpf_tail_call), 132 __imm_addr(map_prog1_socket) 133 : __clobber_all); 134} 135 136SEC("socket") 137__description("runtime/jit: tail_call within bounds, key 2") 138__success __success_unpriv __retval(24) 139__naked void call_within_bounds_key_2(void) 140{ 141 asm volatile (" \ 142 r3 = 2; \ 143 r2 = %[map_prog1_socket] ll; \ 144 call %[bpf_tail_call]; \ 145 r0 = 1; \ 146 exit; \ 147" : 148 : __imm(bpf_tail_call), 149 __imm_addr(map_prog1_socket) 150 : __clobber_all); 151} 152 153SEC("socket") 154__description("runtime/jit: tail_call within bounds, key 2 / key 2, first branch") 155__success __success_unpriv __retval(24) 156__naked void _2_key_2_first_branch(void) 157{ 158 asm volatile (" \ 159 r0 = 13; \ 160 *(u8*)(r1 + %[__sk_buff_cb_0]) = r0; \ 161 r0 = *(u8*)(r1 + %[__sk_buff_cb_0]); \ 162 if r0 == 13 goto l0_%=; \ 163 r3 = 2; \ 164 r2 = %[map_prog1_socket] ll; \ 165 goto l1_%=; \ 166l0_%=: r3 = 2; \ 167 r2 = %[map_prog1_socket] ll; \ 168l1_%=: call %[bpf_tail_call]; \ 169 r0 = 1; \ 170 exit; \ 171" : 172 : __imm(bpf_tail_call), 173 __imm_addr(map_prog1_socket), 174 __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 175 : __clobber_all); 176} 177 178SEC("socket") 179__description("runtime/jit: tail_call within bounds, key 2 / key 2, second branch") 180__success __success_unpriv __retval(24) 181__naked void _2_key_2_second_branch(void) 182{ 183 asm volatile (" \ 184 r0 = 14; \ 185 *(u8*)(r1 + %[__sk_buff_cb_0]) = r0; \ 186 r0 = *(u8*)(r1 + %[__sk_buff_cb_0]); \ 187 if r0 == 13 goto l0_%=; \ 188 r3 = 2; \ 189 r2 = %[map_prog1_socket] ll; \ 190 goto l1_%=; \ 191l0_%=: r3 = 2; \ 192 r2 = %[map_prog1_socket] ll; \ 193l1_%=: call %[bpf_tail_call]; \ 194 r0 = 1; \ 195 exit; \ 196" : 197 : __imm(bpf_tail_call), 198 __imm_addr(map_prog1_socket), 199 __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 200 : __clobber_all); 201} 202 203SEC("socket") 204__description("runtime/jit: tail_call within bounds, key 0 / key 2, first branch") 205__success __success_unpriv __retval(24) 206__naked void _0_key_2_first_branch(void) 207{ 208 asm volatile (" \ 209 r0 = 13; \ 210 *(u8*)(r1 + %[__sk_buff_cb_0]) = r0; \ 211 r0 = *(u8*)(r1 + %[__sk_buff_cb_0]); \ 212 if r0 == 13 goto l0_%=; \ 213 r3 = 0; \ 214 r2 = %[map_prog1_socket] ll; \ 215 goto l1_%=; \ 216l0_%=: r3 = 2; \ 217 r2 = %[map_prog1_socket] ll; \ 218l1_%=: call %[bpf_tail_call]; \ 219 r0 = 1; \ 220 exit; \ 221" : 222 : __imm(bpf_tail_call), 223 __imm_addr(map_prog1_socket), 224 __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 225 : __clobber_all); 226} 227 228SEC("socket") 229__description("runtime/jit: tail_call within bounds, key 0 / key 2, second branch") 230__success __success_unpriv __retval(42) 231__naked void _0_key_2_second_branch(void) 232{ 233 asm volatile (" \ 234 r0 = 14; \ 235 *(u8*)(r1 + %[__sk_buff_cb_0]) = r0; \ 236 r0 = *(u8*)(r1 + %[__sk_buff_cb_0]); \ 237 if r0 == 13 goto l0_%=; \ 238 r3 = 0; \ 239 r2 = %[map_prog1_socket] ll; \ 240 goto l1_%=; \ 241l0_%=: r3 = 2; \ 242 r2 = %[map_prog1_socket] ll; \ 243l1_%=: call %[bpf_tail_call]; \ 244 r0 = 1; \ 245 exit; \ 246" : 247 : __imm(bpf_tail_call), 248 __imm_addr(map_prog1_socket), 249 __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 250 : __clobber_all); 251} 252 253SEC("socket") 254__description("runtime/jit: tail_call within bounds, different maps, first branch") 255__success __failure_unpriv __msg_unpriv("tail_call abusing map_ptr") 256__retval(1) 257__naked void bounds_different_maps_first_branch(void) 258{ 259 asm volatile (" \ 260 r0 = 13; \ 261 *(u8*)(r1 + %[__sk_buff_cb_0]) = r0; \ 262 r0 = *(u8*)(r1 + %[__sk_buff_cb_0]); \ 263 if r0 == 13 goto l0_%=; \ 264 r3 = 0; \ 265 r2 = %[map_prog1_socket] ll; \ 266 goto l1_%=; \ 267l0_%=: r3 = 0; \ 268 r2 = %[map_prog2_socket] ll; \ 269l1_%=: call %[bpf_tail_call]; \ 270 r0 = 1; \ 271 exit; \ 272" : 273 : __imm(bpf_tail_call), 274 __imm_addr(map_prog1_socket), 275 __imm_addr(map_prog2_socket), 276 __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 277 : __clobber_all); 278} 279 280SEC("socket") 281__description("runtime/jit: tail_call within bounds, different maps, second branch") 282__success __failure_unpriv __msg_unpriv("tail_call abusing map_ptr") 283__retval(42) 284__naked void bounds_different_maps_second_branch(void) 285{ 286 asm volatile (" \ 287 r0 = 14; \ 288 *(u8*)(r1 + %[__sk_buff_cb_0]) = r0; \ 289 r0 = *(u8*)(r1 + %[__sk_buff_cb_0]); \ 290 if r0 == 13 goto l0_%=; \ 291 r3 = 0; \ 292 r2 = %[map_prog1_socket] ll; \ 293 goto l1_%=; \ 294l0_%=: r3 = 0; \ 295 r2 = %[map_prog2_socket] ll; \ 296l1_%=: call %[bpf_tail_call]; \ 297 r0 = 1; \ 298 exit; \ 299" : 300 : __imm(bpf_tail_call), 301 __imm_addr(map_prog1_socket), 302 __imm_addr(map_prog2_socket), 303 __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 304 : __clobber_all); 305} 306 307SEC("socket") 308__description("runtime/jit: tail_call out of bounds") 309__success __success_unpriv __retval(2) 310__naked void tail_call_out_of_bounds(void) 311{ 312 asm volatile (" \ 313 r3 = 256; \ 314 r2 = %[map_prog1_socket] ll; \ 315 call %[bpf_tail_call]; \ 316 r0 = 2; \ 317 exit; \ 318" : 319 : __imm(bpf_tail_call), 320 __imm_addr(map_prog1_socket) 321 : __clobber_all); 322} 323 324SEC("socket") 325__description("runtime/jit: pass negative index to tail_call") 326__success __success_unpriv __retval(2) 327__naked void negative_index_to_tail_call(void) 328{ 329 asm volatile (" \ 330 r3 = -1; \ 331 r2 = %[map_prog1_socket] ll; \ 332 call %[bpf_tail_call]; \ 333 r0 = 2; \ 334 exit; \ 335" : 336 : __imm(bpf_tail_call), 337 __imm_addr(map_prog1_socket) 338 : __clobber_all); 339} 340 341SEC("socket") 342__description("runtime/jit: pass > 32bit index to tail_call") 343__success __success_unpriv __retval(42) 344/* Verifier rewrite for unpriv skips tail call here. */ 345__retval_unpriv(2) 346__naked void _32bit_index_to_tail_call(void) 347{ 348 asm volatile (" \ 349 r3 = 0x100000000 ll; \ 350 r2 = %[map_prog1_socket] ll; \ 351 call %[bpf_tail_call]; \ 352 r0 = 2; \ 353 exit; \ 354" : 355 : __imm(bpf_tail_call), 356 __imm_addr(map_prog1_socket) 357 : __clobber_all); 358} 359 360char _license[] SEC("license") = "GPL"; 361