Commit 2a79690e authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'two-small-fixes-for-global-subprog-tagging'



Andrii Nakryiko says:

====================
Two small fixes for global subprog tagging

Fix a bug with passing trusted PTR_TO_BTF_ID_OR_NULL register into global
subprog that expects `__arg_trusted __arg_nullable` arguments, which was
discovered when adopting production BPF application.

Also fix annoying warnings that are irrelevant for static subprogs, which are
just an artifact of using btf_prepare_func_args() for both static and global
subprogs.
====================

Acked-by: default avatarEduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240202190529.2374377-1-andrii@kernel.org


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents a68b50f4 1eb98674
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -7122,6 +7122,8 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
	args = (const struct btf_param *)(t + 1);
	nargs = btf_type_vlen(t);
	if (nargs > MAX_BPF_FUNC_REG_ARGS) {
		if (!is_global)
			return -EINVAL;
		bpf_log(log, "Global function %s() with %d > %d args. Buggy compiler.\n",
			tname, nargs, MAX_BPF_FUNC_REG_ARGS);
		return -EINVAL;
@@ -7131,6 +7133,8 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
	while (btf_type_is_modifier(t))
		t = btf_type_by_id(btf, t->type);
	if (!btf_type_is_int(t) && !btf_is_any_enum(t)) {
		if (!is_global)
			return -EINVAL;
		bpf_log(log,
			"Global function %s() doesn't return scalar. Only those are supported.\n",
			tname);
@@ -7251,6 +7255,8 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
			sub->args[i].arg_type = ARG_ANYTHING;
			continue;
		}
		if (!is_global)
			return -EINVAL;
		bpf_log(log, "Arg#%d type %s in %s() is not supported yet.\n",
			i, btf_type_str(t), tname);
		return -EINVAL;
+1 −0
Original line number Diff line number Diff line
@@ -8242,6 +8242,7 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
	switch ((int)reg->type) {
	case PTR_TO_BTF_ID:
	case PTR_TO_BTF_ID | PTR_TRUSTED:
	case PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL:
	case PTR_TO_BTF_ID | MEM_RCU:
	case PTR_TO_BTF_ID | PTR_MAYBE_NULL:
	case PTR_TO_BTF_ID | PTR_MAYBE_NULL | MEM_RCU:
+29 −3
Original line number Diff line number Diff line
@@ -19,15 +19,41 @@ __weak int subprog_trusted_task_nullable(struct task_struct *task __arg_trusted
	return task->pid + task->tgid;
}

SEC("?kprobe")
__weak int subprog_trusted_task_nullable_extra_layer(struct task_struct *task __arg_trusted __arg_nullable)
{
	return subprog_trusted_task_nullable(task) + subprog_trusted_task_nullable(NULL);
}

SEC("?tp_btf/task_newtask")
__success __log_level(2)
__msg("Validating subprog_trusted_task_nullable() func#1...")
__msg(": R1=trusted_ptr_or_null_task_struct(")
int trusted_task_arg_nullable(void *ctx)
{
	struct task_struct *t = bpf_get_current_task_btf();
	struct task_struct *t1 = bpf_get_current_task_btf();
	struct task_struct *t2 = bpf_task_acquire(t1);
	int res = 0;

	/* known NULL */
	res += subprog_trusted_task_nullable(NULL);

	return subprog_trusted_task_nullable(t) + subprog_trusted_task_nullable(NULL);
	/* known non-NULL */
	res += subprog_trusted_task_nullable(t1);
	res += subprog_trusted_task_nullable_extra_layer(t1);

	/* unknown if NULL or not */
	res += subprog_trusted_task_nullable(t2);
	res += subprog_trusted_task_nullable_extra_layer(t2);

	if (t2) {
		/* known non-NULL after explicit NULL check, just in case */
		res += subprog_trusted_task_nullable(t2);
		res += subprog_trusted_task_nullable_extra_layer(t2);

		bpf_task_release(t2);
	}

	return res;
}

__weak int subprog_trusted_task_nonnull(struct task_struct *task __arg_trusted)