Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240202190529.2374377-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+36 -3
+6
kernel/bpf/btf.c
··· 7122 7122 args = (const struct btf_param *)(t + 1); 7123 7123 nargs = btf_type_vlen(t); 7124 7124 if (nargs > MAX_BPF_FUNC_REG_ARGS) { 7125 + if (!is_global) 7126 + return -EINVAL; 7125 7127 bpf_log(log, "Global function %s() with %d > %d args. Buggy compiler.\n", 7126 7128 tname, nargs, MAX_BPF_FUNC_REG_ARGS); 7127 7129 return -EINVAL; ··· 7133 7131 while (btf_type_is_modifier(t)) 7134 7132 t = btf_type_by_id(btf, t->type); 7135 7133 if (!btf_type_is_int(t) && !btf_is_any_enum(t)) { 7134 + if (!is_global) 7135 + return -EINVAL; 7136 7136 bpf_log(log, 7137 7137 "Global function %s() doesn't return scalar. Only those are supported.\n", 7138 7138 tname); ··· 7255 7251 sub->args[i].arg_type = ARG_ANYTHING; 7256 7252 continue; 7257 7253 } 7254 + if (!is_global) 7255 + return -EINVAL; 7258 7256 bpf_log(log, "Arg#%d type %s in %s() is not supported yet.\n", 7259 7257 i, btf_type_str(t), tname); 7260 7258 return -EINVAL;
+1
kernel/bpf/verifier.c
··· 8242 8242 switch ((int)reg->type) { 8243 8243 case PTR_TO_BTF_ID: 8244 8244 case PTR_TO_BTF_ID | PTR_TRUSTED: 8245 + case PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL: 8245 8246 case PTR_TO_BTF_ID | MEM_RCU: 8246 8247 case PTR_TO_BTF_ID | PTR_MAYBE_NULL: 8247 8248 case PTR_TO_BTF_ID | PTR_MAYBE_NULL | MEM_RCU:
+29 -3
tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c
··· 19 19 return task->pid + task->tgid; 20 20 } 21 21 22 - SEC("?kprobe") 22 + __weak int subprog_trusted_task_nullable_extra_layer(struct task_struct *task __arg_trusted __arg_nullable) 23 + { 24 + return subprog_trusted_task_nullable(task) + subprog_trusted_task_nullable(NULL); 25 + } 26 + 27 + SEC("?tp_btf/task_newtask") 23 28 __success __log_level(2) 24 29 __msg("Validating subprog_trusted_task_nullable() func#1...") 25 30 __msg(": R1=trusted_ptr_or_null_task_struct(") 26 31 int trusted_task_arg_nullable(void *ctx) 27 32 { 28 - struct task_struct *t = bpf_get_current_task_btf(); 33 + struct task_struct *t1 = bpf_get_current_task_btf(); 34 + struct task_struct *t2 = bpf_task_acquire(t1); 35 + int res = 0; 29 36 30 - return subprog_trusted_task_nullable(t) + subprog_trusted_task_nullable(NULL); 37 + /* known NULL */ 38 + res += subprog_trusted_task_nullable(NULL); 39 + 40 + /* known non-NULL */ 41 + res += subprog_trusted_task_nullable(t1); 42 + res += subprog_trusted_task_nullable_extra_layer(t1); 43 + 44 + /* unknown if NULL or not */ 45 + res += subprog_trusted_task_nullable(t2); 46 + res += subprog_trusted_task_nullable_extra_layer(t2); 47 + 48 + if (t2) { 49 + /* known non-NULL after explicit NULL check, just in case */ 50 + res += subprog_trusted_task_nullable(t2); 51 + res += subprog_trusted_task_nullable_extra_layer(t2); 52 + 53 + bpf_task_release(t2); 54 + } 55 + 56 + return res; 31 57 } 32 58 33 59 __weak int subprog_trusted_task_nonnull(struct task_struct *task __arg_trusted)