Skip to content

Commit eed807f

Browse files
kkdwvdAlexei Starovoitov
authored andcommitted
bpf: Tweak definition of KF_TRUSTED_ARGS
Instead of forcing all arguments to be referenced pointers with non-zero reg->ref_obj_id, tweak the definition of KF_TRUSTED_ARGS to mean that only PTR_TO_BTF_ID (and socket types translated to PTR_TO_BTF_ID) have that constraint, and require their offset to be set to 0. The rest of pointer types are also accomodated in this definition of trusted pointers, but with more relaxed rules regarding offsets. The inherent meaning of setting this flag is that all kfunc pointer arguments have a guranteed lifetime, and kernel object pointers (PTR_TO_BTF_ID, PTR_TO_CTX) are passed in their unmodified form (with offset 0). In general, this is not true for PTR_TO_BTF_ID as it can be obtained using pointer walks. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://lore.kernel.org/r/cdede0043c47ed7a357f0a915d16f9ce06a1d589.1663778601.git.lorenzo@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 1d8b82c commit eed807f

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

Documentation/bpf/kfuncs.rst

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,22 @@ KF_ACQUIRE and KF_RET_NULL flags.
137137
--------------------------
138138

139139
The KF_TRUSTED_ARGS flag is used for kfuncs taking pointer arguments. It
140-
indicates that the all pointer arguments will always be refcounted, and have
141-
their offset set to 0. It can be used to enforce that a pointer to a refcounted
142-
object acquired from a kfunc or BPF helper is passed as an argument to this
143-
kfunc without any modifications (e.g. pointer arithmetic) such that it is
144-
trusted and points to the original object. This flag is often used for kfuncs
145-
that operate (change some property, perform some operation) on an object that
146-
was obtained using an acquire kfunc. Such kfuncs need an unchanged pointer to
147-
ensure the integrity of the operation being performed on the expected object.
140+
indicates that the all pointer arguments will always have a guaranteed lifetime,
141+
and pointers to kernel objects are always passed to helpers in their unmodified
142+
form (as obtained from acquire kfuncs).
143+
144+
It can be used to enforce that a pointer to a refcounted object acquired from a
145+
kfunc or BPF helper is passed as an argument to this kfunc without any
146+
modifications (e.g. pointer arithmetic) such that it is trusted and points to
147+
the original object.
148+
149+
Meanwhile, it is also allowed pass pointers to normal memory to such kfuncs,
150+
but those can have a non-zero offset.
151+
152+
This flag is often used for kfuncs that operate (change some property, perform
153+
some operation) on an object that was obtained using an acquire kfunc. Such
154+
kfuncs need an unchanged pointer to ensure the integrity of the operation being
155+
performed on the expected object.
148156

149157
2.4.6 KF_SLEEPABLE flag
150158
-----------------------

kernel/bpf/btf.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6227,7 +6227,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
62276227
bool processing_call)
62286228
{
62296229
enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
6230-
bool rel = false, kptr_get = false, trusted_arg = false;
6230+
bool rel = false, kptr_get = false, trusted_args = false;
62316231
bool sleepable = false;
62326232
struct bpf_verifier_log *log = &env->log;
62336233
u32 i, nargs, ref_id, ref_obj_id = 0;
@@ -6265,7 +6265,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
62656265
/* Only kfunc can be release func */
62666266
rel = kfunc_meta->flags & KF_RELEASE;
62676267
kptr_get = kfunc_meta->flags & KF_KPTR_GET;
6268-
trusted_arg = kfunc_meta->flags & KF_TRUSTED_ARGS;
6268+
trusted_args = kfunc_meta->flags & KF_TRUSTED_ARGS;
62696269
sleepable = kfunc_meta->flags & KF_SLEEPABLE;
62706270
}
62716271

@@ -6276,6 +6276,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
62766276
enum bpf_arg_type arg_type = ARG_DONTCARE;
62776277
u32 regno = i + 1;
62786278
struct bpf_reg_state *reg = &regs[regno];
6279+
bool obj_ptr = false;
62796280

62806281
t = btf_type_skip_modifiers(btf, args[i].type, NULL);
62816282
if (btf_type_is_scalar(t)) {
@@ -6323,10 +6324,17 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
63236324
return -EINVAL;
63246325
}
63256326

6327+
/* These register types have special constraints wrt ref_obj_id
6328+
* and offset checks. The rest of trusted args don't.
6329+
*/
6330+
obj_ptr = reg->type == PTR_TO_CTX || reg->type == PTR_TO_BTF_ID ||
6331+
reg2btf_ids[base_type(reg->type)];
6332+
63266333
/* Check if argument must be a referenced pointer, args + i has
63276334
* been verified to be a pointer (after skipping modifiers).
6335+
* PTR_TO_CTX is ok without having non-zero ref_obj_id.
63286336
*/
6329-
if (is_kfunc && trusted_arg && !reg->ref_obj_id) {
6337+
if (is_kfunc && trusted_args && (obj_ptr && reg->type != PTR_TO_CTX) && !reg->ref_obj_id) {
63306338
bpf_log(log, "R%d must be referenced\n", regno);
63316339
return -EINVAL;
63326340
}
@@ -6335,7 +6343,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
63356343
ref_tname = btf_name_by_offset(btf, ref_t->name_off);
63366344

63376345
/* Trusted args have the same offset checks as release arguments */
6338-
if (trusted_arg || (rel && reg->ref_obj_id))
6346+
if ((trusted_args && obj_ptr) || (rel && reg->ref_obj_id))
63396347
arg_type |= OBJ_RELEASE;
63406348
ret = check_func_arg_reg_off(env, reg, regno, arg_type);
63416349
if (ret < 0)
@@ -6435,7 +6443,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
64356443
reg_ref_t->name_off);
64366444
if (!btf_struct_ids_match(log, reg_btf, reg_ref_id,
64376445
reg->off, btf, ref_id,
6438-
trusted_arg || (rel && reg->ref_obj_id))) {
6446+
trusted_args || (rel && reg->ref_obj_id))) {
64396447
bpf_log(log, "kernel function %s args#%d expected pointer to %s %s but R%d has a pointer to %s %s\n",
64406448
func_name, i,
64416449
btf_type_str(ref_t), ref_tname,

0 commit comments

Comments
 (0)