361 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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_unpriv41__naked void dummy_prog_42_socket(void)42{43 asm volatile ("r0 = 42; exit;");44}45 46SEC("socket")47__auxiliary __auxiliary_unpriv48__naked void dummy_prog_24_socket(void)49{50 asm volatile ("r0 = 24; exit;");51}52 53SEC("socket")54__auxiliary __auxiliary_unpriv55__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_unpriv71__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