History

bpf: mark a NULL memory argument of a call precise

check_mem_reg() allows bpf_register_is_null() for nullable arguments w/o marking the underlying scalar register precise. Hence a checkpoint created on such a path would prune against arbitrary scalar value. The argument may live on the stack rather than in a register when a call has more than MAX_BPF_FUNC_REG_ARGS arguments, hence the new mark_arg_precision() helper.

Eduard Zingerman committed 2 months ago

Commit f1e41811 parent 593c8eb1 file · +10 −1Browse files

Unified · Split

kernel/bpf/verifier.c+10−1
@@ -4246,6 +4246,15 @@ static int mark_stack_arg_precision(struct bpf_verifier_env *env, int arg_idx) · 4245 unmodified lines
42464246 return mark_chain_precision_batch(env, env->cur_state);
42474247 }
42484248
4249+static int mark_arg_precision(struct bpf_verifier_env *env, argno_t argno)
4250+{
4251+ int regno = reg_from_argno(argno);
4252+
4253+ if (regno >= 0)
4254+ return mark_chain_precision(env, regno);
4255+ return mark_stack_arg_precision(env, arg_idx_from_argno(argno));
4256+}
4257+
42494258 static int check_outgoing_stack_args(struct bpf_verifier_env *env, struct bpf_func_state *caller,
42504259 int nargs, const char *callee_name, const struct btf *btf,
42514260 const struct btf_param *args)
@@ -7175,7 +7184,7 @@ static int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg · 2923 unmodified lines
71757184 int size, err = 0;
71767185
71777186 if (bpf_register_is_null(reg))
7178− return 0;
7187+ return mark_arg_precision(env, argno);
71797188 if (known_memory)
71807189 *known_memory = true;
71817190