Commit 485ec51e authored by Joanne Koong's avatar Joanne Koong Committed by Alexei Starovoitov
Browse files

bpf: Refactor verifier dynptr into get_dynptr_arg_reg



This commit refactors the logic for determining which register in a
function is the dynptr into "get_dynptr_arg_reg". This will be used
in the future when the dynptr reg for BPF_FUNC_dynptr_write will need
to be obtained in order to support writes for skb dynptrs.

Signed-off-by: default avatarJoanne Koong <joannelkoong@gmail.com>
Link: https://lore.kernel.org/r/20230301154953.641654-6-joannelkoong@gmail.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 8357b366
Loading
Loading
Loading
Loading
+50 −30
Original line number Diff line number Diff line
@@ -6689,6 +6689,28 @@ int check_func_arg_reg_off(struct bpf_verifier_env *env,
	}
}
static struct bpf_reg_state *get_dynptr_arg_reg(struct bpf_verifier_env *env,
						const struct bpf_func_proto *fn,
						struct bpf_reg_state *regs)
{
	struct bpf_reg_state *state = NULL;
	int i;
	for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++)
		if (arg_type_is_dynptr(fn->arg_type[i])) {
			if (state) {
				verbose(env, "verifier internal error: multiple dynptr args\n");
				return NULL;
			}
			state = &regs[BPF_REG_1 + i];
		}
	if (!state)
		verbose(env, "verifier internal error: no dynptr arg found\n");
	return state;
}
static int dynptr_id(struct bpf_verifier_env *env, struct bpf_reg_state *reg)
{
	struct bpf_func_state *state = func(env, reg);
@@ -8326,16 +8348,19 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
		}
		break;
	case BPF_FUNC_dynptr_data:
		for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
			if (arg_type_is_dynptr(fn->arg_type[i])) {
				struct bpf_reg_state *reg = &regs[BPF_REG_1 + i];
	{
		struct bpf_reg_state *reg;
		int id, ref_obj_id;
		reg = get_dynptr_arg_reg(env, fn, regs);
		if (!reg)
			return -EFAULT;
		if (meta.dynptr_id) {
			verbose(env, "verifier internal error: meta.dynptr_id already set\n");
			return -EFAULT;
		}
		if (meta.ref_obj_id) {
			verbose(env, "verifier internal error: meta.ref_obj_id already set\n");
			return -EFAULT;
@@ -8355,14 +8380,9 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
		meta.dynptr_id = id;
		meta.ref_obj_id = ref_obj_id;
		break;
	}
		}
		if (i == MAX_BPF_FUNC_REG_ARGS) {
			verbose(env, "verifier internal error: no dynptr in bpf_dynptr_data()\n");
			return -EFAULT;
		}
		break;
	case BPF_FUNC_user_ringbuf_drain:
		err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
					set_user_ringbuf_callback_state);