diff options
author | Anay Wadhera <awadhera@berkeley.edu> | 2021-05-20 21:56:46 -0700 |
---|---|---|
committer | Michael Bestas <mkbestas@lineageos.org> | 2022-04-19 00:49:45 +0300 |
commit | fa8efd4e5634b873b21339864fac3e35d3b05aa6 (patch) | |
tree | c34c0aa8ca9a5ef16dc3b5157dfbd1ac0e4e6ed3 /kernel/bpf | |
parent | 4a5b59ae5f3fa258554687d32001ff87ee31b556 (diff) |
Revert "bpf: don't (ab)use instructions to store state"
This reverts commit 0748b80e432584502d1559b1a51b7df58f5e2fce.
Signed-off-by: Chatur27 <jasonbright2709@gmail.com>
Diffstat (limited to 'kernel/bpf')
-rw-r--r-- | kernel/bpf/verifier.c | 67 |
1 files changed, 28 insertions, 39 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 769d2ec44802..261c90233dcd 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -186,10 +186,6 @@ struct verifier_stack_elem { struct verifier_stack_elem *next; }; -struct bpf_insn_aux_data { - enum bpf_reg_type ptr_type; /* pointer type for load/store insns */ -}; - #define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */ /* single container for all structs @@ -204,7 +200,6 @@ struct verifier_env { struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */ u32 used_map_cnt; /* number of used maps */ bool allow_ptr_leaks; - struct bpf_insn_aux_data *insn_aux_data; /* array of per-insn state */ }; /* verbose verifier prints what it's seeing @@ -1789,7 +1784,7 @@ static int do_check(struct verifier_env *env) return err; } else if (class == BPF_LDX) { - enum bpf_reg_type *prev_src_type, src_reg_type; + enum bpf_reg_type src_reg_type; /* check for reserved fields is already done */ @@ -1818,18 +1813,16 @@ static int do_check(struct verifier_env *env) continue; } - prev_src_type = &env->insn_aux_data[insn_idx].ptr_type; - - if (*prev_src_type == NOT_INIT) { + if (insn->imm == 0) { /* saw a valid insn * dst_reg = *(u32 *)(src_reg + off) - * save type to validate intersecting paths + * use reserved 'imm' field to mark this insn */ - *prev_src_type = src_reg_type; + insn->imm = src_reg_type; - } else if (src_reg_type != *prev_src_type && + } else if (src_reg_type != insn->imm && (src_reg_type == PTR_TO_CTX || - *prev_src_type == PTR_TO_CTX)) { + insn->imm == PTR_TO_CTX)) { /* ABuser program is trying to use the same insn * dst_reg = *(u32*) (src_reg + off) * with different pointer types: @@ -1842,7 +1835,7 @@ static int do_check(struct verifier_env *env) } } else if (class == BPF_STX) { - enum bpf_reg_type *prev_dst_type, dst_reg_type; + enum bpf_reg_type dst_reg_type; if (BPF_MODE(insn->code) == BPF_XADD) { err = check_xadd(env, insn); @@ -1870,13 +1863,11 @@ static int do_check(struct verifier_env *env) if (err) return err; - prev_dst_type = &env->insn_aux_data[insn_idx].ptr_type; - - if (*prev_dst_type == NOT_INIT) { - *prev_dst_type = dst_reg_type; - } else if (dst_reg_type != *prev_dst_type && + if (insn->imm == 0) { + insn->imm = dst_reg_type; + } else if (dst_reg_type != insn->imm && (dst_reg_type == PTR_TO_CTX || - *prev_dst_type == PTR_TO_CTX)) { + insn->imm == PTR_TO_CTX)) { verbose("same insn cannot be used with different pointers\n"); return -EINVAL; } @@ -2113,17 +2104,17 @@ static void convert_pseudo_ld_imm64(struct verifier_env *env) static int convert_ctx_accesses(struct verifier_env *env) { struct bpf_insn *insn = env->prog->insnsi; - const int insn_cnt = env->prog->len; + int insn_cnt = env->prog->len; struct bpf_insn insn_buf[16]; struct bpf_prog *new_prog; enum bpf_access_type type; - int i, delta = 0; + int i; if (!env->prog->aux->ops->convert_ctx_access) return 0; for (i = 0; i < insn_cnt; i++, insn++) { - u32 cnt; + u32 insn_delta, cnt; if (insn->code == (BPF_LDX | BPF_MEM | BPF_W)) type = BPF_READ; @@ -2132,8 +2123,11 @@ static int convert_ctx_accesses(struct verifier_env *env) else continue; - if (env->insn_aux_data[i].ptr_type != PTR_TO_CTX) + if (insn->imm != PTR_TO_CTX) { + /* clear internal mark */ + insn->imm = 0; continue; + } cnt = env->prog->aux->ops-> convert_ctx_access(type, insn->dst_reg, insn->src_reg, @@ -2143,16 +2137,18 @@ static int convert_ctx_accesses(struct verifier_env *env) return -EINVAL; } - new_prog = bpf_patch_insn_single(env->prog, i + delta, insn_buf, - cnt); + new_prog = bpf_patch_insn_single(env->prog, i, insn_buf, cnt); if (!new_prog) return -ENOMEM; - delta += cnt - 1; + insn_delta = cnt - 1; /* keep walking new program and skip insns we just inserted */ env->prog = new_prog; - insn = new_prog->insnsi + i + delta; + insn = new_prog->insnsi + i + insn_delta; + + insn_cnt += insn_delta; + i += insn_delta; } return 0; @@ -2196,11 +2192,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr) if (!env) return -ENOMEM; - env->insn_aux_data = vzalloc(sizeof(struct bpf_insn_aux_data) * - (*prog)->len); - ret = -ENOMEM; - if (!env->insn_aux_data) - goto err_free_env; env->prog = *prog; /* grab the mutex to protect few globals used by verifier */ @@ -2219,12 +2210,12 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr) /* log_* values have to be sane */ if (log_size < 128 || log_size > UINT_MAX >> 8 || log_level == 0 || log_ubuf == NULL) - goto err_unlock; + goto free_env; ret = -ENOMEM; log_buf = vmalloc(log_size); if (!log_buf) - goto err_unlock; + goto free_env; } else { log_level = 0; } @@ -2293,16 +2284,14 @@ skip_full_check: free_log_buf: if (log_level) vfree(log_buf); +free_env: if (!env->prog->aux->used_maps) /* if we didn't copy map pointers into bpf_prog_info, release * them now. Otherwise free_bpf_prog_info() will release them. */ release_maps(env); *prog = env->prog; -err_unlock: - mutex_unlock(&bpf_verifier_lock); - vfree(env->insn_aux_data); -err_free_env: kfree(env); + mutex_unlock(&bpf_verifier_lock); return ret; } |