Commit 138b9a05 authored by Jiri Olsa's avatar Jiri Olsa Committed by Alexei Starovoitov
Browse files

bpf: Remove btf_id helpers resolving



Now when we moved the helpers btf_id arrays into .BTF_ids section,
we can remove the code that resolve those IDs in runtime.

Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Tested-by: default avatarAndrii Nakryiko <andriin@fb.com>
Acked-by: default avatarAndrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200711215329.41165-6-jolsa@kernel.org
parent c9a0f3b8
Loading
Loading
Loading
Loading
+5 −84
Original line number Diff line number Diff line
@@ -4079,96 +4079,17 @@ error:
	return -EINVAL;
}

static int __btf_resolve_helper_id(struct bpf_verifier_log *log, void *fn,
				   int arg)
{
	char fnname[KSYM_SYMBOL_LEN + 4] = "btf_";
	const struct btf_param *args;
	const struct btf_type *t;
	const char *tname, *sym;
	u32 btf_id, i;

	if (IS_ERR(btf_vmlinux)) {
		bpf_log(log, "btf_vmlinux is malformed\n");
		return -EINVAL;
	}

	sym = kallsyms_lookup((long)fn, NULL, NULL, NULL, fnname + 4);
	if (!sym) {
		bpf_log(log, "kernel doesn't have kallsyms\n");
		return -EFAULT;
	}

	for (i = 1; i <= btf_vmlinux->nr_types; i++) {
		t = btf_type_by_id(btf_vmlinux, i);
		if (BTF_INFO_KIND(t->info) != BTF_KIND_TYPEDEF)
			continue;
		tname = __btf_name_by_offset(btf_vmlinux, t->name_off);
		if (!strcmp(tname, fnname))
			break;
	}
	if (i > btf_vmlinux->nr_types) {
		bpf_log(log, "helper %s type is not found\n", fnname);
		return -ENOENT;
	}

	t = btf_type_by_id(btf_vmlinux, t->type);
	if (!btf_type_is_ptr(t))
		return -EFAULT;
	t = btf_type_by_id(btf_vmlinux, t->type);
	if (!btf_type_is_func_proto(t))
		return -EFAULT;

	args = (const struct btf_param *)(t + 1);
	if (arg >= btf_type_vlen(t)) {
		bpf_log(log, "bpf helper %s doesn't have %d-th argument\n",
			fnname, arg);
		return -EINVAL;
	}

	t = btf_type_by_id(btf_vmlinux, args[arg].type);
	if (!btf_type_is_ptr(t) || !t->type) {
		/* anything but the pointer to struct is a helper config bug */
		bpf_log(log, "ARG_PTR_TO_BTF is misconfigured\n");
		return -EFAULT;
	}
	btf_id = t->type;
	t = btf_type_by_id(btf_vmlinux, t->type);
	/* skip modifiers */
	while (btf_type_is_modifier(t)) {
		btf_id = t->type;
		t = btf_type_by_id(btf_vmlinux, t->type);
	}
	if (!btf_type_is_struct(t)) {
		bpf_log(log, "ARG_PTR_TO_BTF is not a struct\n");
		return -EFAULT;
	}
	bpf_log(log, "helper %s arg%d has btf_id %d struct %s\n", fnname + 4,
		arg, btf_id, __btf_name_by_offset(btf_vmlinux, t->name_off));
	return btf_id;
}

int btf_resolve_helper_id(struct bpf_verifier_log *log,
			  const struct bpf_func_proto *fn, int arg)
{
	int *btf_id = &fn->btf_id[arg];
	int ret;
	int id;

	if (fn->arg_type[arg] != ARG_PTR_TO_BTF_ID)
		return -EINVAL;

	ret = READ_ONCE(*btf_id);
	if (ret)
		return ret;
	/* ok to race the search. The result is the same */
	ret = __btf_resolve_helper_id(log, fn->func, arg);
	if (!ret) {
		/* Function argument cannot be type 'void' */
		bpf_log(log, "BTF resolution bug\n");
		return -EFAULT;
	}
	WRITE_ONCE(*btf_id, ret);
	return ret;
	id = fn->btf_id[arg];
	if (!id || id > btf_vmlinux->nr_types)
		return -EINVAL;
	return id;
}

static int __get_type_size(struct btf *btf, u32 btf_id,