Skip to content

Commit 2edc3de

Browse files
Alexei Starovoitovanakryiko
authored andcommitted
bpf: Recognize btf_decl_tag("arg: Arena") as PTR_TO_ARENA.
In global bpf functions recognize btf_decl_tag("arg:arena") as PTR_TO_ARENA. Note, when the verifier sees: __weak void foo(struct bar *p) it recognizes 'p' as PTR_TO_MEM and 'struct bar' has to be a struct with scalars. Hence the only way to use arena pointers in global functions is to tag them with "arg:arena". Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Acked-by: Kumar Kartikeya Dwivedi <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 6082b6c commit 2edc3de

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ enum bpf_arg_type {
712712
* on eBPF program stack
713713
*/
714714
ARG_PTR_TO_MEM, /* pointer to valid memory (stack, packet, map value) */
715+
ARG_PTR_TO_ARENA,
715716

716717
ARG_CONST_SIZE, /* number of bytes accessed from memory */
717718
ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */

kernel/bpf/btf.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7111,10 +7111,11 @@ static int btf_get_ptr_to_btf_id(struct bpf_verifier_log *log, int arg_idx,
71117111
}
71127112

71137113
enum btf_arg_tag {
7114-
ARG_TAG_CTX = 0x1,
7115-
ARG_TAG_NONNULL = 0x2,
7116-
ARG_TAG_TRUSTED = 0x4,
7117-
ARG_TAG_NULLABLE = 0x8,
7114+
ARG_TAG_CTX = BIT_ULL(0),
7115+
ARG_TAG_NONNULL = BIT_ULL(1),
7116+
ARG_TAG_TRUSTED = BIT_ULL(2),
7117+
ARG_TAG_NULLABLE = BIT_ULL(3),
7118+
ARG_TAG_ARENA = BIT_ULL(4),
71187119
};
71197120

71207121
/* Process BTF of a function to produce high-level expectation of function
@@ -7226,6 +7227,8 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
72267227
tags |= ARG_TAG_NONNULL;
72277228
} else if (strcmp(tag, "nullable") == 0) {
72287229
tags |= ARG_TAG_NULLABLE;
7230+
} else if (strcmp(tag, "arena") == 0) {
7231+
tags |= ARG_TAG_ARENA;
72297232
} else {
72307233
bpf_log(log, "arg#%d has unsupported set of tags\n", i);
72317234
return -EOPNOTSUPP;
@@ -7280,6 +7283,14 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
72807283
sub->args[i].btf_id = kern_type_id;
72817284
continue;
72827285
}
7286+
if (tags & ARG_TAG_ARENA) {
7287+
if (tags & ~ARG_TAG_ARENA) {
7288+
bpf_log(log, "arg#%d arena cannot be combined with any other tags\n", i);
7289+
return -EINVAL;
7290+
}
7291+
sub->args[i].arg_type = ARG_PTR_TO_ARENA;
7292+
continue;
7293+
}
72837294
if (is_global) { /* generic user data pointer */
72847295
u32 mem_size;
72857296

kernel/bpf/verifier.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9379,6 +9379,18 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
93799379
bpf_log(log, "arg#%d is expected to be non-NULL\n", i);
93809380
return -EINVAL;
93819381
}
9382+
} else if (base_type(arg->arg_type) == ARG_PTR_TO_ARENA) {
9383+
/*
9384+
* Can pass any value and the kernel won't crash, but
9385+
* only PTR_TO_ARENA or SCALAR make sense. Everything
9386+
* else is a bug in the bpf program. Point it out to
9387+
* the user at the verification time instead of
9388+
* run-time debug nightmare.
9389+
*/
9390+
if (reg->type != PTR_TO_ARENA && reg->type != SCALAR_VALUE) {
9391+
bpf_log(log, "R%d is not a pointer to arena or scalar.\n", regno);
9392+
return -EINVAL;
9393+
}
93829394
} else if (arg->arg_type == (ARG_PTR_TO_DYNPTR | MEM_RDONLY)) {
93839395
ret = process_dynptr_func(env, regno, -1, arg->arg_type, 0);
93849396
if (ret)
@@ -20448,6 +20460,9 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
2044820460
reg->btf = bpf_get_btf_vmlinux(); /* can't fail at this point */
2044920461
reg->btf_id = arg->btf_id;
2045020462
reg->id = ++env->id_gen;
20463+
} else if (base_type(arg->arg_type) == ARG_PTR_TO_ARENA) {
20464+
/* caller can pass either PTR_TO_ARENA or SCALAR */
20465+
mark_reg_unknown(env, regs, i);
2045120466
} else {
2045220467
WARN_ONCE(1, "BUG: unhandled arg#%d type %d\n",
2045320468
i - BPF_REG_1, arg->arg_type);

0 commit comments

Comments
 (0)