1*4a400ef9SEduard Zingerman // SPDX-License-Identifier: GPL-2.0
2*4a400ef9SEduard Zingerman /* Converted from tools/testing/selftests/bpf/verifier/map_in_map.c */
3*4a400ef9SEduard Zingerman 
4*4a400ef9SEduard Zingerman #include <linux/bpf.h>
5*4a400ef9SEduard Zingerman #include <bpf/bpf_helpers.h>
6*4a400ef9SEduard Zingerman #include "bpf_misc.h"
7*4a400ef9SEduard Zingerman 
8*4a400ef9SEduard Zingerman struct {
9*4a400ef9SEduard Zingerman 	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
10*4a400ef9SEduard Zingerman 	__uint(max_entries, 1);
11*4a400ef9SEduard Zingerman 	__type(key, int);
12*4a400ef9SEduard Zingerman 	__type(value, int);
13*4a400ef9SEduard Zingerman 	__array(values, struct {
14*4a400ef9SEduard Zingerman 		__uint(type, BPF_MAP_TYPE_ARRAY);
15*4a400ef9SEduard Zingerman 		__uint(max_entries, 1);
16*4a400ef9SEduard Zingerman 		__type(key, int);
17*4a400ef9SEduard Zingerman 		__type(value, int);
18*4a400ef9SEduard Zingerman 	});
19*4a400ef9SEduard Zingerman } map_in_map SEC(".maps");
20*4a400ef9SEduard Zingerman 
21*4a400ef9SEduard Zingerman SEC("socket")
22*4a400ef9SEduard Zingerman __description("map in map access")
23*4a400ef9SEduard Zingerman __success __success_unpriv __retval(0)
map_in_map_access(void)24*4a400ef9SEduard Zingerman __naked void map_in_map_access(void)
25*4a400ef9SEduard Zingerman {
26*4a400ef9SEduard Zingerman 	asm volatile ("					\
27*4a400ef9SEduard Zingerman 	r1 = 0;						\
28*4a400ef9SEduard Zingerman 	*(u32*)(r10 - 4) = r1;				\
29*4a400ef9SEduard Zingerman 	r2 = r10;					\
30*4a400ef9SEduard Zingerman 	r2 += -4;					\
31*4a400ef9SEduard Zingerman 	r1 = %[map_in_map] ll;				\
32*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
33*4a400ef9SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
34*4a400ef9SEduard Zingerman 	r1 = 0;						\
35*4a400ef9SEduard Zingerman 	*(u32*)(r10 - 4) = r1;				\
36*4a400ef9SEduard Zingerman 	r2 = r10;					\
37*4a400ef9SEduard Zingerman 	r2 += -4;					\
38*4a400ef9SEduard Zingerman 	r1 = r0;					\
39*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
40*4a400ef9SEduard Zingerman l0_%=:	r0 = 0;						\
41*4a400ef9SEduard Zingerman 	exit;						\
42*4a400ef9SEduard Zingerman "	:
43*4a400ef9SEduard Zingerman 	: __imm(bpf_map_lookup_elem),
44*4a400ef9SEduard Zingerman 	  __imm_addr(map_in_map)
45*4a400ef9SEduard Zingerman 	: __clobber_all);
46*4a400ef9SEduard Zingerman }
47*4a400ef9SEduard Zingerman 
48*4a400ef9SEduard Zingerman SEC("xdp")
49*4a400ef9SEduard Zingerman __description("map in map state pruning")
50*4a400ef9SEduard Zingerman __success __msg("processed 26 insns")
__flag(BPF_F_TEST_STATE_FREQ)51*4a400ef9SEduard Zingerman __log_level(2) __retval(0) __flag(BPF_F_TEST_STATE_FREQ)
52*4a400ef9SEduard Zingerman __naked void map_in_map_state_pruning(void)
53*4a400ef9SEduard Zingerman {
54*4a400ef9SEduard Zingerman 	asm volatile ("					\
55*4a400ef9SEduard Zingerman 	r1 = 0;						\
56*4a400ef9SEduard Zingerman 	*(u32*)(r10 - 4) = r1;				\
57*4a400ef9SEduard Zingerman 	r6 = r10;					\
58*4a400ef9SEduard Zingerman 	r6 += -4;					\
59*4a400ef9SEduard Zingerman 	r2 = r6;					\
60*4a400ef9SEduard Zingerman 	r1 = %[map_in_map] ll;				\
61*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
62*4a400ef9SEduard Zingerman 	if r0 != 0 goto l0_%=;				\
63*4a400ef9SEduard Zingerman 	exit;						\
64*4a400ef9SEduard Zingerman l0_%=:	r2 = r6;					\
65*4a400ef9SEduard Zingerman 	r1 = r0;					\
66*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
67*4a400ef9SEduard Zingerman 	if r0 != 0 goto l1_%=;				\
68*4a400ef9SEduard Zingerman 	r2 = r6;					\
69*4a400ef9SEduard Zingerman 	r1 = %[map_in_map] ll;				\
70*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
71*4a400ef9SEduard Zingerman 	if r0 != 0 goto l2_%=;				\
72*4a400ef9SEduard Zingerman 	exit;						\
73*4a400ef9SEduard Zingerman l2_%=:	r2 = r6;					\
74*4a400ef9SEduard Zingerman 	r1 = r0;					\
75*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
76*4a400ef9SEduard Zingerman 	if r0 != 0 goto l1_%=;				\
77*4a400ef9SEduard Zingerman 	exit;						\
78*4a400ef9SEduard Zingerman l1_%=:	r0 = *(u32*)(r0 + 0);				\
79*4a400ef9SEduard Zingerman 	exit;						\
80*4a400ef9SEduard Zingerman "	:
81*4a400ef9SEduard Zingerman 	: __imm(bpf_map_lookup_elem),
82*4a400ef9SEduard Zingerman 	  __imm_addr(map_in_map)
83*4a400ef9SEduard Zingerman 	: __clobber_all);
84*4a400ef9SEduard Zingerman }
85*4a400ef9SEduard Zingerman 
86*4a400ef9SEduard Zingerman SEC("socket")
87*4a400ef9SEduard Zingerman __description("invalid inner map pointer")
88*4a400ef9SEduard Zingerman __failure __msg("R1 pointer arithmetic on map_ptr prohibited")
89*4a400ef9SEduard Zingerman __failure_unpriv
invalid_inner_map_pointer(void)90*4a400ef9SEduard Zingerman __naked void invalid_inner_map_pointer(void)
91*4a400ef9SEduard Zingerman {
92*4a400ef9SEduard Zingerman 	asm volatile ("					\
93*4a400ef9SEduard Zingerman 	r1 = 0;						\
94*4a400ef9SEduard Zingerman 	*(u32*)(r10 - 4) = r1;				\
95*4a400ef9SEduard Zingerman 	r2 = r10;					\
96*4a400ef9SEduard Zingerman 	r2 += -4;					\
97*4a400ef9SEduard Zingerman 	r1 = %[map_in_map] ll;				\
98*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
99*4a400ef9SEduard Zingerman 	if r0 == 0 goto l0_%=;				\
100*4a400ef9SEduard Zingerman 	r1 = 0;						\
101*4a400ef9SEduard Zingerman 	*(u32*)(r10 - 4) = r1;				\
102*4a400ef9SEduard Zingerman 	r2 = r10;					\
103*4a400ef9SEduard Zingerman 	r2 += -4;					\
104*4a400ef9SEduard Zingerman 	r1 = r0;					\
105*4a400ef9SEduard Zingerman 	r1 += 8;					\
106*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
107*4a400ef9SEduard Zingerman l0_%=:	r0 = 0;						\
108*4a400ef9SEduard Zingerman 	exit;						\
109*4a400ef9SEduard Zingerman "	:
110*4a400ef9SEduard Zingerman 	: __imm(bpf_map_lookup_elem),
111*4a400ef9SEduard Zingerman 	  __imm_addr(map_in_map)
112*4a400ef9SEduard Zingerman 	: __clobber_all);
113*4a400ef9SEduard Zingerman }
114*4a400ef9SEduard Zingerman 
115*4a400ef9SEduard Zingerman SEC("socket")
116*4a400ef9SEduard Zingerman __description("forgot null checking on the inner map pointer")
117*4a400ef9SEduard Zingerman __failure __msg("R1 type=map_value_or_null expected=map_ptr")
118*4a400ef9SEduard Zingerman __failure_unpriv
on_the_inner_map_pointer(void)119*4a400ef9SEduard Zingerman __naked void on_the_inner_map_pointer(void)
120*4a400ef9SEduard Zingerman {
121*4a400ef9SEduard Zingerman 	asm volatile ("					\
122*4a400ef9SEduard Zingerman 	r1 = 0;						\
123*4a400ef9SEduard Zingerman 	*(u32*)(r10 - 4) = r1;				\
124*4a400ef9SEduard Zingerman 	r2 = r10;					\
125*4a400ef9SEduard Zingerman 	r2 += -4;					\
126*4a400ef9SEduard Zingerman 	r1 = %[map_in_map] ll;				\
127*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
128*4a400ef9SEduard Zingerman 	r1 = 0;						\
129*4a400ef9SEduard Zingerman 	*(u32*)(r10 - 4) = r1;				\
130*4a400ef9SEduard Zingerman 	r2 = r10;					\
131*4a400ef9SEduard Zingerman 	r2 += -4;					\
132*4a400ef9SEduard Zingerman 	r1 = r0;					\
133*4a400ef9SEduard Zingerman 	call %[bpf_map_lookup_elem];			\
134*4a400ef9SEduard Zingerman 	r0 = 0;						\
135*4a400ef9SEduard Zingerman 	exit;						\
136*4a400ef9SEduard Zingerman "	:
137*4a400ef9SEduard Zingerman 	: __imm(bpf_map_lookup_elem),
138*4a400ef9SEduard Zingerman 	  __imm_addr(map_in_map)
139*4a400ef9SEduard Zingerman 	: __clobber_all);
140*4a400ef9SEduard Zingerman }
141*4a400ef9SEduard Zingerman 
142*4a400ef9SEduard Zingerman char _license[] SEC("license") = "GPL";
143