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