xref: /linux/kernel/bpf/scev.c (revision 32e962577d2d8a09fb09d4be2ddf96b82ae447c6)
11501b536SEduard Zingerman // SPDX-License-Identifier: GPL-2.0-only
21501b536SEduard Zingerman /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
31501b536SEduard Zingerman 
46ccf49f7SEduard Zingerman #include "linux/cnum.h"
51501b536SEduard Zingerman #include <linux/bpf_verifier.h>
61501b536SEduard Zingerman #include <linux/jhash.h>
71501b536SEduard Zingerman #include <linux/log2.h>
84cce2861SEduard Zingerman #include <linux/math64.h>
91501b536SEduard Zingerman #include <linux/min_heap.h>
101501b536SEduard Zingerman #include <linux/bug.h>
116ccf49f7SEduard Zingerman #include <linux/tnum.h>
126ccf49f7SEduard Zingerman #include <linux/overflow.h>
131501b536SEduard Zingerman 
14088a5477SEduard Zingerman #define REGS_NUM BPF_SCEV_REGS_NUM
151501b536SEduard Zingerman #define UNKNOWN_EXPR_ID 0
161501b536SEduard Zingerman #define OPAQUE_EXPR_ID  1
171501b536SEduard Zingerman 
181501b536SEduard Zingerman /*
191501b536SEduard Zingerman  * BPF instructions use 'code', 'src_reg', 'off' and 'imm' fields for instruction encoding.
201501b536SEduard Zingerman  * For scalar evolution purpose we want to reuse most of the opcode definitions,
211501b536SEduard Zingerman  * but also add a few custom operations (REG and IMM).
221501b536SEduard Zingerman  * Use the enum below to uniformly represent all operations relevant for SCEV.
231501b536SEduard Zingerman  */
241501b536SEduard Zingerman enum expr_op {
251501b536SEduard Zingerman 	/* leave range 0..255 for standard bpf opcodes */
261501b536SEduard Zingerman 	UNKNOWN = 256, /* start custom opcodes from the second byte */
271501b536SEduard Zingerman 	REG,
281501b536SEduard Zingerman 	IMM,
291501b536SEduard Zingerman 	SDIV, SMOD,
301501b536SEduard Zingerman 	SEXT8, SEXT16, SEXT32,
311501b536SEduard Zingerman 	ZEXT8, ZEXT16, ZEXT32,
321501b536SEduard Zingerman 	BSWAP16, BSWAP32, BSWAP64,
331501b536SEduard Zingerman 	/* during the loop body execution the value can be either of param[0] or param[1] */
341501b536SEduard Zingerman 	ANY,
351501b536SEduard Zingerman 	/* some value that verifier is not going to track precisely */
361501b536SEduard Zingerman 	OPAQUE,
371501b536SEduard Zingerman 	/* '*(u8/16/32 *)(r10 + X) = Y' writes define slot contents only partially */
381501b536SEduard Zingerman 	SPILL8, SPILL16, SPILL32,
391501b536SEduard Zingerman 	/*
401501b536SEduard Zingerman 	 * SCEV expression corresponding to linear equation 'param[0] + param[1] * k',
411501b536SEduard Zingerman 	 * where k is a loop iteration number. Loop here refers to innermost loop
421501b536SEduard Zingerman 	 * containing instruction associated with this expression, as returned by
431501b536SEduard Zingerman 	 * bpf_loop_at_index().
441501b536SEduard Zingerman 	 */
451501b536SEduard Zingerman 	LINEAR_SCEV,
461501b536SEduard Zingerman };
471501b536SEduard Zingerman 
481501b536SEduard Zingerman struct expr {
491501b536SEduard Zingerman 	u32 op;
501501b536SEduard Zingerman 	union {
511501b536SEduard Zingerman 		u32 params[2];
521501b536SEduard Zingerman 		s64 imm;
531501b536SEduard Zingerman 	};
541501b536SEduard Zingerman };
551501b536SEduard Zingerman 
561501b536SEduard Zingerman struct expr_bucket {
571501b536SEduard Zingerman 	u32 cnt;
581501b536SEduard Zingerman 	u32 cap;
591501b536SEduard Zingerman 	u32 ids[];
601501b536SEduard Zingerman };
611501b536SEduard Zingerman 
621501b536SEduard Zingerman struct env {
631501b536SEduard Zingerman 	bool empty;
641501b536SEduard Zingerman 	u32 reg2expr[REGS_NUM];
651501b536SEduard Zingerman 	u32 reg2scev[REGS_NUM];
661501b536SEduard Zingerman };
671501b536SEduard Zingerman 
681501b536SEduard Zingerman struct insn_envs {
691501b536SEduard Zingerman 	u32 cnt;
701501b536SEduard Zingerman 	struct {
711501b536SEduard Zingerman 		int loop_header;
721501b536SEduard Zingerman 		struct env *env;
731501b536SEduard Zingerman 	} entries[];
741501b536SEduard Zingerman };
751501b536SEduard Zingerman 
761501b536SEduard Zingerman #define EXPR_STACK_DEPTH 8
771501b536SEduard Zingerman 
781501b536SEduard Zingerman struct expr_stack_elt {
791501b536SEduard Zingerman 	u32 id:28;
801501b536SEduard Zingerman 	u32 pre:1;
811501b536SEduard Zingerman 	u32 next_param:2;
821501b536SEduard Zingerman };
831501b536SEduard Zingerman 
841501b536SEduard Zingerman DEFINE_MIN_HEAP(int, scev_worklist);
851501b536SEduard Zingerman 
861501b536SEduard Zingerman struct scev {
876ccf49f7SEduard Zingerman 	/* Read-only representatives for stack slots without a saved register. */
886ccf49f7SEduard Zingerman 	struct bpf_reg_state zero_reg;
896ccf49f7SEduard Zingerman 	struct bpf_reg_state unknown_reg;
901501b536SEduard Zingerman 	/*
911501b536SEduard Zingerman 	 * Expressions are identified by id, exprs_ht ensures that
921501b536SEduard Zingerman 	 * each expression exists as a unique instance.
931501b536SEduard Zingerman 	 * This allows for fast equivalence check: id1 === id2.
941501b536SEduard Zingerman 	 */
951501b536SEduard Zingerman 	struct expr_bucket **exprs_ht;
961501b536SEduard Zingerman 	struct scev_worklist worklist;
971501b536SEduard Zingerman 	struct insn_envs **envs;
981501b536SEduard Zingerman 	struct expr *exprs;
991501b536SEduard Zingerman 	/*
1001501b536SEduard Zingerman 	 * Loops are analyzed one by one, this array keeps track if a particular
1011501b536SEduard Zingerman 	 * instruction was visited on a current pass.
1021501b536SEduard Zingerman 	 */
1031501b536SEduard Zingerman 	u32 *discovered;
1041501b536SEduard Zingerman 	u32 exprs_ht_cnt;
1051501b536SEduard Zingerman 	int exprs_cnt;
1061501b536SEduard Zingerman 	int exprs_cap;
1071501b536SEduard Zingerman 	int envs_cnt;
1081501b536SEduard Zingerman 	int stack_sz;
1091501b536SEduard Zingerman 	struct expr_stack_elt expr_stack[EXPR_STACK_DEPTH];
1101501b536SEduard Zingerman 	u32 ids_buf[EXPR_STACK_DEPTH];
1111501b536SEduard Zingerman };
1121501b536SEduard Zingerman 
1131501b536SEduard Zingerman static u32 expr_hash(struct expr *e)
1141501b536SEduard Zingerman {
1151501b536SEduard Zingerman 	return jhash_3words(e->op, e->params[0], e->params[1], 0);
1161501b536SEduard Zingerman }
1171501b536SEduard Zingerman 
1181501b536SEduard Zingerman static int expr_eq(struct expr *a, struct expr *b)
1191501b536SEduard Zingerman {
1201501b536SEduard Zingerman 	return a->op == b->op && a->imm == b->imm;
1211501b536SEduard Zingerman }
1221501b536SEduard Zingerman 
1231501b536SEduard Zingerman static int add_expr(struct scev *scev, struct expr e)
1241501b536SEduard Zingerman {
1251501b536SEduard Zingerman 	struct expr_bucket *bucket;
1261501b536SEduard Zingerman 	u32 i, id, hash, new_cap;
1271501b536SEduard Zingerman 	void *tmp;
1281501b536SEduard Zingerman 
1291501b536SEduard Zingerman 	hash = expr_hash(&e) & (scev->exprs_ht_cnt - 1);
1301501b536SEduard Zingerman 	bucket = scev->exprs_ht[hash];
1311501b536SEduard Zingerman 
1321501b536SEduard Zingerman 	if (bucket) {
1331501b536SEduard Zingerman 		for (i = 0; i < bucket->cnt; i++) {
1341501b536SEduard Zingerman 			id = bucket->ids[i];
1351501b536SEduard Zingerman 			if (expr_eq(&e, &scev->exprs[id]))
1361501b536SEduard Zingerman 				return id;
1371501b536SEduard Zingerman 		}
1381501b536SEduard Zingerman 	}
1391501b536SEduard Zingerman 
1401501b536SEduard Zingerman 	if (!bucket || bucket->cap == bucket->cnt) {
1411501b536SEduard Zingerman 		new_cap = bucket ? bucket->cap * 2 : 4;
1421501b536SEduard Zingerman 		bucket = kvrealloc(bucket, sizeof(*bucket) + sizeof(u32) * new_cap, GFP_KERNEL_ACCOUNT | __GFP_ZERO);
1431501b536SEduard Zingerman 		if (!bucket)
1441501b536SEduard Zingerman 			return -ENOMEM;
1451501b536SEduard Zingerman 		scev->exprs_ht[hash] = bucket;
1461501b536SEduard Zingerman 		bucket->cap = new_cap;
1471501b536SEduard Zingerman 	}
1481501b536SEduard Zingerman 
1491501b536SEduard Zingerman 	if (scev->exprs_cnt == scev->exprs_cap) {
1501501b536SEduard Zingerman 		new_cap = scev->exprs_cap ? scev->exprs_cap * 2 : 256;
1511501b536SEduard Zingerman 		tmp = kvrealloc(scev->exprs, sizeof(struct expr) * new_cap, GFP_KERNEL_ACCOUNT);
1521501b536SEduard Zingerman 		if (!tmp)
1531501b536SEduard Zingerman 			return -ENOMEM;
1541501b536SEduard Zingerman 		scev->exprs = tmp;
1551501b536SEduard Zingerman 		scev->exprs_cap = new_cap;
1561501b536SEduard Zingerman 	}
1571501b536SEduard Zingerman 
1581501b536SEduard Zingerman 	id = scev->exprs_cnt++;
1591501b536SEduard Zingerman 	scev->exprs[id] = e;
1601501b536SEduard Zingerman 	bucket->ids[bucket->cnt++] = id;
1611501b536SEduard Zingerman 	return id;
1621501b536SEduard Zingerman }
1631501b536SEduard Zingerman 
1641501b536SEduard Zingerman static int expr2(struct scev *scev, u32 op, int a, int b)
1651501b536SEduard Zingerman {
1661501b536SEduard Zingerman 	if (a < 0)
1671501b536SEduard Zingerman 		return a;
1681501b536SEduard Zingerman 	if (b < 0)
1691501b536SEduard Zingerman 		return b;
1701501b536SEduard Zingerman 	return add_expr(scev, (struct expr){ .op = op, .params = {a, b} });
1711501b536SEduard Zingerman }
1721501b536SEduard Zingerman 
1731501b536SEduard Zingerman static int expr1(struct scev *scev, u32 op, int a)
1741501b536SEduard Zingerman {
1751501b536SEduard Zingerman 	if (a < 0)
1761501b536SEduard Zingerman 		return a;
1771501b536SEduard Zingerman 	return expr2(scev, op, a, 0);
1781501b536SEduard Zingerman }
1791501b536SEduard Zingerman 
1801501b536SEduard Zingerman static int expr0(struct scev *scev, u32 op)
1811501b536SEduard Zingerman {
1821501b536SEduard Zingerman 	return expr2(scev, op, 0, 0);
1831501b536SEduard Zingerman }
1841501b536SEduard Zingerman 
1851501b536SEduard Zingerman static int imm_expr(struct scev *scev, s64 value)
1861501b536SEduard Zingerman {
1871501b536SEduard Zingerman 	return add_expr(scev, (struct expr){ .op = IMM, .imm = value });
1881501b536SEduard Zingerman }
1891501b536SEduard Zingerman 
1901501b536SEduard Zingerman static bool same_exprs(struct scev *scev, int id_a, int id_b)
1911501b536SEduard Zingerman {
1921501b536SEduard Zingerman 	return id_a == id_b;
1931501b536SEduard Zingerman }
1941501b536SEduard Zingerman 
1951501b536SEduard Zingerman static bool is_imm(struct scev *scev, int id, s64 *imm)
1961501b536SEduard Zingerman {
1971501b536SEduard Zingerman 	if (scev->exprs[id].op != IMM)
1981501b536SEduard Zingerman 		return false;
1991501b536SEduard Zingerman 	*imm = scev->exprs[id].imm;
2001501b536SEduard Zingerman 	return true;
2011501b536SEduard Zingerman }
2021501b536SEduard Zingerman 
2031501b536SEduard Zingerman static bool is_op(struct scev *scev, int id, u32 op)
2041501b536SEduard Zingerman {
2051501b536SEduard Zingerman 	if (scev->exprs[id].op != op)
2061501b536SEduard Zingerman 		return false;
2071501b536SEduard Zingerman 	return true;
2081501b536SEduard Zingerman }
2091501b536SEduard Zingerman 
2101501b536SEduard Zingerman static bool is_unop(struct scev *scev, enum expr_op op, int id, u32 *p0)
2111501b536SEduard Zingerman {
2121501b536SEduard Zingerman 	if (scev->exprs[id].op != op)
2131501b536SEduard Zingerman 		return false;
2141501b536SEduard Zingerman 	*p0 = scev->exprs[id].params[0];
2151501b536SEduard Zingerman 	return true;
2161501b536SEduard Zingerman }
2171501b536SEduard Zingerman 
2181501b536SEduard Zingerman static bool is_binop(struct scev *scev, enum expr_op op, int id, u32 *p0, u32 *p1)
2191501b536SEduard Zingerman {
2201501b536SEduard Zingerman 	if (scev->exprs[id].op != op)
2211501b536SEduard Zingerman 		return false;
2221501b536SEduard Zingerman 	*p0 = scev->exprs[id].params[0];
2231501b536SEduard Zingerman 	*p1 = scev->exprs[id].params[1];
2241501b536SEduard Zingerman 	return true;
2251501b536SEduard Zingerman }
2261501b536SEduard Zingerman 
2271501b536SEduard Zingerman static bool is_reg(struct scev *scev, int id, u32 *reg)
2281501b536SEduard Zingerman {
2291501b536SEduard Zingerman 	return is_unop(scev, REG, id, reg);
2301501b536SEduard Zingerman }
2311501b536SEduard Zingerman 
2321501b536SEduard Zingerman static bool is_add(struct scev *scev, int id, u32 *left, u32 *right)
2331501b536SEduard Zingerman {
2341501b536SEduard Zingerman 	return is_binop(scev, BPF_ADD, id, left, right);
2351501b536SEduard Zingerman }
2361501b536SEduard Zingerman 
2371501b536SEduard Zingerman static bool is_zext32(struct scev *scev, int id, u32 *left)
2381501b536SEduard Zingerman {
2391501b536SEduard Zingerman 	return is_unop(scev, ZEXT32, id, left);
2401501b536SEduard Zingerman }
2411501b536SEduard Zingerman 
2421501b536SEduard Zingerman static bool is_any(struct scev *scev, int id, u32 *left, u32 *right)
2431501b536SEduard Zingerman {
2441501b536SEduard Zingerman 	return is_binop(scev, ANY, id, left, right);
2451501b536SEduard Zingerman }
2461501b536SEduard Zingerman 
2471501b536SEduard Zingerman static bool is_linear(struct scev *scev, int id, u32 *base, u32 *slope)
2481501b536SEduard Zingerman {
2491501b536SEduard Zingerman 	return is_binop(scev, LINEAR_SCEV, id, base, slope);
2501501b536SEduard Zingerman }
2511501b536SEduard Zingerman 
252*32e96257SEduard Zingerman static bool is_linear_or_linear32(struct scev *scev, int id, u32 *base, u32 *slope, bool *zext32)
253*32e96257SEduard Zingerman {
254*32e96257SEduard Zingerman 	u32 t;
255*32e96257SEduard Zingerman 
256*32e96257SEduard Zingerman 	*zext32 = is_zext32(scev, id, &t);
257*32e96257SEduard Zingerman 	return is_linear(scev, *zext32 ? t : id, base, slope);
258*32e96257SEduard Zingerman }
259*32e96257SEduard Zingerman 
2601501b536SEduard Zingerman static bool is_opaque(struct scev *scev, int id)
2611501b536SEduard Zingerman {
2621501b536SEduard Zingerman 	return is_op(scev, id, OPAQUE);
2631501b536SEduard Zingerman }
2641501b536SEduard Zingerman 
2651501b536SEduard Zingerman static void log_reg(struct bpf_verifier_env *env, u32 reg)
2661501b536SEduard Zingerman {
2671501b536SEduard Zingerman 	if (reg < MAX_BPF_REG)
2681501b536SEduard Zingerman 		bpf_log(&env->log, "r%d", reg);
2691501b536SEduard Zingerman 	else
2701501b536SEduard Zingerman 		bpf_log(&env->log, "*fp%d", (MAX_BPF_REG - reg - 1) * 8);
2711501b536SEduard Zingerman }
2721501b536SEduard Zingerman 
2731501b536SEduard Zingerman static const char *op_str(u32 op)
2741501b536SEduard Zingerman {
2751501b536SEduard Zingerman 	switch (op) {
2761501b536SEduard Zingerman 	case BPF_ADD:  return "+";
2771501b536SEduard Zingerman 	case BPF_SUB:  return "-";
2781501b536SEduard Zingerman 	case BPF_MUL:  return "*";
2791501b536SEduard Zingerman 	case BPF_DIV:  return "/";
2801501b536SEduard Zingerman 	case SDIV:     return "s/";
2811501b536SEduard Zingerman 	case BPF_OR:   return "|";
2821501b536SEduard Zingerman 	case BPF_AND:  return "&";
2831501b536SEduard Zingerman 	case BPF_LSH:  return "<<";
2841501b536SEduard Zingerman 	case BPF_RSH:  return ">>";
2851501b536SEduard Zingerman 	case BPF_NEG:  return "-";
2861501b536SEduard Zingerman 	case BPF_MOD:  return "%";
2871501b536SEduard Zingerman 	case SMOD:     return "s%";
2881501b536SEduard Zingerman 	case BPF_XOR:  return "^";
2891501b536SEduard Zingerman 	case BPF_ARSH: return "s>>";
2901501b536SEduard Zingerman 	case SEXT8:    return "sext8";
2911501b536SEduard Zingerman 	case SEXT16:   return "sext16";
2921501b536SEduard Zingerman 	case SEXT32:   return "sext32";
2931501b536SEduard Zingerman 	case ZEXT8:    return "zext8";
2941501b536SEduard Zingerman 	case ZEXT16:   return "zext16";
2951501b536SEduard Zingerman 	case ZEXT32:   return "zext32";
2961501b536SEduard Zingerman 	case BSWAP16:  return "bswap16";
2971501b536SEduard Zingerman 	case BSWAP32:  return "bswap32";
2981501b536SEduard Zingerman 	case BSWAP64:  return "bswap64";
2991501b536SEduard Zingerman 	case SPILL8:   return "spill8";
3001501b536SEduard Zingerman 	case SPILL16:  return "spill16";
3011501b536SEduard Zingerman 	case SPILL32:  return "spill32";
3021501b536SEduard Zingerman 	case ANY:      return "any";
3031501b536SEduard Zingerman 	case LINEAR_SCEV:  return "linear";
3041501b536SEduard Zingerman 	}
3051501b536SEduard Zingerman 	return NULL;
3061501b536SEduard Zingerman }
3071501b536SEduard Zingerman 
3081501b536SEduard Zingerman static u32 op_params_num(u32 op)
3091501b536SEduard Zingerman {
3101501b536SEduard Zingerman 	switch (op) {
3111501b536SEduard Zingerman 	case BPF_ADD:
3121501b536SEduard Zingerman 	case BPF_SUB:
3131501b536SEduard Zingerman 	case BPF_MUL:
3141501b536SEduard Zingerman 	case BPF_DIV:
3151501b536SEduard Zingerman 	case BPF_MOD:
3161501b536SEduard Zingerman 	case BPF_OR:
3171501b536SEduard Zingerman 	case BPF_XOR:
3181501b536SEduard Zingerman 	case BPF_AND:
3191501b536SEduard Zingerman 	case BPF_LSH:
3201501b536SEduard Zingerman 	case BPF_RSH:
3211501b536SEduard Zingerman 	case BPF_ARSH:
3221501b536SEduard Zingerman 	case SDIV:
3231501b536SEduard Zingerman 	case SMOD:
3241501b536SEduard Zingerman 	case ANY:
3251501b536SEduard Zingerman 	case LINEAR_SCEV:
3261501b536SEduard Zingerman 		return 2;
3271501b536SEduard Zingerman 	case BPF_NEG:
3281501b536SEduard Zingerman 	case SEXT8:
3291501b536SEduard Zingerman 	case SEXT16:
3301501b536SEduard Zingerman 	case SEXT32:
3311501b536SEduard Zingerman 	case ZEXT8:
3321501b536SEduard Zingerman 	case ZEXT16:
3331501b536SEduard Zingerman 	case ZEXT32:
3341501b536SEduard Zingerman 	case BSWAP16:
3351501b536SEduard Zingerman 	case BSWAP32:
3361501b536SEduard Zingerman 	case BSWAP64:
3371501b536SEduard Zingerman 	case SPILL8:
3381501b536SEduard Zingerman 	case SPILL16:
3391501b536SEduard Zingerman 	case SPILL32:
3401501b536SEduard Zingerman 		return 1;
3411501b536SEduard Zingerman 	case REG:
3421501b536SEduard Zingerman 	case IMM:
3431501b536SEduard Zingerman 	case OPAQUE:
3441501b536SEduard Zingerman 		return 0;
3451501b536SEduard Zingerman 	default:
3461501b536SEduard Zingerman 		return 0;
3471501b536SEduard Zingerman 	}
3481501b536SEduard Zingerman }
3491501b536SEduard Zingerman 
3501501b536SEduard Zingerman static bool expr_stack_push(struct scev *scev, u32 id)
3511501b536SEduard Zingerman {
3521501b536SEduard Zingerman 	if (scev->stack_sz >= EXPR_STACK_DEPTH)
3531501b536SEduard Zingerman 		return false;
3541501b536SEduard Zingerman 	scev->expr_stack[scev->stack_sz].id = id;
3551501b536SEduard Zingerman 	scev->expr_stack[scev->stack_sz].pre = true;
3561501b536SEduard Zingerman 	scev->expr_stack[scev->stack_sz].next_param = 0;
3571501b536SEduard Zingerman 	scev->stack_sz++;
3581501b536SEduard Zingerman 	return true;
3591501b536SEduard Zingerman }
3601501b536SEduard Zingerman 
3611501b536SEduard Zingerman enum {
3621501b536SEduard Zingerman 	PRE = BIT(1), POST = BIT(2), DEPTH_LIMIT = BIT(3)
3631501b536SEduard Zingerman };
3641501b536SEduard Zingerman 
3651501b536SEduard Zingerman static bool expr_next(struct scev *scev, u32 *id, u32 *order)
3661501b536SEduard Zingerman {
3671501b536SEduard Zingerman 	struct expr_stack_elt *elt;
3681501b536SEduard Zingerman 	struct expr *expr;
3691501b536SEduard Zingerman 	u32 num_params;
3701501b536SEduard Zingerman 
3711501b536SEduard Zingerman 	if (scev->stack_sz == 0)
3721501b536SEduard Zingerman 		return false;
3731501b536SEduard Zingerman 
3741501b536SEduard Zingerman 	elt = &scev->expr_stack[scev->stack_sz - 1];
3751501b536SEduard Zingerman 	*id = elt->id;
3761501b536SEduard Zingerman 	*order = 0;
3771501b536SEduard Zingerman 	expr = &scev->exprs[elt->id];
3781501b536SEduard Zingerman 	num_params = op_params_num(expr->op);
3791501b536SEduard Zingerman 	if (elt->pre) {
3801501b536SEduard Zingerman 		elt->pre = false;
3811501b536SEduard Zingerman 		*order = PRE;
3821501b536SEduard Zingerman 		return true;
3831501b536SEduard Zingerman 	}
3841501b536SEduard Zingerman 	if (elt->next_param == num_params) {
3851501b536SEduard Zingerman 		*order = POST;
3861501b536SEduard Zingerman 		scev->stack_sz--;
3871501b536SEduard Zingerman 		return true;
3881501b536SEduard Zingerman 	}
3891501b536SEduard Zingerman 	if (scev->stack_sz == EXPR_STACK_DEPTH) {
3901501b536SEduard Zingerman 		*order = POST | DEPTH_LIMIT;
3911501b536SEduard Zingerman 		scev->stack_sz--;
3921501b536SEduard Zingerman 		return true;
3931501b536SEduard Zingerman 	}
3941501b536SEduard Zingerman 	expr_stack_push(scev, expr->params[elt->next_param]);
3951501b536SEduard Zingerman 	elt->next_param++;
3961501b536SEduard Zingerman 	return expr_next(scev, id, order);
3971501b536SEduard Zingerman }
3981501b536SEduard Zingerman 
3991501b536SEduard Zingerman static void log_expr(struct bpf_verifier_env *env, u32 id)
4001501b536SEduard Zingerman {
4011501b536SEduard Zingerman 	struct bpf_verifier_log *log = &env->log;
4021501b536SEduard Zingerman 	struct scev *scev = env->scev;
4031501b536SEduard Zingerman 	struct expr *expr;
4041501b536SEduard Zingerman 	const char *str;
4051501b536SEduard Zingerman 	u32 order;
4061501b536SEduard Zingerman 
4071501b536SEduard Zingerman 	scev->stack_sz = 0;
4081501b536SEduard Zingerman 	expr_stack_push(scev, id);
4091501b536SEduard Zingerman 	while (expr_next(scev, &id, &order)) {
4101501b536SEduard Zingerman 		if ((order & PRE) && scev->stack_sz > 1)
4111501b536SEduard Zingerman 			bpf_log(log, " ");
4121501b536SEduard Zingerman 		expr = &scev->exprs[id];
4131501b536SEduard Zingerman 		switch (expr->op) {
4141501b536SEduard Zingerman 		case UNKNOWN:
4151501b536SEduard Zingerman 			if (order & PRE)
4161501b536SEduard Zingerman 				bpf_log(log, "?");
4171501b536SEduard Zingerman 			break;
4181501b536SEduard Zingerman 		case OPAQUE:
4191501b536SEduard Zingerman 			if (order & PRE)
4201501b536SEduard Zingerman 				bpf_log(log, "_");
4211501b536SEduard Zingerman 			break;
4221501b536SEduard Zingerman 		case REG:
4231501b536SEduard Zingerman 			if (order & PRE)
4241501b536SEduard Zingerman 				log_reg(env, expr->params[0]);
4251501b536SEduard Zingerman 			break;
4261501b536SEduard Zingerman 		case IMM:
4271501b536SEduard Zingerman 			if (order & PRE)
4281501b536SEduard Zingerman 				bpf_log(log, "%lld", expr->imm);
4291501b536SEduard Zingerman 			break;
4301501b536SEduard Zingerman 		default:
4311501b536SEduard Zingerman 			if (order & PRE) {
4321501b536SEduard Zingerman 				str = op_str(expr->op);
4331501b536SEduard Zingerman 				bpf_log(log, "(");
4341501b536SEduard Zingerman 				if (str)
4351501b536SEduard Zingerman 					bpf_log(log, "%s", str);
4361501b536SEduard Zingerman 				else
4371501b536SEduard Zingerman 					bpf_log(log, "bad-expr-op %x", expr->op);
4381501b536SEduard Zingerman 			}
4391501b536SEduard Zingerman 			if (order & DEPTH_LIMIT)
4401501b536SEduard Zingerman 				bpf_log(log, "...");
4411501b536SEduard Zingerman 			if (order & POST)
4421501b536SEduard Zingerman 				bpf_log(log, ")");
4431501b536SEduard Zingerman 		}
4441501b536SEduard Zingerman 	}
4451501b536SEduard Zingerman }
4461501b536SEduard Zingerman 
4471501b536SEduard Zingerman static bool reg_alive_at(struct bpf_verifier_env *env, u32 reg, u32 insn_idx)
4481501b536SEduard Zingerman {
4491501b536SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
4501501b536SEduard Zingerman 	u16 live_regs = aux[insn_idx].live_regs_before;
4511501b536SEduard Zingerman 
4521501b536SEduard Zingerman 	return reg < MAX_BPF_REG
4531501b536SEduard Zingerman 	       ? (BIT(reg) & live_regs)
4541501b536SEduard Zingerman 	       : test_bit(reg - MAX_BPF_REG, aux[insn_idx].live_stack_before);
4551501b536SEduard Zingerman }
4561501b536SEduard Zingerman 
4571501b536SEduard Zingerman static void print_env(struct bpf_verifier_env *env, struct env *e, u32 insn_idx)
4581501b536SEduard Zingerman {
4591501b536SEduard Zingerman 	struct bpf_verifier_log *log = &env->log;
4601501b536SEduard Zingerman 	struct scev *scev = env->scev;
4611501b536SEduard Zingerman 	bool printed_some = false;
4621501b536SEduard Zingerman 	bool is_self_scev;
4631501b536SEduard Zingerman 	bool is_self_reg;
4641501b536SEduard Zingerman 	int i, r;
4651501b536SEduard Zingerman 
4661501b536SEduard Zingerman 	if (e->empty) {
4671501b536SEduard Zingerman 		bpf_log(log, "  <empty>\n");
4681501b536SEduard Zingerman 		return;
4691501b536SEduard Zingerman 	}
4701501b536SEduard Zingerman 
4711501b536SEduard Zingerman 	for (i = 0; i < REGS_NUM; i++) {
4721501b536SEduard Zingerman 		if (!reg_alive_at(env, i, insn_idx))
4731501b536SEduard Zingerman 			continue;
4741501b536SEduard Zingerman 		is_self_reg = is_reg(scev, e->reg2expr[i], &r) && i == r;
4751501b536SEduard Zingerman 		is_self_scev = is_reg(scev, e->reg2scev[i], &r) && i == r;
4761501b536SEduard Zingerman 		if (is_self_reg && is_self_scev)
4771501b536SEduard Zingerman 			continue;
4781501b536SEduard Zingerman 		printed_some = true;
4791501b536SEduard Zingerman 		bpf_log(log, "  ");
4801501b536SEduard Zingerman 		log_reg(env, i);
4811501b536SEduard Zingerman 		bpf_log(log, "=");
4821501b536SEduard Zingerman 		log_expr(env, e->reg2expr[i]);
4831501b536SEduard Zingerman 		if (e->reg2expr[i] != UNKNOWN_EXPR_ID) {
4841501b536SEduard Zingerman 			bpf_log(log, " / ");
4851501b536SEduard Zingerman 			log_expr(env, e->reg2scev[i]);
4861501b536SEduard Zingerman 		}
4871501b536SEduard Zingerman 		bpf_log(log, "\n");
4881501b536SEduard Zingerman 	}
4891501b536SEduard Zingerman 	if (!printed_some)
4901501b536SEduard Zingerman 		bpf_log(log, "  <all regs unchanged>\n");
4911501b536SEduard Zingerman }
4921501b536SEduard Zingerman static struct env *find_loop_env(struct scev *scev, int loop_header, int insn_idx)
4931501b536SEduard Zingerman {
4941501b536SEduard Zingerman 	struct insn_envs *envs = scev->envs[insn_idx];
4951501b536SEduard Zingerman 	u32 i;
4961501b536SEduard Zingerman 
4971501b536SEduard Zingerman 	if (!envs)
4981501b536SEduard Zingerman 		return NULL;
4991501b536SEduard Zingerman 	for (i = 0; i < envs->cnt; i++)
5001501b536SEduard Zingerman 		if (envs->entries[i].loop_header == loop_header)
5011501b536SEduard Zingerman 			return envs->entries[i].env;
5021501b536SEduard Zingerman 	return NULL;
5031501b536SEduard Zingerman }
5041501b536SEduard Zingerman 
5051501b536SEduard Zingerman static struct env *find_header_env(struct scev *scev, int header)
5061501b536SEduard Zingerman {
5071501b536SEduard Zingerman 	return find_loop_env(scev, header, header);
5081501b536SEduard Zingerman }
5091501b536SEduard Zingerman 
5101501b536SEduard Zingerman static struct env *get_loop_env(struct scev *scev, int loop_header, int insn_idx)
5111501b536SEduard Zingerman {
5121501b536SEduard Zingerman 	struct insn_envs *envs = scev->envs[insn_idx];
5131501b536SEduard Zingerman 	u32 cnt = envs ? envs->cnt : 0;
5141501b536SEduard Zingerman 	struct insn_envs *tmp;
5151501b536SEduard Zingerman 	struct env *e;
5161501b536SEduard Zingerman 
5171501b536SEduard Zingerman 	e = find_loop_env(scev, loop_header, insn_idx);
5181501b536SEduard Zingerman 	if (e)
5191501b536SEduard Zingerman 		return e;
5201501b536SEduard Zingerman 
5211501b536SEduard Zingerman 	e = kzalloc(sizeof(*e), GFP_KERNEL_ACCOUNT);
5221501b536SEduard Zingerman 	if (!e)
5231501b536SEduard Zingerman 		return NULL;
5241501b536SEduard Zingerman 
5251501b536SEduard Zingerman 	tmp = krealloc(envs, struct_size(envs, entries, cnt + 1), GFP_KERNEL_ACCOUNT);
5261501b536SEduard Zingerman 	if (!tmp) {
5271501b536SEduard Zingerman 		kfree(e);
5281501b536SEduard Zingerman 		return NULL;
5291501b536SEduard Zingerman 	}
5301501b536SEduard Zingerman 
5311501b536SEduard Zingerman 	e->empty = true;
5321501b536SEduard Zingerman 	tmp->entries[cnt].loop_header = loop_header;
5331501b536SEduard Zingerman 	tmp->entries[cnt].env = e;
5341501b536SEduard Zingerman 	tmp->cnt = cnt + 1;
5351501b536SEduard Zingerman 	scev->envs[insn_idx] = tmp;
5361501b536SEduard Zingerman 	return e;
5371501b536SEduard Zingerman }
5381501b536SEduard Zingerman 
5391501b536SEduard Zingerman static int replace_reg(struct scev *scev, struct env *e, u32 reg, int id)
5401501b536SEduard Zingerman {
5411501b536SEduard Zingerman 	if (id < 0)
5421501b536SEduard Zingerman 		return id;
5431501b536SEduard Zingerman 	e->reg2expr[reg] = id;
5441501b536SEduard Zingerman 	return 0;
5451501b536SEduard Zingerman }
5461501b536SEduard Zingerman 
5471501b536SEduard Zingerman static int setup_initial_loop_env(struct bpf_verifier_env *env, struct env *e, int insn_idx)
5481501b536SEduard Zingerman {
5491501b536SEduard Zingerman 	struct scev *scev = env->scev;
5501501b536SEduard Zingerman 	int i, err;
5511501b536SEduard Zingerman 
5521501b536SEduard Zingerman 	/*
5531501b536SEduard Zingerman 	 * Initial assignments are of form rX -> rX are needed as seeds for subsequent
5541501b536SEduard Zingerman 	 * work queue pop / transfer() calls. Because e->empty is true, the first backedge
5551501b536SEduard Zingerman 	 * join() will overwrite the them. compute_header_scevs() accounts for register
5561501b536SEduard Zingerman 	 * states at loop entry.
5571501b536SEduard Zingerman 	 */
5581501b536SEduard Zingerman 	for (i = 0; i < REGS_NUM; i++) {
5591501b536SEduard Zingerman 		err = replace_reg(scev, e, i, expr1(scev, REG, i));
5601501b536SEduard Zingerman 		if (err)
5611501b536SEduard Zingerman 			return err;
5621501b536SEduard Zingerman 	}
5631501b536SEduard Zingerman 	return 0;
5641501b536SEduard Zingerman }
5651501b536SEduard Zingerman 
5661501b536SEduard Zingerman static void forget_call_regs(struct env *e)
5671501b536SEduard Zingerman {
5681501b536SEduard Zingerman 	int i;
5691501b536SEduard Zingerman 
5701501b536SEduard Zingerman 	for (i = BPF_REG_0; i <= BPF_REG_5; i++)
5711501b536SEduard Zingerman 		e->reg2expr[i] = UNKNOWN_EXPR_ID;
5721501b536SEduard Zingerman }
5731501b536SEduard Zingerman 
5741501b536SEduard Zingerman static u32 spill_spi(struct bpf_insn *insn)
5751501b536SEduard Zingerman {
5761501b536SEduard Zingerman 	return -insn->off / BPF_REG_SIZE - 1;
5771501b536SEduard Zingerman }
5781501b536SEduard Zingerman 
5791501b536SEduard Zingerman static u32 off_to_reg(struct bpf_insn *insn)
5801501b536SEduard Zingerman {
5811501b536SEduard Zingerman 	return spill_spi(insn) + MAX_BPF_REG;
5821501b536SEduard Zingerman }
5831501b536SEduard Zingerman 
5841501b536SEduard Zingerman static bool is_spill_off(int off)
5851501b536SEduard Zingerman {
5861501b536SEduard Zingerman 	return off % BPF_REG_SIZE == 0 &&
5871501b536SEduard Zingerman 	       off <= -BPF_REG_SIZE &&
5881501b536SEduard Zingerman 	       off >= -MAX_BPF_STACK_JIT;
5891501b536SEduard Zingerman }
5901501b536SEduard Zingerman 
5911501b536SEduard Zingerman static void mark_opaque(struct env *e, int off, int size)
5921501b536SEduard Zingerman {
5931501b536SEduard Zingerman 	int b, spi;
5941501b536SEduard Zingerman 
5951501b536SEduard Zingerman 	for (b = off; b < off + size; b++) {
5961501b536SEduard Zingerman 		if (b >= 0 || b < -MAX_BPF_STACK_JIT)
5971501b536SEduard Zingerman 			continue;
5981501b536SEduard Zingerman 		spi = (-b - 1) / BPF_REG_SIZE;
5991501b536SEduard Zingerman 		e->reg2expr[MAX_BPF_REG + spi] = OPAQUE_EXPR_ID;
6001501b536SEduard Zingerman 	}
6011501b536SEduard Zingerman }
6021501b536SEduard Zingerman 
6031501b536SEduard Zingerman static int mk_spill(struct scev *scev, u8 size, int id)
6041501b536SEduard Zingerman {
6051501b536SEduard Zingerman 	switch (size) {
6061501b536SEduard Zingerman 	case BPF_B:  return expr1(scev, SPILL8,  id);
6071501b536SEduard Zingerman 	case BPF_H:  return expr1(scev, SPILL16, id);
6081501b536SEduard Zingerman 	case BPF_W:  return expr1(scev, SPILL32, id);
6091501b536SEduard Zingerman 	case BPF_DW: return id;
6101501b536SEduard Zingerman 	}
6111501b536SEduard Zingerman 	return UNKNOWN_EXPR_ID;
6121501b536SEduard Zingerman }
6131501b536SEduard Zingerman 
6141501b536SEduard Zingerman static int mk_fill(struct scev *scev, int id, u8 code)
6151501b536SEduard Zingerman {
6161501b536SEduard Zingerman 	bool sx = BPF_MODE(code) == BPF_MEMSX;
6171501b536SEduard Zingerman 
6181501b536SEduard Zingerman #ifdef __BIG_ENDIAN
6191501b536SEduard Zingerman 	/* A narrow fill from a DW spill reads high bits on big-endian. */
6201501b536SEduard Zingerman 	if (BPF_SIZE(code) != BPF_DW)
6211501b536SEduard Zingerman 		return OPAQUE_EXPR_ID;
6221501b536SEduard Zingerman #endif
6231501b536SEduard Zingerman 
6241501b536SEduard Zingerman 	switch (BPF_SIZE(code)) {
6251501b536SEduard Zingerman 	case BPF_B:  return expr1(scev, sx ? SEXT8  : ZEXT8,  id);
6261501b536SEduard Zingerman 	case BPF_H:  return expr1(scev, sx ? SEXT16 : ZEXT16, id);
6271501b536SEduard Zingerman 	case BPF_W:  return expr1(scev, sx ? SEXT32 : ZEXT32, id);
6281501b536SEduard Zingerman 	case BPF_DW: return sx ? UNKNOWN_EXPR_ID : id; /* DW sign-extended load is invalid */
6291501b536SEduard Zingerman 	}
6301501b536SEduard Zingerman 	return UNKNOWN_EXPR_ID;
6311501b536SEduard Zingerman }
6321501b536SEduard Zingerman 
6331501b536SEduard Zingerman static int maybe_store_fp(struct scev *scev, struct env *e, struct bpf_insn *insn, int id)
6341501b536SEduard Zingerman {
6351501b536SEduard Zingerman 	u8 size = BPF_SIZE(insn->code);
6361501b536SEduard Zingerman 
6371501b536SEduard Zingerman 	if (insn->dst_reg != BPF_REG_FP)
6381501b536SEduard Zingerman 		return 0;
6391501b536SEduard Zingerman 	if (is_spill_off(insn->off))
6401501b536SEduard Zingerman 		return replace_reg(scev, e, off_to_reg(insn), mk_spill(scev, size, id));
6411501b536SEduard Zingerman 	mark_opaque(e, insn->off, bpf_size_to_bytes(size));
6421501b536SEduard Zingerman 	return 0;
6431501b536SEduard Zingerman }
6441501b536SEduard Zingerman 
6451501b536SEduard Zingerman static int maybe_load_fp(struct scev *scev, struct env *e, struct bpf_insn *insn)
6461501b536SEduard Zingerman {
6471501b536SEduard Zingerman 	int id;
6481501b536SEduard Zingerman 
6491501b536SEduard Zingerman 	if (insn->src_reg == BPF_REG_FP && is_spill_off(insn->off))
6501501b536SEduard Zingerman 		id = mk_fill(scev, e->reg2expr[off_to_reg(insn)], insn->code);
6511501b536SEduard Zingerman 	else
6521501b536SEduard Zingerman 		id = OPAQUE_EXPR_ID;
6531501b536SEduard Zingerman 	return replace_reg(scev, e, insn->dst_reg, id);
6541501b536SEduard Zingerman }
6551501b536SEduard Zingerman 
6561501b536SEduard Zingerman static int transfer(struct bpf_verifier_env *env, struct env *e, int idx)
6571501b536SEduard Zingerman {
6581501b536SEduard Zingerman 	const bool little_endian = htons(0x3412) == 0x1234;
6591501b536SEduard Zingerman 	struct bpf_insn *insn = &env->prog->insnsi[idx];
6601501b536SEduard Zingerman 	struct scev *scev = env->scev;
6611501b536SEduard Zingerman 	u32 *reg2expr = e->reg2expr;
6621501b536SEduard Zingerman 	u8 class = BPF_CLASS(insn->code);
6631501b536SEduard Zingerman 	u8 x_or_k = BPF_SRC(insn->code);
6641501b536SEduard Zingerman 	u8 opcode = BPF_OP(insn->code);
6651501b536SEduard Zingerman 	u8 mode = BPF_MODE(insn->code);
6661501b536SEduard Zingerman 	u32 dst = insn->dst_reg;
6671501b536SEduard Zingerman 	u32 src = insn->src_reg;
6681501b536SEduard Zingerman 	u32 op, sext;
6691501b536SEduard Zingerman 	bool need_bswap;
6701501b536SEduard Zingerman 	int i, id;
6711501b536SEduard Zingerman 	s64 imm;
6721501b536SEduard Zingerman 
6731501b536SEduard Zingerman 	switch (class) {
6741501b536SEduard Zingerman 	case BPF_ALU:
6751501b536SEduard Zingerman 	case BPF_ALU64:
6761501b536SEduard Zingerman 		switch (opcode) {
6771501b536SEduard Zingerman 		case BPF_MOV:
6781501b536SEduard Zingerman 			switch (insn->off) {
6791501b536SEduard Zingerman 			case 0: sext = 0; break;
6801501b536SEduard Zingerman 			case 8: sext = SEXT8; break;
6811501b536SEduard Zingerman 			case 16: sext = SEXT16; break;
6821501b536SEduard Zingerman 			case 32: sext = SEXT32; break;
6831501b536SEduard Zingerman 			default:
6841501b536SEduard Zingerman 				goto mark_dst_unknown;
6851501b536SEduard Zingerman 			}
6861501b536SEduard Zingerman 
6871501b536SEduard Zingerman 			if (x_or_k == BPF_X && insn->imm == 0)
6881501b536SEduard Zingerman 				id = reg2expr[src];
6891501b536SEduard Zingerman 			else if (x_or_k == BPF_K && src == 0 && insn->off == 0)
6901501b536SEduard Zingerman 				id = imm_expr(scev, insn->imm);
6911501b536SEduard Zingerman 			else
6921501b536SEduard Zingerman 				goto mark_dst_unknown;
6931501b536SEduard Zingerman 
6941501b536SEduard Zingerman 			if (sext)
6951501b536SEduard Zingerman 				id = expr1(scev, sext, id);
6961501b536SEduard Zingerman 			if (class == BPF_ALU)
6971501b536SEduard Zingerman 				id = expr1(scev, ZEXT32, id);
6981501b536SEduard Zingerman 
6991501b536SEduard Zingerman 			return replace_reg(scev, e, dst, id);
7001501b536SEduard Zingerman 
7011501b536SEduard Zingerman 		case BPF_ADD:
7021501b536SEduard Zingerman 		case BPF_SUB:
7031501b536SEduard Zingerman 		case BPF_MUL:
7041501b536SEduard Zingerman 		case BPF_DIV:
7051501b536SEduard Zingerman 		case BPF_MOD:
7061501b536SEduard Zingerman 		case BPF_OR:
7071501b536SEduard Zingerman 		case BPF_XOR:
7081501b536SEduard Zingerman 		case BPF_AND:
7091501b536SEduard Zingerman 		case BPF_LSH:
7101501b536SEduard Zingerman 		case BPF_RSH:
7111501b536SEduard Zingerman 		case BPF_ARSH:
7121501b536SEduard Zingerman 			if (opcode == BPF_DIV && insn->off == 1)
7131501b536SEduard Zingerman 				op = SDIV;
7141501b536SEduard Zingerman 			else if (opcode == BPF_MOD && insn->off == 1)
7151501b536SEduard Zingerman 				op = SMOD;
7161501b536SEduard Zingerman 			else if (insn->off == 0)
7171501b536SEduard Zingerman 				op = opcode;
7181501b536SEduard Zingerman 			else
7191501b536SEduard Zingerman 				goto mark_dst_unknown;
7201501b536SEduard Zingerman 
7211501b536SEduard Zingerman 			if (x_or_k == BPF_X && insn->imm == 0)
7221501b536SEduard Zingerman 				id = reg2expr[src];
7231501b536SEduard Zingerman 			else if (x_or_k == BPF_K && src == 0)
7241501b536SEduard Zingerman 				id = imm_expr(scev, insn->imm);
7251501b536SEduard Zingerman 			else
7261501b536SEduard Zingerman 				goto mark_dst_unknown;
7271501b536SEduard Zingerman 
7281501b536SEduard Zingerman 			id = expr2(scev, op, reg2expr[dst], id);
7291501b536SEduard Zingerman 
7301501b536SEduard Zingerman 			if (class == BPF_ALU)
7311501b536SEduard Zingerman 				id = expr1(scev, ZEXT32, id);
7321501b536SEduard Zingerman 
7331501b536SEduard Zingerman 			return replace_reg(scev, e, dst, id);
7341501b536SEduard Zingerman 
7351501b536SEduard Zingerman 		case BPF_NEG:
7361501b536SEduard Zingerman 			if (src == 0 && insn->off == 0 && insn->imm == 0)
7371501b536SEduard Zingerman 				id = expr1(scev, BPF_NEG, reg2expr[dst]);
7381501b536SEduard Zingerman 			else
7391501b536SEduard Zingerman 				goto mark_dst_unknown;
7401501b536SEduard Zingerman 
7411501b536SEduard Zingerman 			if (class == BPF_ALU)
7421501b536SEduard Zingerman 				id = expr1(scev, ZEXT32, id);
7431501b536SEduard Zingerman 
7441501b536SEduard Zingerman 			return replace_reg(scev, e, dst, id);
7451501b536SEduard Zingerman 
7461501b536SEduard Zingerman 		case BPF_END:
7471501b536SEduard Zingerman 			if (src != 0 || insn->off != 0 || (class == BPF_ALU64 && x_or_k != 0))
7481501b536SEduard Zingerman 				goto mark_dst_unknown;
7491501b536SEduard Zingerman 
7501501b536SEduard Zingerman 			need_bswap = class == BPF_ALU64 || ((x_or_k == BPF_TO_LE) != little_endian);
7511501b536SEduard Zingerman 			switch (insn->imm) {
7521501b536SEduard Zingerman 			case 16: op = need_bswap ? BSWAP16 : ZEXT16; break;
7531501b536SEduard Zingerman 			case 32: op = need_bswap ? BSWAP32 : ZEXT32; break;
7541501b536SEduard Zingerman 			case 64: op = need_bswap ? BSWAP64 : 0; break;
7551501b536SEduard Zingerman 			default:
7561501b536SEduard Zingerman 				goto mark_dst_unknown;
7571501b536SEduard Zingerman 			}
7581501b536SEduard Zingerman 
7591501b536SEduard Zingerman 			id = reg2expr[dst];
7601501b536SEduard Zingerman 			if (op)
7611501b536SEduard Zingerman 				id = expr1(scev, op, reg2expr[dst]);
7621501b536SEduard Zingerman 
7631501b536SEduard Zingerman 			return replace_reg(scev, e, dst, id);
7641501b536SEduard Zingerman 		default:
7651501b536SEduard Zingerman 			goto mark_dst_unknown;
7661501b536SEduard Zingerman 		}
7671501b536SEduard Zingerman 		break;
7681501b536SEduard Zingerman 	case BPF_LDX:
7691501b536SEduard Zingerman 		switch (mode) {
7701501b536SEduard Zingerman 		case BPF_MEM:
7711501b536SEduard Zingerman 		case BPF_MEMSX:
7721501b536SEduard Zingerman 			return maybe_load_fp(scev, e, insn);
7731501b536SEduard Zingerman 		default:
7741501b536SEduard Zingerman 			goto mark_dst_unknown;
7751501b536SEduard Zingerman 		}
7761501b536SEduard Zingerman 	case BPF_STX:
7771501b536SEduard Zingerman 		switch (mode) {
7781501b536SEduard Zingerman 		case BPF_MEM:
7791501b536SEduard Zingerman 			return maybe_store_fp(scev, e, insn, reg2expr[src]);
7801501b536SEduard Zingerman 		case BPF_ATOMIC:
7811501b536SEduard Zingerman 			if (insn->imm == BPF_LOAD_ACQ)
7821501b536SEduard Zingerman 				return maybe_load_fp(scev, e, insn);
7831501b536SEduard Zingerman 			if (insn->imm == BPF_STORE_REL) {
7841501b536SEduard Zingerman 				return maybe_store_fp(scev, e, insn, reg2expr[src]);
7851501b536SEduard Zingerman 			}
7861501b536SEduard Zingerman 			/*
7871501b536SEduard Zingerman 			 * verifier does not track other atomic ops precisely,
7881501b536SEduard Zingerman 			 * hence mark the results as opaque.
7891501b536SEduard Zingerman 			 */
7901501b536SEduard Zingerman 			if (insn->dst_reg == BPF_REG_FP)
7911501b536SEduard Zingerman 				mark_opaque(e, insn->off, bpf_size_to_bytes(BPF_SIZE(insn->code)));
7921501b536SEduard Zingerman 			if (insn->imm == BPF_CMPXCHG)
7931501b536SEduard Zingerman 				return replace_reg(scev, e, BPF_REG_0, OPAQUE_EXPR_ID);
7941501b536SEduard Zingerman 			if (insn->imm & BPF_FETCH)
7951501b536SEduard Zingerman 				return replace_reg(scev, e, src, OPAQUE_EXPR_ID);
7961501b536SEduard Zingerman 			break;
7971501b536SEduard Zingerman 		}
7981501b536SEduard Zingerman 		break;
7991501b536SEduard Zingerman 	case BPF_ST:
8001501b536SEduard Zingerman 		if (insn->dst_reg == BPF_REG_FP) {
8011501b536SEduard Zingerman 			id = imm_expr(scev, insn->imm);
8021501b536SEduard Zingerman 			if (id < 0)
8031501b536SEduard Zingerman 				return id;
8041501b536SEduard Zingerman 			return maybe_store_fp(scev, e, insn, id);
8051501b536SEduard Zingerman 		}
8061501b536SEduard Zingerman 		break;
8071501b536SEduard Zingerman 	case BPF_JMP:
8081501b536SEduard Zingerman 	case BPF_JMP32:
8091501b536SEduard Zingerman 		if (opcode == BPF_CALL)
8101501b536SEduard Zingerman 			forget_call_regs(e);
8111501b536SEduard Zingerman 		/* for non-CALL there are no changes in register states */
8121501b536SEduard Zingerman 		break;
8131501b536SEduard Zingerman 	case BPF_LD:
8141501b536SEduard Zingerman 		switch (mode) {
8151501b536SEduard Zingerman 		case BPF_IMM:
8161501b536SEduard Zingerman 			/* rX = imm ll */
8171501b536SEduard Zingerman 			if (BPF_SIZE(insn->code) == BPF_DW && insn->src_reg == 0) {
8181501b536SEduard Zingerman 				imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm;
8191501b536SEduard Zingerman 				return replace_reg(scev, e, dst, imm_expr(scev, imm));
8201501b536SEduard Zingerman 			}
8211501b536SEduard Zingerman 			/* map, map value, BTF id, function */
8221501b536SEduard Zingerman 			if (BPF_SIZE(insn->code) == BPF_DW)
8231501b536SEduard Zingerman 				return replace_reg(scev, e, dst, OPAQUE_EXPR_ID);
8241501b536SEduard Zingerman 			goto mark_dst_unknown;
8251501b536SEduard Zingerman 		case BPF_ABS:
8261501b536SEduard Zingerman 		case BPF_IND:
8271501b536SEduard Zingerman 			forget_call_regs(e);
8281501b536SEduard Zingerman 			break;
8291501b536SEduard Zingerman 		default:
8301501b536SEduard Zingerman 			goto mark_dst_unknown;
8311501b536SEduard Zingerman 		}
8321501b536SEduard Zingerman 		break;
8331501b536SEduard Zingerman 	default:
8341501b536SEduard Zingerman 		/* unknown instruction, nuke state */
8351501b536SEduard Zingerman 		for (i = 0; i < REGS_NUM; i++)
8361501b536SEduard Zingerman 			reg2expr[i] = UNKNOWN_EXPR_ID;
8371501b536SEduard Zingerman 		break;
8381501b536SEduard Zingerman 	}
8391501b536SEduard Zingerman 	return 0;
8401501b536SEduard Zingerman 
8411501b536SEduard Zingerman mark_dst_unknown:
8421501b536SEduard Zingerman 	reg2expr[dst] = UNKNOWN_EXPR_ID;
8431501b536SEduard Zingerman 	return 0;
8441501b536SEduard Zingerman }
8451501b536SEduard Zingerman 
8461501b536SEduard Zingerman /*
8471501b536SEduard Zingerman  * Construct minimal 'ANY' expression by traversing 'a' and 'b'
8481501b536SEduard Zingerman  * and accumulating non-duplicated non-ANY entries.
8491501b536SEduard Zingerman  */
8501501b536SEduard Zingerman static int mk_any(struct scev *scev, int a, int b)
8511501b536SEduard Zingerman {
8521501b536SEduard Zingerman 	struct expr_stack_elt *elt;
8531501b536SEduard Zingerman 	struct expr *expr;
8541501b536SEduard Zingerman 	u32 i, j, ids_buf_sz;
8551501b536SEduard Zingerman 	u32 roots[2] = {a, b};
8561501b536SEduard Zingerman 	int id;
8571501b536SEduard Zingerman 
8581501b536SEduard Zingerman 	if (a < 0)
8591501b536SEduard Zingerman 		return a;
8601501b536SEduard Zingerman 	if (b < 0)
8611501b536SEduard Zingerman 		return b;
8621501b536SEduard Zingerman 	ids_buf_sz = 0;
8631501b536SEduard Zingerman 	for (i = 0; i < ARRAY_SIZE(roots); i++) {
8641501b536SEduard Zingerman 		scev->stack_sz = 0;
8651501b536SEduard Zingerman 		expr_stack_push(scev, roots[i]);
8661501b536SEduard Zingerman 		while (scev->stack_sz) {
8671501b536SEduard Zingerman 			elt = &scev->expr_stack[--scev->stack_sz];
8681501b536SEduard Zingerman 			id = elt->id;
8691501b536SEduard Zingerman 			expr = &scev->exprs[elt->id];
8701501b536SEduard Zingerman 			if (expr->op == ANY) {
8711501b536SEduard Zingerman 				if (!expr_stack_push(scev, expr->params[1]) ||
8721501b536SEduard Zingerman 				    !expr_stack_push(scev, expr->params[0]))
8731501b536SEduard Zingerman 					return UNKNOWN_EXPR_ID;
8741501b536SEduard Zingerman 			} else {
8751501b536SEduard Zingerman 				for (j = 0; j < ids_buf_sz; j++) {
8761501b536SEduard Zingerman 					if (same_exprs(scev, scev->ids_buf[j], id))
8771501b536SEduard Zingerman 						goto next;
8781501b536SEduard Zingerman 				}
8791501b536SEduard Zingerman 				if (ids_buf_sz == ARRAY_SIZE(scev->ids_buf))
8801501b536SEduard Zingerman 					return UNKNOWN_EXPR_ID;
8811501b536SEduard Zingerman 				scev->ids_buf[ids_buf_sz++] = id;
8821501b536SEduard Zingerman 			}
8831501b536SEduard Zingerman next:;
8841501b536SEduard Zingerman 		}
8851501b536SEduard Zingerman 	}
8861501b536SEduard Zingerman 	if (WARN_ON(ids_buf_sz == 0))
8871501b536SEduard Zingerman 		return -EFAULT;
8881501b536SEduard Zingerman 	id = scev->ids_buf[0];
8891501b536SEduard Zingerman 	for (i = 1; i < ids_buf_sz; i++) {
8901501b536SEduard Zingerman 		id = expr2(scev, ANY, id, scev->ids_buf[i]);
8911501b536SEduard Zingerman 		if (id < 0)
8921501b536SEduard Zingerman 			return id;
8931501b536SEduard Zingerman 	}
8941501b536SEduard Zingerman 	return id;
8951501b536SEduard Zingerman }
8961501b536SEduard Zingerman 
8971501b536SEduard Zingerman static int join(struct scev *scev, struct env *acc, struct env *cur)
8981501b536SEduard Zingerman {
8991501b536SEduard Zingerman 	int i, id;
9001501b536SEduard Zingerman 
9011501b536SEduard Zingerman 	if (acc->empty) {
9021501b536SEduard Zingerman 		memcpy(acc, cur, sizeof(*acc));
9031501b536SEduard Zingerman 		acc->empty = false;
9041501b536SEduard Zingerman 		return 0;
9051501b536SEduard Zingerman 	}
9061501b536SEduard Zingerman 
9071501b536SEduard Zingerman 	for (i = 0; i < REGS_NUM; i++) {
9081501b536SEduard Zingerman 		if (!same_exprs(scev, acc->reg2expr[i], cur->reg2expr[i])) {
9091501b536SEduard Zingerman 			id = mk_any(scev, acc->reg2expr[i], cur->reg2expr[i]);
9101501b536SEduard Zingerman 			if (id < 0)
9111501b536SEduard Zingerman 				return id;
9121501b536SEduard Zingerman 			acc->reg2expr[i] = id;
9131501b536SEduard Zingerman 		}
9141501b536SEduard Zingerman 	}
9151501b536SEduard Zingerman 	return 0;
9161501b536SEduard Zingerman }
9171501b536SEduard Zingerman 
9181501b536SEduard Zingerman /* Mark any register modified in 'e' as unknown in 'acc'. */
9191501b536SEduard Zingerman static void forget_modified_regs(struct scev *scev, struct env *acc, struct env *e)
9201501b536SEduard Zingerman {
9211501b536SEduard Zingerman 	u32 i, reg;
9221501b536SEduard Zingerman 
9231501b536SEduard Zingerman 	for (i = 0; i < REGS_NUM; i++) {
9241501b536SEduard Zingerman 		if (e && is_reg(scev, e->reg2expr[i], &reg) && reg == i)
9251501b536SEduard Zingerman 			continue;
9261501b536SEduard Zingerman 		acc->reg2expr[i] = UNKNOWN_EXPR_ID;
9271501b536SEduard Zingerman 	}
9281501b536SEduard Zingerman }
9291501b536SEduard Zingerman 
9301501b536SEduard Zingerman /* For a loop H at `header`, mark any register modified as a result of H execution as unknown. */
9311501b536SEduard Zingerman static void forget_non_invariants(struct bpf_verifier_env *env, struct env *acc, int header)
9321501b536SEduard Zingerman {
9331501b536SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
9341501b536SEduard Zingerman 	struct bpf_loop *loop = aux[header].loop;
9351501b536SEduard Zingerman 	struct scev *scev = env->scev;
9361501b536SEduard Zingerman 	int i, idx, h;
9371501b536SEduard Zingerman 
9381501b536SEduard Zingerman 	acc->empty = false;
9391501b536SEduard Zingerman 	forget_modified_regs(scev, acc, find_header_env(scev, header));
9401501b536SEduard Zingerman 	for (i = 0; i < loop->exits_cnt; i++) {
9411501b536SEduard Zingerman 		idx = loop->exits[i].from;
9421501b536SEduard Zingerman 		h = bpf_loop_at_index(env, idx);
9431501b536SEduard Zingerman 		/*
9441501b536SEduard Zingerman 		 * In order to account for situations like this:
9451501b536SEduard Zingerman 		 *
9461501b536SEduard Zingerman 		 * header:
9471501b536SEduard Zingerman 		 *   do {
9481501b536SEduard Zingerman 		 *	saved = rX;
9491501b536SEduard Zingerman 		 *	rX = -1000;
9501501b536SEduard Zingerman 		 *	do {				// H
9511501b536SEduard Zingerman 		 *		if (random())
9521501b536SEduard Zingerman 		 *			goto out;	// E
9531501b536SEduard Zingerman 		 *	} while (inner_again);
9541501b536SEduard Zingerman 		 *	rX = saved;
9551501b536SEduard Zingerman 		 *    } while (outer_again);
9561501b536SEduard Zingerman 		 *  out:
9571501b536SEduard Zingerman 		 *
9581501b536SEduard Zingerman 		 * For exits originating in nested loops check that rX is invariant
9591501b536SEduard Zingerman 		 * both at the header (H) and at exit (E).
9601501b536SEduard Zingerman 		 */
9611501b536SEduard Zingerman 		while (h != header) {
9621501b536SEduard Zingerman 			forget_modified_regs(scev, acc, find_header_env(scev, h));
9631501b536SEduard Zingerman 			forget_modified_regs(scev, acc, find_loop_env(scev, h, idx));
9641501b536SEduard Zingerman 			idx = h;
9651501b536SEduard Zingerman 			h = aux[h].loop_header;
9661501b536SEduard Zingerman 		}
9671501b536SEduard Zingerman 		/*
9681501b536SEduard Zingerman 		 * For exits originating at the same loop the header is already accounted for,
9691501b536SEduard Zingerman 		 * check only the exit environment.
9701501b536SEduard Zingerman 		 */
9711501b536SEduard Zingerman 		forget_modified_regs(scev, acc, find_loop_env(scev, header, idx));
9721501b536SEduard Zingerman 	}
9731501b536SEduard Zingerman }
9741501b536SEduard Zingerman 
9751501b536SEduard Zingerman /* Order worklist in reverse post-order. */
9761501b536SEduard Zingerman static bool reverse_postorder_less(const void *a, const void *b, void *arg)
9771501b536SEduard Zingerman {
9781501b536SEduard Zingerman 	const int *rank = arg;
9791501b536SEduard Zingerman 
9801501b536SEduard Zingerman 	return rank[*(const int *)a] > rank[*(const int *)b];
9811501b536SEduard Zingerman }
9821501b536SEduard Zingerman 
9831501b536SEduard Zingerman static const struct min_heap_callbacks worklist_cb = {
9841501b536SEduard Zingerman 	.less = reverse_postorder_less,
9851501b536SEduard Zingerman };
9861501b536SEduard Zingerman 
9871501b536SEduard Zingerman static int worklist_push(struct bpf_verifier_env *env, int loop_header, int idx)
9881501b536SEduard Zingerman {
9891501b536SEduard Zingerman 	struct scev *scev = env->scev;
9901501b536SEduard Zingerman 	struct scev_worklist *worklist = &scev->worklist;
9911501b536SEduard Zingerman 	u32 tag = (u32)loop_header + 1;
9921501b536SEduard Zingerman 
9931501b536SEduard Zingerman 	if (scev->discovered[idx] == tag)
9941501b536SEduard Zingerman 		return 0;
9951501b536SEduard Zingerman 
9961501b536SEduard Zingerman 	if (min_heap_full_inline(worklist)) {
9971501b536SEduard Zingerman 		size_t size = worklist->size ? worklist->size * 2 : 16;
9981501b536SEduard Zingerman 		int *data;
9991501b536SEduard Zingerman 
10001501b536SEduard Zingerman 		data = kvrealloc(worklist->data, array_size(size, sizeof(*data)),
10011501b536SEduard Zingerman 				GFP_KERNEL_ACCOUNT);
10021501b536SEduard Zingerman 		if (!data)
10031501b536SEduard Zingerman 			return -ENOMEM;
10041501b536SEduard Zingerman 		worklist->data = data;
10051501b536SEduard Zingerman 		worklist->size = size;
10061501b536SEduard Zingerman 	}
10071501b536SEduard Zingerman 	if (!min_heap_push_inline(worklist, &idx, &worklist_cb, env->cfg.postorder_nums))
10081501b536SEduard Zingerman 		return -EFAULT;
10091501b536SEduard Zingerman 
10101501b536SEduard Zingerman 	scev->discovered[idx] = tag;
10111501b536SEduard Zingerman 	return 0;
10121501b536SEduard Zingerman }
10131501b536SEduard Zingerman 
10141501b536SEduard Zingerman static bool reg_alive_at_succ(struct bpf_verifier_env *env, u32 r, u32 insn_idx)
10151501b536SEduard Zingerman {
10161501b536SEduard Zingerman 	struct bpf_iarray *succ = bpf_insn_successors(env, insn_idx);
10171501b536SEduard Zingerman 	u32 i;
10181501b536SEduard Zingerman 
10191501b536SEduard Zingerman 	for (i = 0; i < succ->cnt; i++)
10201501b536SEduard Zingerman 		if (reg_alive_at(env, r, succ->items[i]))
10211501b536SEduard Zingerman 			return true;
10221501b536SEduard Zingerman 	return false;
10231501b536SEduard Zingerman }
10241501b536SEduard Zingerman 
10251501b536SEduard Zingerman enum changes_at {
10261501b536SEduard Zingerman 	LOG_AT_TRANSFER,
10271501b536SEduard Zingerman 	LOG_AT_JOIN,
10281501b536SEduard Zingerman };
10291501b536SEduard Zingerman 
10301501b536SEduard Zingerman static void log_env_changes(struct bpf_verifier_env *env, enum changes_at at,
10311501b536SEduard Zingerman 			    struct env *old, struct env *new, int insn_idx)
10321501b536SEduard Zingerman {
10331501b536SEduard Zingerman 	struct bpf_verifier_log *log = &env->log;
10341501b536SEduard Zingerman 	struct scev *scev = env->scev;
10351501b536SEduard Zingerman 	u64 null_pos = log->end_pos;
10361501b536SEduard Zingerman 	u32 old_id, new_id, regno;
10371501b536SEduard Zingerman 	bool any_changes = false;
10381501b536SEduard Zingerman 	bool is_self_scev;
10391501b536SEduard Zingerman 	u64 len;
10401501b536SEduard Zingerman 	int r;
10411501b536SEduard Zingerman 
10421501b536SEduard Zingerman 	bpf_log(log, "%s %4d: ", at == LOG_AT_TRANSFER ? "t" : "j", insn_idx);
10431501b536SEduard Zingerman 	bpf_verbose_insn(env, &env->prog->insnsi[insn_idx]);
10441501b536SEduard Zingerman 	len = log->end_pos - null_pos;
10451501b536SEduard Zingerman 	bpf_log(log, "%*s", max(37 - (int)len, 1), " ");
10461501b536SEduard Zingerman 	bpf_log(log, " ; ");
10471501b536SEduard Zingerman 	for (r = 0; r < REGS_NUM; r++) {
10481501b536SEduard Zingerman 		old_id = old->reg2expr[r];
10491501b536SEduard Zingerman 		new_id = new->reg2expr[r];
10501501b536SEduard Zingerman 		if (at == LOG_AT_TRANSFER && !reg_alive_at_succ(env, r, insn_idx))
10511501b536SEduard Zingerman 			continue;
10521501b536SEduard Zingerman 		if (at == LOG_AT_JOIN && !reg_alive_at(env, r, insn_idx))
10531501b536SEduard Zingerman 			continue;
10541501b536SEduard Zingerman 		if (same_exprs(scev, old_id, new_id))
10551501b536SEduard Zingerman 			continue;
10561501b536SEduard Zingerman 		is_self_scev = is_reg(scev, new_id, &regno) && r == regno;
10571501b536SEduard Zingerman 		if (old->empty && is_self_scev)
10581501b536SEduard Zingerman 			continue;
10591501b536SEduard Zingerman 		if (any_changes)
10601501b536SEduard Zingerman 			bpf_log(log, ", ");
10611501b536SEduard Zingerman 		log_reg(env, r);
10621501b536SEduard Zingerman 		bpf_log(log, " ");
10631501b536SEduard Zingerman 		log_expr(env, old_id);
10641501b536SEduard Zingerman 		bpf_log(log, " -> ");
10651501b536SEduard Zingerman 		log_expr(env, new_id);
10661501b536SEduard Zingerman 		any_changes = true;
10671501b536SEduard Zingerman 	}
10681501b536SEduard Zingerman 	if (old->empty && !any_changes)
10691501b536SEduard Zingerman 		bpf_log(log, "<empty join>");
10701501b536SEduard Zingerman 	bpf_log(log, "\n");
10711501b536SEduard Zingerman 	if (!old->empty && !any_changes)
10721501b536SEduard Zingerman 		bpf_vlog_reset(log, null_pos);
10731501b536SEduard Zingerman }
10741501b536SEduard Zingerman 
10751501b536SEduard Zingerman static bool is_probe_read_helper(u32 func_id)
10761501b536SEduard Zingerman {
10771501b536SEduard Zingerman 	return func_id == BPF_FUNC_probe_read ||
10781501b536SEduard Zingerman 	       func_id == BPF_FUNC_probe_read_kernel ||
10791501b536SEduard Zingerman 	       func_id == BPF_FUNC_probe_read_user ||
10801501b536SEduard Zingerman 	       func_id == BPF_FUNC_probe_read_str ||
10811501b536SEduard Zingerman 	       func_id == BPF_FUNC_probe_read_kernel_str ||
10821501b536SEduard Zingerman 	       func_id == BPF_FUNC_probe_read_user_str;
10831501b536SEduard Zingerman }
10841501b536SEduard Zingerman 
10851501b536SEduard Zingerman /*
10861501b536SEduard Zingerman  * If instruction is an indirect write to stack, invalidate SCEVs for spi's
10871501b536SEduard Zingerman  * that this instruction can touch.
10881501b536SEduard Zingerman  */
10891501b536SEduard Zingerman static void reset_scevs_at_indirect_writes(struct bpf_verifier_env *env, struct env *cur_env, int idx)
10901501b536SEduard Zingerman {
10911501b536SEduard Zingerman 	struct bpf_insn *insn = &env->prog->insnsi[idx];
10921501b536SEduard Zingerman 	struct scev *scev = env->scev;
10931501b536SEduard Zingerman 	u8 class = BPF_CLASS(insn->code);
10941501b536SEduard Zingerman 	const unsigned long *mask;
10951501b536SEduard Zingerman 	u32 spi, reg;
10961501b536SEduard Zingerman 	bool opaque;
10971501b536SEduard Zingerman 
10981501b536SEduard Zingerman 	/* Direct fp stores are fine. */
10991501b536SEduard Zingerman 	if ((class == BPF_ST || class == BPF_STX) && insn->dst_reg == BPF_REG_FP)
11001501b536SEduard Zingerman 		return;
11011501b536SEduard Zingerman 
11021501b536SEduard Zingerman 	mask = bpf_may_write_mask(env, idx);
11031501b536SEduard Zingerman 	opaque = bpf_helper_call(insn) && is_probe_read_helper(insn->imm);
11041501b536SEduard Zingerman 	for_each_set_bit(spi, mask, MAX_BPF_STACK_SLOTS) {
11051501b536SEduard Zingerman 		reg = MAX_BPF_REG + spi;
11061501b536SEduard Zingerman 		if (cur_env->reg2expr[reg] == UNKNOWN_EXPR_ID)
11071501b536SEduard Zingerman 			continue;
11081501b536SEduard Zingerman 		replace_reg(scev, cur_env, reg, opaque ? OPAQUE_EXPR_ID : UNKNOWN_EXPR_ID);
11091501b536SEduard Zingerman 	}
11101501b536SEduard Zingerman }
11111501b536SEduard Zingerman 
1112088a5477SEduard Zingerman /*
1113088a5477SEduard Zingerman  * Collect loop-entry registers referenced by expr 'id', best effort.
1114088a5477SEduard Zingerman  * DEPTH_LIMIT may leave dependencies unrecorded. This mask only avoids
1115088a5477SEduard Zingerman  * widening that would lose stack-access precision; missing dependencies
1116088a5477SEduard Zingerman  * may cause false rejections, but this is not a soundness issue.
1117088a5477SEduard Zingerman  */
1118088a5477SEduard Zingerman static void or_expr_regs(struct bpf_verifier_env *env, u32 id, unsigned long *mask)
1119088a5477SEduard Zingerman {
1120088a5477SEduard Zingerman 	struct scev *scev = env->scev;
1121088a5477SEduard Zingerman 	u32 order;
1122088a5477SEduard Zingerman 
1123088a5477SEduard Zingerman 	scev->stack_sz = 0;
1124088a5477SEduard Zingerman 	expr_stack_push(scev, id);
1125088a5477SEduard Zingerman 	while (expr_next(scev, &id, &order)) {
1126088a5477SEduard Zingerman 		if ((order & PRE) && scev->exprs[id].op == REG)
1127088a5477SEduard Zingerman 			__set_bit(scev->exprs[id].params[0], mask);
1128088a5477SEduard Zingerman 	}
1129088a5477SEduard Zingerman }
1130088a5477SEduard Zingerman 
1131088a5477SEduard Zingerman /* Mask of argument registers (R1..R5) a call at 'idx' passes by register. */
1132088a5477SEduard Zingerman static u16 call_params_mask(struct bpf_verifier_env *env, int idx)
1133088a5477SEduard Zingerman {
1134088a5477SEduard Zingerman 	struct bpf_insn *insn = &env->prog->insnsi[idx];
1135088a5477SEduard Zingerman 	struct bpf_call_summary cs;
1136088a5477SEduard Zingerman 	int n = bpf_get_call_summary(env, insn, &cs) ? cs.arg_slot_cnt : MAX_BPF_FUNC_REG_ARGS;
1137088a5477SEduard Zingerman 
1138088a5477SEduard Zingerman 	return n ? GENMASK(BPF_REG_1 + n - 1, BPF_REG_1) : 0;
1139088a5477SEduard Zingerman }
1140088a5477SEduard Zingerman 
1141088a5477SEduard Zingerman /*
1142088a5477SEduard Zingerman  * For instructions like:
1143088a5477SEduard Zingerman  * - *(u64 *)(rBase + off) = rX
1144088a5477SEduard Zingerman  * - rX = *(u64 *)(rBase + off)
1145088a5477SEduard Zingerman  * - calls that construct objects on stack (e.g. dynptr_from_mem(rBase, ...))
1146088a5477SEduard Zingerman  * When 'rBase' can be a stack pointer and is derived from some registers Rs
1147088a5477SEduard Zingerman  * defined at loop entry, record Rs into 'mask'.
1148088a5477SEduard Zingerman  */
1149088a5477SEduard Zingerman static void collect_store_base_regs(struct bpf_verifier_env *env,
1150088a5477SEduard Zingerman 				    struct env *cur_env, int idx, unsigned long *mask)
1151088a5477SEduard Zingerman {
1152088a5477SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
1153088a5477SEduard Zingerman 	struct bpf_insn *insn = &env->prog->insnsi[idx];
1154088a5477SEduard Zingerman 	u8 class = BPF_CLASS(insn->code);
1155088a5477SEduard Zingerman 	u8 size = BPF_SIZE(insn->code);
1156088a5477SEduard Zingerman 	u16 base_regs = 0;
1157088a5477SEduard Zingerman 	u32 r;
1158088a5477SEduard Zingerman 
1159088a5477SEduard Zingerman 	if (size == BPF_W || size == BPF_DW) {
1160088a5477SEduard Zingerman 		if ((class == BPF_STX || class == BPF_ST) && insn->dst_reg != BPF_REG_FP)
1161088a5477SEduard Zingerman 			base_regs |= BIT(insn->dst_reg);
1162088a5477SEduard Zingerman 		else if (class == BPF_LDX && insn->src_reg != BPF_REG_FP)
1163088a5477SEduard Zingerman 			base_regs |= BIT(insn->src_reg);
1164088a5477SEduard Zingerman 	}
1165088a5477SEduard Zingerman 
1166088a5477SEduard Zingerman 	if (class == BPF_JMP && BPF_OP(insn->code) == BPF_CALL &&
1167088a5477SEduard Zingerman 	    bpf_needs_fixed_stack_off(env, idx))
1168088a5477SEduard Zingerman 		base_regs |= call_params_mask(env, idx);
1169088a5477SEduard Zingerman 
1170088a5477SEduard Zingerman 	base_regs &= aux[idx].stack_ptrs;
1171088a5477SEduard Zingerman 	for (r = 0; r < MAX_BPF_REG; r++)
1172088a5477SEduard Zingerman 		if (base_regs & BIT(r))
1173088a5477SEduard Zingerman 			or_expr_regs(env, cur_env->reg2expr[r], mask);
1174088a5477SEduard Zingerman }
1175088a5477SEduard Zingerman 
11761501b536SEduard Zingerman /* Find the topmost loop header containing idx inside cur_header, or -1 if none. */
11771501b536SEduard Zingerman static int topmost_nested_loop(struct bpf_verifier_env *env, int idx, int cur_header)
11781501b536SEduard Zingerman {
11791501b536SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
11801501b536SEduard Zingerman 	int header;
11811501b536SEduard Zingerman 
11821501b536SEduard Zingerman 	for (header = bpf_loop_at_index(env, idx); header >= 0;
11831501b536SEduard Zingerman 	     header = aux[header].loop_header)
11841501b536SEduard Zingerman 		if (aux[header].loop_header == cur_header)
11851501b536SEduard Zingerman 			return header;
11861501b536SEduard Zingerman 
11871501b536SEduard Zingerman 	return -1;
11881501b536SEduard Zingerman }
11891501b536SEduard Zingerman 
11901501b536SEduard Zingerman /*
11911501b536SEduard Zingerman  * Join cur_env into the successor's environment and schedule their traversal.
11921501b536SEduard Zingerman  * Map successors in nested loops to their topmost nested header.
11931501b536SEduard Zingerman  * Ignore successors outside the current loop and its nested loops.
11941501b536SEduard Zingerman  */
11951501b536SEduard Zingerman static int join_successor(struct bpf_verifier_env *env, int cur_header, int succ_idx,
11961501b536SEduard Zingerman 			  struct env *old_env, struct env *cur_env)
11971501b536SEduard Zingerman {
11981501b536SEduard Zingerman 	bool log_level2 = env->log.level & BPF_LOG_LEVEL2;
11991501b536SEduard Zingerman 	struct scev *scev = env->scev;
12001501b536SEduard Zingerman 	int err, nested_header;
12011501b536SEduard Zingerman 	struct env *succ_env;
12021501b536SEduard Zingerman 
12031501b536SEduard Zingerman 	/*
12041501b536SEduard Zingerman 	 * There are several possibilities for a successor:
12051501b536SEduard Zingerman 	 * - succ_idx can be a part of a loop outside of the cur_header's loop,
12061501b536SEduard Zingerman 	 *   such edges are ignored.
12071501b536SEduard Zingerman 	 * - succ_idx can be a part of the same loop as cur_header,
12081501b536SEduard Zingerman 	 *   for such edges succ_idx environment is updated:
12091501b536SEduard Zingerman 	 *     e[succ_idx] = join(e[succ_idx], cur_env)
12101501b536SEduard Zingerman 	 * - succ_idx can be a part of some loop inner to cur_header,
12111501b536SEduard Zingerman 	 *   in such a case there exists some loop header H,
12121501b536SEduard Zingerman 	 *   such that H.loop_header == cur_header
12131501b536SEduard Zingerman 	 *   and H is the same as succ_idx's loop or contains it.
12141501b536SEduard Zingerman 	 */
12151501b536SEduard Zingerman 	if (bpf_loop_at_index(env, succ_idx) != cur_header) {
12161501b536SEduard Zingerman 		/*
12171501b536SEduard Zingerman 		 * topmost_nested_loop() either finds H or returns -1,
12181501b536SEduard Zingerman 		 * in case if succ_idx is a part of a loop outer to cur_header.
12191501b536SEduard Zingerman 		 */
12201501b536SEduard Zingerman 		nested_header = topmost_nested_loop(env, succ_idx, cur_header);
12211501b536SEduard Zingerman 		if (nested_header < 0)
12221501b536SEduard Zingerman 			return 0;
12231501b536SEduard Zingerman 		succ_idx = nested_header;
12241501b536SEduard Zingerman 	}
12251501b536SEduard Zingerman 	succ_env = get_loop_env(scev, cur_header, succ_idx);
12261501b536SEduard Zingerman 	if (!succ_env)
12271501b536SEduard Zingerman 		return -ENOMEM;
12281501b536SEduard Zingerman 	if (log_level2)
12291501b536SEduard Zingerman 		memcpy(old_env, succ_env, sizeof(*old_env));
12301501b536SEduard Zingerman 	err = join(scev, succ_env, cur_env);
12311501b536SEduard Zingerman 	if (err)
12321501b536SEduard Zingerman 		return err;
12331501b536SEduard Zingerman 	err = worklist_push(env, cur_header, succ_idx);
12341501b536SEduard Zingerman 	if (err)
12351501b536SEduard Zingerman 		return err;
12361501b536SEduard Zingerman 	if (log_level2)
12371501b536SEduard Zingerman 		log_env_changes(env, LOG_AT_JOIN, old_env, succ_env, succ_idx);
12381501b536SEduard Zingerman 	return 0;
12391501b536SEduard Zingerman }
12401501b536SEduard Zingerman 
12411501b536SEduard Zingerman /* Unsupported loops get only an unknown header environment. */
12421501b536SEduard Zingerman static bool can_compute_loop_scev(const struct bpf_loop *loop)
12431501b536SEduard Zingerman {
12441501b536SEduard Zingerman 	return !loop->irreducible && !loop->exits_overflow;
12451501b536SEduard Zingerman }
12461501b536SEduard Zingerman 
12471501b536SEduard Zingerman static int compute_scev_for_loop(struct bpf_verifier_env *env, int cur_header)
12481501b536SEduard Zingerman {
12491501b536SEduard Zingerman 	struct scev_worklist *worklist = &env->scev->worklist;
12501501b536SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
12511501b536SEduard Zingerman 	struct bpf_loop *cur_loop = aux[cur_header].loop;
12521501b536SEduard Zingerman 	struct env *header_env;
12531501b536SEduard Zingerman 	struct scev *scev = env->scev;
12541501b536SEduard Zingerman 	struct bpf_loop *nested_loop;
12551501b536SEduard Zingerman 	struct env *cur_env = NULL;
12561501b536SEduard Zingerman 	struct env *old_env = NULL;
12571501b536SEduard Zingerman 	struct bpf_iarray *succ;
12581501b536SEduard Zingerman 	bool log_level2 = env->log.level & BPF_LOG_LEVEL2;
12591501b536SEduard Zingerman 	int s, i, err, idx, succ_idx;
1260088a5477SEduard Zingerman 	u32 r;
12611501b536SEduard Zingerman 
12621501b536SEduard Zingerman 	if (log_level2)
12631501b536SEduard Zingerman 		bpf_log(&env->log, "Computing SCEV for loop at %d:\n", cur_header);
12641501b536SEduard Zingerman 
12651501b536SEduard Zingerman 	/*
12661501b536SEduard Zingerman 	 * For irreducible loops, and for loops nesting a loop with a truncated
12671501b536SEduard Zingerman 	 * exit list, just assume that everything is clobbered for now.
12681501b536SEduard Zingerman 	 */
12691501b536SEduard Zingerman 	if (!can_compute_loop_scev(cur_loop)) {
12701501b536SEduard Zingerman 		header_env = get_loop_env(scev, cur_header, cur_header);
12711501b536SEduard Zingerman 		if (!header_env)
12721501b536SEduard Zingerman 			return -ENOMEM;
12731501b536SEduard Zingerman 		/* The freshly allocated environment has all expressions unknown. */
1274088a5477SEduard Zingerman 		bitmap_fill(cur_loop->store_base_regs, REGS_NUM);
12751501b536SEduard Zingerman 		header_env->empty = false;
12761501b536SEduard Zingerman 		return 0;
12771501b536SEduard Zingerman 	}
12781501b536SEduard Zingerman 
12791501b536SEduard Zingerman 	cur_env = kzalloc(sizeof(*cur_env), GFP_KERNEL_ACCOUNT);
12801501b536SEduard Zingerman 	if (!cur_env)
12811501b536SEduard Zingerman 		goto nomem;
12821501b536SEduard Zingerman 	if (log_level2) {
12831501b536SEduard Zingerman 		old_env = kzalloc(sizeof(*old_env), GFP_KERNEL_ACCOUNT);
12841501b536SEduard Zingerman 		if (!old_env)
12851501b536SEduard Zingerman 			goto nomem;
12861501b536SEduard Zingerman 	}
12871501b536SEduard Zingerman 	header_env = get_loop_env(scev, cur_header, cur_header);
12881501b536SEduard Zingerman 	if (!header_env)
12891501b536SEduard Zingerman 		goto nomem;
12901501b536SEduard Zingerman 	err = setup_initial_loop_env(env, header_env, cur_header);
12911501b536SEduard Zingerman 	if (err)
12921501b536SEduard Zingerman 		goto out;
12931501b536SEduard Zingerman 	err = worklist_push(env, cur_header, cur_header);
12941501b536SEduard Zingerman 	if (err)
12951501b536SEduard Zingerman 		goto out;
12961501b536SEduard Zingerman 
12971501b536SEduard Zingerman 	while (worklist->nr) {
12981501b536SEduard Zingerman 		idx = *min_heap_peek_inline(worklist);
12991501b536SEduard Zingerman 		min_heap_pop_inline(worklist, &worklist_cb, env->cfg.postorder_nums);
13001501b536SEduard Zingerman 
13011501b536SEduard Zingerman 		/* join_successor() maps nested-loop entries to their representative header. */
13021501b536SEduard Zingerman 		nested_loop = idx != cur_header ? aux[idx].loop : NULL;
13031501b536SEduard Zingerman 		memcpy(cur_env, find_loop_env(scev, cur_header, idx), sizeof(*cur_env));
13041501b536SEduard Zingerman 		if (nested_loop) {
13051501b536SEduard Zingerman 			/*
13061501b536SEduard Zingerman 			 * Process nested loop as a single instruction by
13071501b536SEduard Zingerman 			 * forgetting anything non-invariant in the nested loop
13081501b536SEduard Zingerman 			 */
13091501b536SEduard Zingerman 			if (log_level2)
13101501b536SEduard Zingerman 				memcpy(old_env, cur_env, sizeof(*old_env));
1311088a5477SEduard Zingerman 			/* Pull the nested loop's stack-store base dependencies up. */
1312088a5477SEduard Zingerman 			for_each_set_bit(r, nested_loop->store_base_regs, BPF_SCEV_REGS_NUM)
1313088a5477SEduard Zingerman 				or_expr_regs(env, cur_env->reg2expr[r], cur_loop->store_base_regs);
13141501b536SEduard Zingerman 			forget_non_invariants(env, cur_env, idx);
13151501b536SEduard Zingerman 			if (log_level2)
13161501b536SEduard Zingerman 				log_env_changes(env, LOG_AT_TRANSFER, old_env, cur_env, idx);
13171501b536SEduard Zingerman 			/*
13181501b536SEduard Zingerman 			 * Treat nested loop exits as successors,
13191501b536SEduard Zingerman 			 * join cur_env into successor's envs.
13201501b536SEduard Zingerman 			 */
13211501b536SEduard Zingerman 			for (i = 0; i < nested_loop->exits_cnt; i++) {
13221501b536SEduard Zingerman 				s = nested_loop->exits[i].to;
13231501b536SEduard Zingerman 				err = join_successor(env, cur_header, s, old_env, cur_env);
13241501b536SEduard Zingerman 				if (err)
13251501b536SEduard Zingerman 					goto out;
13261501b536SEduard Zingerman 			}
13271501b536SEduard Zingerman 		} else {
13281501b536SEduard Zingerman 			/*
13291501b536SEduard Zingerman 			 * Iterate instructions within a single basic block
13301501b536SEduard Zingerman 			 * starting at 'idx' mutating 'cur_env'.
13311501b536SEduard Zingerman 			 */
13321501b536SEduard Zingerman 			for (;;) {
13331501b536SEduard Zingerman 				if (log_level2)
13341501b536SEduard Zingerman 					memcpy(old_env, cur_env, sizeof(*old_env));
1335088a5477SEduard Zingerman 				collect_store_base_regs(env, cur_env, idx, cur_loop->store_base_regs);
13361501b536SEduard Zingerman 				err = transfer(env, cur_env, idx);
13371501b536SEduard Zingerman 				if (err)
13381501b536SEduard Zingerman 					goto out;
13391501b536SEduard Zingerman 				reset_scevs_at_indirect_writes(env, cur_env, idx);
13401501b536SEduard Zingerman 				if (log_level2)
13411501b536SEduard Zingerman 					log_env_changes(env, LOG_AT_TRANSFER, old_env, cur_env, idx);
13421501b536SEduard Zingerman 				succ = bpf_insn_successors(env, idx);
13431501b536SEduard Zingerman 				if (succ->cnt != 1)
13441501b536SEduard Zingerman 					break;
13451501b536SEduard Zingerman 				succ_idx = succ->items[0];
13461501b536SEduard Zingerman 				if (aux[idx].bb_end || aux[succ_idx].need_scev ||
13471501b536SEduard Zingerman 				    bpf_loop_at_index(env, succ_idx) != cur_header)
13481501b536SEduard Zingerman 					break;
13491501b536SEduard Zingerman 				idx = succ_idx;
13501501b536SEduard Zingerman 			}
13511501b536SEduard Zingerman 			/* Join cur_env into basic block successor's envs. */
13521501b536SEduard Zingerman 			iarray_for_each(s, succ) {
13531501b536SEduard Zingerman 				err = join_successor(env, cur_header, s, old_env, cur_env);
13541501b536SEduard Zingerman 				if (err)
13551501b536SEduard Zingerman 					goto out;
13561501b536SEduard Zingerman 			}
13571501b536SEduard Zingerman 		}
13581501b536SEduard Zingerman 	}
13591501b536SEduard Zingerman 
13601501b536SEduard Zingerman 	err = 0;
13611501b536SEduard Zingerman out:
13621501b536SEduard Zingerman 	kfree(cur_env);
13631501b536SEduard Zingerman 	kfree(old_env);
13641501b536SEduard Zingerman 	return err;
13651501b536SEduard Zingerman nomem:
13661501b536SEduard Zingerman 	err = -ENOMEM;
13671501b536SEduard Zingerman 	goto out;
13681501b536SEduard Zingerman }
13691501b536SEduard Zingerman 
13701501b536SEduard Zingerman static void mark_latches(struct bpf_verifier_env *env)
13711501b536SEduard Zingerman {
13721501b536SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
13731501b536SEduard Zingerman 	struct bpf_loop *loop;
13741501b536SEduard Zingerman 	int len = env->prog->len;
13751501b536SEduard Zingerman 	int i, j, k, from;
13761501b536SEduard Zingerman 
13771501b536SEduard Zingerman 	for (i = 0; i < len; i++) {
13781501b536SEduard Zingerman 		loop = aux[i].loop;
13791501b536SEduard Zingerman 		if (!loop)
13801501b536SEduard Zingerman 			continue;
13811501b536SEduard Zingerman 		aux[i].need_scev = true;
13821501b536SEduard Zingerman 		if (!can_compute_loop_scev(loop))
13831501b536SEduard Zingerman 			continue;
13841501b536SEduard Zingerman 		/*
13851501b536SEduard Zingerman 		 * Make sure to only set .need_scev for exits and latches
13861501b536SEduard Zingerman 		 * belonging to the loop at `i`. If can_compute_loop_scev()
13871501b536SEduard Zingerman 		 * fails for a loop, it should hide it's instructions from
13881501b536SEduard Zingerman 		 * compute_insn_scevs().
13891501b536SEduard Zingerman 		 */
13901501b536SEduard Zingerman 		for (j = 0; j < loop->backedges_cnt; j++)
13911501b536SEduard Zingerman 			for (k = 0; k < loop->backedges[j].latches_cnt; k++)
13921501b536SEduard Zingerman 				aux[loop->backedges[j].latches[k]].need_scev = true;
13931501b536SEduard Zingerman 		for (j = 0; j < loop->exits_cnt; j++) {
13941501b536SEduard Zingerman 			from = loop->exits[j].from;
13951501b536SEduard Zingerman 			if (bpf_loop_at_index(env, from) == i)
13961501b536SEduard Zingerman 				aux[from].need_scev = true;
13971501b536SEduard Zingerman 		}
13981501b536SEduard Zingerman 	}
13991501b536SEduard Zingerman }
14001501b536SEduard Zingerman 
14011501b536SEduard Zingerman static bool is_any_imm_reg_opaque(struct scev *scev, u32 id)
14021501b536SEduard Zingerman {
14031501b536SEduard Zingerman 	u32 l, r, reg, order;
14041501b536SEduard Zingerman 	s64 imm;
14051501b536SEduard Zingerman 
14061501b536SEduard Zingerman 	scev->stack_sz = 0;
14071501b536SEduard Zingerman 	expr_stack_push(scev, id);
14081501b536SEduard Zingerman 	while (expr_next(scev, &id, &order)) {
14091501b536SEduard Zingerman 		if (order & DEPTH_LIMIT)
14101501b536SEduard Zingerman 			return false;
14111501b536SEduard Zingerman 		if (!(order & PRE) ||
14121501b536SEduard Zingerman 		    is_imm(scev, id, &imm) ||
14131501b536SEduard Zingerman 		    is_reg(scev, id, &reg) ||
14141501b536SEduard Zingerman 		    is_opaque(scev, id) ||
14151501b536SEduard Zingerman 		    is_any(scev, id, &l, &r))
14161501b536SEduard Zingerman 			continue;
14171501b536SEduard Zingerman 		return false;
14181501b536SEduard Zingerman 	}
14191501b536SEduard Zingerman 	return true;
14201501b536SEduard Zingerman }
14211501b536SEduard Zingerman 
14221501b536SEduard Zingerman /*
14231501b536SEduard Zingerman  * Can implement explicit stack version, but it is harder to read.
14241501b536SEduard Zingerman  * Stick with recursive version for now.
14251501b536SEduard Zingerman  */
14261501b536SEduard Zingerman static int transform_expr_once(struct scev *scev, u32 lvl, u32 root, void *priv,
14271501b536SEduard Zingerman 			       int (*fn)(struct scev *scev, u32 id, void *priv))
14281501b536SEduard Zingerman {
14291501b536SEduard Zingerman 	struct expr expr;
14301501b536SEduard Zingerman 	int p0, p1, id;
14311501b536SEduard Zingerman 
14321501b536SEduard Zingerman 	if (lvl >= EXPR_STACK_DEPTH)
14331501b536SEduard Zingerman 		return UNKNOWN_EXPR_ID;
14341501b536SEduard Zingerman 
14351501b536SEduard Zingerman 	expr = scev->exprs[root]; /* snapshot the expr before potential realloc */
14361501b536SEduard Zingerman 	switch (op_params_num(expr.op)) {
14371501b536SEduard Zingerman 	case 0:
14381501b536SEduard Zingerman 		id = root;
14391501b536SEduard Zingerman 		break;
14401501b536SEduard Zingerman 	case 1:
14411501b536SEduard Zingerman 		p0 = transform_expr_once(scev, lvl + 1, expr.params[0], priv, fn);
14421501b536SEduard Zingerman 		id = expr1(scev, expr.op, p0);
14431501b536SEduard Zingerman 		break;
14441501b536SEduard Zingerman 	case 2:
14451501b536SEduard Zingerman 		p0 = transform_expr_once(scev, lvl + 1, expr.params[0], priv, fn);
14461501b536SEduard Zingerman 		p1 = transform_expr_once(scev, lvl + 1, expr.params[1], priv, fn);
14471501b536SEduard Zingerman 		id = expr2(scev, expr.op, p0, p1);
14481501b536SEduard Zingerman 		break;
14491501b536SEduard Zingerman 	}
14501501b536SEduard Zingerman 	return id < 0 ? id : fn(scev, id, priv);
14511501b536SEduard Zingerman }
14521501b536SEduard Zingerman 
14531501b536SEduard Zingerman static int transform_expr(struct scev *scev, u32 root, void *priv,
14541501b536SEduard Zingerman 			  int (*fn)(struct scev *scev, u32 id, void *priv))
14551501b536SEduard Zingerman {
14561501b536SEduard Zingerman 	int i = 0, id_old, id_new = root;
14571501b536SEduard Zingerman 
14581501b536SEduard Zingerman 	do {
14591501b536SEduard Zingerman 		/*
14601501b536SEduard Zingerman 		 * The depth limit is somewhat arbitrary and is essentially a failsafe.
14611501b536SEduard Zingerman 		 * oscillation should not really happen. Still, it seems harsh to error out.
14621501b536SEduard Zingerman 		 */
14631501b536SEduard Zingerman 		if (i++ == 4 * EXPR_STACK_DEPTH)
14641501b536SEduard Zingerman 			return UNKNOWN_EXPR_ID;
14651501b536SEduard Zingerman 		id_old = id_new;
14661501b536SEduard Zingerman 		id_new = transform_expr_once(scev, 0, id_old, priv, fn);
14671501b536SEduard Zingerman 		if (id_new < 0)
14681501b536SEduard Zingerman 			return id_new;
14691501b536SEduard Zingerman 	} while (id_old != id_new);
14701501b536SEduard Zingerman 	return id_new;
14711501b536SEduard Zingerman }
14721501b536SEduard Zingerman 
14731501b536SEduard Zingerman static int simplify(struct scev *scev, u32 id, void *priv)
14741501b536SEduard Zingerman {
1475*32e96257SEduard Zingerman 	int a, b, l, r, t, base, slope;
14761501b536SEduard Zingerman 	s64 imm1, imm2;
14771501b536SEduard Zingerman 
14781501b536SEduard Zingerman 	/* (+ (linear base slope) imm) -> (linear (+ base imm) slope) */
14791501b536SEduard Zingerman 	if (is_add(scev, id, &l, &r) &&
14801501b536SEduard Zingerman 	    is_linear(scev, l, &base, &slope) &&
14811501b536SEduard Zingerman 	    is_imm(scev, r, &imm1))
14821501b536SEduard Zingerman 		return expr2(scev, LINEAR_SCEV, expr2(scev, BPF_ADD, base, r), slope);
14831501b536SEduard Zingerman 
14841501b536SEduard Zingerman 	/* (+ imm imm) -> imm */
14851501b536SEduard Zingerman 	if (is_add(scev, id, &l, &r) &&
14861501b536SEduard Zingerman 	    is_imm(scev, l, &imm1) &&
14871501b536SEduard Zingerman 	    is_imm(scev, r, &imm2))
14881501b536SEduard Zingerman 		return imm_expr(scev, imm1 + imm2);
14891501b536SEduard Zingerman 
14901501b536SEduard Zingerman 	/* (zext32 (imm X)) -> (imm (u32)X) */
14911501b536SEduard Zingerman 	if (is_zext32(scev, id, &l) && is_imm(scev, l, &imm1))
14921501b536SEduard Zingerman 		return imm_expr(scev, (u64)(u32)imm1);
14931501b536SEduard Zingerman 
1494*32e96257SEduard Zingerman 	/*
1495*32e96257SEduard Zingerman 	 * (zext32 (+ (zext32 $a) $b)) -> (zext32 (+ $a $b))
1496*32e96257SEduard Zingerman 	 * (zext32 (+ $a (zext32 $b))) -> (zext32 (+ $a $b))
1497*32e96257SEduard Zingerman 	 */
1498*32e96257SEduard Zingerman 	if ((is_zext32(scev, id, &t) && is_add(scev, t, &l, &b) && is_zext32(scev, l, &a)) ||
1499*32e96257SEduard Zingerman 	    (is_zext32(scev, id, &t) && is_add(scev, t, &a, &r) && is_zext32(scev, r, &b))) {
1500*32e96257SEduard Zingerman 		t = expr2(scev, BPF_ADD, a, b);
1501*32e96257SEduard Zingerman 		t = expr1(scev, ZEXT32, t);
1502*32e96257SEduard Zingerman 		return t;
1503*32e96257SEduard Zingerman 	}
1504*32e96257SEduard Zingerman 
15051501b536SEduard Zingerman 	return id;
15061501b536SEduard Zingerman }
15071501b536SEduard Zingerman 
15081501b536SEduard Zingerman static int compute_header_scevs(struct bpf_verifier_env *env, struct env *header_env)
15091501b536SEduard Zingerman {
15101501b536SEduard Zingerman 	struct scev *scev = env->scev;
1511*32e96257SEduard Zingerman 	int l, r, t, id, ra, rb, ra_expr;
15121501b536SEduard Zingerman 	s64 imm;
15131501b536SEduard Zingerman 
15141501b536SEduard Zingerman 	/*
15151501b536SEduard Zingerman 	 * Note:
15161501b536SEduard Zingerman 	 * reg2expr[ra] describes a change in rA's value over a single loop iteration.
15171501b536SEduard Zingerman 	 * It does not account for rA's entry value. However, the SCEV constructed for rA
15181501b536SEduard Zingerman 	 * must include an additional rA entry edge. For example:
15191501b536SEduard Zingerman 	 *
15201501b536SEduard Zingerman 	 *      r0 = ..., r1 = 7
15211501b536SEduard Zingerman 	 *   l: if r0 == 10 goto e // reg2expr[r1] == (imm 42) => reg2scev[r1] == (any r1 42)
15221501b536SEduard Zingerman 	 *      r0 += 1
15231501b536SEduard Zingerman 	 *      r1 = 42
15241501b536SEduard Zingerman 	 *      goto l
15251501b536SEduard Zingerman 	 *   e:
15261501b536SEduard Zingerman 	 *      ... at exit r1 is in {7,42} ...
15271501b536SEduard Zingerman 	 */
15281501b536SEduard Zingerman 	for (ra = 0; ra < REGS_NUM; ra++) {
15291501b536SEduard Zingerman 		ra_expr = transform_expr(scev, header_env->reg2expr[ra], NULL, simplify);
15301501b536SEduard Zingerman 		if (ra_expr < 0)
15311501b536SEduard Zingerman 			return ra_expr;
15321501b536SEduard Zingerman 		header_env->reg2expr[ra] = ra_expr;
15331501b536SEduard Zingerman 		/* rA = (+ rA IMM) -> (linear rA IMM) */
15341501b536SEduard Zingerman 		if (is_add(scev, ra_expr, &l, &r) &&
15351501b536SEduard Zingerman 		    is_reg(scev, l, &rb) &&
15361501b536SEduard Zingerman 		    is_imm(scev, r, &imm) &&
15371501b536SEduard Zingerman 		    ra == rb) {
15381501b536SEduard Zingerman 			id = expr2(scev, LINEAR_SCEV, l, r);
15391501b536SEduard Zingerman 			if (id < 0)
15401501b536SEduard Zingerman 				return id;
15411501b536SEduard Zingerman 			header_env->reg2scev[ra] = id;
15421501b536SEduard Zingerman 			continue;
15431501b536SEduard Zingerman 		}
1544*32e96257SEduard Zingerman 		/* rA = (is_zext32 (+ rA IMM)) -> (is_zext32 (linear rA IMM)) */
1545*32e96257SEduard Zingerman 		if (is_zext32(scev, ra_expr, &t) &&
1546*32e96257SEduard Zingerman 		    is_add(scev, t, &l, &r) &&
1547*32e96257SEduard Zingerman 		    is_reg(scev, l, &rb) &&
1548*32e96257SEduard Zingerman 		    is_imm(scev, r, &imm) &&
1549*32e96257SEduard Zingerman 		    ra == rb) {
1550*32e96257SEduard Zingerman 			id = expr2(scev, LINEAR_SCEV, l, r);
1551*32e96257SEduard Zingerman 			id = expr1(scev, ZEXT32, id);
1552*32e96257SEduard Zingerman 			if (id < 0)
1553*32e96257SEduard Zingerman 				return id;
1554*32e96257SEduard Zingerman 			header_env->reg2scev[ra] = id;
1555*32e96257SEduard Zingerman 			continue;
1556*32e96257SEduard Zingerman 		}
15571501b536SEduard Zingerman 		/* rA = rA -> rA*/
15581501b536SEduard Zingerman 		if (is_reg(scev, ra_expr, &rb) && ra == rb) {
15591501b536SEduard Zingerman 			header_env->reg2scev[ra] = ra_expr;
15601501b536SEduard Zingerman 			continue;
15611501b536SEduard Zingerman 		}
15621501b536SEduard Zingerman 		/* rA = (any 1 2 3 4 ...) -> (any rA 1 2 3 4 ...) */
15631501b536SEduard Zingerman 		if (is_any_imm_reg_opaque(scev, ra_expr)) {
15641501b536SEduard Zingerman 			id = mk_any(scev, expr1(scev, REG, ra), ra_expr);
15651501b536SEduard Zingerman 			if (id < 0)
15661501b536SEduard Zingerman 				return id;
15671501b536SEduard Zingerman 			header_env->reg2scev[ra] = id;
15681501b536SEduard Zingerman 			continue;
15691501b536SEduard Zingerman 		}
15701501b536SEduard Zingerman 
15711501b536SEduard Zingerman 	}
15721501b536SEduard Zingerman 	return 0;
15731501b536SEduard Zingerman }
15741501b536SEduard Zingerman static int instantiate_header_scevs(struct scev *scev, u32 id, void *priv)
15751501b536SEduard Zingerman {
15761501b536SEduard Zingerman 	u32 reg, *reg2scev = priv;
15771501b536SEduard Zingerman 
15781501b536SEduard Zingerman 	/* (reg r) -> ... equation at header ... */
15791501b536SEduard Zingerman 	if (is_reg(scev, id, &reg))
15801501b536SEduard Zingerman 		return reg2scev[reg];
15811501b536SEduard Zingerman 	/* keep expression shapes */
15821501b536SEduard Zingerman 	return id;
15831501b536SEduard Zingerman }
15841501b536SEduard Zingerman 
15851501b536SEduard Zingerman static int compute_insn_scevs(struct bpf_verifier_env *env, struct env *eheader, struct env *einsn)
15861501b536SEduard Zingerman {
15871501b536SEduard Zingerman 	struct scev *scev = env->scev;
15881501b536SEduard Zingerman 	int id, reg;
15891501b536SEduard Zingerman 
15901501b536SEduard Zingerman 	for (reg = 0; reg < REGS_NUM; reg++) {
15911501b536SEduard Zingerman 		id = einsn->reg2expr[reg];
15921501b536SEduard Zingerman 		id = transform_expr_once(scev, 0, id, eheader->reg2scev, instantiate_header_scevs);
15931501b536SEduard Zingerman 		if (id < 0)
15941501b536SEduard Zingerman 			return id;
15951501b536SEduard Zingerman 		id = transform_expr(scev, id, NULL, simplify);
15961501b536SEduard Zingerman 		if (id < 0)
15971501b536SEduard Zingerman 			return id;
15981501b536SEduard Zingerman 		einsn->reg2scev[reg] = id;
15991501b536SEduard Zingerman 	}
16001501b536SEduard Zingerman 
16011501b536SEduard Zingerman 	return 0;
16021501b536SEduard Zingerman }
16031501b536SEduard Zingerman 
16041501b536SEduard Zingerman static int log_scevs(struct bpf_verifier_env *env)
16051501b536SEduard Zingerman {
16061501b536SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
16071501b536SEduard Zingerman 	struct bpf_verifier_log *log = &env->log;
16081501b536SEduard Zingerman 	struct env *header_env, *latch_env;
16091501b536SEduard Zingerman 	struct scev *scev = env->scev;
16101501b536SEduard Zingerman 	struct bpf_loop *loop;
16111501b536SEduard Zingerman 	int i, j, k, len, latch;
16121501b536SEduard Zingerman 
16131501b536SEduard Zingerman 	len = env->prog->len;
16141501b536SEduard Zingerman 	for (i = 0; i < len; i++) {
16151501b536SEduard Zingerman 		loop = aux[i].loop;
16161501b536SEduard Zingerman 		if (!loop)
16171501b536SEduard Zingerman 			continue;
16181501b536SEduard Zingerman 		header_env = find_header_env(scev, i);
16191501b536SEduard Zingerman 		bpf_log(log, "scev at header %d:\n", i);
16201501b536SEduard Zingerman 		print_env(env, header_env, i);
16211501b536SEduard Zingerman 		if (!can_compute_loop_scev(loop))
16221501b536SEduard Zingerman 			continue;
16231501b536SEduard Zingerman 		for (j = 0; j < loop->backedges_cnt; j++) {
16241501b536SEduard Zingerman 			for (k = 0; k < loop->backedges[j].latches_cnt; k++) {
16251501b536SEduard Zingerman 				latch = loop->backedges[j].latches[k];
16261501b536SEduard Zingerman 				bpf_log(log, " scev at %s %d:\n", k ? "exit" : "latch", latch);
16271501b536SEduard Zingerman 				latch_env = find_loop_env(scev, i, latch);
16281501b536SEduard Zingerman 				if (verifier_bug_if(!latch_env, env, "i=%d, latch=%d", i, latch))
16291501b536SEduard Zingerman 					return -EFAULT;
16301501b536SEduard Zingerman 				print_env(env, latch_env, latch);
16311501b536SEduard Zingerman 			}
16321501b536SEduard Zingerman 		}
16331501b536SEduard Zingerman 	}
16341501b536SEduard Zingerman 	return 0;
16351501b536SEduard Zingerman }
16361501b536SEduard Zingerman 
16371501b536SEduard Zingerman int bpf_compute_scev(struct bpf_verifier_env *env)
16381501b536SEduard Zingerman {
16391501b536SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
16401501b536SEduard Zingerman 	struct scev *scev = env->scev;
16411501b536SEduard Zingerman 	int *postorder = env->cfg.insn_postorder;
16421501b536SEduard Zingerman 	int cnt = env->cfg.cur_postorder;
16431501b536SEduard Zingerman 	int i, idx, err, header;
16441501b536SEduard Zingerman 
16451501b536SEduard Zingerman 	mark_latches(env);
16461501b536SEduard Zingerman 	/*
16471501b536SEduard Zingerman 	 * Visit loop headers in postorder, to guarantee that scevs
16481501b536SEduard Zingerman 	 * for innermost loops are computed first.
16491501b536SEduard Zingerman 	 */
16501501b536SEduard Zingerman 	for (i = 0; i < cnt; i++) {
16511501b536SEduard Zingerman 		idx = postorder[i];
16521501b536SEduard Zingerman 		if (!aux[idx].loop)
16531501b536SEduard Zingerman 			continue;
16541501b536SEduard Zingerman 		err = compute_scev_for_loop(env, idx);
16551501b536SEduard Zingerman 		if (err)
16561501b536SEduard Zingerman 			return err;
16571501b536SEduard Zingerman 	}
16581501b536SEduard Zingerman 
16591501b536SEduard Zingerman 	/*
16601501b536SEduard Zingerman 	 * Compute scevs from exprs collected on a previous step. Iterate instructions in
16611501b536SEduard Zingerman 	 * reverse post-order so that each loop header is processed before instructions
16621501b536SEduard Zingerman 	 * reachable from it.
16631501b536SEduard Zingerman 	 */
16641501b536SEduard Zingerman 	for (i = cnt - 1; i >= 0; i--) {
16651501b536SEduard Zingerman 		idx = postorder[i];
16661501b536SEduard Zingerman 		if (!aux[idx].need_scev)
16671501b536SEduard Zingerman 			continue;
16681501b536SEduard Zingerman 		header = bpf_loop_at_index(env, idx);
16691501b536SEduard Zingerman 		err = aux[idx].loop
16701501b536SEduard Zingerman 		      ? compute_header_scevs(env, find_header_env(scev, header))
16711501b536SEduard Zingerman 		      : compute_insn_scevs(env,
16721501b536SEduard Zingerman 					   find_header_env(scev, header),
16731501b536SEduard Zingerman 					   find_loop_env(scev, header, idx));
16741501b536SEduard Zingerman 		if (err)
16751501b536SEduard Zingerman 			return err;
16761501b536SEduard Zingerman 	}
16771501b536SEduard Zingerman 
16781501b536SEduard Zingerman 	for (i = 0; i < env->prog->len; i++)
16791501b536SEduard Zingerman 		if (aux[i].loop)
16801501b536SEduard Zingerman 			aux[i].prune_point = true;
16811501b536SEduard Zingerman 
16821501b536SEduard Zingerman 	if (env->log.level & BPF_LOG_LEVEL2) {
16831501b536SEduard Zingerman 		err = log_scevs(env);
16841501b536SEduard Zingerman 		if (err)
16851501b536SEduard Zingerman 			return err;
16861501b536SEduard Zingerman 	}
16871501b536SEduard Zingerman 
16881501b536SEduard Zingerman 	return 0;
16891501b536SEduard Zingerman }
16901501b536SEduard Zingerman 
16911501b536SEduard Zingerman void bpf_free_scev(struct bpf_verifier_env *env)
16921501b536SEduard Zingerman {
16931501b536SEduard Zingerman 	struct scev *scev = env->scev;
16941501b536SEduard Zingerman 	struct insn_envs *envs;
16951501b536SEduard Zingerman 	int i;
16961501b536SEduard Zingerman 	u32 j;
16971501b536SEduard Zingerman 
16981501b536SEduard Zingerman 	if (!scev)
16991501b536SEduard Zingerman 		return;
17001501b536SEduard Zingerman 	for (i = 0; i < scev->envs_cnt; i++) {
17011501b536SEduard Zingerman 		envs = scev->envs[i];
17021501b536SEduard Zingerman 		if (!envs)
17031501b536SEduard Zingerman 			continue;
17041501b536SEduard Zingerman 		for (j = 0; j < envs->cnt; j++)
17051501b536SEduard Zingerman 			kfree(envs->entries[j].env);
17061501b536SEduard Zingerman 		kfree(envs);
17071501b536SEduard Zingerman 	}
17081501b536SEduard Zingerman 	if (scev->exprs_ht)
17091501b536SEduard Zingerman 		for (i = 0; i < scev->exprs_ht_cnt; i++)
17101501b536SEduard Zingerman 			kvfree(scev->exprs_ht[i]);
17111501b536SEduard Zingerman 	kvfree(scev->exprs_ht);
17121501b536SEduard Zingerman 	kvfree(scev->worklist.data);
17131501b536SEduard Zingerman 	kvfree(scev->envs);
17141501b536SEduard Zingerman 	kvfree(scev->exprs);
17151501b536SEduard Zingerman 	kvfree(scev->discovered);
17161501b536SEduard Zingerman 	kfree(scev);
17171501b536SEduard Zingerman 	env->scev = NULL;
17181501b536SEduard Zingerman }
17191501b536SEduard Zingerman 
17201501b536SEduard Zingerman int bpf_init_scev(struct bpf_verifier_env *env)
17211501b536SEduard Zingerman {
17221501b536SEduard Zingerman 	struct scev *scev;
17231501b536SEduard Zingerman 
17241501b536SEduard Zingerman 	scev = kzalloc(sizeof(struct scev), GFP_KERNEL_ACCOUNT);
17251501b536SEduard Zingerman 	if (!scev)
17261501b536SEduard Zingerman 		return -ENOMEM;
17271501b536SEduard Zingerman 	env->scev = scev;
17286ccf49f7SEduard Zingerman 	bpf_mark_reg_known_scalar(&scev->zero_reg, 0);
17296ccf49f7SEduard Zingerman 	bpf_mark_reg_unknown_imprecise(&scev->unknown_reg);
17301501b536SEduard Zingerman 	/* A power of two for hash & (exprs_ht_cnt - 1)` indexing. */
17311501b536SEduard Zingerman 	scev->exprs_ht_cnt = roundup_pow_of_two(max(256U, DIV_ROUND_UP(env->prog->len, 4)));
17321501b536SEduard Zingerman 	scev->exprs_ht = kvcalloc(scev->exprs_ht_cnt, sizeof(*scev->exprs_ht), GFP_KERNEL_ACCOUNT);
17331501b536SEduard Zingerman 	if (!scev->exprs_ht)
17341501b536SEduard Zingerman 		goto nomem;
17351501b536SEduard Zingerman 	if (expr0(scev, UNKNOWN) < 0 || expr0(scev, OPAQUE)  < 0)
17361501b536SEduard Zingerman 		goto nomem;
17371501b536SEduard Zingerman 	scev->envs = kvcalloc(env->prog->len, sizeof(*scev->envs), GFP_KERNEL_ACCOUNT);
17381501b536SEduard Zingerman 	scev->discovered = kvcalloc(env->prog->len, sizeof(*scev->discovered), GFP_KERNEL_ACCOUNT);
17391501b536SEduard Zingerman 	if (!scev->envs || !scev->discovered)
17401501b536SEduard Zingerman 		goto nomem;
17411501b536SEduard Zingerman 	/*
17421501b536SEduard Zingerman 	 * Remember original program length, in case bpf_free_scev()
17431501b536SEduard Zingerman 	 * is called after bpf program rewrites that increase program
17441501b536SEduard Zingerman 	 * length.
17451501b536SEduard Zingerman 	 */
17461501b536SEduard Zingerman 	scev->envs_cnt = env->prog->len;
17471501b536SEduard Zingerman 	return 0;
17481501b536SEduard Zingerman nomem:
17491501b536SEduard Zingerman 	bpf_free_scev(env);
17501501b536SEduard Zingerman 	return -ENOMEM;
17511501b536SEduard Zingerman }
17526ccf49f7SEduard Zingerman 
17536ccf49f7SEduard Zingerman static struct bpf_stack_state *scev_regno_to_stack(const struct bpf_func_state *st, u32 r)
17546ccf49f7SEduard Zingerman {
17556ccf49f7SEduard Zingerman 	int spi, slots_available;
17566ccf49f7SEduard Zingerman 
17576ccf49f7SEduard Zingerman 	if (r < MAX_BPF_REG)
17586ccf49f7SEduard Zingerman 		return NULL;
17596ccf49f7SEduard Zingerman 
17606ccf49f7SEduard Zingerman 	slots_available = st->allocated_stack / BPF_REG_SIZE;
17616ccf49f7SEduard Zingerman 	spi = r - MAX_BPF_REG;
17626ccf49f7SEduard Zingerman 	if (spi < slots_available)
17636ccf49f7SEduard Zingerman 		return &st->stack[spi];
17646ccf49f7SEduard Zingerman 
17656ccf49f7SEduard Zingerman 	return NULL;
17666ccf49f7SEduard Zingerman }
17676ccf49f7SEduard Zingerman 
17686ccf49f7SEduard Zingerman static struct bpf_reg_state *scev_regno_to_reg(struct bpf_func_state *st, u32 r)
17696ccf49f7SEduard Zingerman {
17706ccf49f7SEduard Zingerman 	return r < MAX_BPF_REG ? &st->regs[r] : NULL;
17716ccf49f7SEduard Zingerman }
17726ccf49f7SEduard Zingerman 
17736ccf49f7SEduard Zingerman /* Linear widening requires a physical register or a full spill. */
17746ccf49f7SEduard Zingerman static struct bpf_reg_state *scev_reg_for_linear(struct bpf_func_state *st, u32 r)
17756ccf49f7SEduard Zingerman {
17766ccf49f7SEduard Zingerman 	struct bpf_stack_state *stack;
17776ccf49f7SEduard Zingerman 
17786ccf49f7SEduard Zingerman 	if (r < MAX_BPF_REG)
17796ccf49f7SEduard Zingerman 		return scev_regno_to_reg(st, r);
17806ccf49f7SEduard Zingerman 	stack = scev_regno_to_stack(st, r);
17816ccf49f7SEduard Zingerman 	if (!stack || bpf_spill_size(stack) != BPF_REG_SIZE)
17826ccf49f7SEduard Zingerman 		return NULL;
17836ccf49f7SEduard Zingerman 	return &stack->spilled_ptr;
17846ccf49f7SEduard Zingerman }
17856ccf49f7SEduard Zingerman 
17866ccf49f7SEduard Zingerman /*
17876ccf49f7SEduard Zingerman  * Return a borrowed value; never use it as a widening destination.
17886ccf49f7SEduard Zingerman  * NULL denotes no readable value.
17896ccf49f7SEduard Zingerman  */
17906ccf49f7SEduard Zingerman static const struct bpf_reg_state *
17916ccf49f7SEduard Zingerman scev_reg_for_read(struct bpf_verifier_env *env, const struct bpf_func_state *st, u32 r)
17926ccf49f7SEduard Zingerman {
17936ccf49f7SEduard Zingerman 	const struct bpf_stack_state *stack;
17946ccf49f7SEduard Zingerman 	bool zero = true;
17956ccf49f7SEduard Zingerman 	int i;
17966ccf49f7SEduard Zingerman 
17976ccf49f7SEduard Zingerman 	if (r < MAX_BPF_REG)
17986ccf49f7SEduard Zingerman 		return st->regs[r].type == NOT_INIT ? NULL : &st->regs[r];
17996ccf49f7SEduard Zingerman 	if (r >= REGS_NUM || r - MAX_BPF_REG >= env->stack_limit / BPF_REG_SIZE)
18006ccf49f7SEduard Zingerman 		return NULL;
18016ccf49f7SEduard Zingerman 
18026ccf49f7SEduard Zingerman 	stack = scev_regno_to_stack(st, r);
18036ccf49f7SEduard Zingerman 	if (!stack)
18046ccf49f7SEduard Zingerman 		return &env->scev->unknown_reg;
18056ccf49f7SEduard Zingerman 	if (bpf_spill_size(stack) == BPF_REG_SIZE)
18066ccf49f7SEduard Zingerman 		return &stack->spilled_ptr;
18076ccf49f7SEduard Zingerman 
18086ccf49f7SEduard Zingerman 	/* Partial spills do not describe the value of the whole slot. */
18096ccf49f7SEduard Zingerman 	for (i = 0; i < BPF_REG_SIZE; i++) {
18106ccf49f7SEduard Zingerman 		switch (stack->slot_type[i]) {
18116ccf49f7SEduard Zingerman 		case STACK_ZERO:
18126ccf49f7SEduard Zingerman 			break;
18136ccf49f7SEduard Zingerman 		case STACK_INVALID:
18146ccf49f7SEduard Zingerman 		case STACK_POISON:
18156ccf49f7SEduard Zingerman 		case STACK_MISC:
18166ccf49f7SEduard Zingerman 			zero = false;
18176ccf49f7SEduard Zingerman 			break;
18186ccf49f7SEduard Zingerman 		case STACK_SPILL:
18196ccf49f7SEduard Zingerman 			if (!bpf_is_spilled_scalar_reg(stack))
18206ccf49f7SEduard Zingerman 				return NULL;
18216ccf49f7SEduard Zingerman 			zero = false;
18226ccf49f7SEduard Zingerman 			break;
18236ccf49f7SEduard Zingerman 		default:
18246ccf49f7SEduard Zingerman 			return NULL;
18256ccf49f7SEduard Zingerman 		}
18266ccf49f7SEduard Zingerman 	}
18276ccf49f7SEduard Zingerman 	return zero ? &env->scev->zero_reg : &env->scev->unknown_reg;
18286ccf49f7SEduard Zingerman }
18296ccf49f7SEduard Zingerman 
18306ccf49f7SEduard Zingerman /* Materialize a writable value in the current state, growing its stack if needed. */
18316ccf49f7SEduard Zingerman static int scev_reg_for_write(struct bpf_verifier_env *env, struct bpf_func_state *st,
18326ccf49f7SEduard Zingerman 			      u32 r, struct bpf_reg_state **out)
18336ccf49f7SEduard Zingerman {
18346ccf49f7SEduard Zingerman 	const struct bpf_reg_state *value;
18356ccf49f7SEduard Zingerman 	struct bpf_stack_state *stack;
18366ccf49f7SEduard Zingerman 	u32 spi;
18376ccf49f7SEduard Zingerman 	int err;
18386ccf49f7SEduard Zingerman 
18396ccf49f7SEduard Zingerman 	*out = scev_regno_to_reg(st, r);
18406ccf49f7SEduard Zingerman 	if (*out)
18416ccf49f7SEduard Zingerman 		return 0;
18426ccf49f7SEduard Zingerman 	if (r >= REGS_NUM || r - MAX_BPF_REG >= env->stack_limit / BPF_REG_SIZE)
18436ccf49f7SEduard Zingerman 		return -EINVAL;
18446ccf49f7SEduard Zingerman 
18456ccf49f7SEduard Zingerman 	spi = r - MAX_BPF_REG;
18466ccf49f7SEduard Zingerman 	err = bpf_grow_stack_state(env, st, (spi + 1) * BPF_REG_SIZE);
18476ccf49f7SEduard Zingerman 	if (err)
18486ccf49f7SEduard Zingerman 		return err;
18496ccf49f7SEduard Zingerman 
18506ccf49f7SEduard Zingerman 	/* Resolve pointers after growth, which may relocate the stack. */
18516ccf49f7SEduard Zingerman 	value = scev_reg_for_read(env, st, r);
18526ccf49f7SEduard Zingerman 	if (!value)
18536ccf49f7SEduard Zingerman 		return -EINVAL;
18546ccf49f7SEduard Zingerman 	stack = scev_regno_to_stack(st, r);
18556ccf49f7SEduard Zingerman 	stack->spilled_ptr = *value;
18566ccf49f7SEduard Zingerman 	memset(stack->slot_type, STACK_SPILL, sizeof(stack->slot_type));
18576ccf49f7SEduard Zingerman 	*out = &stack->spilled_ptr;
18586ccf49f7SEduard Zingerman 	return 0;
18596ccf49f7SEduard Zingerman }
18606ccf49f7SEduard Zingerman 
18616ccf49f7SEduard Zingerman static bool scev_reg_alive(struct bpf_verifier_env *env, struct bpf_verifier_state *st, u32 r)
18626ccf49f7SEduard Zingerman {
18636ccf49f7SEduard Zingerman 	int insn_idx = bpf_frame_insn_idx(st, st->curframe);
18646ccf49f7SEduard Zingerman 	u16 live_regs = env->insn_aux_data[insn_idx].live_regs_before;
18656ccf49f7SEduard Zingerman 	int spi;
18666ccf49f7SEduard Zingerman 
18676ccf49f7SEduard Zingerman 	if (r < MAX_BPF_REG) {
18686ccf49f7SEduard Zingerman 		return BIT(r) & live_regs;
18696ccf49f7SEduard Zingerman 	} else {
18706ccf49f7SEduard Zingerman 		spi = r - MAX_BPF_REG;
18716ccf49f7SEduard Zingerman 		return bpf_stack_slot_alive(env, st->curframe, spi * 2) ||
18726ccf49f7SEduard Zingerman 		       bpf_stack_slot_alive(env, st->curframe, spi * 2 + 1);
18736ccf49f7SEduard Zingerman 	}
18746ccf49f7SEduard Zingerman }
18756ccf49f7SEduard Zingerman 
18766ccf49f7SEduard Zingerman /*
18776ccf49f7SEduard Zingerman  * Latch is a condition deciding if execution remains inside a loop.
18786ccf49f7SEduard Zingerman  * Linear latch represents a condition 'if <reg> <op> <loop invariant> goto <loop-header>',
18796ccf49f7SEduard Zingerman  * where equation '<base> + i * <step> <op> <bound>' describes values taken by register <reg>,
18806ccf49f7SEduard Zingerman  * 'i' is the loop iteration number, starting from 0.
1881*32e96257SEduard Zingerman  * 'zext32' indicates the latch is for (zext32 (linear ...)) SCEV.
1882*32e96257SEduard Zingerman  * 'jmp32' indicates that the latch is a JMP32 instruction.
18836ccf49f7SEduard Zingerman  */
18846ccf49f7SEduard Zingerman struct linear_latch {
18856ccf49f7SEduard Zingerman 	u32 insn_idx;
18866ccf49f7SEduard Zingerman 	u32 base_expr;
18876ccf49f7SEduard Zingerman 	u32 step_expr;
18886ccf49f7SEduard Zingerman 	u32 bound_expr;
1889*32e96257SEduard Zingerman 	u8 op;
1890*32e96257SEduard Zingerman 	bool zext32;
1891*32e96257SEduard Zingerman 	bool jmp32;
18926ccf49f7SEduard Zingerman };
18936ccf49f7SEduard Zingerman 
18946ccf49f7SEduard Zingerman static bool loop_invariant(struct scev *scev, u32 id)
18956ccf49f7SEduard Zingerman {
18966ccf49f7SEduard Zingerman 	s64 imm;
18976ccf49f7SEduard Zingerman 	u32 reg;
18986ccf49f7SEduard Zingerman 
18996ccf49f7SEduard Zingerman 	return is_reg(scev, id, &reg) || is_imm(scev, id, &imm);
19006ccf49f7SEduard Zingerman }
19016ccf49f7SEduard Zingerman 
19026ccf49f7SEduard Zingerman static int match_linear_latch(struct bpf_verifier_env *env,
19036ccf49f7SEduard Zingerman 			      u32 header,
19046ccf49f7SEduard Zingerman 			      u32 latch_idx,
19056ccf49f7SEduard Zingerman 			      struct linear_latch *latch)
19066ccf49f7SEduard Zingerman {
19076ccf49f7SEduard Zingerman 	struct bpf_insn *insn = &env->prog->insnsi[latch_idx];
19086ccf49f7SEduard Zingerman 	struct scev *scev = env->scev;
19096ccf49f7SEduard Zingerman 	struct env *latch_env;
19106ccf49f7SEduard Zingerman 	u32 true_branch_loop;
19116ccf49f7SEduard Zingerman 	u32 true_branch_tgt;
19126ccf49f7SEduard Zingerman 	u32 src_reg_scev;
19136ccf49f7SEduard Zingerman 	u32 dst_reg_scev;
19146ccf49f7SEduard Zingerman 	u32 t, l, r, op;
19156ccf49f7SEduard Zingerman 	int id;
19166ccf49f7SEduard Zingerman 
19176ccf49f7SEduard Zingerman 	op = BPF_OP(insn->code);
1918*32e96257SEduard Zingerman 	latch->jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
19196ccf49f7SEduard Zingerman 	/* Flip the condition if true branch jumps out of the loop. */
19206ccf49f7SEduard Zingerman 	true_branch_tgt = latch_idx + bpf_jmp_offset(insn) + 1;
19216ccf49f7SEduard Zingerman 	true_branch_loop = bpf_loop_at_index(env, true_branch_tgt);
19226ccf49f7SEduard Zingerman 	if (true_branch_loop != header &&
19236ccf49f7SEduard Zingerman 	    !bpf_is_nested_loop(env, true_branch_loop, header))
19246ccf49f7SEduard Zingerman 		op = bpf_rev_opcode(op);
19256ccf49f7SEduard Zingerman 	switch (op) {
19266ccf49f7SEduard Zingerman 	case BPF_JSLT:
19276ccf49f7SEduard Zingerman 	case BPF_JSLE:
19286ccf49f7SEduard Zingerman 	case BPF_JSGT:
19296ccf49f7SEduard Zingerman 	case BPF_JSGE:
19306ccf49f7SEduard Zingerman 	case BPF_JLT:
19316ccf49f7SEduard Zingerman 	case BPF_JLE:
19326ccf49f7SEduard Zingerman 	case BPF_JGT:
19336ccf49f7SEduard Zingerman 	case BPF_JGE:
19346ccf49f7SEduard Zingerman 	case BPF_JNE:
19356ccf49f7SEduard Zingerman 		break;
19366ccf49f7SEduard Zingerman 	default:
19376ccf49f7SEduard Zingerman 		return false;
19386ccf49f7SEduard Zingerman 	}
19396ccf49f7SEduard Zingerman 
19406ccf49f7SEduard Zingerman 	latch->insn_idx = latch_idx;
19416ccf49f7SEduard Zingerman 
19426ccf49f7SEduard Zingerman 	latch_env = find_loop_env(scev, header, latch_idx);
19436ccf49f7SEduard Zingerman 	if (verifier_bug_if(!latch_env, env, "header_idx=%d, latch_idx=%d\n", header, latch_idx))
19446ccf49f7SEduard Zingerman 		return -EFAULT;
19456ccf49f7SEduard Zingerman 	dst_reg_scev = latch_env->reg2scev[insn->dst_reg];
19466ccf49f7SEduard Zingerman 	src_reg_scev = latch_env->reg2scev[insn->src_reg];
19476ccf49f7SEduard Zingerman 	/*
19486ccf49f7SEduard Zingerman 	 * Make sure (linear ...) is in dst_reg_scev:
19496ccf49f7SEduard Zingerman 	 *   'if <invariant> <op> <linear>' ⇔
19506ccf49f7SEduard Zingerman 	 * 'if <linear> <flip(op)> <invariant>'.
19516ccf49f7SEduard Zingerman 	 */
1952*32e96257SEduard Zingerman 	if (BPF_SRC(insn->code) == BPF_X &&
1953*32e96257SEduard Zingerman 	    is_linear_or_linear32(scev, src_reg_scev, &l, &r, &latch->zext32)) {
19546ccf49f7SEduard Zingerman 		swap(dst_reg_scev, src_reg_scev);
19556ccf49f7SEduard Zingerman 		op = bpf_flip_opcode(op);
19566ccf49f7SEduard Zingerman 	}
19576ccf49f7SEduard Zingerman 	latch->op = op;
19586ccf49f7SEduard Zingerman 	/*
19596ccf49f7SEduard Zingerman 	 * simplify() produces two shapes for linear latches:
19606ccf49f7SEduard Zingerman 	 * - (linear register step)
19616ccf49f7SEduard Zingerman 	 *           ^----------------------------+-- base_expr
19626ccf49f7SEduard Zingerman 	 *           base_expr                    |
19636ccf49f7SEduard Zingerman 	 * - (linear (+ register imm) step)       |
19646ccf49f7SEduard Zingerman 	 *           ^----------------------------'
19656ccf49f7SEduard Zingerman 	 */
1966*32e96257SEduard Zingerman 	if (!is_linear_or_linear32(scev, dst_reg_scev,
1967*32e96257SEduard Zingerman 				   &latch->base_expr, &latch->step_expr, &latch->zext32))
19686ccf49f7SEduard Zingerman 		return false;
19696ccf49f7SEduard Zingerman 
19706ccf49f7SEduard Zingerman 	if (BPF_SRC(insn->code) == BPF_K) {
19716ccf49f7SEduard Zingerman 		id = imm_expr(scev, insn->imm);
19726ccf49f7SEduard Zingerman 		if (id < 0)
19736ccf49f7SEduard Zingerman 			return id;
19746ccf49f7SEduard Zingerman 		latch->bound_expr = id;
19756ccf49f7SEduard Zingerman 	} else {
19766ccf49f7SEduard Zingerman 		latch->bound_expr = src_reg_scev;
19776ccf49f7SEduard Zingerman 	}
19786ccf49f7SEduard Zingerman 
19796ccf49f7SEduard Zingerman 	if (!loop_invariant(scev, latch->step_expr) ||
19806ccf49f7SEduard Zingerman 	    !loop_invariant(scev, latch->bound_expr))
19816ccf49f7SEduard Zingerman 		return false;
19826ccf49f7SEduard Zingerman 
19836ccf49f7SEduard Zingerman 	/* (linear register step) */
19846ccf49f7SEduard Zingerman 	if (is_reg(scev, latch->base_expr, &t))
19856ccf49f7SEduard Zingerman 		return true;
19866ccf49f7SEduard Zingerman 
19876ccf49f7SEduard Zingerman 	/* (linear (+ register imm) step) */
19886ccf49f7SEduard Zingerman 	if (is_add(scev, latch->base_expr, &l, &r) &&
19896ccf49f7SEduard Zingerman 	    is_reg(scev, l, &t) &&
19906ccf49f7SEduard Zingerman 	    loop_invariant(scev, r))
19916ccf49f7SEduard Zingerman 		return true;
19926ccf49f7SEduard Zingerman 
19936ccf49f7SEduard Zingerman 	return false;
19946ccf49f7SEduard Zingerman }
19956ccf49f7SEduard Zingerman 
19966ccf49f7SEduard Zingerman struct scev_value {
19976ccf49f7SEduard Zingerman 	u64 value;	/* scalar value or a pointer offset */
19986ccf49f7SEduard Zingerman 	int ptr_reg;	/* SCEV register identifying the pointer origin, or -1. */
19996ccf49f7SEduard Zingerman };
20006ccf49f7SEduard Zingerman 
20016ccf49f7SEduard Zingerman static void log_scev_value(struct bpf_verifier_env *env, struct bpf_func_state *st,
20026ccf49f7SEduard Zingerman 			   const struct scev_value *v)
20036ccf49f7SEduard Zingerman {
20046ccf49f7SEduard Zingerman 	const struct bpf_reg_state *reg;
20056ccf49f7SEduard Zingerman 
20066ccf49f7SEduard Zingerman 	if (v->ptr_reg >= 0) {
20076ccf49f7SEduard Zingerman 		reg = scev_reg_for_read(env, st, v->ptr_reg);
20086ccf49f7SEduard Zingerman 		log_reg(env, v->ptr_reg);
20096ccf49f7SEduard Zingerman 		bpf_log(&env->log, " (%s)", reg ? reg_type_str(env, reg->type) : "unavailable");
20106ccf49f7SEduard Zingerman 	} else {
20116ccf49f7SEduard Zingerman 		bpf_log(&env->log, "scalar %llu", v->value);
20126ccf49f7SEduard Zingerman 	}
20136ccf49f7SEduard Zingerman }
20146ccf49f7SEduard Zingerman 
20156ccf49f7SEduard Zingerman static void log_incompatible_scev_values(struct bpf_verifier_env *env, const char *reason,
20166ccf49f7SEduard Zingerman 					struct bpf_func_state *st,
20176ccf49f7SEduard Zingerman 					const struct scev_value *a, const struct scev_value *b)
20186ccf49f7SEduard Zingerman {
20196ccf49f7SEduard Zingerman 	bpf_log(&env->log, "scev: %s ", reason);
20206ccf49f7SEduard Zingerman 	log_scev_value(env, st, a);
20216ccf49f7SEduard Zingerman 	bpf_log(&env->log, ", ");
20226ccf49f7SEduard Zingerman 	log_scev_value(env, st, b);
20236ccf49f7SEduard Zingerman 	bpf_log(&env->log, "\n");
20246ccf49f7SEduard Zingerman }
20256ccf49f7SEduard Zingerman 
20266ccf49f7SEduard Zingerman static bool scev_value_compatible(struct bpf_verifier_env *env, struct bpf_func_state *st,
20276ccf49f7SEduard Zingerman 				  const struct scev_value *a, const struct scev_value *b)
20286ccf49f7SEduard Zingerman {
20296ccf49f7SEduard Zingerman 	const struct bpf_reg_state *ra, *rb;
20306ccf49f7SEduard Zingerman 
20316ccf49f7SEduard Zingerman 	if (a->ptr_reg < 0 || b->ptr_reg < 0) {
20326ccf49f7SEduard Zingerman 		if (a->ptr_reg < 0 && b->ptr_reg < 0)
20336ccf49f7SEduard Zingerman 			return true;
20346ccf49f7SEduard Zingerman 		goto incompatible;
20356ccf49f7SEduard Zingerman 	}
20366ccf49f7SEduard Zingerman 	ra = scev_reg_for_read(env, st, a->ptr_reg);
20376ccf49f7SEduard Zingerman 	rb = scev_reg_for_read(env, st, b->ptr_reg);
20386ccf49f7SEduard Zingerman 	if (ra && rb && bpf_same_memory_origin(ra, rb))
20396ccf49f7SEduard Zingerman 		return true;
20406ccf49f7SEduard Zingerman 
20416ccf49f7SEduard Zingerman incompatible:
20426ccf49f7SEduard Zingerman 	if (env->log.level & BPF_LOG_LEVEL2)
20436ccf49f7SEduard Zingerman 		log_incompatible_scev_values(env, "incompatible latch operands", st, a, b);
20446ccf49f7SEduard Zingerman 	return false;
20456ccf49f7SEduard Zingerman }
20466ccf49f7SEduard Zingerman 
20476ccf49f7SEduard Zingerman static bool scev_value_add(struct bpf_verifier_env *env, struct bpf_func_state *st,
20486ccf49f7SEduard Zingerman 			   const struct scev_value *a, const struct scev_value *b,
20496ccf49f7SEduard Zingerman 			   struct scev_value *result)
20506ccf49f7SEduard Zingerman {
20516ccf49f7SEduard Zingerman 	if (a->ptr_reg >= 0 && b->ptr_reg >= 0) {
20526ccf49f7SEduard Zingerman 		if (env->log.level & BPF_LOG_LEVEL2)
20536ccf49f7SEduard Zingerman 			log_incompatible_scev_values(env, "can't add two pointers", st, a, b);
20546ccf49f7SEduard Zingerman 		return false;
20556ccf49f7SEduard Zingerman 	}
20566ccf49f7SEduard Zingerman 	result->value = a->value + b->value;
20576ccf49f7SEduard Zingerman 	result->ptr_reg = a->ptr_reg >= 0 ? a->ptr_reg : b->ptr_reg;
20586ccf49f7SEduard Zingerman 	return true;
20596ccf49f7SEduard Zingerman }
20606ccf49f7SEduard Zingerman 
20616ccf49f7SEduard Zingerman static bool eval_expr(struct bpf_verifier_env *env, struct scev *scev,
20626ccf49f7SEduard Zingerman 		      struct bpf_func_state *st, u32 id, struct scev_value *result)
20636ccf49f7SEduard Zingerman {
20646ccf49f7SEduard Zingerman 	struct scev_value lval, rval;
20656ccf49f7SEduard Zingerman 	const struct bpf_reg_state *reg;
20666ccf49f7SEduard Zingerman 	u32 l, r, regno;
20676ccf49f7SEduard Zingerman 	s64 imm;
20686ccf49f7SEduard Zingerman 
20696ccf49f7SEduard Zingerman 	if (is_reg(scev, id, &regno)) {
20706ccf49f7SEduard Zingerman 		reg = scev_reg_for_read(env, st, regno);
20716ccf49f7SEduard Zingerman 		if (!reg || reg->type == NOT_INIT || !tnum_is_const(reg->var_off))
20726ccf49f7SEduard Zingerman 			return false;
20736ccf49f7SEduard Zingerman 		result->value = reg->var_off.value;
20746ccf49f7SEduard Zingerman 		result->ptr_reg = reg->type == SCALAR_VALUE ? -1 : (int)regno;
20756ccf49f7SEduard Zingerman 		return true;
20766ccf49f7SEduard Zingerman 	} else if (is_imm(scev, id, &imm)) {
20776ccf49f7SEduard Zingerman 		result->value = imm;
20786ccf49f7SEduard Zingerman 		result->ptr_reg = -1;
20796ccf49f7SEduard Zingerman 		return true;
20806ccf49f7SEduard Zingerman 	} else if (is_add(scev, id, &l, &r) &&
20816ccf49f7SEduard Zingerman 		   eval_expr(env, scev, st, l, &lval) &&
20826ccf49f7SEduard Zingerman 		   eval_expr(env, scev, st, r, &rval)) {
20836ccf49f7SEduard Zingerman 		return scev_value_add(env, st, &lval, &rval, result);
20846ccf49f7SEduard Zingerman 	}
20856ccf49f7SEduard Zingerman 	return false;
20866ccf49f7SEduard Zingerman }
20876ccf49f7SEduard Zingerman 
2088*32e96257SEduard Zingerman static bool is_signed_op(u8 op)
20896ccf49f7SEduard Zingerman {
2090*32e96257SEduard Zingerman 	switch (op) {
2091*32e96257SEduard Zingerman 	case BPF_JSLT:
2092*32e96257SEduard Zingerman 	case BPF_JSLE:
2093*32e96257SEduard Zingerman 	case BPF_JSGT:
2094*32e96257SEduard Zingerman 	case BPF_JSGE:
2095*32e96257SEduard Zingerman 		return true;
2096*32e96257SEduard Zingerman 	default:
2097*32e96257SEduard Zingerman 		return false;
2098*32e96257SEduard Zingerman 	}
2099*32e96257SEduard Zingerman }
2100*32e96257SEduard Zingerman 
2101*32e96257SEduard Zingerman static bool compute_backedge_taken_count(u8 op, u64 initial, u64 step, u64 bound, u64 *result)
2102*32e96257SEduard Zingerman {
2103*32e96257SEduard Zingerman 	u64 rem, diff, backedge_taken_count;
21046ccf49f7SEduard Zingerman 	bool up, down;
21056ccf49f7SEduard Zingerman 
21066ccf49f7SEduard Zingerman 	if (step == 0)
21076ccf49f7SEduard Zingerman 		return false;
21086ccf49f7SEduard Zingerman 	down = (s64)step < 0;
21096ccf49f7SEduard Zingerman 	up = (s64)step > 0;
21106ccf49f7SEduard Zingerman 	diff = bound - initial;
21116ccf49f7SEduard Zingerman 	switch (op) {
21126ccf49f7SEduard Zingerman 	case BPF_JLT:
21136ccf49f7SEduard Zingerman 		/*
21146ccf49f7SEduard Zingerman 		 * E.g.: 3 + 2*i < 7 ⇔ 2*i < 4 ⇔ i ∈ [0,1].
21156ccf49f7SEduard Zingerman 		 * Here the inequality describes a set of values `i` might take
21166ccf49f7SEduard Zingerman 		 * while the latch condition remains true (the backedge is taken).
21176ccf49f7SEduard Zingerman 		 * The backedge_taken_count is the size of this set.
21186ccf49f7SEduard Zingerman 		 */
21196ccf49f7SEduard Zingerman 		if (/*
21206ccf49f7SEduard Zingerman 		     * If the condition is initially true, decreasing values won't
21216ccf49f7SEduard Zingerman 		     * change that without underflow. If the condition is initially false,
21226ccf49f7SEduard Zingerman 		     * the main pass would do a single iteration anyway.
21236ccf49f7SEduard Zingerman 		     */
21246ccf49f7SEduard Zingerman 		    down ||
21256ccf49f7SEduard Zingerman 		    /* Is the latch condition false on the first iteration? */
21266ccf49f7SEduard Zingerman 		    initial >= bound ||
21276ccf49f7SEduard Zingerman 		    /* Count iterations satisfying the strict inequality, including i=0. */
21284cce2861SEduard Zingerman 		    check_add_overflow(div64_u64(diff - 1, step), 1, &backedge_taken_count) ||
21296ccf49f7SEduard Zingerman 		    /*
21306ccf49f7SEduard Zingerman 		     * Check if the last iteration overflows the counter:
21316ccf49f7SEduard Zingerman 		     *   initial + backedge_taken_count * step > U64_MAX
21326ccf49f7SEduard Zingerman 		     */
21334cce2861SEduard Zingerman 		    backedge_taken_count > div64_u64(U64_MAX - initial, step))
21346ccf49f7SEduard Zingerman 			return false;
21356ccf49f7SEduard Zingerman 		break;
21366ccf49f7SEduard Zingerman 	case BPF_JLE:
21376ccf49f7SEduard Zingerman 		/* E.g.: 3 + 2*i ≤ 7 ⇔ 2*i ≤ 4 ⇔ i ∈ [0,1,2]. */
21386ccf49f7SEduard Zingerman 		if (down || initial > bound ||
21396ccf49f7SEduard Zingerman 		    /* Count iterations satisfying the non-strict inequality. */
21404cce2861SEduard Zingerman 		    check_add_overflow(div64_u64(diff, step), 1, &backedge_taken_count) ||
21414cce2861SEduard Zingerman 		    backedge_taken_count > div64_u64(U64_MAX - initial, step))
21426ccf49f7SEduard Zingerman 			return false;
21436ccf49f7SEduard Zingerman 		break;
21446ccf49f7SEduard Zingerman 	case BPF_JGT:
21456ccf49f7SEduard Zingerman 		/* E.g.: 7 - 2*i > 3 ⇔ 2*i < 4 ⇔ i ∈ [0,1]. */
21466ccf49f7SEduard Zingerman 		if (up || initial <= bound ||
21474cce2861SEduard Zingerman 		    check_add_overflow(div64_u64(-diff - 1, -step), 1, &backedge_taken_count) ||
21486ccf49f7SEduard Zingerman 		    /*
21496ccf49f7SEduard Zingerman 		     * The last iteration underflows the counter if:
21506ccf49f7SEduard Zingerman 		     *   initial + backedge_taken_count * step < 0 ⇔
21516ccf49f7SEduard Zingerman 		     *             backedge_taken_count * step < -initial ⇔
21526ccf49f7SEduard Zingerman 		     *                    backedge_taken_count > initial / -step
21536ccf49f7SEduard Zingerman 		     * (direction flips because step < 0)
21546ccf49f7SEduard Zingerman 		     */
21554cce2861SEduard Zingerman 		    backedge_taken_count > div64_u64(initial, -step))
21566ccf49f7SEduard Zingerman 			return false;
21576ccf49f7SEduard Zingerman 		break;
21586ccf49f7SEduard Zingerman 	case BPF_JGE:
21596ccf49f7SEduard Zingerman 		/* E.g.: 7 - 2*i ≥ 3 ⇔ 2*i ≤ 4 ⇔ i ∈ [0,1,2]. */
21606ccf49f7SEduard Zingerman 		if (up || initial < bound ||
21614cce2861SEduard Zingerman 		    check_add_overflow(div64_u64(-diff, -step), 1, &backedge_taken_count) ||
21624cce2861SEduard Zingerman 		    backedge_taken_count > div64_u64(initial, -step))
21636ccf49f7SEduard Zingerman 			return false;
21646ccf49f7SEduard Zingerman 		break;
21656ccf49f7SEduard Zingerman 	case BPF_JSLT:
21666ccf49f7SEduard Zingerman 		if (down || (s64)initial >= (s64)bound ||
21674cce2861SEduard Zingerman 		    check_add_overflow(div64_u64(diff - 1, step), 1, &backedge_taken_count) ||
21686ccf49f7SEduard Zingerman 		    /*
21696ccf49f7SEduard Zingerman 		     * Check if the last iteration overflows the signed counter:
21706ccf49f7SEduard Zingerman 		     *   (s64)initial + backedge_taken_count * step > S64_MAX
21716ccf49f7SEduard Zingerman 		     */
21724cce2861SEduard Zingerman 		    backedge_taken_count > div64_u64((u64)S64_MAX - initial, step))
21736ccf49f7SEduard Zingerman 			return false;
21746ccf49f7SEduard Zingerman 		break;
21756ccf49f7SEduard Zingerman 	case BPF_JSLE:
21766ccf49f7SEduard Zingerman 		if (down || (s64)initial > (s64)bound ||
21774cce2861SEduard Zingerman 		    check_add_overflow(div64_u64(diff, step), 1, &backedge_taken_count) ||
21784cce2861SEduard Zingerman 		    backedge_taken_count > div64_u64((u64)S64_MAX - initial, step))
21796ccf49f7SEduard Zingerman 			return false;
21806ccf49f7SEduard Zingerman 		break;
21816ccf49f7SEduard Zingerman 	case BPF_JSGT:
21826ccf49f7SEduard Zingerman 		if (up || (s64)initial <= (s64)bound ||
21834cce2861SEduard Zingerman 		    check_add_overflow(div64_u64(-diff - 1, -step), 1, &backedge_taken_count) ||
21846ccf49f7SEduard Zingerman 		    /*
21856ccf49f7SEduard Zingerman 		     * The last iteration underflows the signed counter if:
21866ccf49f7SEduard Zingerman 		     *   (s64)initial + backedge_taken_count * step < S64_MIN ⇔
21876ccf49f7SEduard Zingerman 		     *                  backedge_taken_count * step < S64_MIN - (s64)initial ⇔
21886ccf49f7SEduard Zingerman 		     *                         backedge_taken_count > initial - (u64)S64_MIN / -step
21896ccf49f7SEduard Zingerman 		     *	 (direction flips because step < 0)
21906ccf49f7SEduard Zingerman 		     */
21914cce2861SEduard Zingerman 		    backedge_taken_count > div64_u64(initial - (u64)S64_MIN, -step))
21926ccf49f7SEduard Zingerman 			return false;
21936ccf49f7SEduard Zingerman 		break;
21946ccf49f7SEduard Zingerman 	case BPF_JSGE:
21956ccf49f7SEduard Zingerman 		if (up || (s64)initial < (s64)bound ||
21964cce2861SEduard Zingerman 		    check_add_overflow(div64_u64(-diff, -step), 1, &backedge_taken_count) ||
21974cce2861SEduard Zingerman 		    backedge_taken_count > div64_u64(initial - (u64)S64_MIN, -step))
21986ccf49f7SEduard Zingerman 			return false;
21996ccf49f7SEduard Zingerman 		break;
22006ccf49f7SEduard Zingerman 	case BPF_JNE:
22016ccf49f7SEduard Zingerman 		/*
22026ccf49f7SEduard Zingerman 		 * For a decreasing counter flip the diff and step:
22036ccf49f7SEduard Zingerman 		 *   7 - 2*i ≠ 3 ⇔ 2*i ≠ 7 - 3.
22046ccf49f7SEduard Zingerman 		 */
22056ccf49f7SEduard Zingerman 		diff = down ? -diff : diff;
22066ccf49f7SEduard Zingerman 		step = down ? -step : step;
22074cce2861SEduard Zingerman 		backedge_taken_count = div64_u64_rem(diff, step, &rem);
22084cce2861SEduard Zingerman 		if (diff == 0 || rem != 0)
22096ccf49f7SEduard Zingerman 			return false;
22106ccf49f7SEduard Zingerman 		break;
22116ccf49f7SEduard Zingerman 	default:
22126ccf49f7SEduard Zingerman 		return false;
22136ccf49f7SEduard Zingerman 	}
22146ccf49f7SEduard Zingerman 
2215*32e96257SEduard Zingerman 	*result = backedge_taken_count;
2216*32e96257SEduard Zingerman 	return true;
2217*32e96257SEduard Zingerman }
2218*32e96257SEduard Zingerman 
2219*32e96257SEduard Zingerman /*
2220*32e96257SEduard Zingerman  * Loop with post-condition:
2221*32e96257SEduard Zingerman  *
2222*32e96257SEduard Zingerman  *    r0 = 0
2223*32e96257SEduard Zingerman  * l: ...                r0 ∈ [0,1,2] header executed 3 times
2224*32e96257SEduard Zingerman  *    r0 += 1            r0 ∈ [0,1,2]
2225*32e96257SEduard Zingerman  *    ...                r0 ∈ [1,2,3]
2226*32e96257SEduard Zingerman  *    if r0 != 3 goto l  r0 ∈ [1,2,3] backedge taken 2 times
2227*32e96257SEduard Zingerman  *    ...                r0 ∈ [3]
2228*32e96257SEduard Zingerman  *
2229*32e96257SEduard Zingerman  * SCEV at header: r0 = k
2230*32e96257SEduard Zingerman  * SCEV at latch:  r0 = 1 + k
2231*32e96257SEduard Zingerman  *
2232*32e96257SEduard Zingerman  * Loop with pre-condition:
2233*32e96257SEduard Zingerman  *
2234*32e96257SEduard Zingerman  *    r0 = 0
2235*32e96257SEduard Zingerman  * l: ...                r0 ∈ [0,1,2,3] header executed 4 times
2236*32e96257SEduard Zingerman  *    if r0 == 3 goto e  r0 ∈ [0,1,2,3] backedge taken 3 times
2237*32e96257SEduard Zingerman  *    r0 += 1            r0 ∈ [0,1,2]
2238*32e96257SEduard Zingerman  *    ...                r0 ∈ [1,2,3]
2239*32e96257SEduard Zingerman  *    goto l             r0 ∈ [1,2,3]
2240*32e96257SEduard Zingerman  * e: ...                r0 ∈ [3]
2241*32e96257SEduard Zingerman  *
2242*32e96257SEduard Zingerman  * SCEV at header: r0 = k
2243*32e96257SEduard Zingerman  * SCEV at latch:  r0 = k
2244*32e96257SEduard Zingerman  */
2245*32e96257SEduard Zingerman static bool compute_max_iters(struct bpf_verifier_env *env,
2246*32e96257SEduard Zingerman 			      struct bpf_func_state *st,
2247*32e96257SEduard Zingerman 			      struct linear_latch *latch,
2248*32e96257SEduard Zingerman 			      struct bpf_loop_iters *iters)
2249*32e96257SEduard Zingerman {
2250*32e96257SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
2251*32e96257SEduard Zingerman 	struct bpf_loop *loop = aux[bpf_loop_at_index(env, latch->insn_idx)].loop;
2252*32e96257SEduard Zingerman 	struct scev *scev = env->scev;
2253*32e96257SEduard Zingerman 	struct scev_value initial_val, step_val, bound_val;
2254*32e96257SEduard Zingerman 	u64 step, bound, initial, total_change, backedge_taken_count;
2255*32e96257SEduard Zingerman 	u8 op = latch->op;
2256*32e96257SEduard Zingerman 
2257*32e96257SEduard Zingerman 	if (!eval_expr(env, scev, st, latch->base_expr, &initial_val) ||
2258*32e96257SEduard Zingerman 	    !eval_expr(env, scev, st, latch->step_expr, &step_val) ||
2259*32e96257SEduard Zingerman 	    !eval_expr(env, scev, st, latch->bound_expr, &bound_val))
2260*32e96257SEduard Zingerman 		return false;
2261*32e96257SEduard Zingerman 
2262*32e96257SEduard Zingerman 	if (step_val.ptr_reg >= 0) {
2263*32e96257SEduard Zingerman 		if (env->log.level & BPF_LOG_LEVEL2) {
2264*32e96257SEduard Zingerman 			bpf_log(&env->log, "scev: latch step is a pointer ");
2265*32e96257SEduard Zingerman 			log_scev_value(env, st, &step_val);
2266*32e96257SEduard Zingerman 			bpf_log(&env->log, "\n");
2267*32e96257SEduard Zingerman 		}
2268*32e96257SEduard Zingerman 		return false;
2269*32e96257SEduard Zingerman 	}
2270*32e96257SEduard Zingerman 	if (!scev_value_compatible(env, st, &initial_val, &bound_val))
2271*32e96257SEduard Zingerman 		return false;
2272*32e96257SEduard Zingerman 
2273*32e96257SEduard Zingerman 	initial = initial_val.value;
2274*32e96257SEduard Zingerman 	step = step_val.value;
2275*32e96257SEduard Zingerman 	bound = bound_val.value;
2276*32e96257SEduard Zingerman 
2277*32e96257SEduard Zingerman 	/*
2278*32e96257SEduard Zingerman 	 * The code below only handles mixed 64-bit/32-bit comparisons/recurrences
2279*32e96257SEduard Zingerman 	 * when initial bounds and step fit in 32-bit domain.
2280*32e96257SEduard Zingerman 	 */
2281*32e96257SEduard Zingerman 	if (latch->zext32 || latch->jmp32) {
2282*32e96257SEduard Zingerman 		/*
2283*32e96257SEduard Zingerman 		 * With the above constraint doing `l: w0 += 1; if r0 s< 256 goto l;`
2284*32e96257SEduard Zingerman 		 *                is equivalent to `l: w0 += 1; if r0 < 256 goto l;`
2285*32e96257SEduard Zingerman 		 */
2286*32e96257SEduard Zingerman 		if (latch->jmp32 && is_signed_op(op)) {
2287*32e96257SEduard Zingerman 			initial = (s64)(s32)(u32)initial;
2288*32e96257SEduard Zingerman 			bound   = (s64)(s32)(u32)bound;
2289*32e96257SEduard Zingerman 			step    = (s64)(s32)(u32)step;
2290*32e96257SEduard Zingerman 		} else {
2291*32e96257SEduard Zingerman 			initial = (u32)initial;
2292*32e96257SEduard Zingerman 			bound   = (u32)bound;
2293*32e96257SEduard Zingerman 			step    = (s64)(s32)(u32)step;
2294*32e96257SEduard Zingerman 		}
2295*32e96257SEduard Zingerman 	}
2296*32e96257SEduard Zingerman 	if (latch->zext32 ^ latch->jmp32 && (initial != initial_val.value ||
2297*32e96257SEduard Zingerman 					     bound != bound_val.value ||
2298*32e96257SEduard Zingerman 					     step != step_val.value)) {
2299*32e96257SEduard Zingerman 		if (env->log.level & BPF_LOG_LEVEL2)
2300*32e96257SEduard Zingerman 			bpf_log(&env->log,
2301*32e96257SEduard Zingerman 				"scev: mixed-width latch has operands outside 32-bit ranges\n");
2302*32e96257SEduard Zingerman 		return false;
2303*32e96257SEduard Zingerman 	}
2304*32e96257SEduard Zingerman 
2305*32e96257SEduard Zingerman 
2306*32e96257SEduard Zingerman 	if (!compute_backedge_taken_count(op, initial, step, bound, &backedge_taken_count))
2307*32e96257SEduard Zingerman 		return false;
2308*32e96257SEduard Zingerman 
2309*32e96257SEduard Zingerman 	if (latch->zext32 || latch->jmp32) {
2310*32e96257SEduard Zingerman 		/*
2311*32e96257SEduard Zingerman 		 * compute_backedge_taken_count() guarantees that 'total_change'
2312*32e96257SEduard Zingerman 		 * does not overflow in 64-bit domain.
2313*32e96257SEduard Zingerman 		 */
2314*32e96257SEduard Zingerman 		total_change = initial + step * backedge_taken_count;
2315*32e96257SEduard Zingerman 		if (latch->jmp32 && is_signed_op(op)) {
2316*32e96257SEduard Zingerman 			if ((s64)total_change < S32_MIN || (s64)total_change > S32_MAX)
2317*32e96257SEduard Zingerman 				return false;
2318*32e96257SEduard Zingerman 		} else {
2319*32e96257SEduard Zingerman 			if (total_change > U32_MAX)
2320*32e96257SEduard Zingerman 				return false;
2321*32e96257SEduard Zingerman 		}
2322*32e96257SEduard Zingerman 	}
2323*32e96257SEduard Zingerman 
23246ccf49f7SEduard Zingerman 	/*
23256ccf49f7SEduard Zingerman 	 * max_header_count is u32 and U32_MAX means "infinite",
23266ccf49f7SEduard Zingerman 	 * check to avoid overflow below.
23276ccf49f7SEduard Zingerman 	 */
23286ccf49f7SEduard Zingerman 	if (backedge_taken_count >= U32_MAX - 1)
23296ccf49f7SEduard Zingerman 		return false;
23306ccf49f7SEduard Zingerman 
23316ccf49f7SEduard Zingerman 	/* The header executes once on entry and once for each taken backedge, hence +1. */
23326ccf49f7SEduard Zingerman 	iters->max_header_count = backedge_taken_count + 1;
23336ccf49f7SEduard Zingerman 	/*
23346ccf49f7SEduard Zingerman 	 * The latch is a conditional jump with one jump target exiting the loop.
23356ccf49f7SEduard Zingerman 	 * Linear latch is matched only if the loop has a single backedge.
23366ccf49f7SEduard Zingerman 	 * The loop still, however can have multiple exits.
23376ccf49f7SEduard Zingerman 	 * In such case, conservatively assume that non-latch exit can happen
23386ccf49f7SEduard Zingerman 	 * at any iteration, thus setting minimal number of iterations as 0.
23396ccf49f7SEduard Zingerman 	 */
23406ccf49f7SEduard Zingerman 	iters->min_header_count = loop->exits_cnt == 1 ? iters->max_header_count : 0;
23416ccf49f7SEduard Zingerman 	return true;
23426ccf49f7SEduard Zingerman }
23436ccf49f7SEduard Zingerman 
23446ccf49f7SEduard Zingerman static void mark_scev_reg_scratched(struct bpf_verifier_env *env, u32 r)
23456ccf49f7SEduard Zingerman {
23466ccf49f7SEduard Zingerman 	if (r < MAX_BPF_REG)
23476ccf49f7SEduard Zingerman 		mark_reg_scratched(env, r);
23486ccf49f7SEduard Zingerman 	else
23496ccf49f7SEduard Zingerman 		mark_stack_slot_scratched(env, r - __MAX_BPF_REG);
23506ccf49f7SEduard Zingerman }
23516ccf49f7SEduard Zingerman 
23526ccf49f7SEduard Zingerman /*
23536ccf49f7SEduard Zingerman  * An unknown scalar is its own widening.
23546ccf49f7SEduard Zingerman  * Stack bytes without a value are represented by scev->unknown_reg.
23556ccf49f7SEduard Zingerman  */
23566ccf49f7SEduard Zingerman static bool is_unbound_scev_reg(struct bpf_verifier_env *env, const struct bpf_func_state *st,
23576ccf49f7SEduard Zingerman 				u32 r)
23586ccf49f7SEduard Zingerman {
23596ccf49f7SEduard Zingerman 	const struct bpf_reg_state *reg = scev_reg_for_read(env, st, r);
23606ccf49f7SEduard Zingerman 
23616ccf49f7SEduard Zingerman 	return reg && reg->type == SCALAR_VALUE && !reg->id && reg->step <= 1 &&
23626ccf49f7SEduard Zingerman 	       tnum_is_unknown(reg->var_off) &&
23636ccf49f7SEduard Zingerman 	       reg->r64.size == U64_MAX && reg->r32.size == U32_MAX;
23646ccf49f7SEduard Zingerman }
23656ccf49f7SEduard Zingerman 
23666ccf49f7SEduard Zingerman /* Main logic in verifier.c forbids varying offsets for certain register types. */
23676ccf49f7SEduard Zingerman static bool is_widenable_reg_type(const struct bpf_reg_state *reg)
23686ccf49f7SEduard Zingerman {
23696ccf49f7SEduard Zingerman 	if (type_may_be_null(reg->type))
23706ccf49f7SEduard Zingerman 		return false;
23716ccf49f7SEduard Zingerman 
23726ccf49f7SEduard Zingerman 	switch (base_type(reg->type)) {
23736ccf49f7SEduard Zingerman 	case SCALAR_VALUE:
23746ccf49f7SEduard Zingerman 	case PTR_TO_MAP_VALUE:
23756ccf49f7SEduard Zingerman 	case PTR_TO_MAP_KEY:
23766ccf49f7SEduard Zingerman 	case PTR_TO_STACK:
23776ccf49f7SEduard Zingerman 	case PTR_TO_PACKET:
23786ccf49f7SEduard Zingerman 	case PTR_TO_PACKET_META:
23796ccf49f7SEduard Zingerman 	case PTR_TO_MEM:
23806ccf49f7SEduard Zingerman 	case PTR_TO_BUF:
23816ccf49f7SEduard Zingerman 	case PTR_TO_BTF_ID:
23826ccf49f7SEduard Zingerman 		return true;
23836ccf49f7SEduard Zingerman 	default:
23846ccf49f7SEduard Zingerman 		return false;
23856ccf49f7SEduard Zingerman 	}
23866ccf49f7SEduard Zingerman }
23876ccf49f7SEduard Zingerman 
23886ccf49f7SEduard Zingerman static void scratch_widened_reg_id(struct bpf_verifier_env *env, struct bpf_reg_state *reg)
23896ccf49f7SEduard Zingerman {
23906ccf49f7SEduard Zingerman 	switch (base_type(reg->type)) {
23916ccf49f7SEduard Zingerman 	case SCALAR_VALUE:
23926ccf49f7SEduard Zingerman 		reg->id = 0;
23936ccf49f7SEduard Zingerman 		break;
23946ccf49f7SEduard Zingerman 	case PTR_TO_PACKET:
23956ccf49f7SEduard Zingerman 	case PTR_TO_PACKET_META:
23966ccf49f7SEduard Zingerman 		reg->id = ++env->id_gen;
23976ccf49f7SEduard Zingerman 		break;
23986ccf49f7SEduard Zingerman 	default:
23996ccf49f7SEduard Zingerman 		break;
24006ccf49f7SEduard Zingerman 	}
24016ccf49f7SEduard Zingerman }
24026ccf49f7SEduard Zingerman 
24036ccf49f7SEduard Zingerman /* Check that ANY leaves can be unioned with r's loop-entry value. */
24046ccf49f7SEduard Zingerman static bool is_widenable_any(struct bpf_verifier_env *env, struct bpf_func_state *loop_entry,
24056ccf49f7SEduard Zingerman 			     struct env *header_env, u32 r, u32 id)
24066ccf49f7SEduard Zingerman {
24076ccf49f7SEduard Zingerman 	const struct bpf_reg_state *reg, *leaf_reg;
24086ccf49f7SEduard Zingerman 	struct scev *scev = env->scev;
24096ccf49f7SEduard Zingerman 	u32 l, ra, rr, leaf, order;
24106ccf49f7SEduard Zingerman 	s64 imm;
24116ccf49f7SEduard Zingerman 
24126ccf49f7SEduard Zingerman 	if (!is_any(scev, id, &l, &rr))
24136ccf49f7SEduard Zingerman 		return false;
24146ccf49f7SEduard Zingerman 	reg = scev_reg_for_read(env, loop_entry, r);
24156ccf49f7SEduard Zingerman 	if (!reg || !is_widenable_reg_type(reg))
24166ccf49f7SEduard Zingerman 		return false;
24176ccf49f7SEduard Zingerman 
24186ccf49f7SEduard Zingerman 	scev->stack_sz = 0;
24196ccf49f7SEduard Zingerman 	expr_stack_push(scev, id);
24206ccf49f7SEduard Zingerman 	while (expr_next(scev, &id, &order)) {
24216ccf49f7SEduard Zingerman 		if (order & DEPTH_LIMIT)
24226ccf49f7SEduard Zingerman 			return false;
24236ccf49f7SEduard Zingerman 		if (!(order & PRE) || is_any(scev, id, &l, &rr))
24246ccf49f7SEduard Zingerman 			continue;
24256ccf49f7SEduard Zingerman 		if (is_imm(scev, id, &imm)) {
24266ccf49f7SEduard Zingerman 			if (reg->type != SCALAR_VALUE)
24276ccf49f7SEduard Zingerman 				return false;
24286ccf49f7SEduard Zingerman 		} else if (is_reg(scev, id, &leaf)) {
24296ccf49f7SEduard Zingerman 			/* Other leaves must denote loop-invariant registers. */
24306ccf49f7SEduard Zingerman 			if (leaf != r &&
24316ccf49f7SEduard Zingerman 			    !(is_reg(scev, header_env->reg2scev[leaf], &ra) && ra == leaf))
24326ccf49f7SEduard Zingerman 				return false;
24336ccf49f7SEduard Zingerman 			leaf_reg = scev_reg_for_read(env, loop_entry, leaf);
24346ccf49f7SEduard Zingerman 			if (!leaf_reg || !bpf_reg_union_compatible(reg, leaf_reg))
24356ccf49f7SEduard Zingerman 				return false;
24366ccf49f7SEduard Zingerman 		} else {
24376ccf49f7SEduard Zingerman 			return false;
24386ccf49f7SEduard Zingerman 		}
24396ccf49f7SEduard Zingerman 	}
24406ccf49f7SEduard Zingerman 	return true;
24416ccf49f7SEduard Zingerman }
24426ccf49f7SEduard Zingerman 
24436ccf49f7SEduard Zingerman struct bounds {
2444*32e96257SEduard Zingerman 	struct cnum64 r64;
2445*32e96257SEduard Zingerman 	struct cnum32 r32;
24466ccf49f7SEduard Zingerman 	u16 base;
24476ccf49f7SEduard Zingerman 	u16 step;
24486ccf49f7SEduard Zingerman };
24496ccf49f7SEduard Zingerman 
2450*32e96257SEduard Zingerman static void log_bounds(struct bpf_verifier_env *env, const struct bounds *bounds)
2451*32e96257SEduard Zingerman {
2452*32e96257SEduard Zingerman 	struct bpf_verifier_log *log = &env->log;
2453*32e96257SEduard Zingerman 
2454*32e96257SEduard Zingerman 	bpf_verbose_snum(env, cnum64_smin(bounds->r64));
2455*32e96257SEduard Zingerman 	bpf_log(log, "..");
2456*32e96257SEduard Zingerman 	bpf_verbose_snum(env, cnum64_smax(bounds->r64));
2457*32e96257SEduard Zingerman 	if (bounds->r32.size < U32_MAX) {
2458*32e96257SEduard Zingerman 		bpf_log(log, " (s32 ");
2459*32e96257SEduard Zingerman 		bpf_verbose_snum(env, cnum32_smin(bounds->r32));
2460*32e96257SEduard Zingerman 		bpf_log(log, "..");
2461*32e96257SEduard Zingerman 		bpf_verbose_snum(env, cnum32_smax(bounds->r32));
2462*32e96257SEduard Zingerman 		bpf_log(log, ")");
2463*32e96257SEduard Zingerman 	}
2464*32e96257SEduard Zingerman 	bpf_log(log, " step %u", bounds->step);
2465*32e96257SEduard Zingerman }
2466*32e96257SEduard Zingerman 
2467*32e96257SEduard Zingerman struct linear_coefs {
2468*32e96257SEduard Zingerman 	u32 base_reg;
2469*32e96257SEduard Zingerman 	s64 slope;
2470*32e96257SEduard Zingerman 	bool zext32;
2471*32e96257SEduard Zingerman };
2472*32e96257SEduard Zingerman 
2473*32e96257SEduard Zingerman static bool is_simple_linear(struct scev *scev, u32 id, struct linear_coefs *out)
24746ccf49f7SEduard Zingerman {
24756ccf49f7SEduard Zingerman 	u32 base, slope;
24766ccf49f7SEduard Zingerman 
2477*32e96257SEduard Zingerman 	return is_linear_or_linear32(scev, id, &base, &slope, &out->zext32) &&
2478*32e96257SEduard Zingerman 	       is_reg(scev, base, &out->base_reg) &&
2479*32e96257SEduard Zingerman 	       is_imm(scev, slope, &out->slope) &&
2480*32e96257SEduard Zingerman 	       out->slope <= S16_MAX &&
2481*32e96257SEduard Zingerman 	       out->slope >= S16_MIN &&
2482*32e96257SEduard Zingerman 	       out->slope != 0;
24836ccf49f7SEduard Zingerman }
24846ccf49f7SEduard Zingerman 
2485*32e96257SEduard Zingerman static struct cnum64 cnum64_zext32(struct cnum32 r32)
24866ccf49f7SEduard Zingerman {
2487*32e96257SEduard Zingerman 	return cnum64_from_urange(cnum32_umin(r32), cnum32_umax(r32));
2488*32e96257SEduard Zingerman }
2489*32e96257SEduard Zingerman 
2490*32e96257SEduard Zingerman /* Compute the range an induction variable in `reg` spans over the loop. */
2491*32e96257SEduard Zingerman static void linear_bounds(struct bpf_reg_state *reg, u32 max_header_count,
2492*32e96257SEduard Zingerman 			  struct linear_coefs *coefs, struct bounds *out)
2493*32e96257SEduard Zingerman {
2494*32e96257SEduard Zingerman 	s64 slope = coefs->slope;
24956ccf49f7SEduard Zingerman 	s64 slope_abs = slope < 0 ? -slope : slope;
24966ccf49f7SEduard Zingerman 	s64 min_val = reg_smin(reg);
24976ccf49f7SEduard Zingerman 	s64 max_val = reg_smax(reg);
2498*32e96257SEduard Zingerman 	struct cnum64 r64;
2499*32e96257SEduard Zingerman 	struct cnum32 r32;
25006ccf49f7SEduard Zingerman 	s64 total_change;
25016ccf49f7SEduard Zingerman 	bool overflow;
25026ccf49f7SEduard Zingerman 
25036ccf49f7SEduard Zingerman 	overflow = check_mul_overflow(slope, (s64)max_header_count - 1, &total_change) ||
25046ccf49f7SEduard Zingerman 		   (slope > 0 && check_add_overflow(max_val, total_change, &max_val)) ||
25056ccf49f7SEduard Zingerman 		   (slope < 0 && check_add_overflow(min_val, total_change, &min_val));
2506*32e96257SEduard Zingerman 	r64 = overflow ? CNUM64_UNBOUNDED : cnum64_from_srange(min_val, max_val);
2507*32e96257SEduard Zingerman 	r32 = CNUM32_UNBOUNDED;
2508*32e96257SEduard Zingerman 	if (coefs->zext32) {
2509*32e96257SEduard Zingerman 		r32 = cnum32_from_cnum64(r64);
2510*32e96257SEduard Zingerman 		r64 = cnum64_zext32(r32);
2511*32e96257SEduard Zingerman 		/*
2512*32e96257SEduard Zingerman 		 * 32-bit iteration overflow is equivalent to subtracting N * 2**32:
2513*32e96257SEduard Zingerman 		 * (base + slope * k) % slope ≠ (base + slope * k - N * 2**32) % slope.
2514*32e96257SEduard Zingerman 		 */
2515*32e96257SEduard Zingerman 		overflow |= cnum32_contains(r32, 0) && cnum32_contains(r32, U32_MAX);
2516*32e96257SEduard Zingerman 		/*
2517*32e96257SEduard Zingerman 		 * The entry and zero-extended values must agree on how they define `base`,
2518*32e96257SEduard Zingerman 		 * otherwise `base + slope * k` would define different sets of points between
2519*32e96257SEduard Zingerman 		 * the two.
2520*32e96257SEduard Zingerman 		 */
2521*32e96257SEduard Zingerman 		overflow |= imod(reg_smin(reg), slope_abs) !=
2522*32e96257SEduard Zingerman 			    imod(cnum64_smin(r64), slope_abs);
2523*32e96257SEduard Zingerman 		/*
2524*32e96257SEduard Zingerman 		 * Full range is a union of a reg's value at loop entry,
2525*32e96257SEduard Zingerman 		 * plus a range produced by 32-bit iteration.
2526*32e96257SEduard Zingerman 		 */
2527*32e96257SEduard Zingerman 		r64 = cnum64_union(reg->r64, r64);
2528*32e96257SEduard Zingerman 		r32 = cnum32_union(reg->r32, r32);
2529*32e96257SEduard Zingerman 	}
25306ccf49f7SEduard Zingerman 	/*
25316ccf49f7SEduard Zingerman 	 * If the entry value is a single point the value set is 'v + slope * k',
25326ccf49f7SEduard Zingerman 	 * so the step is |slope|. Otherwise, only the power-of-two alignment
25336ccf49f7SEduard Zingerman 	 * shared by the entry value and the slope.
25346ccf49f7SEduard Zingerman 	 */
25356ccf49f7SEduard Zingerman 	if (cnum64_is_const(reg->r64) && !overflow) {
25366ccf49f7SEduard Zingerman 		out->step = slope_abs;
2537*32e96257SEduard Zingerman 		out->base = imod(reg_smin(reg), out->step);
25386ccf49f7SEduard Zingerman 	} else {
25396ccf49f7SEduard Zingerman 		out->step = 1u << min_t(u32, tnum_alignment(reg->var_off), __ffs(slope_abs));
25406ccf49f7SEduard Zingerman 		out->base = 0;
25416ccf49f7SEduard Zingerman 	}
2542*32e96257SEduard Zingerman 	out->r64 = r64;
2543*32e96257SEduard Zingerman 	out->r32 = r32;
25446ccf49f7SEduard Zingerman }
25456ccf49f7SEduard Zingerman 
25466ccf49f7SEduard Zingerman static int mark_expr_precise(struct bpf_verifier_env *env, struct bpf_func_state *st, u32 id,
25476ccf49f7SEduard Zingerman 			     unsigned long *precise_regs)
25486ccf49f7SEduard Zingerman {
25496ccf49f7SEduard Zingerman 	struct scev *scev = env->scev;
25506ccf49f7SEduard Zingerman 	struct bpf_reg_state *reg;
25516ccf49f7SEduard Zingerman 	u32 r, order;
25526ccf49f7SEduard Zingerman 
25536ccf49f7SEduard Zingerman 	scev->stack_sz = 0;
25546ccf49f7SEduard Zingerman 	expr_stack_push(scev, id);
25556ccf49f7SEduard Zingerman 	while (expr_next(scev, &id, &order)) {
25566ccf49f7SEduard Zingerman 		if (order & DEPTH_LIMIT) {
25576ccf49f7SEduard Zingerman 			verifier_bug(env, "scev precision marking exceeds expression depth limit");
25586ccf49f7SEduard Zingerman 			return -EFAULT;
25596ccf49f7SEduard Zingerman 		}
25606ccf49f7SEduard Zingerman 		if (!(order & PRE) || !is_reg(scev, id, &r))
25616ccf49f7SEduard Zingerman 			continue;
25626ccf49f7SEduard Zingerman 		/* Synthetic values have no spilled register to mark precise. */
25636ccf49f7SEduard Zingerman 		reg = scev_reg_for_linear(st, r);
25646ccf49f7SEduard Zingerman 		if (reg && reg->type == SCALAR_VALUE)
25656ccf49f7SEduard Zingerman 			__set_bit(r, precise_regs);
25666ccf49f7SEduard Zingerman 	}
25676ccf49f7SEduard Zingerman 	return 0;
25686ccf49f7SEduard Zingerman }
25696ccf49f7SEduard Zingerman 
25706ccf49f7SEduard Zingerman int bpf_compute_loop_iters(struct bpf_verifier_env *env, struct bpf_verifier_state *st,
25716ccf49f7SEduard Zingerman 			   struct bpf_loop_iters *iters)
25726ccf49f7SEduard Zingerman {
25736ccf49f7SEduard Zingerman 	struct bpf_func_state *cur_func = st->frame[st->curframe];
25746ccf49f7SEduard Zingerman 	struct bpf_insn_aux_data *aux = env->insn_aux_data;
25756ccf49f7SEduard Zingerman 	struct bpf_verifier_log *log = &env->log;
25766ccf49f7SEduard Zingerman 	struct scev *scev = env->scev;
25776ccf49f7SEduard Zingerman 	struct env *header_env;
25786ccf49f7SEduard Zingerman 	struct linear_latch latch, best;
2579*32e96257SEduard Zingerman 	struct linear_coefs coefs;
25806ccf49f7SEduard Zingerman 	struct bpf_backedge *backedge;
25816ccf49f7SEduard Zingerman 	struct bpf_loop_iters tmp;
25826ccf49f7SEduard Zingerman 	struct bpf_loop *loop;
25836ccf49f7SEduard Zingerman 	int insn_idx = st->insn_idx;
25846ccf49f7SEduard Zingerman 	bool found = false;
25856ccf49f7SEduard Zingerman 	int linear_latch;
25866ccf49f7SEduard Zingerman 	int latch_idx;
25876ccf49f7SEduard Zingerman 	int err, j;
2588*32e96257SEduard Zingerman 	u32 r;
25896ccf49f7SEduard Zingerman 
25906ccf49f7SEduard Zingerman 	if (!env->allow_uninit_stack)
25916ccf49f7SEduard Zingerman 		return 0;
25926ccf49f7SEduard Zingerman 
25936ccf49f7SEduard Zingerman 	/*
25946ccf49f7SEduard Zingerman 	 * If insn_idx is a loop header for a reducible loop with a single backedge.
25956ccf49f7SEduard Zingerman 	 * loop is NULL for secondary entries to irreducible loops.
25966ccf49f7SEduard Zingerman 	 */
25976ccf49f7SEduard Zingerman 	loop = aux[insn_idx].loop;
25986ccf49f7SEduard Zingerman 	if (!loop || loop->irreducible || loop->backedges_cnt != 1 || loop->backedges_overflow ||
25996ccf49f7SEduard Zingerman 	    loop->exits_overflow) {
26006ccf49f7SEduard Zingerman 		if (log->level & BPF_LOG_LEVEL2)
26016ccf49f7SEduard Zingerman 			bpf_log(log, "loop header at %d, unsupported loop:%s%s%s\n", insn_idx,
26026ccf49f7SEduard Zingerman 				!loop || loop->irreducible ? " irreducible" : "",
26036ccf49f7SEduard Zingerman 				loop && loop->backedges_cnt > 1 ? " multiple backedges" : "",
26046ccf49f7SEduard Zingerman 				loop && loop->exits_overflow ? " too many exits" : "");
26056ccf49f7SEduard Zingerman 		return 0;
26066ccf49f7SEduard Zingerman 	}
26076ccf49f7SEduard Zingerman 
26086ccf49f7SEduard Zingerman 	/* If this backedge has a latch */
26096ccf49f7SEduard Zingerman 	backedge = &loop->backedges[0];
26106ccf49f7SEduard Zingerman 	if (!backedge->latches_cnt) {
26116ccf49f7SEduard Zingerman 		if (log->level & BPF_LOG_LEVEL2)
26126ccf49f7SEduard Zingerman 			bpf_log(log, "loop header at %d, latch not identified\n", insn_idx);
26136ccf49f7SEduard Zingerman 		return 0;
26146ccf49f7SEduard Zingerman 	}
26156ccf49f7SEduard Zingerman 
26166ccf49f7SEduard Zingerman 	/*
26176ccf49f7SEduard Zingerman 	 * Every condition dominating the backedge bounds the number of
26186ccf49f7SEduard Zingerman 	 * iterations from above, keep the smallest bound.
26196ccf49f7SEduard Zingerman 	 */
26206ccf49f7SEduard Zingerman 	for (j = 0; j < backedge->latches_cnt; j++) {
26216ccf49f7SEduard Zingerman 		latch_idx = backedge->latches[j];
26226ccf49f7SEduard Zingerman 		linear_latch = match_linear_latch(env, insn_idx, latch_idx, &latch);
26236ccf49f7SEduard Zingerman 		if (linear_latch < 0)
26246ccf49f7SEduard Zingerman 			return linear_latch;
26256ccf49f7SEduard Zingerman 		if (!linear_latch) {
26266ccf49f7SEduard Zingerman 			if (log->level & BPF_LOG_LEVEL2)
26276ccf49f7SEduard Zingerman 				bpf_log(log, "loop header at %d, non-linear %s at %d\n",
26286ccf49f7SEduard Zingerman 					insn_idx, j ? "exit" : "latch", latch_idx);
26296ccf49f7SEduard Zingerman 			continue;
26306ccf49f7SEduard Zingerman 		}
26316ccf49f7SEduard Zingerman 		if (!compute_max_iters(env, cur_func, &latch, &tmp)) {
26326ccf49f7SEduard Zingerman 			if (log->level & BPF_LOG_LEVEL2)
26336ccf49f7SEduard Zingerman 				bpf_log(log,
26346ccf49f7SEduard Zingerman 					"loop header at %d, can't compute iterations count at %d\n",
26356ccf49f7SEduard Zingerman 					insn_idx, latch_idx);
26366ccf49f7SEduard Zingerman 			continue;
26376ccf49f7SEduard Zingerman 		}
26386ccf49f7SEduard Zingerman 		if (!found || tmp.max_header_count < iters->max_header_count) {
26396ccf49f7SEduard Zingerman 			iters->max_header_count = tmp.max_header_count;
26406ccf49f7SEduard Zingerman 			best = latch;
26416ccf49f7SEduard Zingerman 		}
26426ccf49f7SEduard Zingerman 		iters->min_header_count = found ? min(iters->min_header_count, tmp.min_header_count)
26436ccf49f7SEduard Zingerman 						: tmp.min_header_count;
26446ccf49f7SEduard Zingerman 		found = true;
26456ccf49f7SEduard Zingerman 	}
26466ccf49f7SEduard Zingerman 	if (!found) {
26476ccf49f7SEduard Zingerman 		if (log->level & BPF_LOG_LEVEL2)
26486ccf49f7SEduard Zingerman 			bpf_log(log, "loop header at %d, can't compute iterations count\n", insn_idx);
26496ccf49f7SEduard Zingerman 		return 0;
26506ccf49f7SEduard Zingerman 	}
26516ccf49f7SEduard Zingerman 	latch = best;
26526ccf49f7SEduard Zingerman 
26536ccf49f7SEduard Zingerman 	if (iters->max_header_count == 0) {
26546ccf49f7SEduard Zingerman 		if (log->level & BPF_LOG_LEVEL2)
26556ccf49f7SEduard Zingerman 			bpf_log(log, "loop header at %d, 0 iterations count\n", insn_idx);
26566ccf49f7SEduard Zingerman 		return 0;
26576ccf49f7SEduard Zingerman 	}
26586ccf49f7SEduard Zingerman 
26596ccf49f7SEduard Zingerman 	if (iters->max_header_count == U32_MAX) {
26606ccf49f7SEduard Zingerman 		if (log->level & BPF_LOG_LEVEL2)
26616ccf49f7SEduard Zingerman 			bpf_log(log, "loop header at %d, inf iterations count\n", insn_idx);
26626ccf49f7SEduard Zingerman 		return 0;
26636ccf49f7SEduard Zingerman 	}
26646ccf49f7SEduard Zingerman 
26656ccf49f7SEduard Zingerman 	if (log->level & BPF_LOG_LEVEL2) {
26666ccf49f7SEduard Zingerman 		bpf_log(log, "loop header at %d, header_count is ", insn_idx);
26676ccf49f7SEduard Zingerman 		if (iters->min_header_count == iters->max_header_count)
26686ccf49f7SEduard Zingerman 			bpf_log(log, "%u ", iters->max_header_count);
26696ccf49f7SEduard Zingerman 		else
26706ccf49f7SEduard Zingerman 			bpf_log(log, "[%u..%u] ", iters->min_header_count, iters->max_header_count);
26716ccf49f7SEduard Zingerman 		bpf_log(log, "\n");
26726ccf49f7SEduard Zingerman 	}
26736ccf49f7SEduard Zingerman 
26746ccf49f7SEduard Zingerman 	err = bpf_live_stack_query_init(env, st);
26756ccf49f7SEduard Zingerman 	if (err)
26766ccf49f7SEduard Zingerman 		return err;
26776ccf49f7SEduard Zingerman 
26786ccf49f7SEduard Zingerman 	header_env = find_header_env(scev, insn_idx);
26796ccf49f7SEduard Zingerman 	for (r = 0; r < REGS_NUM; r++) {
26806ccf49f7SEduard Zingerman 		struct bpf_reg_state *reg;
26816ccf49f7SEduard Zingerman 		u32 ra, r_scev, r_expr;
2682088a5477SEduard Zingerman 		bool spill_base = false;
26836ccf49f7SEduard Zingerman 
26846ccf49f7SEduard Zingerman 		if (!scev_reg_alive(env, st, r))
26856ccf49f7SEduard Zingerman 			continue;
26866ccf49f7SEduard Zingerman 		/*
26876ccf49f7SEduard Zingerman 		 * A heuristic:
26886ccf49f7SEduard Zingerman 		 * Ignore SCEVs computed for unbound values and treat those as widened.
26896ccf49f7SEduard Zingerman 		 * This is poor man's modelling of e.g. bpf_probe_read_kernel() effect
26906ccf49f7SEduard Zingerman 		 * on stack, when called from a subprogram. Currently this would produce
26916ccf49f7SEduard Zingerman 		 * an unknown ('?') SCEV as a summary of a subprogram call effects.
26926ccf49f7SEduard Zingerman 		 * Ideally, this should be computed as an OPAQUE value.
26936ccf49f7SEduard Zingerman 		 * However, that would require tracking STACK_MISC writes in the
26946ccf49f7SEduard Zingerman 		 * liveness analysis. Not implemented yet.
26956ccf49f7SEduard Zingerman 		 */
26966ccf49f7SEduard Zingerman 		if (is_unbound_scev_reg(env, cur_func, r))
26976ccf49f7SEduard Zingerman 			continue;
26986ccf49f7SEduard Zingerman 
26996ccf49f7SEduard Zingerman 		r_scev = header_env->reg2scev[r];
27006ccf49f7SEduard Zingerman 		reg = scev_reg_for_linear(cur_func, r);
27016ccf49f7SEduard Zingerman 		/* If SCEV for r is (linear <reg> <slope>) */
2702*32e96257SEduard Zingerman 		if (reg && is_simple_linear(scev, r_scev, &coefs) && is_widenable_reg_type(reg)) {
2703088a5477SEduard Zingerman 			/* Spills at varying offsets lose precision */
2704088a5477SEduard Zingerman 			if (test_bit(r, loop->store_base_regs)) {
2705088a5477SEduard Zingerman 				spill_base = true;
2706088a5477SEduard Zingerman 				goto cant_widen;
2707088a5477SEduard Zingerman 			}
27086ccf49f7SEduard Zingerman 			continue;
27096ccf49f7SEduard Zingerman 		}
27106ccf49f7SEduard Zingerman 
27116ccf49f7SEduard Zingerman 		/* rA = rA, loop does not change this reg */
27126ccf49f7SEduard Zingerman 		if (is_reg(scev, r_scev, &ra) && r == ra)
27136ccf49f7SEduard Zingerman 			continue;
27146ccf49f7SEduard Zingerman 
27156ccf49f7SEduard Zingerman 		/* (any 1 (any 2 (any 3 4))) */
27166ccf49f7SEduard Zingerman 		if (is_widenable_any(env, cur_func, header_env, r, r_scev)) {
2717088a5477SEduard Zingerman 			if (test_bit(r, loop->store_base_regs)) {
2718088a5477SEduard Zingerman 				spill_base = true;
2719088a5477SEduard Zingerman 				goto cant_widen;
2720088a5477SEduard Zingerman 			}
27216ccf49f7SEduard Zingerman 			continue;
27226ccf49f7SEduard Zingerman 		}
2723088a5477SEduard Zingerman cant_widen:
27246ccf49f7SEduard Zingerman 		if (log->level & BPF_LOG_LEVEL2) {
27256ccf49f7SEduard Zingerman 			r_expr = header_env->reg2expr[r];
27266ccf49f7SEduard Zingerman 			bpf_log(log, "loop header at %d, can't widen ", insn_idx);
27276ccf49f7SEduard Zingerman 			log_reg(env, r);
27286ccf49f7SEduard Zingerman 			bpf_log(log, ", expr is ");
27296ccf49f7SEduard Zingerman 			log_expr(env, r_expr);
2730088a5477SEduard Zingerman 			if (spill_base)
2731088a5477SEduard Zingerman 				bpf_log(log, ", requires exact stack-offset tracking");
27326ccf49f7SEduard Zingerman 			bpf_log(log, "\n");
27336ccf49f7SEduard Zingerman 		}
27346ccf49f7SEduard Zingerman 		return 0;
27356ccf49f7SEduard Zingerman 	}
27366ccf49f7SEduard Zingerman 
27376ccf49f7SEduard Zingerman 	bitmap_zero(iters->precise_regs, REGS_NUM);
27386ccf49f7SEduard Zingerman 	err = mark_expr_precise(env, cur_func, latch.base_expr, iters->precise_regs);
27396ccf49f7SEduard Zingerman 	if (err)
27406ccf49f7SEduard Zingerman 		return err;
27416ccf49f7SEduard Zingerman 	err = mark_expr_precise(env, cur_func, latch.step_expr, iters->precise_regs);
27426ccf49f7SEduard Zingerman 	if (err)
27436ccf49f7SEduard Zingerman 		return err;
27446ccf49f7SEduard Zingerman 	err = mark_expr_precise(env, cur_func, latch.bound_expr, iters->precise_regs);
27456ccf49f7SEduard Zingerman 	if (err)
27466ccf49f7SEduard Zingerman 		return err;
27476ccf49f7SEduard Zingerman 
27486ccf49f7SEduard Zingerman 	return 1;
27496ccf49f7SEduard Zingerman }
27506ccf49f7SEduard Zingerman 
27516ccf49f7SEduard Zingerman /* bpf_compute_loop_iters() checked that every leaf can be unioned into acc. */
27526ccf49f7SEduard Zingerman static int union_any_reg(struct bpf_verifier_env *env, struct bpf_func_state *loop_entry,
27536ccf49f7SEduard Zingerman 			 struct bpf_reg_state *acc, u32 id)
27546ccf49f7SEduard Zingerman {
27556ccf49f7SEduard Zingerman 	struct bpf_reg_state *tmp = &env->fake_reg[0];
27566ccf49f7SEduard Zingerman 	const struct bpf_reg_state *leaf_reg;
27576ccf49f7SEduard Zingerman 	struct scev *scev = env->scev;
27586ccf49f7SEduard Zingerman 	u32 l, r, leaf, order;
27596ccf49f7SEduard Zingerman 	s64 imm;
27606ccf49f7SEduard Zingerman 	int err;
27616ccf49f7SEduard Zingerman 
27626ccf49f7SEduard Zingerman 	scev->stack_sz = 0;
27636ccf49f7SEduard Zingerman 	expr_stack_push(scev, id);
27646ccf49f7SEduard Zingerman 	while (expr_next(scev, &id, &order)) {
27656ccf49f7SEduard Zingerman 		if (order & DEPTH_LIMIT) {
27666ccf49f7SEduard Zingerman 			verifier_bug(env, "scev ANY union exceeds expression depth limit");
27676ccf49f7SEduard Zingerman 			return -EFAULT;
27686ccf49f7SEduard Zingerman 		}
27696ccf49f7SEduard Zingerman 		if (!(order & PRE) || is_any(scev, id, &l, &r))
27706ccf49f7SEduard Zingerman 			continue;
27716ccf49f7SEduard Zingerman 		if (is_imm(scev, id, &imm)) {
27726ccf49f7SEduard Zingerman 			bpf_mark_reg_known_scalar(tmp, imm);
27736ccf49f7SEduard Zingerman 			leaf_reg = tmp;
27746ccf49f7SEduard Zingerman 		} else if (is_reg(scev, id, &leaf)) {
27756ccf49f7SEduard Zingerman 			leaf_reg = scev_reg_for_read(env, loop_entry, leaf);
27766ccf49f7SEduard Zingerman 			if (verifier_bug_if(!leaf_reg, env, "unreadable SCEV ANY leaf %u", leaf))
27776ccf49f7SEduard Zingerman 				return -EFAULT;
27786ccf49f7SEduard Zingerman 		} else {
27796ccf49f7SEduard Zingerman 			verifier_bug(env, "scev ANY union has an unsupported leaf");
27806ccf49f7SEduard Zingerman 			return -EFAULT;
27816ccf49f7SEduard Zingerman 		}
27826ccf49f7SEduard Zingerman 		err = bpf_reg_union(env, acc, leaf_reg);
27836ccf49f7SEduard Zingerman 		if (err)
27846ccf49f7SEduard Zingerman 			return err;
27856ccf49f7SEduard Zingerman 	}
27866ccf49f7SEduard Zingerman 	return 0;
27876ccf49f7SEduard Zingerman }
27886ccf49f7SEduard Zingerman 
27896ccf49f7SEduard Zingerman int bpf_widen_scev_regs(struct bpf_verifier_env *env, struct bpf_verifier_state *st,
27906ccf49f7SEduard Zingerman 			struct bpf_verifier_state *loop_entry, struct bpf_loop_iters *iters)
27916ccf49f7SEduard Zingerman {
27926ccf49f7SEduard Zingerman 	struct bpf_func_state *cur_func = st->frame[st->curframe];
27936ccf49f7SEduard Zingerman 	struct bpf_func_state *entry_func = loop_entry->frame[loop_entry->curframe];
27946ccf49f7SEduard Zingerman 	struct bpf_verifier_log *log = &env->log;
27956ccf49f7SEduard Zingerman 	struct scev *scev = env->scev;
27966ccf49f7SEduard Zingerman 	struct bpf_reg_state *reg;
27976ccf49f7SEduard Zingerman 	struct env *header_env;
2798*32e96257SEduard Zingerman 	struct linear_coefs coefs;
27996ccf49f7SEduard Zingerman 	struct bounds bounds;
2800*32e96257SEduard Zingerman 	u32 r, r_expr, a, b;
28016ccf49f7SEduard Zingerman 	int insn_idx = st->insn_idx;
28026ccf49f7SEduard Zingerman 	int err;
28036ccf49f7SEduard Zingerman 
28046ccf49f7SEduard Zingerman 	for_each_set_bit(r, iters->precise_regs, REGS_NUM) {
28056ccf49f7SEduard Zingerman 		if (r < MAX_BPF_REG)
28066ccf49f7SEduard Zingerman 			bpf_bt_set_frame_reg(&env->bt, st->curframe, r);
28076ccf49f7SEduard Zingerman 		else
28086ccf49f7SEduard Zingerman 			bpf_bt_set_frame_slot(&env->bt, st->curframe, r - MAX_BPF_REG);
28096ccf49f7SEduard Zingerman 	}
28106ccf49f7SEduard Zingerman 	err = bpf_mark_chain_precision(env, st, -1, NULL);
28116ccf49f7SEduard Zingerman 	if (err)
28126ccf49f7SEduard Zingerman 		return err;
28136ccf49f7SEduard Zingerman 
28146ccf49f7SEduard Zingerman 	header_env = find_header_env(scev, insn_idx);
28156ccf49f7SEduard Zingerman 	for (r = 0; r < REGS_NUM; r++) {
28166ccf49f7SEduard Zingerman 		if (!scev_reg_alive(env, st, r) || is_unbound_scev_reg(env, cur_func, r))
28176ccf49f7SEduard Zingerman 			continue;
28186ccf49f7SEduard Zingerman 
28196ccf49f7SEduard Zingerman 		r_expr = header_env->reg2scev[r];
28206ccf49f7SEduard Zingerman 		/* If SCEV for r is (linear <reg> <slope>)*/
2821*32e96257SEduard Zingerman 		if (is_simple_linear(scev, r_expr, &coefs) && coefs.base_reg == r) {
28226ccf49f7SEduard Zingerman 			err = scev_reg_for_write(env, cur_func, r, &reg);
28236ccf49f7SEduard Zingerman 			if (err)
28246ccf49f7SEduard Zingerman 				return err;
2825*32e96257SEduard Zingerman 			linear_bounds(reg, iters->max_header_count, &coefs, &bounds);
28266ccf49f7SEduard Zingerman 			if (log->level & BPF_LOG_LEVEL2) {
28276ccf49f7SEduard Zingerman 				bpf_log(log, "loop header at %d, widening ", insn_idx);
28286ccf49f7SEduard Zingerman 				log_reg(env, r);
28296ccf49f7SEduard Zingerman 				bpf_log(log, " to ");
2830*32e96257SEduard Zingerman 				log_bounds(env, &bounds);
2831*32e96257SEduard Zingerman 				bpf_log(log, "\n");
28326ccf49f7SEduard Zingerman 			}
28336ccf49f7SEduard Zingerman 			scratch_widened_reg_id(env, reg);
2834*32e96257SEduard Zingerman 			err = bpf_set_reg_range(env, reg, bounds.r64, bounds.r32,
2835*32e96257SEduard Zingerman 						bounds.base, bounds.step);
28366ccf49f7SEduard Zingerman 			if (err)
28376ccf49f7SEduard Zingerman 				return err;
28386ccf49f7SEduard Zingerman 			mark_scev_reg_scratched(env, r);
28396ccf49f7SEduard Zingerman 		} else if (is_any(scev, r_expr, &a, &b)) {
28406ccf49f7SEduard Zingerman 			err = scev_reg_for_write(env, cur_func, r, &reg);
28416ccf49f7SEduard Zingerman 			if (err)
28426ccf49f7SEduard Zingerman 				return err;
28436ccf49f7SEduard Zingerman 			err = union_any_reg(env, entry_func, reg, r_expr);
28446ccf49f7SEduard Zingerman 			if (err)
28456ccf49f7SEduard Zingerman 				return err;
28466ccf49f7SEduard Zingerman 			if (log->level & BPF_LOG_LEVEL2) {
28476ccf49f7SEduard Zingerman 				bpf_log(log, "loop header at %d, widening ", insn_idx);
28486ccf49f7SEduard Zingerman 				log_reg(env, r);
28496ccf49f7SEduard Zingerman 				bpf_log(log, " to ");
28506ccf49f7SEduard Zingerman 				bpf_verbose_snum(env, reg_smin(reg));
28516ccf49f7SEduard Zingerman 				bpf_log(log, "..");
28526ccf49f7SEduard Zingerman 				bpf_verbose_snum(env, reg_smax(reg));
28536ccf49f7SEduard Zingerman 				bpf_log(log, " step %u\n", reg->step);
28546ccf49f7SEduard Zingerman 			}
28556ccf49f7SEduard Zingerman 			scratch_widened_reg_id(env, reg);
28566ccf49f7SEduard Zingerman 			mark_scev_reg_scratched(env, r);
28576ccf49f7SEduard Zingerman 		}
28586ccf49f7SEduard Zingerman 	}
28596ccf49f7SEduard Zingerman 	return 1;
28606ccf49f7SEduard Zingerman }
28616ccf49f7SEduard Zingerman 
28626ccf49f7SEduard Zingerman int bpf_clamp_scev_regs(struct bpf_verifier_env *env, struct bpf_func_state *cur_func_state, u32 insn_idx,
28636ccf49f7SEduard Zingerman 			struct bpf_verifier_state *entry_state, u32 max_header_count)
28646ccf49f7SEduard Zingerman {
28656ccf49f7SEduard Zingerman 	struct bpf_func_state *entry_st = entry_state->frame[entry_state->curframe];
28666ccf49f7SEduard Zingerman 	struct bpf_verifier_log *log = &env->log;
28676ccf49f7SEduard Zingerman 	struct bpf_reg_state *reg, *entry_reg;
28686ccf49f7SEduard Zingerman 	struct scev *scev = env->scev;
2869*32e96257SEduard Zingerman 	struct linear_coefs coefs;
28706ccf49f7SEduard Zingerman 	struct env *header_env;
28716ccf49f7SEduard Zingerman 	struct bounds bounds;
2872*32e96257SEduard Zingerman 	u32 r;
28736ccf49f7SEduard Zingerman 	int err;
28746ccf49f7SEduard Zingerman 
28756ccf49f7SEduard Zingerman 	if (entry_state->curframe != cur_func_state->frameno) {
28766ccf49f7SEduard Zingerman 		verifier_bug(env, "clamping registers for a wrong frame: %d vs %d\n",
28776ccf49f7SEduard Zingerman 			     entry_state->curframe, cur_func_state->frameno);
28786ccf49f7SEduard Zingerman 		return -EFAULT;
28796ccf49f7SEduard Zingerman 	}
28806ccf49f7SEduard Zingerman 
28816ccf49f7SEduard Zingerman 	header_env = find_header_env(scev, insn_idx);
28826ccf49f7SEduard Zingerman 	for (r = 0; r < REGS_NUM; r++) {
28836ccf49f7SEduard Zingerman 		/* If SCEV for r is (linear <reg> <slope>)*/
2884*32e96257SEduard Zingerman 		if (!is_simple_linear(scev, header_env->reg2scev[r], &coefs) ||
2885*32e96257SEduard Zingerman 		    coefs.base_reg != r)
28866ccf49f7SEduard Zingerman 			continue;
28876ccf49f7SEduard Zingerman 
28886ccf49f7SEduard Zingerman 		entry_reg = scev_reg_for_linear(entry_st, r);
28896ccf49f7SEduard Zingerman 		reg = scev_reg_for_linear(cur_func_state, r);
28906ccf49f7SEduard Zingerman 		if (!entry_reg || !reg || entry_reg->type == NOT_INIT || reg->type == NOT_INIT ||
28916ccf49f7SEduard Zingerman 		    is_unbound_scev_reg(env, entry_st, r))
28926ccf49f7SEduard Zingerman 			continue;
28936ccf49f7SEduard Zingerman 
2894*32e96257SEduard Zingerman 		linear_bounds(entry_reg, max_header_count, &coefs, &bounds);
2895*32e96257SEduard Zingerman 		bounds.r64 = cnum64_intersect(reg->r64, bounds.r64);
2896*32e96257SEduard Zingerman 		bounds.r32 = cnum32_intersect(reg->r32, bounds.r32);
2897*32e96257SEduard Zingerman 		if (cnum64_is_empty(bounds.r64)) {
28986ccf49f7SEduard Zingerman 			verifier_bug(env, "scev clamp produced empty range for r%d", r);
28996ccf49f7SEduard Zingerman 			return -EFAULT;
29006ccf49f7SEduard Zingerman 		}
29016ccf49f7SEduard Zingerman 		if (log->level & BPF_LOG_LEVEL2) {
29026ccf49f7SEduard Zingerman 			bpf_log(log, "loop header at %d, clamping ", insn_idx);
29036ccf49f7SEduard Zingerman 			log_reg(env, r);
29046ccf49f7SEduard Zingerman 			bpf_log(log, " to ");
2905*32e96257SEduard Zingerman 			log_bounds(env, &bounds);
2906*32e96257SEduard Zingerman 			bpf_log(log, "\n");
29076ccf49f7SEduard Zingerman 		}
29086ccf49f7SEduard Zingerman 		scratch_widened_reg_id(env, reg);
2909*32e96257SEduard Zingerman 		err = bpf_set_reg_range(env, reg, bounds.r64, bounds.r32,
2910*32e96257SEduard Zingerman 					bounds.base, bounds.step);
29116ccf49f7SEduard Zingerman 		if (err)
29126ccf49f7SEduard Zingerman 			return err;
29136ccf49f7SEduard Zingerman 		mark_scev_reg_scratched(env, r);
29146ccf49f7SEduard Zingerman 	}
29156ccf49f7SEduard Zingerman 	return 0;
29166ccf49f7SEduard Zingerman }
2917