Skip to content

Commit bc04938

Browse files
kkdwivediAlexei Starovoitov
authored andcommitted
bpf: Add support for __prog argument suffix to pass in prog->aux
Instead of hardcoding the list of kfuncs that need prog->aux passed to them with a combination of fixup_kfunc_call adjustment + __ign suffix, combine both in __prog suffix, which ignores the argument passed in, and fixes it up to the prog->aux. This allows kfuncs to have the prog->aux passed into them without having to touch the verifier. Cc: Tejun Heo <[email protected]> Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 3880cdb commit bc04938

File tree

4 files changed

+47
-8
lines changed

4 files changed

+47
-8
lines changed

Documentation/bpf/kfuncs.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,23 @@ Or::
160160
...
161161
}
162162

163+
2.2.6 __prog Annotation
164+
---------------------------
165+
This annotation is used to indicate that the argument needs to be fixed up to
166+
the bpf_prog_aux of the caller BPF program. Any value passed into this argument
167+
is ignored, and rewritten by the verifier.
168+
169+
An example is given below::
170+
171+
__bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
172+
int (callback_fn)(void *map, int *key, void *value),
173+
unsigned int flags,
174+
void *aux__prog)
175+
{
176+
struct bpf_prog_aux *aux = aux__prog;
177+
...
178+
}
179+
163180
.. _BPF_kfunc_nodef:
164181

165182
2.3 Using an existing kernel function

include/linux/bpf_verifier.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ struct bpf_insn_aux_data {
591591
* bpf_fastcall pattern.
592592
*/
593593
u8 fastcall_spills_num:3;
594+
u8 arg_prog:4;
594595

595596
/* below fields are initialized once */
596597
unsigned int orig_idx; /* original instruction index */

kernel/bpf/helpers.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3002,9 +3002,9 @@ __bpf_kfunc int bpf_wq_start(struct bpf_wq *wq, unsigned int flags)
30023002
__bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
30033003
int (callback_fn)(void *map, int *key, void *value),
30043004
unsigned int flags,
3005-
void *aux__ign)
3005+
void *aux__prog)
30063006
{
3007-
struct bpf_prog_aux *aux = (struct bpf_prog_aux *)aux__ign;
3007+
struct bpf_prog_aux *aux = (struct bpf_prog_aux *)aux__prog;
30083008
struct bpf_async_kern *async = (struct bpf_async_kern *)wq;
30093009

30103010
if (flags)

kernel/bpf/verifier.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ struct bpf_kfunc_call_arg_meta {
322322
struct btf *arg_btf;
323323
u32 arg_btf_id;
324324
bool arg_owning_ref;
325+
bool arg_prog;
325326

326327
struct {
327328
struct btf_field *field;
@@ -11897,6 +11898,11 @@ static bool is_kfunc_arg_irq_flag(const struct btf *btf, const struct btf_param
1189711898
return btf_param_match_suffix(btf, arg, "__irq_flag");
1189811899
}
1189911900

11901+
static bool is_kfunc_arg_prog(const struct btf *btf, const struct btf_param *arg)
11902+
{
11903+
return btf_param_match_suffix(btf, arg, "__prog");
11904+
}
11905+
1190011906
static bool is_kfunc_arg_scalar_with_name(const struct btf *btf,
1190111907
const struct btf_param *arg,
1190211908
const char *name)
@@ -12938,6 +12944,17 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
1293812944
if (is_kfunc_arg_ignore(btf, &args[i]))
1293912945
continue;
1294012946

12947+
if (is_kfunc_arg_prog(btf, &args[i])) {
12948+
/* Used to reject repeated use of __prog. */
12949+
if (meta->arg_prog) {
12950+
verbose(env, "Only 1 prog->aux argument supported per-kfunc\n");
12951+
return -EFAULT;
12952+
}
12953+
meta->arg_prog = true;
12954+
cur_aux(env)->arg_prog = regno;
12955+
continue;
12956+
}
12957+
1294112958
if (btf_type_is_scalar(t)) {
1294212959
if (reg->type != SCALAR_VALUE) {
1294312960
verbose(env, "R%d is not a scalar\n", regno);
@@ -21517,13 +21534,17 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
2151721534
desc->func_id == special_kfunc_list[KF_bpf_rdonly_cast]) {
2151821535
insn_buf[0] = BPF_MOV64_REG(BPF_REG_0, BPF_REG_1);
2151921536
*cnt = 1;
21520-
} else if (is_bpf_wq_set_callback_impl_kfunc(desc->func_id)) {
21521-
struct bpf_insn ld_addrs[2] = { BPF_LD_IMM64(BPF_REG_4, (long)env->prog->aux) };
21537+
}
2152221538

21523-
insn_buf[0] = ld_addrs[0];
21524-
insn_buf[1] = ld_addrs[1];
21525-
insn_buf[2] = *insn;
21526-
*cnt = 3;
21539+
if (env->insn_aux_data[insn_idx].arg_prog) {
21540+
u32 regno = env->insn_aux_data[insn_idx].arg_prog;
21541+
struct bpf_insn ld_addrs[2] = { BPF_LD_IMM64(regno, (long)env->prog->aux) };
21542+
int idx = *cnt;
21543+
21544+
insn_buf[idx++] = ld_addrs[0];
21545+
insn_buf[idx++] = ld_addrs[1];
21546+
insn_buf[idx++] = *insn;
21547+
*cnt = idx;
2152721548
}
2152821549
return 0;
2152921550
}

0 commit comments

Comments
 (0)