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