Skip to content

Commit 498f6e4

Browse files
theihorKernel Patches Daemon
authored andcommitted
bpf: implement KF_IMPLICIT_PROG_AUX_ARG flag
Define KF_IMPLICIT_PROG_AUX_ARG and handle it in the BPF verifier. The mechanism of patching is exactly the same as for __prog parameter annotation: in check_kfunc_args() detect the relevant parameter and remember regno in cur_aux(env)->arg_prog. Then the (unchanged in this patch) fixup_kfunc_call() adds a mov instruction to set the actual pointer to prog_aux. The caveat for KF_IMPLICIT_PROG_AUX_ARG is in implicitness. We have to separately check that the number of arguments is under MAX_BPF_FUNC_REG_ARGS. Signed-off-by: Ihor Solodrai <[email protected]>
1 parent 2225dd1 commit 498f6e4

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

include/linux/btf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@
7979
#define KF_ARENA_RET (1 << 13) /* kfunc returns an arena pointer */
8080
#define KF_ARENA_ARG1 (1 << 14) /* kfunc takes an arena pointer as its first argument */
8181
#define KF_ARENA_ARG2 (1 << 15) /* kfunc takes an arena pointer as its second argument */
82+
/* kfunc takes a pointer to struct bpf_prog_aux as the last argument,
83+
* passed implicitly in BPF */
84+
#define KF_IMPLICIT_PROG_AUX_ARG (1 << 16)
8285

8386
/*
8487
* Tag marking a kernel function as a kfunc. This is meant to minimize the

kernel/bpf/verifier.c

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11948,6 +11948,11 @@ static bool is_kfunc_rcu_protected(struct bpf_kfunc_call_arg_meta *meta)
1194811948
return meta->kfunc_flags & KF_RCU_PROTECTED;
1194911949
}
1195011950

11951+
static bool is_kfunc_with_implicit_prog_aux_arg(struct bpf_kfunc_call_arg_meta *meta)
11952+
{
11953+
return meta->kfunc_flags & KF_IMPLICIT_PROG_AUX_ARG;
11954+
}
11955+
1195111956
static bool is_kfunc_arg_mem_size(const struct btf *btf,
1195211957
const struct btf_param *arg,
1195311958
const struct bpf_reg_state *reg)
@@ -12029,6 +12034,18 @@ static bool is_kfunc_arg_prog(const struct btf *btf, const struct btf_param *arg
1202912034
return btf_param_match_suffix(btf, arg, "__prog");
1203012035
}
1203112036

12037+
static int set_kfunc_arg_prog_regno(struct bpf_verifier_env *env, struct bpf_kfunc_call_arg_meta *meta, u32 regno)
12038+
{
12039+
if (meta->arg_prog) {
12040+
verifier_bug(env, "Only 1 prog->aux argument supported per-kfunc");
12041+
return -EFAULT;
12042+
}
12043+
meta->arg_prog = true;
12044+
cur_aux(env)->arg_prog = regno;
12045+
12046+
return 0;
12047+
}
12048+
1203212049
static bool is_kfunc_arg_scalar_with_name(const struct btf *btf,
1203312050
const struct btf_param *arg,
1203412051
const char *name)
@@ -13050,6 +13067,21 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
1305013067
return -EINVAL;
1305113068
}
1305213069

13070+
/* KF_IMPLICIT_PROG_AUX_ARG means that the kfunc has one less argument in BTF,
13071+
* so we have to set_kfunc_arg_prog_regno() outside the arg check loop.
13072+
*/
13073+
if (is_kfunc_with_implicit_prog_aux_arg(meta)) {
13074+
if (nargs + 1 > MAX_BPF_FUNC_REG_ARGS) {
13075+
verifier_bug(env, "A kfunc with KF_IMPLICIT_PROG_AUX_ARG flag has %d > %d args",
13076+
nargs + 1, MAX_BPF_FUNC_REG_ARGS);
13077+
return -EFAULT;
13078+
}
13079+
u32 regno = nargs + 1;
13080+
ret = set_kfunc_arg_prog_regno(env, meta, regno);
13081+
if (ret)
13082+
return ret;
13083+
}
13084+
1305313085
/* Check that BTF function arguments match actual types that the
1305413086
* verifier sees.
1305513087
*/
@@ -13066,14 +13098,11 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
1306613098
if (is_kfunc_arg_ignore(btf, &args[i]))
1306713099
continue;
1306813100

13101+
/* __prog annotation check for backward compatibility */
1306913102
if (is_kfunc_arg_prog(btf, &args[i])) {
13070-
/* Used to reject repeated use of __prog. */
13071-
if (meta->arg_prog) {
13072-
verifier_bug(env, "Only 1 prog->aux argument supported per-kfunc");
13073-
return -EFAULT;
13074-
}
13075-
meta->arg_prog = true;
13076-
cur_aux(env)->arg_prog = regno;
13103+
ret = set_kfunc_arg_prog_regno(env, meta, regno);
13104+
if (ret)
13105+
return ret;
1307713106
continue;
1307813107
}
1307913108

0 commit comments

Comments
 (0)