1 {
2 	"variable-offset ctx access",
3 	.insns = {
4 	/* Get an unknown value */
5 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
6 	/* Make it small and 4-byte aligned */
7 	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
8 	/* add it to skb.  We now have either &skb->len or
9 	 * &skb->pkt_type, but we don't know which
10 	 */
11 	BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
12 	/* dereference it */
13 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
14 	BPF_EXIT_INSN(),
15 	},
16 	.errstr = "variable ctx access var_off=(0x0; 0x4)",
17 	.result = REJECT,
18 	.prog_type = BPF_PROG_TYPE_LWT_IN,
19 },
20 {
21 	"variable-offset stack access",
22 	.insns = {
23 	/* Fill the top 8 bytes of the stack */
24 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
25 	/* Get an unknown value */
26 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
27 	/* Make it small and 4-byte aligned */
28 	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
29 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
30 	/* add it to fp.  We now have either fp-4 or fp-8, but
31 	 * we don't know which
32 	 */
33 	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
34 	/* dereference it */
35 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 0),
36 	BPF_EXIT_INSN(),
37 	},
38 	.errstr = "variable stack access var_off=(0xfffffffffffffff8; 0x4)",
39 	.result = REJECT,
40 	.prog_type = BPF_PROG_TYPE_LWT_IN,
41 },
42 {
43 	"indirect variable-offset stack access, unbounded",
44 	.insns = {
45 	BPF_MOV64_IMM(BPF_REG_2, 6),
46 	BPF_MOV64_IMM(BPF_REG_3, 28),
47 	/* Fill the top 16 bytes of the stack. */
48 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
49 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
50 	/* Get an unknown value. */
51 	BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_1, offsetof(struct bpf_sock_ops,
52 							   bytes_received)),
53 	/* Check the lower bound but don't check the upper one. */
54 	BPF_JMP_IMM(BPF_JSLT, BPF_REG_4, 0, 4),
55 	/* Point the lower bound to initialized stack. Offset is now in range
56 	 * from fp-16 to fp+0x7fffffffffffffef, i.e. max value is unbounded.
57 	 */
58 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
59 	BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
60 	BPF_MOV64_IMM(BPF_REG_5, 8),
61 	/* Dereference it indirectly. */
62 	BPF_EMIT_CALL(BPF_FUNC_getsockopt),
63 	BPF_MOV64_IMM(BPF_REG_0, 0),
64 	BPF_EXIT_INSN(),
65 	},
66 	.errstr = "R4 unbounded indirect variable offset stack access",
67 	.result = REJECT,
68 	.prog_type = BPF_PROG_TYPE_SOCK_OPS,
69 },
70 {
71 	"indirect variable-offset stack access, max out of bound",
72 	.insns = {
73 	/* Fill the top 8 bytes of the stack */
74 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
75 	/* Get an unknown value */
76 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
77 	/* Make it small and 4-byte aligned */
78 	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
79 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
80 	/* add it to fp.  We now have either fp-4 or fp-8, but
81 	 * we don't know which
82 	 */
83 	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
84 	/* dereference it indirectly */
85 	BPF_LD_MAP_FD(BPF_REG_1, 0),
86 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
87 	BPF_MOV64_IMM(BPF_REG_0, 0),
88 	BPF_EXIT_INSN(),
89 	},
90 	.fixup_map_hash_8b = { 5 },
91 	.errstr = "R2 max value is outside of stack bound",
92 	.result = REJECT,
93 	.prog_type = BPF_PROG_TYPE_LWT_IN,
94 },
95 {
96 	"indirect variable-offset stack access, min out of bound",
97 	.insns = {
98 	/* Fill the top 8 bytes of the stack */
99 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
100 	/* Get an unknown value */
101 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
102 	/* Make it small and 4-byte aligned */
103 	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
104 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 516),
105 	/* add it to fp.  We now have either fp-516 or fp-512, but
106 	 * we don't know which
107 	 */
108 	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
109 	/* dereference it indirectly */
110 	BPF_LD_MAP_FD(BPF_REG_1, 0),
111 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
112 	BPF_MOV64_IMM(BPF_REG_0, 0),
113 	BPF_EXIT_INSN(),
114 	},
115 	.fixup_map_hash_8b = { 5 },
116 	.errstr = "R2 min value is outside of stack bound",
117 	.result = REJECT,
118 	.prog_type = BPF_PROG_TYPE_LWT_IN,
119 },
120 {
121 	"indirect variable-offset stack access, max_off+size > max_initialized",
122 	.insns = {
123 	/* Fill only the second from top 8 bytes of the stack. */
124 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
125 	/* Get an unknown value. */
126 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
127 	/* Make it small and 4-byte aligned. */
128 	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
129 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
130 	/* Add it to fp.  We now have either fp-12 or fp-16, but we don't know
131 	 * which. fp-12 size 8 is partially uninitialized stack.
132 	 */
133 	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
134 	/* Dereference it indirectly. */
135 	BPF_LD_MAP_FD(BPF_REG_1, 0),
136 	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
137 	BPF_MOV64_IMM(BPF_REG_0, 0),
138 	BPF_EXIT_INSN(),
139 	},
140 	.fixup_map_hash_8b = { 5 },
141 	.errstr = "invalid indirect read from stack var_off",
142 	.result = REJECT,
143 	.prog_type = BPF_PROG_TYPE_LWT_IN,
144 },
145 {
146 	"indirect variable-offset stack access, min_off < min_initialized",
147 	.insns = {
148 	/* Fill only the top 8 bytes of the stack. */
149 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
150 	/* Get an unknown value */
151 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
152 	/* Make it small and 4-byte aligned. */
153 	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
154 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
155 	/* Add it to fp.  We now have either fp-12 or fp-16, but we don't know
156 	 * which. fp-16 size 8 is partially uninitialized stack.
157 	 */
158 	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
159 	/* Dereference it indirectly. */
160 	BPF_LD_MAP_FD(BPF_REG_1, 0),
161 	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
162 	BPF_MOV64_IMM(BPF_REG_0, 0),
163 	BPF_EXIT_INSN(),
164 	},
165 	.fixup_map_hash_8b = { 5 },
166 	.errstr = "invalid indirect read from stack var_off",
167 	.result = REJECT,
168 	.prog_type = BPF_PROG_TYPE_LWT_IN,
169 },
170 {
171 	"indirect variable-offset stack access, priv vs unpriv",
172 	.insns = {
173 	/* Fill the top 16 bytes of the stack. */
174 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
175 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
176 	/* Get an unknown value. */
177 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
178 	/* Make it small and 4-byte aligned. */
179 	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
180 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
181 	/* Add it to fp.  We now have either fp-12 or fp-16, we don't know
182 	 * which, but either way it points to initialized stack.
183 	 */
184 	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
185 	/* Dereference it indirectly. */
186 	BPF_LD_MAP_FD(BPF_REG_1, 0),
187 	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
188 	BPF_MOV64_IMM(BPF_REG_0, 0),
189 	BPF_EXIT_INSN(),
190 	},
191 	.fixup_map_hash_8b = { 6 },
192 	.errstr_unpriv = "R2 stack pointer arithmetic goes out of range, prohibited for !root",
193 	.result_unpriv = REJECT,
194 	.result = ACCEPT,
195 	.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
196 },
197 {
198 	"indirect variable-offset stack access, uninitialized",
199 	.insns = {
200 	BPF_MOV64_IMM(BPF_REG_2, 6),
201 	BPF_MOV64_IMM(BPF_REG_3, 28),
202 	/* Fill the top 16 bytes of the stack. */
203 	BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0),
204 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
205 	/* Get an unknown value. */
206 	BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0),
207 	/* Make it small and 4-byte aligned. */
208 	BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4),
209 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
210 	/* Add it to fp.  We now have either fp-12 or fp-16, we don't know
211 	 * which, but either way it points to initialized stack.
212 	 */
213 	BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
214 	BPF_MOV64_IMM(BPF_REG_5, 8),
215 	/* Dereference it indirectly. */
216 	BPF_EMIT_CALL(BPF_FUNC_getsockopt),
217 	BPF_MOV64_IMM(BPF_REG_0, 0),
218 	BPF_EXIT_INSN(),
219 	},
220 	.errstr = "invalid indirect read from stack var_off",
221 	.result = REJECT,
222 	.prog_type = BPF_PROG_TYPE_SOCK_OPS,
223 },
224 {
225 	"indirect variable-offset stack access, ok",
226 	.insns = {
227 	/* Fill the top 16 bytes of the stack. */
228 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
229 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
230 	/* Get an unknown value. */
231 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
232 	/* Make it small and 4-byte aligned. */
233 	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
234 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
235 	/* Add it to fp.  We now have either fp-12 or fp-16, we don't know
236 	 * which, but either way it points to initialized stack.
237 	 */
238 	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
239 	/* Dereference it indirectly. */
240 	BPF_LD_MAP_FD(BPF_REG_1, 0),
241 	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
242 	BPF_MOV64_IMM(BPF_REG_0, 0),
243 	BPF_EXIT_INSN(),
244 	},
245 	.fixup_map_hash_8b = { 6 },
246 	.result = ACCEPT,
247 	.prog_type = BPF_PROG_TYPE_LWT_IN,
248 },
249