xref: /linux/kernel/bpf/cfg.c (revision f5ad4101009e7f5f5984ffea6923d4fcd470932a)
1*f8a8faceSAlexei Starovoitov // SPDX-License-Identifier: GPL-2.0-only
2*f8a8faceSAlexei Starovoitov /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
3*f8a8faceSAlexei Starovoitov #include <linux/bpf.h>
4*f8a8faceSAlexei Starovoitov #include <linux/bpf_verifier.h>
5*f8a8faceSAlexei Starovoitov #include <linux/filter.h>
6*f8a8faceSAlexei Starovoitov #include <linux/sort.h>
7*f8a8faceSAlexei Starovoitov 
8*f8a8faceSAlexei Starovoitov #define verbose(env, fmt, args...) bpf_verifier_log_write(env, fmt, ##args)
9*f8a8faceSAlexei Starovoitov 
10*f8a8faceSAlexei Starovoitov /* non-recursive DFS pseudo code
11*f8a8faceSAlexei Starovoitov  * 1  procedure DFS-iterative(G,v):
12*f8a8faceSAlexei Starovoitov  * 2      label v as discovered
13*f8a8faceSAlexei Starovoitov  * 3      let S be a stack
14*f8a8faceSAlexei Starovoitov  * 4      S.push(v)
15*f8a8faceSAlexei Starovoitov  * 5      while S is not empty
16*f8a8faceSAlexei Starovoitov  * 6            t <- S.peek()
17*f8a8faceSAlexei Starovoitov  * 7            if t is what we're looking for:
18*f8a8faceSAlexei Starovoitov  * 8                return t
19*f8a8faceSAlexei Starovoitov  * 9            for all edges e in G.adjacentEdges(t) do
20*f8a8faceSAlexei Starovoitov  * 10               if edge e is already labelled
21*f8a8faceSAlexei Starovoitov  * 11                   continue with the next edge
22*f8a8faceSAlexei Starovoitov  * 12               w <- G.adjacentVertex(t,e)
23*f8a8faceSAlexei Starovoitov  * 13               if vertex w is not discovered and not explored
24*f8a8faceSAlexei Starovoitov  * 14                   label e as tree-edge
25*f8a8faceSAlexei Starovoitov  * 15                   label w as discovered
26*f8a8faceSAlexei Starovoitov  * 16                   S.push(w)
27*f8a8faceSAlexei Starovoitov  * 17                   continue at 5
28*f8a8faceSAlexei Starovoitov  * 18               else if vertex w is discovered
29*f8a8faceSAlexei Starovoitov  * 19                   label e as back-edge
30*f8a8faceSAlexei Starovoitov  * 20               else
31*f8a8faceSAlexei Starovoitov  * 21                   // vertex w is explored
32*f8a8faceSAlexei Starovoitov  * 22                   label e as forward- or cross-edge
33*f8a8faceSAlexei Starovoitov  * 23           label t as explored
34*f8a8faceSAlexei Starovoitov  * 24           S.pop()
35*f8a8faceSAlexei Starovoitov  *
36*f8a8faceSAlexei Starovoitov  * convention:
37*f8a8faceSAlexei Starovoitov  * 0x10 - discovered
38*f8a8faceSAlexei Starovoitov  * 0x11 - discovered and fall-through edge labelled
39*f8a8faceSAlexei Starovoitov  * 0x12 - discovered and fall-through and branch edges labelled
40*f8a8faceSAlexei Starovoitov  * 0x20 - explored
41*f8a8faceSAlexei Starovoitov  */
42*f8a8faceSAlexei Starovoitov 
43*f8a8faceSAlexei Starovoitov enum {
44*f8a8faceSAlexei Starovoitov 	DISCOVERED = 0x10,
45*f8a8faceSAlexei Starovoitov 	EXPLORED = 0x20,
46*f8a8faceSAlexei Starovoitov 	FALLTHROUGH = 1,
47*f8a8faceSAlexei Starovoitov 	BRANCH = 2,
48*f8a8faceSAlexei Starovoitov };
49*f8a8faceSAlexei Starovoitov 
50*f8a8faceSAlexei Starovoitov 
51*f8a8faceSAlexei Starovoitov static void mark_subprog_changes_pkt_data(struct bpf_verifier_env *env, int off)
52*f8a8faceSAlexei Starovoitov {
53*f8a8faceSAlexei Starovoitov 	struct bpf_subprog_info *subprog;
54*f8a8faceSAlexei Starovoitov 
55*f8a8faceSAlexei Starovoitov 	subprog = bpf_find_containing_subprog(env, off);
56*f8a8faceSAlexei Starovoitov 	subprog->changes_pkt_data = true;
57*f8a8faceSAlexei Starovoitov }
58*f8a8faceSAlexei Starovoitov 
59*f8a8faceSAlexei Starovoitov static void mark_subprog_might_sleep(struct bpf_verifier_env *env, int off)
60*f8a8faceSAlexei Starovoitov {
61*f8a8faceSAlexei Starovoitov 	struct bpf_subprog_info *subprog;
62*f8a8faceSAlexei Starovoitov 
63*f8a8faceSAlexei Starovoitov 	subprog = bpf_find_containing_subprog(env, off);
64*f8a8faceSAlexei Starovoitov 	subprog->might_sleep = true;
65*f8a8faceSAlexei Starovoitov }
66*f8a8faceSAlexei Starovoitov 
67*f8a8faceSAlexei Starovoitov /* 't' is an index of a call-site.
68*f8a8faceSAlexei Starovoitov  * 'w' is a callee entry point.
69*f8a8faceSAlexei Starovoitov  * Eventually this function would be called when env->cfg.insn_state[w] == EXPLORED.
70*f8a8faceSAlexei Starovoitov  * Rely on DFS traversal order and absence of recursive calls to guarantee that
71*f8a8faceSAlexei Starovoitov  * callee's change_pkt_data marks would be correct at that moment.
72*f8a8faceSAlexei Starovoitov  */
73*f8a8faceSAlexei Starovoitov static void merge_callee_effects(struct bpf_verifier_env *env, int t, int w)
74*f8a8faceSAlexei Starovoitov {
75*f8a8faceSAlexei Starovoitov 	struct bpf_subprog_info *caller, *callee;
76*f8a8faceSAlexei Starovoitov 
77*f8a8faceSAlexei Starovoitov 	caller = bpf_find_containing_subprog(env, t);
78*f8a8faceSAlexei Starovoitov 	callee = bpf_find_containing_subprog(env, w);
79*f8a8faceSAlexei Starovoitov 	caller->changes_pkt_data |= callee->changes_pkt_data;
80*f8a8faceSAlexei Starovoitov 	caller->might_sleep |= callee->might_sleep;
81*f8a8faceSAlexei Starovoitov }
82*f8a8faceSAlexei Starovoitov 
83*f8a8faceSAlexei Starovoitov enum {
84*f8a8faceSAlexei Starovoitov 	DONE_EXPLORING = 0,
85*f8a8faceSAlexei Starovoitov 	KEEP_EXPLORING = 1,
86*f8a8faceSAlexei Starovoitov };
87*f8a8faceSAlexei Starovoitov 
88*f8a8faceSAlexei Starovoitov /* t, w, e - match pseudo-code above:
89*f8a8faceSAlexei Starovoitov  * t - index of current instruction
90*f8a8faceSAlexei Starovoitov  * w - next instruction
91*f8a8faceSAlexei Starovoitov  * e - edge
92*f8a8faceSAlexei Starovoitov  */
93*f8a8faceSAlexei Starovoitov static int push_insn(int t, int w, int e, struct bpf_verifier_env *env)
94*f8a8faceSAlexei Starovoitov {
95*f8a8faceSAlexei Starovoitov 	int *insn_stack = env->cfg.insn_stack;
96*f8a8faceSAlexei Starovoitov 	int *insn_state = env->cfg.insn_state;
97*f8a8faceSAlexei Starovoitov 
98*f8a8faceSAlexei Starovoitov 	if (e == FALLTHROUGH && insn_state[t] >= (DISCOVERED | FALLTHROUGH))
99*f8a8faceSAlexei Starovoitov 		return DONE_EXPLORING;
100*f8a8faceSAlexei Starovoitov 
101*f8a8faceSAlexei Starovoitov 	if (e == BRANCH && insn_state[t] >= (DISCOVERED | BRANCH))
102*f8a8faceSAlexei Starovoitov 		return DONE_EXPLORING;
103*f8a8faceSAlexei Starovoitov 
104*f8a8faceSAlexei Starovoitov 	if (w < 0 || w >= env->prog->len) {
105*f8a8faceSAlexei Starovoitov 		verbose_linfo(env, t, "%d: ", t);
106*f8a8faceSAlexei Starovoitov 		verbose(env, "jump out of range from insn %d to %d\n", t, w);
107*f8a8faceSAlexei Starovoitov 		return -EINVAL;
108*f8a8faceSAlexei Starovoitov 	}
109*f8a8faceSAlexei Starovoitov 
110*f8a8faceSAlexei Starovoitov 	if (e == BRANCH) {
111*f8a8faceSAlexei Starovoitov 		/* mark branch target for state pruning */
112*f8a8faceSAlexei Starovoitov 		mark_prune_point(env, w);
113*f8a8faceSAlexei Starovoitov 		mark_jmp_point(env, w);
114*f8a8faceSAlexei Starovoitov 	}
115*f8a8faceSAlexei Starovoitov 
116*f8a8faceSAlexei Starovoitov 	if (insn_state[w] == 0) {
117*f8a8faceSAlexei Starovoitov 		/* tree-edge */
118*f8a8faceSAlexei Starovoitov 		insn_state[t] = DISCOVERED | e;
119*f8a8faceSAlexei Starovoitov 		insn_state[w] = DISCOVERED;
120*f8a8faceSAlexei Starovoitov 		if (env->cfg.cur_stack >= env->prog->len)
121*f8a8faceSAlexei Starovoitov 			return -E2BIG;
122*f8a8faceSAlexei Starovoitov 		insn_stack[env->cfg.cur_stack++] = w;
123*f8a8faceSAlexei Starovoitov 		return KEEP_EXPLORING;
124*f8a8faceSAlexei Starovoitov 	} else if ((insn_state[w] & 0xF0) == DISCOVERED) {
125*f8a8faceSAlexei Starovoitov 		if (env->bpf_capable)
126*f8a8faceSAlexei Starovoitov 			return DONE_EXPLORING;
127*f8a8faceSAlexei Starovoitov 		verbose_linfo(env, t, "%d: ", t);
128*f8a8faceSAlexei Starovoitov 		verbose_linfo(env, w, "%d: ", w);
129*f8a8faceSAlexei Starovoitov 		verbose(env, "back-edge from insn %d to %d\n", t, w);
130*f8a8faceSAlexei Starovoitov 		return -EINVAL;
131*f8a8faceSAlexei Starovoitov 	} else if (insn_state[w] == EXPLORED) {
132*f8a8faceSAlexei Starovoitov 		/* forward- or cross-edge */
133*f8a8faceSAlexei Starovoitov 		insn_state[t] = DISCOVERED | e;
134*f8a8faceSAlexei Starovoitov 	} else {
135*f8a8faceSAlexei Starovoitov 		verifier_bug(env, "insn state internal bug");
136*f8a8faceSAlexei Starovoitov 		return -EFAULT;
137*f8a8faceSAlexei Starovoitov 	}
138*f8a8faceSAlexei Starovoitov 	return DONE_EXPLORING;
139*f8a8faceSAlexei Starovoitov }
140*f8a8faceSAlexei Starovoitov 
141*f8a8faceSAlexei Starovoitov static int visit_func_call_insn(int t, struct bpf_insn *insns,
142*f8a8faceSAlexei Starovoitov 				struct bpf_verifier_env *env,
143*f8a8faceSAlexei Starovoitov 				bool visit_callee)
144*f8a8faceSAlexei Starovoitov {
145*f8a8faceSAlexei Starovoitov 	int ret, insn_sz;
146*f8a8faceSAlexei Starovoitov 	int w;
147*f8a8faceSAlexei Starovoitov 
148*f8a8faceSAlexei Starovoitov 	insn_sz = bpf_is_ldimm64(&insns[t]) ? 2 : 1;
149*f8a8faceSAlexei Starovoitov 	ret = push_insn(t, t + insn_sz, FALLTHROUGH, env);
150*f8a8faceSAlexei Starovoitov 	if (ret)
151*f8a8faceSAlexei Starovoitov 		return ret;
152*f8a8faceSAlexei Starovoitov 
153*f8a8faceSAlexei Starovoitov 	mark_prune_point(env, t + insn_sz);
154*f8a8faceSAlexei Starovoitov 	/* when we exit from subprog, we need to record non-linear history */
155*f8a8faceSAlexei Starovoitov 	mark_jmp_point(env, t + insn_sz);
156*f8a8faceSAlexei Starovoitov 
157*f8a8faceSAlexei Starovoitov 	if (visit_callee) {
158*f8a8faceSAlexei Starovoitov 		w = t + insns[t].imm + 1;
159*f8a8faceSAlexei Starovoitov 		mark_prune_point(env, t);
160*f8a8faceSAlexei Starovoitov 		merge_callee_effects(env, t, w);
161*f8a8faceSAlexei Starovoitov 		ret = push_insn(t, w, BRANCH, env);
162*f8a8faceSAlexei Starovoitov 	}
163*f8a8faceSAlexei Starovoitov 	return ret;
164*f8a8faceSAlexei Starovoitov }
165*f8a8faceSAlexei Starovoitov 
166*f8a8faceSAlexei Starovoitov struct bpf_iarray *bpf_iarray_realloc(struct bpf_iarray *old, size_t n_elem)
167*f8a8faceSAlexei Starovoitov {
168*f8a8faceSAlexei Starovoitov 	size_t new_size = sizeof(struct bpf_iarray) + n_elem * sizeof(old->items[0]);
169*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *new;
170*f8a8faceSAlexei Starovoitov 
171*f8a8faceSAlexei Starovoitov 	new = kvrealloc(old, new_size, GFP_KERNEL_ACCOUNT);
172*f8a8faceSAlexei Starovoitov 	if (!new) {
173*f8a8faceSAlexei Starovoitov 		/* this is what callers always want, so simplify the call site */
174*f8a8faceSAlexei Starovoitov 		kvfree(old);
175*f8a8faceSAlexei Starovoitov 		return NULL;
176*f8a8faceSAlexei Starovoitov 	}
177*f8a8faceSAlexei Starovoitov 
178*f8a8faceSAlexei Starovoitov 	new->cnt = n_elem;
179*f8a8faceSAlexei Starovoitov 	return new;
180*f8a8faceSAlexei Starovoitov }
181*f8a8faceSAlexei Starovoitov 
182*f8a8faceSAlexei Starovoitov static int copy_insn_array(struct bpf_map *map, u32 start, u32 end, u32 *items)
183*f8a8faceSAlexei Starovoitov {
184*f8a8faceSAlexei Starovoitov 	struct bpf_insn_array_value *value;
185*f8a8faceSAlexei Starovoitov 	u32 i;
186*f8a8faceSAlexei Starovoitov 
187*f8a8faceSAlexei Starovoitov 	for (i = start; i <= end; i++) {
188*f8a8faceSAlexei Starovoitov 		value = map->ops->map_lookup_elem(map, &i);
189*f8a8faceSAlexei Starovoitov 		/*
190*f8a8faceSAlexei Starovoitov 		 * map_lookup_elem of an array map will never return an error,
191*f8a8faceSAlexei Starovoitov 		 * but not checking it makes some static analysers to worry
192*f8a8faceSAlexei Starovoitov 		 */
193*f8a8faceSAlexei Starovoitov 		if (IS_ERR(value))
194*f8a8faceSAlexei Starovoitov 			return PTR_ERR(value);
195*f8a8faceSAlexei Starovoitov 		else if (!value)
196*f8a8faceSAlexei Starovoitov 			return -EINVAL;
197*f8a8faceSAlexei Starovoitov 		items[i - start] = value->xlated_off;
198*f8a8faceSAlexei Starovoitov 	}
199*f8a8faceSAlexei Starovoitov 	return 0;
200*f8a8faceSAlexei Starovoitov }
201*f8a8faceSAlexei Starovoitov 
202*f8a8faceSAlexei Starovoitov static int cmp_ptr_to_u32(const void *a, const void *b)
203*f8a8faceSAlexei Starovoitov {
204*f8a8faceSAlexei Starovoitov 	return *(u32 *)a - *(u32 *)b;
205*f8a8faceSAlexei Starovoitov }
206*f8a8faceSAlexei Starovoitov 
207*f8a8faceSAlexei Starovoitov static int sort_insn_array_uniq(u32 *items, int cnt)
208*f8a8faceSAlexei Starovoitov {
209*f8a8faceSAlexei Starovoitov 	int unique = 1;
210*f8a8faceSAlexei Starovoitov 	int i;
211*f8a8faceSAlexei Starovoitov 
212*f8a8faceSAlexei Starovoitov 	sort(items, cnt, sizeof(items[0]), cmp_ptr_to_u32, NULL);
213*f8a8faceSAlexei Starovoitov 
214*f8a8faceSAlexei Starovoitov 	for (i = 1; i < cnt; i++)
215*f8a8faceSAlexei Starovoitov 		if (items[i] != items[unique - 1])
216*f8a8faceSAlexei Starovoitov 			items[unique++] = items[i];
217*f8a8faceSAlexei Starovoitov 
218*f8a8faceSAlexei Starovoitov 	return unique;
219*f8a8faceSAlexei Starovoitov }
220*f8a8faceSAlexei Starovoitov 
221*f8a8faceSAlexei Starovoitov /*
222*f8a8faceSAlexei Starovoitov  * sort_unique({map[start], ..., map[end]}) into off
223*f8a8faceSAlexei Starovoitov  */
224*f8a8faceSAlexei Starovoitov int bpf_copy_insn_array_uniq(struct bpf_map *map, u32 start, u32 end, u32 *off)
225*f8a8faceSAlexei Starovoitov {
226*f8a8faceSAlexei Starovoitov 	u32 n = end - start + 1;
227*f8a8faceSAlexei Starovoitov 	int err;
228*f8a8faceSAlexei Starovoitov 
229*f8a8faceSAlexei Starovoitov 	err = copy_insn_array(map, start, end, off);
230*f8a8faceSAlexei Starovoitov 	if (err)
231*f8a8faceSAlexei Starovoitov 		return err;
232*f8a8faceSAlexei Starovoitov 
233*f8a8faceSAlexei Starovoitov 	return sort_insn_array_uniq(off, n);
234*f8a8faceSAlexei Starovoitov }
235*f8a8faceSAlexei Starovoitov 
236*f8a8faceSAlexei Starovoitov /*
237*f8a8faceSAlexei Starovoitov  * Copy all unique offsets from the map
238*f8a8faceSAlexei Starovoitov  */
239*f8a8faceSAlexei Starovoitov static struct bpf_iarray *jt_from_map(struct bpf_map *map)
240*f8a8faceSAlexei Starovoitov {
241*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *jt;
242*f8a8faceSAlexei Starovoitov 	int err;
243*f8a8faceSAlexei Starovoitov 	int n;
244*f8a8faceSAlexei Starovoitov 
245*f8a8faceSAlexei Starovoitov 	jt = bpf_iarray_realloc(NULL, map->max_entries);
246*f8a8faceSAlexei Starovoitov 	if (!jt)
247*f8a8faceSAlexei Starovoitov 		return ERR_PTR(-ENOMEM);
248*f8a8faceSAlexei Starovoitov 
249*f8a8faceSAlexei Starovoitov 	n = bpf_copy_insn_array_uniq(map, 0, map->max_entries - 1, jt->items);
250*f8a8faceSAlexei Starovoitov 	if (n < 0) {
251*f8a8faceSAlexei Starovoitov 		err = n;
252*f8a8faceSAlexei Starovoitov 		goto err_free;
253*f8a8faceSAlexei Starovoitov 	}
254*f8a8faceSAlexei Starovoitov 	if (n == 0) {
255*f8a8faceSAlexei Starovoitov 		err = -EINVAL;
256*f8a8faceSAlexei Starovoitov 		goto err_free;
257*f8a8faceSAlexei Starovoitov 	}
258*f8a8faceSAlexei Starovoitov 	jt->cnt = n;
259*f8a8faceSAlexei Starovoitov 	return jt;
260*f8a8faceSAlexei Starovoitov 
261*f8a8faceSAlexei Starovoitov err_free:
262*f8a8faceSAlexei Starovoitov 	kvfree(jt);
263*f8a8faceSAlexei Starovoitov 	return ERR_PTR(err);
264*f8a8faceSAlexei Starovoitov }
265*f8a8faceSAlexei Starovoitov 
266*f8a8faceSAlexei Starovoitov /*
267*f8a8faceSAlexei Starovoitov  * Find and collect all maps which fit in the subprog. Return the result as one
268*f8a8faceSAlexei Starovoitov  * combined jump table in jt->items (allocated with kvcalloc)
269*f8a8faceSAlexei Starovoitov  */
270*f8a8faceSAlexei Starovoitov static struct bpf_iarray *jt_from_subprog(struct bpf_verifier_env *env,
271*f8a8faceSAlexei Starovoitov 					  int subprog_start, int subprog_end)
272*f8a8faceSAlexei Starovoitov {
273*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *jt = NULL;
274*f8a8faceSAlexei Starovoitov 	struct bpf_map *map;
275*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *jt_cur;
276*f8a8faceSAlexei Starovoitov 	int i;
277*f8a8faceSAlexei Starovoitov 
278*f8a8faceSAlexei Starovoitov 	for (i = 0; i < env->insn_array_map_cnt; i++) {
279*f8a8faceSAlexei Starovoitov 		/*
280*f8a8faceSAlexei Starovoitov 		 * TODO (when needed): collect only jump tables, not static keys
281*f8a8faceSAlexei Starovoitov 		 * or maps for indirect calls
282*f8a8faceSAlexei Starovoitov 		 */
283*f8a8faceSAlexei Starovoitov 		map = env->insn_array_maps[i];
284*f8a8faceSAlexei Starovoitov 
285*f8a8faceSAlexei Starovoitov 		jt_cur = jt_from_map(map);
286*f8a8faceSAlexei Starovoitov 		if (IS_ERR(jt_cur)) {
287*f8a8faceSAlexei Starovoitov 			kvfree(jt);
288*f8a8faceSAlexei Starovoitov 			return jt_cur;
289*f8a8faceSAlexei Starovoitov 		}
290*f8a8faceSAlexei Starovoitov 
291*f8a8faceSAlexei Starovoitov 		/*
292*f8a8faceSAlexei Starovoitov 		 * This is enough to check one element. The full table is
293*f8a8faceSAlexei Starovoitov 		 * checked to fit inside the subprog later in create_jt()
294*f8a8faceSAlexei Starovoitov 		 */
295*f8a8faceSAlexei Starovoitov 		if (jt_cur->items[0] >= subprog_start && jt_cur->items[0] < subprog_end) {
296*f8a8faceSAlexei Starovoitov 			u32 old_cnt = jt ? jt->cnt : 0;
297*f8a8faceSAlexei Starovoitov 			jt = bpf_iarray_realloc(jt, old_cnt + jt_cur->cnt);
298*f8a8faceSAlexei Starovoitov 			if (!jt) {
299*f8a8faceSAlexei Starovoitov 				kvfree(jt_cur);
300*f8a8faceSAlexei Starovoitov 				return ERR_PTR(-ENOMEM);
301*f8a8faceSAlexei Starovoitov 			}
302*f8a8faceSAlexei Starovoitov 			memcpy(jt->items + old_cnt, jt_cur->items, jt_cur->cnt << 2);
303*f8a8faceSAlexei Starovoitov 		}
304*f8a8faceSAlexei Starovoitov 
305*f8a8faceSAlexei Starovoitov 		kvfree(jt_cur);
306*f8a8faceSAlexei Starovoitov 	}
307*f8a8faceSAlexei Starovoitov 
308*f8a8faceSAlexei Starovoitov 	if (!jt) {
309*f8a8faceSAlexei Starovoitov 		verbose(env, "no jump tables found for subprog starting at %u\n", subprog_start);
310*f8a8faceSAlexei Starovoitov 		return ERR_PTR(-EINVAL);
311*f8a8faceSAlexei Starovoitov 	}
312*f8a8faceSAlexei Starovoitov 
313*f8a8faceSAlexei Starovoitov 	jt->cnt = sort_insn_array_uniq(jt->items, jt->cnt);
314*f8a8faceSAlexei Starovoitov 	return jt;
315*f8a8faceSAlexei Starovoitov }
316*f8a8faceSAlexei Starovoitov 
317*f8a8faceSAlexei Starovoitov static struct bpf_iarray *
318*f8a8faceSAlexei Starovoitov create_jt(int t, struct bpf_verifier_env *env)
319*f8a8faceSAlexei Starovoitov {
320*f8a8faceSAlexei Starovoitov 	struct bpf_subprog_info *subprog;
321*f8a8faceSAlexei Starovoitov 	int subprog_start, subprog_end;
322*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *jt;
323*f8a8faceSAlexei Starovoitov 	int i;
324*f8a8faceSAlexei Starovoitov 
325*f8a8faceSAlexei Starovoitov 	subprog = bpf_find_containing_subprog(env, t);
326*f8a8faceSAlexei Starovoitov 	subprog_start = subprog->start;
327*f8a8faceSAlexei Starovoitov 	subprog_end = (subprog + 1)->start;
328*f8a8faceSAlexei Starovoitov 	jt = jt_from_subprog(env, subprog_start, subprog_end);
329*f8a8faceSAlexei Starovoitov 	if (IS_ERR(jt))
330*f8a8faceSAlexei Starovoitov 		return jt;
331*f8a8faceSAlexei Starovoitov 
332*f8a8faceSAlexei Starovoitov 	/* Check that the every element of the jump table fits within the given subprogram */
333*f8a8faceSAlexei Starovoitov 	for (i = 0; i < jt->cnt; i++) {
334*f8a8faceSAlexei Starovoitov 		if (jt->items[i] < subprog_start || jt->items[i] >= subprog_end) {
335*f8a8faceSAlexei Starovoitov 			verbose(env, "jump table for insn %d points outside of the subprog [%u,%u]\n",
336*f8a8faceSAlexei Starovoitov 					t, subprog_start, subprog_end);
337*f8a8faceSAlexei Starovoitov 			kvfree(jt);
338*f8a8faceSAlexei Starovoitov 			return ERR_PTR(-EINVAL);
339*f8a8faceSAlexei Starovoitov 		}
340*f8a8faceSAlexei Starovoitov 	}
341*f8a8faceSAlexei Starovoitov 
342*f8a8faceSAlexei Starovoitov 	return jt;
343*f8a8faceSAlexei Starovoitov }
344*f8a8faceSAlexei Starovoitov 
345*f8a8faceSAlexei Starovoitov /* "conditional jump with N edges" */
346*f8a8faceSAlexei Starovoitov static int visit_gotox_insn(int t, struct bpf_verifier_env *env)
347*f8a8faceSAlexei Starovoitov {
348*f8a8faceSAlexei Starovoitov 	int *insn_stack = env->cfg.insn_stack;
349*f8a8faceSAlexei Starovoitov 	int *insn_state = env->cfg.insn_state;
350*f8a8faceSAlexei Starovoitov 	bool keep_exploring = false;
351*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *jt;
352*f8a8faceSAlexei Starovoitov 	int i, w;
353*f8a8faceSAlexei Starovoitov 
354*f8a8faceSAlexei Starovoitov 	jt = env->insn_aux_data[t].jt;
355*f8a8faceSAlexei Starovoitov 	if (!jt) {
356*f8a8faceSAlexei Starovoitov 		jt = create_jt(t, env);
357*f8a8faceSAlexei Starovoitov 		if (IS_ERR(jt))
358*f8a8faceSAlexei Starovoitov 			return PTR_ERR(jt);
359*f8a8faceSAlexei Starovoitov 
360*f8a8faceSAlexei Starovoitov 		env->insn_aux_data[t].jt = jt;
361*f8a8faceSAlexei Starovoitov 	}
362*f8a8faceSAlexei Starovoitov 
363*f8a8faceSAlexei Starovoitov 	mark_prune_point(env, t);
364*f8a8faceSAlexei Starovoitov 	for (i = 0; i < jt->cnt; i++) {
365*f8a8faceSAlexei Starovoitov 		w = jt->items[i];
366*f8a8faceSAlexei Starovoitov 		if (w < 0 || w >= env->prog->len) {
367*f8a8faceSAlexei Starovoitov 			verbose(env, "indirect jump out of range from insn %d to %d\n", t, w);
368*f8a8faceSAlexei Starovoitov 			return -EINVAL;
369*f8a8faceSAlexei Starovoitov 		}
370*f8a8faceSAlexei Starovoitov 
371*f8a8faceSAlexei Starovoitov 		mark_jmp_point(env, w);
372*f8a8faceSAlexei Starovoitov 
373*f8a8faceSAlexei Starovoitov 		/* EXPLORED || DISCOVERED */
374*f8a8faceSAlexei Starovoitov 		if (insn_state[w])
375*f8a8faceSAlexei Starovoitov 			continue;
376*f8a8faceSAlexei Starovoitov 
377*f8a8faceSAlexei Starovoitov 		if (env->cfg.cur_stack >= env->prog->len)
378*f8a8faceSAlexei Starovoitov 			return -E2BIG;
379*f8a8faceSAlexei Starovoitov 
380*f8a8faceSAlexei Starovoitov 		insn_stack[env->cfg.cur_stack++] = w;
381*f8a8faceSAlexei Starovoitov 		insn_state[w] |= DISCOVERED;
382*f8a8faceSAlexei Starovoitov 		keep_exploring = true;
383*f8a8faceSAlexei Starovoitov 	}
384*f8a8faceSAlexei Starovoitov 
385*f8a8faceSAlexei Starovoitov 	return keep_exploring ? KEEP_EXPLORING : DONE_EXPLORING;
386*f8a8faceSAlexei Starovoitov }
387*f8a8faceSAlexei Starovoitov 
388*f8a8faceSAlexei Starovoitov /*
389*f8a8faceSAlexei Starovoitov  * Instructions that can abnormally return from a subprog (tail_call
390*f8a8faceSAlexei Starovoitov  * upon success, ld_{abs,ind} upon load failure) have a hidden exit
391*f8a8faceSAlexei Starovoitov  * that the verifier must account for.
392*f8a8faceSAlexei Starovoitov  */
393*f8a8faceSAlexei Starovoitov static int visit_abnormal_return_insn(struct bpf_verifier_env *env, int t)
394*f8a8faceSAlexei Starovoitov {
395*f8a8faceSAlexei Starovoitov 	struct bpf_subprog_info *subprog;
396*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *jt;
397*f8a8faceSAlexei Starovoitov 
398*f8a8faceSAlexei Starovoitov 	if (env->insn_aux_data[t].jt)
399*f8a8faceSAlexei Starovoitov 		return 0;
400*f8a8faceSAlexei Starovoitov 
401*f8a8faceSAlexei Starovoitov 	jt = bpf_iarray_realloc(NULL, 2);
402*f8a8faceSAlexei Starovoitov 	if (!jt)
403*f8a8faceSAlexei Starovoitov 		return -ENOMEM;
404*f8a8faceSAlexei Starovoitov 
405*f8a8faceSAlexei Starovoitov 	subprog = bpf_find_containing_subprog(env, t);
406*f8a8faceSAlexei Starovoitov 	jt->items[0] = t + 1;
407*f8a8faceSAlexei Starovoitov 	jt->items[1] = subprog->exit_idx;
408*f8a8faceSAlexei Starovoitov 	env->insn_aux_data[t].jt = jt;
409*f8a8faceSAlexei Starovoitov 	return 0;
410*f8a8faceSAlexei Starovoitov }
411*f8a8faceSAlexei Starovoitov 
412*f8a8faceSAlexei Starovoitov /* Visits the instruction at index t and returns one of the following:
413*f8a8faceSAlexei Starovoitov  *  < 0 - an error occurred
414*f8a8faceSAlexei Starovoitov  *  DONE_EXPLORING - the instruction was fully explored
415*f8a8faceSAlexei Starovoitov  *  KEEP_EXPLORING - there is still work to be done before it is fully explored
416*f8a8faceSAlexei Starovoitov  */
417*f8a8faceSAlexei Starovoitov static int visit_insn(int t, struct bpf_verifier_env *env)
418*f8a8faceSAlexei Starovoitov {
419*f8a8faceSAlexei Starovoitov 	struct bpf_insn *insns = env->prog->insnsi, *insn = &insns[t];
420*f8a8faceSAlexei Starovoitov 	int ret, off, insn_sz;
421*f8a8faceSAlexei Starovoitov 
422*f8a8faceSAlexei Starovoitov 	if (bpf_pseudo_func(insn))
423*f8a8faceSAlexei Starovoitov 		return visit_func_call_insn(t, insns, env, true);
424*f8a8faceSAlexei Starovoitov 
425*f8a8faceSAlexei Starovoitov 	/* All non-branch instructions have a single fall-through edge. */
426*f8a8faceSAlexei Starovoitov 	if (BPF_CLASS(insn->code) != BPF_JMP &&
427*f8a8faceSAlexei Starovoitov 	    BPF_CLASS(insn->code) != BPF_JMP32) {
428*f8a8faceSAlexei Starovoitov 		if (BPF_CLASS(insn->code) == BPF_LD &&
429*f8a8faceSAlexei Starovoitov 		    (BPF_MODE(insn->code) == BPF_ABS ||
430*f8a8faceSAlexei Starovoitov 		     BPF_MODE(insn->code) == BPF_IND)) {
431*f8a8faceSAlexei Starovoitov 			ret = visit_abnormal_return_insn(env, t);
432*f8a8faceSAlexei Starovoitov 			if (ret)
433*f8a8faceSAlexei Starovoitov 				return ret;
434*f8a8faceSAlexei Starovoitov 		}
435*f8a8faceSAlexei Starovoitov 		insn_sz = bpf_is_ldimm64(insn) ? 2 : 1;
436*f8a8faceSAlexei Starovoitov 		return push_insn(t, t + insn_sz, FALLTHROUGH, env);
437*f8a8faceSAlexei Starovoitov 	}
438*f8a8faceSAlexei Starovoitov 
439*f8a8faceSAlexei Starovoitov 	switch (BPF_OP(insn->code)) {
440*f8a8faceSAlexei Starovoitov 	case BPF_EXIT:
441*f8a8faceSAlexei Starovoitov 		return DONE_EXPLORING;
442*f8a8faceSAlexei Starovoitov 
443*f8a8faceSAlexei Starovoitov 	case BPF_CALL:
444*f8a8faceSAlexei Starovoitov 		if (bpf_is_async_callback_calling_insn(insn))
445*f8a8faceSAlexei Starovoitov 			/* Mark this call insn as a prune point to trigger
446*f8a8faceSAlexei Starovoitov 			 * is_state_visited() check before call itself is
447*f8a8faceSAlexei Starovoitov 			 * processed by __check_func_call(). Otherwise new
448*f8a8faceSAlexei Starovoitov 			 * async state will be pushed for further exploration.
449*f8a8faceSAlexei Starovoitov 			 */
450*f8a8faceSAlexei Starovoitov 			mark_prune_point(env, t);
451*f8a8faceSAlexei Starovoitov 		/* For functions that invoke callbacks it is not known how many times
452*f8a8faceSAlexei Starovoitov 		 * callback would be called. Verifier models callback calling functions
453*f8a8faceSAlexei Starovoitov 		 * by repeatedly visiting callback bodies and returning to origin call
454*f8a8faceSAlexei Starovoitov 		 * instruction.
455*f8a8faceSAlexei Starovoitov 		 * In order to stop such iteration verifier needs to identify when a
456*f8a8faceSAlexei Starovoitov 		 * state identical some state from a previous iteration is reached.
457*f8a8faceSAlexei Starovoitov 		 * Check below forces creation of checkpoint before callback calling
458*f8a8faceSAlexei Starovoitov 		 * instruction to allow search for such identical states.
459*f8a8faceSAlexei Starovoitov 		 */
460*f8a8faceSAlexei Starovoitov 		if (bpf_is_sync_callback_calling_insn(insn)) {
461*f8a8faceSAlexei Starovoitov 			mark_calls_callback(env, t);
462*f8a8faceSAlexei Starovoitov 			mark_force_checkpoint(env, t);
463*f8a8faceSAlexei Starovoitov 			mark_prune_point(env, t);
464*f8a8faceSAlexei Starovoitov 			mark_jmp_point(env, t);
465*f8a8faceSAlexei Starovoitov 		}
466*f8a8faceSAlexei Starovoitov 		if (bpf_helper_call(insn)) {
467*f8a8faceSAlexei Starovoitov 			const struct bpf_func_proto *fp;
468*f8a8faceSAlexei Starovoitov 
469*f8a8faceSAlexei Starovoitov 			ret = bpf_get_helper_proto(env, insn->imm, &fp);
470*f8a8faceSAlexei Starovoitov 			/* If called in a non-sleepable context program will be
471*f8a8faceSAlexei Starovoitov 			 * rejected anyway, so we should end up with precise
472*f8a8faceSAlexei Starovoitov 			 * sleepable marks on subprogs, except for dead code
473*f8a8faceSAlexei Starovoitov 			 * elimination.
474*f8a8faceSAlexei Starovoitov 			 */
475*f8a8faceSAlexei Starovoitov 			if (ret == 0 && fp->might_sleep)
476*f8a8faceSAlexei Starovoitov 				mark_subprog_might_sleep(env, t);
477*f8a8faceSAlexei Starovoitov 			if (bpf_helper_changes_pkt_data(insn->imm))
478*f8a8faceSAlexei Starovoitov 				mark_subprog_changes_pkt_data(env, t);
479*f8a8faceSAlexei Starovoitov 			if (insn->imm == BPF_FUNC_tail_call) {
480*f8a8faceSAlexei Starovoitov 				ret = visit_abnormal_return_insn(env, t);
481*f8a8faceSAlexei Starovoitov 				if (ret)
482*f8a8faceSAlexei Starovoitov 					return ret;
483*f8a8faceSAlexei Starovoitov 			}
484*f8a8faceSAlexei Starovoitov 		} else if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
485*f8a8faceSAlexei Starovoitov 			struct bpf_kfunc_call_arg_meta meta;
486*f8a8faceSAlexei Starovoitov 
487*f8a8faceSAlexei Starovoitov 			ret = bpf_fetch_kfunc_arg_meta(env, insn->imm, insn->off, &meta);
488*f8a8faceSAlexei Starovoitov 			if (ret == 0 && bpf_is_iter_next_kfunc(&meta)) {
489*f8a8faceSAlexei Starovoitov 				mark_prune_point(env, t);
490*f8a8faceSAlexei Starovoitov 				/* Checking and saving state checkpoints at iter_next() call
491*f8a8faceSAlexei Starovoitov 				 * is crucial for fast convergence of open-coded iterator loop
492*f8a8faceSAlexei Starovoitov 				 * logic, so we need to force it. If we don't do that,
493*f8a8faceSAlexei Starovoitov 				 * is_state_visited() might skip saving a checkpoint, causing
494*f8a8faceSAlexei Starovoitov 				 * unnecessarily long sequence of not checkpointed
495*f8a8faceSAlexei Starovoitov 				 * instructions and jumps, leading to exhaustion of jump
496*f8a8faceSAlexei Starovoitov 				 * history buffer, and potentially other undesired outcomes.
497*f8a8faceSAlexei Starovoitov 				 * It is expected that with correct open-coded iterators
498*f8a8faceSAlexei Starovoitov 				 * convergence will happen quickly, so we don't run a risk of
499*f8a8faceSAlexei Starovoitov 				 * exhausting memory.
500*f8a8faceSAlexei Starovoitov 				 */
501*f8a8faceSAlexei Starovoitov 				mark_force_checkpoint(env, t);
502*f8a8faceSAlexei Starovoitov 			}
503*f8a8faceSAlexei Starovoitov 			/* Same as helpers, if called in a non-sleepable context
504*f8a8faceSAlexei Starovoitov 			 * program will be rejected anyway, so we should end up
505*f8a8faceSAlexei Starovoitov 			 * with precise sleepable marks on subprogs, except for
506*f8a8faceSAlexei Starovoitov 			 * dead code elimination.
507*f8a8faceSAlexei Starovoitov 			 */
508*f8a8faceSAlexei Starovoitov 			if (ret == 0 && bpf_is_kfunc_sleepable(&meta))
509*f8a8faceSAlexei Starovoitov 				mark_subprog_might_sleep(env, t);
510*f8a8faceSAlexei Starovoitov 			if (ret == 0 && bpf_is_kfunc_pkt_changing(&meta))
511*f8a8faceSAlexei Starovoitov 				mark_subprog_changes_pkt_data(env, t);
512*f8a8faceSAlexei Starovoitov 		}
513*f8a8faceSAlexei Starovoitov 		return visit_func_call_insn(t, insns, env, insn->src_reg == BPF_PSEUDO_CALL);
514*f8a8faceSAlexei Starovoitov 
515*f8a8faceSAlexei Starovoitov 	case BPF_JA:
516*f8a8faceSAlexei Starovoitov 		if (BPF_SRC(insn->code) == BPF_X)
517*f8a8faceSAlexei Starovoitov 			return visit_gotox_insn(t, env);
518*f8a8faceSAlexei Starovoitov 
519*f8a8faceSAlexei Starovoitov 		if (BPF_CLASS(insn->code) == BPF_JMP)
520*f8a8faceSAlexei Starovoitov 			off = insn->off;
521*f8a8faceSAlexei Starovoitov 		else
522*f8a8faceSAlexei Starovoitov 			off = insn->imm;
523*f8a8faceSAlexei Starovoitov 
524*f8a8faceSAlexei Starovoitov 		/* unconditional jump with single edge */
525*f8a8faceSAlexei Starovoitov 		ret = push_insn(t, t + off + 1, FALLTHROUGH, env);
526*f8a8faceSAlexei Starovoitov 		if (ret)
527*f8a8faceSAlexei Starovoitov 			return ret;
528*f8a8faceSAlexei Starovoitov 
529*f8a8faceSAlexei Starovoitov 		mark_prune_point(env, t + off + 1);
530*f8a8faceSAlexei Starovoitov 		mark_jmp_point(env, t + off + 1);
531*f8a8faceSAlexei Starovoitov 
532*f8a8faceSAlexei Starovoitov 		return ret;
533*f8a8faceSAlexei Starovoitov 
534*f8a8faceSAlexei Starovoitov 	default:
535*f8a8faceSAlexei Starovoitov 		/* conditional jump with two edges */
536*f8a8faceSAlexei Starovoitov 		mark_prune_point(env, t);
537*f8a8faceSAlexei Starovoitov 		if (bpf_is_may_goto_insn(insn))
538*f8a8faceSAlexei Starovoitov 			mark_force_checkpoint(env, t);
539*f8a8faceSAlexei Starovoitov 
540*f8a8faceSAlexei Starovoitov 		ret = push_insn(t, t + 1, FALLTHROUGH, env);
541*f8a8faceSAlexei Starovoitov 		if (ret)
542*f8a8faceSAlexei Starovoitov 			return ret;
543*f8a8faceSAlexei Starovoitov 
544*f8a8faceSAlexei Starovoitov 		return push_insn(t, t + insn->off + 1, BRANCH, env);
545*f8a8faceSAlexei Starovoitov 	}
546*f8a8faceSAlexei Starovoitov }
547*f8a8faceSAlexei Starovoitov 
548*f8a8faceSAlexei Starovoitov /* non-recursive depth-first-search to detect loops in BPF program
549*f8a8faceSAlexei Starovoitov  * loop == back-edge in directed graph
550*f8a8faceSAlexei Starovoitov  */
551*f8a8faceSAlexei Starovoitov int bpf_check_cfg(struct bpf_verifier_env *env)
552*f8a8faceSAlexei Starovoitov {
553*f8a8faceSAlexei Starovoitov 	int insn_cnt = env->prog->len;
554*f8a8faceSAlexei Starovoitov 	int *insn_stack, *insn_state;
555*f8a8faceSAlexei Starovoitov 	int ex_insn_beg, i, ret = 0;
556*f8a8faceSAlexei Starovoitov 
557*f8a8faceSAlexei Starovoitov 	insn_state = env->cfg.insn_state = kvzalloc_objs(int, insn_cnt,
558*f8a8faceSAlexei Starovoitov 							 GFP_KERNEL_ACCOUNT);
559*f8a8faceSAlexei Starovoitov 	if (!insn_state)
560*f8a8faceSAlexei Starovoitov 		return -ENOMEM;
561*f8a8faceSAlexei Starovoitov 
562*f8a8faceSAlexei Starovoitov 	insn_stack = env->cfg.insn_stack = kvzalloc_objs(int, insn_cnt,
563*f8a8faceSAlexei Starovoitov 							 GFP_KERNEL_ACCOUNT);
564*f8a8faceSAlexei Starovoitov 	if (!insn_stack) {
565*f8a8faceSAlexei Starovoitov 		kvfree(insn_state);
566*f8a8faceSAlexei Starovoitov 		return -ENOMEM;
567*f8a8faceSAlexei Starovoitov 	}
568*f8a8faceSAlexei Starovoitov 
569*f8a8faceSAlexei Starovoitov 	ex_insn_beg = env->exception_callback_subprog
570*f8a8faceSAlexei Starovoitov 		      ? env->subprog_info[env->exception_callback_subprog].start
571*f8a8faceSAlexei Starovoitov 		      : 0;
572*f8a8faceSAlexei Starovoitov 
573*f8a8faceSAlexei Starovoitov 	insn_state[0] = DISCOVERED; /* mark 1st insn as discovered */
574*f8a8faceSAlexei Starovoitov 	insn_stack[0] = 0; /* 0 is the first instruction */
575*f8a8faceSAlexei Starovoitov 	env->cfg.cur_stack = 1;
576*f8a8faceSAlexei Starovoitov 
577*f8a8faceSAlexei Starovoitov walk_cfg:
578*f8a8faceSAlexei Starovoitov 	while (env->cfg.cur_stack > 0) {
579*f8a8faceSAlexei Starovoitov 		int t = insn_stack[env->cfg.cur_stack - 1];
580*f8a8faceSAlexei Starovoitov 
581*f8a8faceSAlexei Starovoitov 		ret = visit_insn(t, env);
582*f8a8faceSAlexei Starovoitov 		switch (ret) {
583*f8a8faceSAlexei Starovoitov 		case DONE_EXPLORING:
584*f8a8faceSAlexei Starovoitov 			insn_state[t] = EXPLORED;
585*f8a8faceSAlexei Starovoitov 			env->cfg.cur_stack--;
586*f8a8faceSAlexei Starovoitov 			break;
587*f8a8faceSAlexei Starovoitov 		case KEEP_EXPLORING:
588*f8a8faceSAlexei Starovoitov 			break;
589*f8a8faceSAlexei Starovoitov 		default:
590*f8a8faceSAlexei Starovoitov 			if (ret > 0) {
591*f8a8faceSAlexei Starovoitov 				verifier_bug(env, "visit_insn internal bug");
592*f8a8faceSAlexei Starovoitov 				ret = -EFAULT;
593*f8a8faceSAlexei Starovoitov 			}
594*f8a8faceSAlexei Starovoitov 			goto err_free;
595*f8a8faceSAlexei Starovoitov 		}
596*f8a8faceSAlexei Starovoitov 	}
597*f8a8faceSAlexei Starovoitov 
598*f8a8faceSAlexei Starovoitov 	if (env->cfg.cur_stack < 0) {
599*f8a8faceSAlexei Starovoitov 		verifier_bug(env, "pop stack internal bug");
600*f8a8faceSAlexei Starovoitov 		ret = -EFAULT;
601*f8a8faceSAlexei Starovoitov 		goto err_free;
602*f8a8faceSAlexei Starovoitov 	}
603*f8a8faceSAlexei Starovoitov 
604*f8a8faceSAlexei Starovoitov 	if (ex_insn_beg && insn_state[ex_insn_beg] != EXPLORED) {
605*f8a8faceSAlexei Starovoitov 		insn_state[ex_insn_beg] = DISCOVERED;
606*f8a8faceSAlexei Starovoitov 		insn_stack[0] = ex_insn_beg;
607*f8a8faceSAlexei Starovoitov 		env->cfg.cur_stack = 1;
608*f8a8faceSAlexei Starovoitov 		goto walk_cfg;
609*f8a8faceSAlexei Starovoitov 	}
610*f8a8faceSAlexei Starovoitov 
611*f8a8faceSAlexei Starovoitov 	for (i = 0; i < insn_cnt; i++) {
612*f8a8faceSAlexei Starovoitov 		struct bpf_insn *insn = &env->prog->insnsi[i];
613*f8a8faceSAlexei Starovoitov 
614*f8a8faceSAlexei Starovoitov 		if (insn_state[i] != EXPLORED) {
615*f8a8faceSAlexei Starovoitov 			verbose(env, "unreachable insn %d\n", i);
616*f8a8faceSAlexei Starovoitov 			ret = -EINVAL;
617*f8a8faceSAlexei Starovoitov 			goto err_free;
618*f8a8faceSAlexei Starovoitov 		}
619*f8a8faceSAlexei Starovoitov 		if (bpf_is_ldimm64(insn)) {
620*f8a8faceSAlexei Starovoitov 			if (insn_state[i + 1] != 0) {
621*f8a8faceSAlexei Starovoitov 				verbose(env, "jump into the middle of ldimm64 insn %d\n", i);
622*f8a8faceSAlexei Starovoitov 				ret = -EINVAL;
623*f8a8faceSAlexei Starovoitov 				goto err_free;
624*f8a8faceSAlexei Starovoitov 			}
625*f8a8faceSAlexei Starovoitov 			i++; /* skip second half of ldimm64 */
626*f8a8faceSAlexei Starovoitov 		}
627*f8a8faceSAlexei Starovoitov 	}
628*f8a8faceSAlexei Starovoitov 	ret = 0; /* cfg looks good */
629*f8a8faceSAlexei Starovoitov 	env->prog->aux->changes_pkt_data = env->subprog_info[0].changes_pkt_data;
630*f8a8faceSAlexei Starovoitov 	env->prog->aux->might_sleep = env->subprog_info[0].might_sleep;
631*f8a8faceSAlexei Starovoitov 
632*f8a8faceSAlexei Starovoitov err_free:
633*f8a8faceSAlexei Starovoitov 	kvfree(insn_state);
634*f8a8faceSAlexei Starovoitov 	kvfree(insn_stack);
635*f8a8faceSAlexei Starovoitov 	env->cfg.insn_state = env->cfg.insn_stack = NULL;
636*f8a8faceSAlexei Starovoitov 	return ret;
637*f8a8faceSAlexei Starovoitov }
638*f8a8faceSAlexei Starovoitov 
639*f8a8faceSAlexei Starovoitov /*
640*f8a8faceSAlexei Starovoitov  * For each subprogram 'i' fill array env->cfg.insn_subprogram sub-range
641*f8a8faceSAlexei Starovoitov  * [env->subprog_info[i].postorder_start, env->subprog_info[i+1].postorder_start)
642*f8a8faceSAlexei Starovoitov  * with indices of 'i' instructions in postorder.
643*f8a8faceSAlexei Starovoitov  */
644*f8a8faceSAlexei Starovoitov int bpf_compute_postorder(struct bpf_verifier_env *env)
645*f8a8faceSAlexei Starovoitov {
646*f8a8faceSAlexei Starovoitov 	u32 cur_postorder, i, top, stack_sz, s;
647*f8a8faceSAlexei Starovoitov 	int *stack = NULL, *postorder = NULL, *state = NULL;
648*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *succ;
649*f8a8faceSAlexei Starovoitov 
650*f8a8faceSAlexei Starovoitov 	postorder = kvzalloc_objs(int, env->prog->len, GFP_KERNEL_ACCOUNT);
651*f8a8faceSAlexei Starovoitov 	state = kvzalloc_objs(int, env->prog->len, GFP_KERNEL_ACCOUNT);
652*f8a8faceSAlexei Starovoitov 	stack = kvzalloc_objs(int, env->prog->len, GFP_KERNEL_ACCOUNT);
653*f8a8faceSAlexei Starovoitov 	if (!postorder || !state || !stack) {
654*f8a8faceSAlexei Starovoitov 		kvfree(postorder);
655*f8a8faceSAlexei Starovoitov 		kvfree(state);
656*f8a8faceSAlexei Starovoitov 		kvfree(stack);
657*f8a8faceSAlexei Starovoitov 		return -ENOMEM;
658*f8a8faceSAlexei Starovoitov 	}
659*f8a8faceSAlexei Starovoitov 	cur_postorder = 0;
660*f8a8faceSAlexei Starovoitov 	for (i = 0; i < env->subprog_cnt; i++) {
661*f8a8faceSAlexei Starovoitov 		env->subprog_info[i].postorder_start = cur_postorder;
662*f8a8faceSAlexei Starovoitov 		stack[0] = env->subprog_info[i].start;
663*f8a8faceSAlexei Starovoitov 		stack_sz = 1;
664*f8a8faceSAlexei Starovoitov 		do {
665*f8a8faceSAlexei Starovoitov 			top = stack[stack_sz - 1];
666*f8a8faceSAlexei Starovoitov 			state[top] |= DISCOVERED;
667*f8a8faceSAlexei Starovoitov 			if (state[top] & EXPLORED) {
668*f8a8faceSAlexei Starovoitov 				postorder[cur_postorder++] = top;
669*f8a8faceSAlexei Starovoitov 				stack_sz--;
670*f8a8faceSAlexei Starovoitov 				continue;
671*f8a8faceSAlexei Starovoitov 			}
672*f8a8faceSAlexei Starovoitov 			succ = bpf_insn_successors(env, top);
673*f8a8faceSAlexei Starovoitov 			for (s = 0; s < succ->cnt; ++s) {
674*f8a8faceSAlexei Starovoitov 				if (!state[succ->items[s]]) {
675*f8a8faceSAlexei Starovoitov 					stack[stack_sz++] = succ->items[s];
676*f8a8faceSAlexei Starovoitov 					state[succ->items[s]] |= DISCOVERED;
677*f8a8faceSAlexei Starovoitov 				}
678*f8a8faceSAlexei Starovoitov 			}
679*f8a8faceSAlexei Starovoitov 			state[top] |= EXPLORED;
680*f8a8faceSAlexei Starovoitov 		} while (stack_sz);
681*f8a8faceSAlexei Starovoitov 	}
682*f8a8faceSAlexei Starovoitov 	env->subprog_info[i].postorder_start = cur_postorder;
683*f8a8faceSAlexei Starovoitov 	env->cfg.insn_postorder = postorder;
684*f8a8faceSAlexei Starovoitov 	env->cfg.cur_postorder = cur_postorder;
685*f8a8faceSAlexei Starovoitov 	kvfree(stack);
686*f8a8faceSAlexei Starovoitov 	kvfree(state);
687*f8a8faceSAlexei Starovoitov 	return 0;
688*f8a8faceSAlexei Starovoitov }
689*f8a8faceSAlexei Starovoitov 
690*f8a8faceSAlexei Starovoitov /*
691*f8a8faceSAlexei Starovoitov  * Compute strongly connected components (SCCs) on the CFG.
692*f8a8faceSAlexei Starovoitov  * Assign an SCC number to each instruction, recorded in env->insn_aux[*].scc.
693*f8a8faceSAlexei Starovoitov  * If instruction is a sole member of its SCC and there are no self edges,
694*f8a8faceSAlexei Starovoitov  * assign it SCC number of zero.
695*f8a8faceSAlexei Starovoitov  * Uses a non-recursive adaptation of Tarjan's algorithm for SCC computation.
696*f8a8faceSAlexei Starovoitov  */
697*f8a8faceSAlexei Starovoitov int bpf_compute_scc(struct bpf_verifier_env *env)
698*f8a8faceSAlexei Starovoitov {
699*f8a8faceSAlexei Starovoitov 	const u32 NOT_ON_STACK = U32_MAX;
700*f8a8faceSAlexei Starovoitov 
701*f8a8faceSAlexei Starovoitov 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
702*f8a8faceSAlexei Starovoitov 	const u32 insn_cnt = env->prog->len;
703*f8a8faceSAlexei Starovoitov 	int stack_sz, dfs_sz, err = 0;
704*f8a8faceSAlexei Starovoitov 	u32 *stack, *pre, *low, *dfs;
705*f8a8faceSAlexei Starovoitov 	u32 i, j, t, w;
706*f8a8faceSAlexei Starovoitov 	u32 next_preorder_num;
707*f8a8faceSAlexei Starovoitov 	u32 next_scc_id;
708*f8a8faceSAlexei Starovoitov 	bool assign_scc;
709*f8a8faceSAlexei Starovoitov 	struct bpf_iarray *succ;
710*f8a8faceSAlexei Starovoitov 
711*f8a8faceSAlexei Starovoitov 	next_preorder_num = 1;
712*f8a8faceSAlexei Starovoitov 	next_scc_id = 1;
713*f8a8faceSAlexei Starovoitov 	/*
714*f8a8faceSAlexei Starovoitov 	 * - 'stack' accumulates vertices in DFS order, see invariant comment below;
715*f8a8faceSAlexei Starovoitov 	 * - 'pre[t] == p' => preorder number of vertex 't' is 'p';
716*f8a8faceSAlexei Starovoitov 	 * - 'low[t] == n' => smallest preorder number of the vertex reachable from 't' is 'n';
717*f8a8faceSAlexei Starovoitov 	 * - 'dfs' DFS traversal stack, used to emulate explicit recursion.
718*f8a8faceSAlexei Starovoitov 	 */
719*f8a8faceSAlexei Starovoitov 	stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
720*f8a8faceSAlexei Starovoitov 	pre = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
721*f8a8faceSAlexei Starovoitov 	low = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
722*f8a8faceSAlexei Starovoitov 	dfs = kvcalloc(insn_cnt, sizeof(*dfs), GFP_KERNEL_ACCOUNT);
723*f8a8faceSAlexei Starovoitov 	if (!stack || !pre || !low || !dfs) {
724*f8a8faceSAlexei Starovoitov 		err = -ENOMEM;
725*f8a8faceSAlexei Starovoitov 		goto exit;
726*f8a8faceSAlexei Starovoitov 	}
727*f8a8faceSAlexei Starovoitov 	/*
728*f8a8faceSAlexei Starovoitov 	 * References:
729*f8a8faceSAlexei Starovoitov 	 * [1] R. Tarjan "Depth-First Search and Linear Graph Algorithms"
730*f8a8faceSAlexei Starovoitov 	 * [2] D. J. Pearce "A Space-Efficient Algorithm for Finding Strongly Connected Components"
731*f8a8faceSAlexei Starovoitov 	 *
732*f8a8faceSAlexei Starovoitov 	 * The algorithm maintains the following invariant:
733*f8a8faceSAlexei Starovoitov 	 * - suppose there is a path 'u' ~> 'v', such that 'pre[v] < pre[u]';
734*f8a8faceSAlexei Starovoitov 	 * - then, vertex 'u' remains on stack while vertex 'v' is on stack.
735*f8a8faceSAlexei Starovoitov 	 *
736*f8a8faceSAlexei Starovoitov 	 * Consequently:
737*f8a8faceSAlexei Starovoitov 	 * - If 'low[v] < pre[v]', there is a path from 'v' to some vertex 'u',
738*f8a8faceSAlexei Starovoitov 	 *   such that 'pre[u] == low[v]'; vertex 'u' is currently on the stack,
739*f8a8faceSAlexei Starovoitov 	 *   and thus there is an SCC (loop) containing both 'u' and 'v'.
740*f8a8faceSAlexei Starovoitov 	 * - If 'low[v] == pre[v]', loops containing 'v' have been explored,
741*f8a8faceSAlexei Starovoitov 	 *   and 'v' can be considered the root of some SCC.
742*f8a8faceSAlexei Starovoitov 	 *
743*f8a8faceSAlexei Starovoitov 	 * Here is a pseudo-code for an explicitly recursive version of the algorithm:
744*f8a8faceSAlexei Starovoitov 	 *
745*f8a8faceSAlexei Starovoitov 	 *    NOT_ON_STACK = insn_cnt + 1
746*f8a8faceSAlexei Starovoitov 	 *    pre = [0] * insn_cnt
747*f8a8faceSAlexei Starovoitov 	 *    low = [0] * insn_cnt
748*f8a8faceSAlexei Starovoitov 	 *    scc = [0] * insn_cnt
749*f8a8faceSAlexei Starovoitov 	 *    stack = []
750*f8a8faceSAlexei Starovoitov 	 *
751*f8a8faceSAlexei Starovoitov 	 *    next_preorder_num = 1
752*f8a8faceSAlexei Starovoitov 	 *    next_scc_id = 1
753*f8a8faceSAlexei Starovoitov 	 *
754*f8a8faceSAlexei Starovoitov 	 *    def recur(w):
755*f8a8faceSAlexei Starovoitov 	 *        nonlocal next_preorder_num
756*f8a8faceSAlexei Starovoitov 	 *        nonlocal next_scc_id
757*f8a8faceSAlexei Starovoitov 	 *
758*f8a8faceSAlexei Starovoitov 	 *        pre[w] = next_preorder_num
759*f8a8faceSAlexei Starovoitov 	 *        low[w] = next_preorder_num
760*f8a8faceSAlexei Starovoitov 	 *        next_preorder_num += 1
761*f8a8faceSAlexei Starovoitov 	 *        stack.append(w)
762*f8a8faceSAlexei Starovoitov 	 *        for s in successors(w):
763*f8a8faceSAlexei Starovoitov 	 *            # Note: for classic algorithm the block below should look as:
764*f8a8faceSAlexei Starovoitov 	 *            #
765*f8a8faceSAlexei Starovoitov 	 *            # if pre[s] == 0:
766*f8a8faceSAlexei Starovoitov 	 *            #     recur(s)
767*f8a8faceSAlexei Starovoitov 	 *            #     low[w] = min(low[w], low[s])
768*f8a8faceSAlexei Starovoitov 	 *            # elif low[s] != NOT_ON_STACK:
769*f8a8faceSAlexei Starovoitov 	 *            #     low[w] = min(low[w], pre[s])
770*f8a8faceSAlexei Starovoitov 	 *            #
771*f8a8faceSAlexei Starovoitov 	 *            # But replacing both 'min' instructions with 'low[w] = min(low[w], low[s])'
772*f8a8faceSAlexei Starovoitov 	 *            # does not break the invariant and makes iterative version of the algorithm
773*f8a8faceSAlexei Starovoitov 	 *            # simpler. See 'Algorithm #3' from [2].
774*f8a8faceSAlexei Starovoitov 	 *
775*f8a8faceSAlexei Starovoitov 	 *            # 's' not yet visited
776*f8a8faceSAlexei Starovoitov 	 *            if pre[s] == 0:
777*f8a8faceSAlexei Starovoitov 	 *                recur(s)
778*f8a8faceSAlexei Starovoitov 	 *            # if 's' is on stack, pick lowest reachable preorder number from it;
779*f8a8faceSAlexei Starovoitov 	 *            # if 's' is not on stack 'low[s] == NOT_ON_STACK > low[w]',
780*f8a8faceSAlexei Starovoitov 	 *            # so 'min' would be a noop.
781*f8a8faceSAlexei Starovoitov 	 *            low[w] = min(low[w], low[s])
782*f8a8faceSAlexei Starovoitov 	 *
783*f8a8faceSAlexei Starovoitov 	 *        if low[w] == pre[w]:
784*f8a8faceSAlexei Starovoitov 	 *            # 'w' is the root of an SCC, pop all vertices
785*f8a8faceSAlexei Starovoitov 	 *            # below 'w' on stack and assign same SCC to them.
786*f8a8faceSAlexei Starovoitov 	 *            while True:
787*f8a8faceSAlexei Starovoitov 	 *                t = stack.pop()
788*f8a8faceSAlexei Starovoitov 	 *                low[t] = NOT_ON_STACK
789*f8a8faceSAlexei Starovoitov 	 *                scc[t] = next_scc_id
790*f8a8faceSAlexei Starovoitov 	 *                if t == w:
791*f8a8faceSAlexei Starovoitov 	 *                    break
792*f8a8faceSAlexei Starovoitov 	 *            next_scc_id += 1
793*f8a8faceSAlexei Starovoitov 	 *
794*f8a8faceSAlexei Starovoitov 	 *    for i in range(0, insn_cnt):
795*f8a8faceSAlexei Starovoitov 	 *        if pre[i] == 0:
796*f8a8faceSAlexei Starovoitov 	 *            recur(i)
797*f8a8faceSAlexei Starovoitov 	 *
798*f8a8faceSAlexei Starovoitov 	 * Below implementation replaces explicit recursion with array 'dfs'.
799*f8a8faceSAlexei Starovoitov 	 */
800*f8a8faceSAlexei Starovoitov 	for (i = 0; i < insn_cnt; i++) {
801*f8a8faceSAlexei Starovoitov 		if (pre[i])
802*f8a8faceSAlexei Starovoitov 			continue;
803*f8a8faceSAlexei Starovoitov 		stack_sz = 0;
804*f8a8faceSAlexei Starovoitov 		dfs_sz = 1;
805*f8a8faceSAlexei Starovoitov 		dfs[0] = i;
806*f8a8faceSAlexei Starovoitov dfs_continue:
807*f8a8faceSAlexei Starovoitov 		while (dfs_sz) {
808*f8a8faceSAlexei Starovoitov 			w = dfs[dfs_sz - 1];
809*f8a8faceSAlexei Starovoitov 			if (pre[w] == 0) {
810*f8a8faceSAlexei Starovoitov 				low[w] = next_preorder_num;
811*f8a8faceSAlexei Starovoitov 				pre[w] = next_preorder_num;
812*f8a8faceSAlexei Starovoitov 				next_preorder_num++;
813*f8a8faceSAlexei Starovoitov 				stack[stack_sz++] = w;
814*f8a8faceSAlexei Starovoitov 			}
815*f8a8faceSAlexei Starovoitov 			/* Visit 'w' successors */
816*f8a8faceSAlexei Starovoitov 			succ = bpf_insn_successors(env, w);
817*f8a8faceSAlexei Starovoitov 			for (j = 0; j < succ->cnt; ++j) {
818*f8a8faceSAlexei Starovoitov 				if (pre[succ->items[j]]) {
819*f8a8faceSAlexei Starovoitov 					low[w] = min(low[w], low[succ->items[j]]);
820*f8a8faceSAlexei Starovoitov 				} else {
821*f8a8faceSAlexei Starovoitov 					dfs[dfs_sz++] = succ->items[j];
822*f8a8faceSAlexei Starovoitov 					goto dfs_continue;
823*f8a8faceSAlexei Starovoitov 				}
824*f8a8faceSAlexei Starovoitov 			}
825*f8a8faceSAlexei Starovoitov 			/*
826*f8a8faceSAlexei Starovoitov 			 * Preserve the invariant: if some vertex above in the stack
827*f8a8faceSAlexei Starovoitov 			 * is reachable from 'w', keep 'w' on the stack.
828*f8a8faceSAlexei Starovoitov 			 */
829*f8a8faceSAlexei Starovoitov 			if (low[w] < pre[w]) {
830*f8a8faceSAlexei Starovoitov 				dfs_sz--;
831*f8a8faceSAlexei Starovoitov 				goto dfs_continue;
832*f8a8faceSAlexei Starovoitov 			}
833*f8a8faceSAlexei Starovoitov 			/*
834*f8a8faceSAlexei Starovoitov 			 * Assign SCC number only if component has two or more elements,
835*f8a8faceSAlexei Starovoitov 			 * or if component has a self reference, or if instruction is a
836*f8a8faceSAlexei Starovoitov 			 * callback calling function (implicit loop).
837*f8a8faceSAlexei Starovoitov 			 */
838*f8a8faceSAlexei Starovoitov 			assign_scc = stack[stack_sz - 1] != w;	/* two or more elements? */
839*f8a8faceSAlexei Starovoitov 			for (j = 0; j < succ->cnt; ++j) {	/* self reference? */
840*f8a8faceSAlexei Starovoitov 				if (succ->items[j] == w) {
841*f8a8faceSAlexei Starovoitov 					assign_scc = true;
842*f8a8faceSAlexei Starovoitov 					break;
843*f8a8faceSAlexei Starovoitov 				}
844*f8a8faceSAlexei Starovoitov 			}
845*f8a8faceSAlexei Starovoitov 			if (bpf_calls_callback(env, w)) /* implicit loop? */
846*f8a8faceSAlexei Starovoitov 				assign_scc = true;
847*f8a8faceSAlexei Starovoitov 			/* Pop component elements from stack */
848*f8a8faceSAlexei Starovoitov 			do {
849*f8a8faceSAlexei Starovoitov 				t = stack[--stack_sz];
850*f8a8faceSAlexei Starovoitov 				low[t] = NOT_ON_STACK;
851*f8a8faceSAlexei Starovoitov 				if (assign_scc)
852*f8a8faceSAlexei Starovoitov 					aux[t].scc = next_scc_id;
853*f8a8faceSAlexei Starovoitov 			} while (t != w);
854*f8a8faceSAlexei Starovoitov 			if (assign_scc)
855*f8a8faceSAlexei Starovoitov 				next_scc_id++;
856*f8a8faceSAlexei Starovoitov 			dfs_sz--;
857*f8a8faceSAlexei Starovoitov 		}
858*f8a8faceSAlexei Starovoitov 	}
859*f8a8faceSAlexei Starovoitov 	env->scc_info = kvzalloc_objs(*env->scc_info, next_scc_id,
860*f8a8faceSAlexei Starovoitov 				      GFP_KERNEL_ACCOUNT);
861*f8a8faceSAlexei Starovoitov 	if (!env->scc_info) {
862*f8a8faceSAlexei Starovoitov 		err = -ENOMEM;
863*f8a8faceSAlexei Starovoitov 		goto exit;
864*f8a8faceSAlexei Starovoitov 	}
865*f8a8faceSAlexei Starovoitov 	env->scc_cnt = next_scc_id;
866*f8a8faceSAlexei Starovoitov exit:
867*f8a8faceSAlexei Starovoitov 	kvfree(stack);
868*f8a8faceSAlexei Starovoitov 	kvfree(pre);
869*f8a8faceSAlexei Starovoitov 	kvfree(low);
870*f8a8faceSAlexei Starovoitov 	kvfree(dfs);
871*f8a8faceSAlexei Starovoitov 	return err;
872*f8a8faceSAlexei Starovoitov }
873