@@ -2796,22 +2796,33 @@ static void mark_reg_not_init(struct bpf_verifier_env *env,
27962796 __mark_reg_not_init(env, regs + regno);
27972797}
27982798
2799- static void mark_btf_ld_reg(struct bpf_verifier_env *env,
2800- struct bpf_reg_state *regs, u32 regno,
2801- enum bpf_reg_type reg_type,
2802- struct btf *btf, u32 btf_id,
2803- enum bpf_type_flag flag)
2799+ static int mark_btf_ld_reg(struct bpf_verifier_env *env,
2800+ struct bpf_reg_state *regs, u32 regno,
2801+ enum bpf_reg_type reg_type,
2802+ struct btf *btf, u32 btf_id,
2803+ enum bpf_type_flag flag)
28042804{
2805- if (reg_type == SCALAR_VALUE) {
2805+ switch (reg_type) {
2806+ case SCALAR_VALUE:
28062807 mark_reg_unknown(env, regs, regno);
2807- return;
2808+ return 0;
2809+ case PTR_TO_BTF_ID:
2810+ mark_reg_known_zero(env, regs, regno);
2811+ regs[regno].type = PTR_TO_BTF_ID | flag;
2812+ regs[regno].btf = btf;
2813+ regs[regno].btf_id = btf_id;
2814+ if (type_may_be_null(flag))
2815+ regs[regno].id = ++env->id_gen;
2816+ return 0;
2817+ case PTR_TO_MEM:
2818+ mark_reg_known_zero(env, regs, regno);
2819+ regs[regno].type = PTR_TO_MEM | flag;
2820+ regs[regno].mem_size = 0;
2821+ return 0;
2822+ default:
2823+ verifier_bug(env, "unexpected reg_type %d in %s\n", reg_type, __func__);
2824+ return -EFAULT;
28082825 }
2809- mark_reg_known_zero(env, regs, regno);
2810- regs[regno].type = PTR_TO_BTF_ID | flag;
2811- regs[regno].btf = btf;
2812- regs[regno].btf_id = btf_id;
2813- if (type_may_be_null(flag))
2814- regs[regno].id = ++env->id_gen;
28152826}
28162827
28172828#define DEF_NOT_SUBREG (0)
@@ -5965,6 +5976,7 @@ static int check_map_kptr_access(struct bpf_verifier_env *env, u32 regno,
59655976 struct bpf_insn *insn = &env->prog->insnsi[insn_idx];
59665977 int class = BPF_CLASS(insn->code);
59675978 struct bpf_reg_state *val_reg;
5979+ int ret;
59685980
59695981 /* Things we already checked for in check_map_access and caller:
59705982 * - Reject cases where variable offset may touch kptr
@@ -5998,8 +6010,11 @@ static int check_map_kptr_access(struct bpf_verifier_env *env, u32 regno,
59986010 /* We can simply mark the value_regno receiving the pointer
59996011 * value from map as PTR_TO_BTF_ID, with the correct type.
60006012 */
6001- mark_btf_ld_reg(env, cur_regs(env), value_regno, PTR_TO_BTF_ID, kptr_field->kptr.btf,
6002- kptr_field->kptr.btf_id, btf_ld_kptr_type(env, kptr_field));
6013+ ret = mark_btf_ld_reg(env, cur_regs(env), value_regno, PTR_TO_BTF_ID,
6014+ kptr_field->kptr.btf, kptr_field->kptr.btf_id,
6015+ btf_ld_kptr_type(env, kptr_field));
6016+ if (ret < 0)
6017+ return ret;
60036018 } else if (class == BPF_STX) {
60046019 val_reg = reg_state(env, value_regno);
60056020 if (!register_is_null(val_reg) &&
@@ -7298,8 +7313,11 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
72987313 clear_trusted_flags(&flag);
72997314 }
73007315
7301- if (atype == BPF_READ && value_regno >= 0)
7302- mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
7316+ if (atype == BPF_READ && value_regno >= 0) {
7317+ ret = mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
7318+ if (ret < 0)
7319+ return ret;
7320+ }
73037321
73047322 return 0;
73057323}
@@ -7353,13 +7371,19 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env,
73537371
73547372 /* Simulate access to a PTR_TO_BTF_ID */
73557373 memset(&map_reg, 0, sizeof(map_reg));
7356- mark_btf_ld_reg(env, &map_reg, 0, PTR_TO_BTF_ID, btf_vmlinux, *map->ops->map_btf_id, 0);
7374+ ret = mark_btf_ld_reg(env, &map_reg, 0, PTR_TO_BTF_ID,
7375+ btf_vmlinux, *map->ops->map_btf_id, 0);
7376+ if (ret < 0)
7377+ return ret;
73577378 ret = btf_struct_access(&env->log, &map_reg, off, size, atype, &btf_id, &flag, NULL);
73587379 if (ret < 0)
73597380 return ret;
73607381
7361- if (value_regno >= 0)
7362- mark_btf_ld_reg(env, regs, value_regno, ret, btf_vmlinux, btf_id, flag);
7382+ if (value_regno >= 0) {
7383+ ret = mark_btf_ld_reg(env, regs, value_regno, ret, btf_vmlinux, btf_id, flag);
7384+ if (ret < 0)
7385+ return ret;
7386+ }
73637387
73647388 return 0;
73657389}
@@ -10413,6 +10437,12 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
1041310437 bpf_log(log, "R%d is not a scalar\n", regno);
1041410438 return -EINVAL;
1041510439 }
10440+ } else if (arg->arg_type & PTR_UNTRUSTED) {
10441+ /*
10442+ * Anything is allowed for untrusted arguments, as these are
10443+ * read-only and probe read instructions would protect against
10444+ * invalid memory access.
10445+ */
1041610446 } else if (arg->arg_type == ARG_PTR_TO_CTX) {
1041710447 ret = check_func_arg_reg_off(env, reg, regno, ARG_DONTCARE);
1041810448 if (ret < 0)
@@ -19923,6 +19953,7 @@ static int do_check(struct bpf_verifier_env *env)
1992319953
1992419954 for (;;) {
1992519955 struct bpf_insn *insn;
19956+ struct bpf_insn_aux_data *insn_aux;
1992619957 int err;
1992719958
1992819959 /* reset current history entry on each new instruction */
@@ -19936,6 +19967,7 @@ static int do_check(struct bpf_verifier_env *env)
1993619967 }
1993719968
1993819969 insn = &insns[env->insn_idx];
19970+ insn_aux = &env->insn_aux_data[env->insn_idx];
1993919971
1994019972 if (++env->insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) {
1994119973 verbose(env,
@@ -20012,19 +20044,19 @@ static int do_check(struct bpf_verifier_env *env)
2001220044 /* Reduce verification complexity by stopping speculative path
2001320045 * verification when a nospec is encountered.
2001420046 */
20015- if (state->speculative && cur_aux(env) ->nospec)
20047+ if (state->speculative && insn_aux ->nospec)
2001620048 goto process_bpf_exit;
2001720049
2001820050 err = do_check_insn(env, &do_print_state);
2001920051 if (error_recoverable_with_nospec(err) && state->speculative) {
2002020052 /* Prevent this speculative path from ever reaching the
2002120053 * insn that would have been unsafe to execute.
2002220054 */
20023- cur_aux(env) ->nospec = true;
20055+ insn_aux ->nospec = true;
2002420056 /* If it was an ADD/SUB insn, potentially remove any
2002520057 * markings for alu sanitization.
2002620058 */
20027- cur_aux(env) ->alu_state = 0;
20059+ insn_aux ->alu_state = 0;
2002820060 goto process_bpf_exit;
2002920061 } else if (err < 0) {
2003020062 return err;
@@ -20033,7 +20065,7 @@ static int do_check(struct bpf_verifier_env *env)
2003320065 }
2003420066 WARN_ON_ONCE(err);
2003520067
20036- if (state->speculative && cur_aux(env) ->nospec_result) {
20068+ if (state->speculative && insn_aux ->nospec_result) {
2003720069 /* If we are on a path that performed a jump-op, this
2003820070 * may skip a nospec patched-in after the jump. This can
2003920071 * currently never happen because nospec_result is only
@@ -20042,8 +20074,15 @@ static int do_check(struct bpf_verifier_env *env)
2004220074 * never skip the following insn. Still, add a warning
2004320075 * to document this in case nospec_result is used
2004420076 * elsewhere in the future.
20077+ *
20078+ * All non-branch instructions have a single
20079+ * fall-through edge. For these, nospec_result should
20080+ * already work.
2004520081 */
20046- WARN_ON_ONCE(env->insn_idx != prev_insn_idx + 1);
20082+ if (verifier_bug_if(BPF_CLASS(insn->code) == BPF_JMP ||
20083+ BPF_CLASS(insn->code) == BPF_JMP32, env,
20084+ "speculation barrier after jump instruction may not have the desired effect"))
20085+ return -EFAULT;
2004720086process_bpf_exit:
2004820087 mark_verifier_state_scratched(env);
2004920088 err = update_branch_counts(env, env->cur_state);
@@ -23122,11 +23161,12 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
2312223161 __mark_dynptr_reg(reg, BPF_DYNPTR_TYPE_LOCAL, true, ++env->id_gen);
2312323162 } else if (base_type(arg->arg_type) == ARG_PTR_TO_MEM) {
2312423163 reg->type = PTR_TO_MEM;
23125- if ( arg->arg_type & PTR_MAYBE_NULL)
23126- reg->type |= PTR_MAYBE_NULL;
23164+ reg->type |= arg->arg_type &
23165+ ( PTR_MAYBE_NULL | PTR_UNTRUSTED | MEM_RDONLY) ;
2312723166 mark_reg_known_zero(env, regs, i);
2312823167 reg->mem_size = arg->mem_size;
23129- reg->id = ++env->id_gen;
23168+ if (arg->arg_type & PTR_MAYBE_NULL)
23169+ reg->id = ++env->id_gen;
2313023170 } else if (base_type(arg->arg_type) == ARG_PTR_TO_BTF_ID) {
2313123171 reg->type = PTR_TO_BTF_ID;
2313223172 if (arg->arg_type & PTR_MAYBE_NULL)
0 commit comments