bpf: add bpf_func_t and trampoline helpers

I'll be adding lsm cgroup specific helpers that grab
trampoline mutex.

No functional changes.

Reviewed-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/r/20220628174314.1216643-2-sdf@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Stanislav Fomichev 2022-06-28 10:43:04 -07:00 коммит произвёл Alexei Starovoitov
Родитель c5c7358e4c
Коммит af3f413400
2 изменённых файлов: 38 добавлений и 36 удалений

Просмотреть файл

@ -56,6 +56,8 @@ typedef u64 (*bpf_callback_t)(u64, u64, u64, u64, u64);
typedef int (*bpf_iter_init_seq_priv_t)(void *private_data, typedef int (*bpf_iter_init_seq_priv_t)(void *private_data,
struct bpf_iter_aux_info *aux); struct bpf_iter_aux_info *aux);
typedef void (*bpf_iter_fini_seq_priv_t)(void *private_data); typedef void (*bpf_iter_fini_seq_priv_t)(void *private_data);
typedef unsigned int (*bpf_func_t)(const void *,
const struct bpf_insn *);
struct bpf_iter_seq_info { struct bpf_iter_seq_info {
const struct seq_operations *seq_ops; const struct seq_operations *seq_ops;
bpf_iter_init_seq_priv_t init_seq_private; bpf_iter_init_seq_priv_t init_seq_private;
@ -879,8 +881,7 @@ struct bpf_dispatcher {
static __always_inline __nocfi unsigned int bpf_dispatcher_nop_func( static __always_inline __nocfi unsigned int bpf_dispatcher_nop_func(
const void *ctx, const void *ctx,
const struct bpf_insn *insnsi, const struct bpf_insn *insnsi,
unsigned int (*bpf_func)(const void *, bpf_func_t bpf_func)
const struct bpf_insn *))
{ {
return bpf_func(ctx, insnsi); return bpf_func(ctx, insnsi);
} }
@ -909,8 +910,7 @@ int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs);
noinline __nocfi unsigned int bpf_dispatcher_##name##_func( \ noinline __nocfi unsigned int bpf_dispatcher_##name##_func( \
const void *ctx, \ const void *ctx, \
const struct bpf_insn *insnsi, \ const struct bpf_insn *insnsi, \
unsigned int (*bpf_func)(const void *, \ bpf_func_t bpf_func) \
const struct bpf_insn *)) \
{ \ { \
return bpf_func(ctx, insnsi); \ return bpf_func(ctx, insnsi); \
} \ } \
@ -921,8 +921,7 @@ int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs);
unsigned int bpf_dispatcher_##name##_func( \ unsigned int bpf_dispatcher_##name##_func( \
const void *ctx, \ const void *ctx, \
const struct bpf_insn *insnsi, \ const struct bpf_insn *insnsi, \
unsigned int (*bpf_func)(const void *, \ bpf_func_t bpf_func); \
const struct bpf_insn *)); \
extern struct bpf_dispatcher bpf_dispatcher_##name; extern struct bpf_dispatcher bpf_dispatcher_##name;
#define BPF_DISPATCHER_FUNC(name) bpf_dispatcher_##name##_func #define BPF_DISPATCHER_FUNC(name) bpf_dispatcher_##name##_func
#define BPF_DISPATCHER_PTR(name) (&bpf_dispatcher_##name) #define BPF_DISPATCHER_PTR(name) (&bpf_dispatcher_##name)

Просмотреть файл

@ -410,7 +410,7 @@ static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(struct bpf_prog *prog)
} }
} }
int bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr) static int __bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr)
{ {
enum bpf_tramp_prog_type kind; enum bpf_tramp_prog_type kind;
struct bpf_tramp_link *link_exiting; struct bpf_tramp_link *link_exiting;
@ -418,44 +418,33 @@ int bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_trampoline
int cnt = 0, i; int cnt = 0, i;
kind = bpf_attach_type_to_tramp(link->link.prog); kind = bpf_attach_type_to_tramp(link->link.prog);
mutex_lock(&tr->mutex); if (tr->extension_prog)
if (tr->extension_prog) {
/* cannot attach fentry/fexit if extension prog is attached. /* cannot attach fentry/fexit if extension prog is attached.
* cannot overwrite extension prog either. * cannot overwrite extension prog either.
*/ */
err = -EBUSY; return -EBUSY;
goto out;
}
for (i = 0; i < BPF_TRAMP_MAX; i++) for (i = 0; i < BPF_TRAMP_MAX; i++)
cnt += tr->progs_cnt[i]; cnt += tr->progs_cnt[i];
if (kind == BPF_TRAMP_REPLACE) { if (kind == BPF_TRAMP_REPLACE) {
/* Cannot attach extension if fentry/fexit are in use. */ /* Cannot attach extension if fentry/fexit are in use. */
if (cnt) { if (cnt)
err = -EBUSY; return -EBUSY;
goto out;
}
tr->extension_prog = link->link.prog; tr->extension_prog = link->link.prog;
err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP, NULL, return bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP, NULL,
link->link.prog->bpf_func); link->link.prog->bpf_func);
goto out;
} }
if (cnt >= BPF_MAX_TRAMP_LINKS) { if (cnt >= BPF_MAX_TRAMP_LINKS)
err = -E2BIG; return -E2BIG;
goto out; if (!hlist_unhashed(&link->tramp_hlist))
}
if (!hlist_unhashed(&link->tramp_hlist)) {
/* prog already linked */ /* prog already linked */
err = -EBUSY; return -EBUSY;
goto out;
}
hlist_for_each_entry(link_exiting, &tr->progs_hlist[kind], tramp_hlist) { hlist_for_each_entry(link_exiting, &tr->progs_hlist[kind], tramp_hlist) {
if (link_exiting->link.prog != link->link.prog) if (link_exiting->link.prog != link->link.prog)
continue; continue;
/* prog already linked */ /* prog already linked */
err = -EBUSY; return -EBUSY;
goto out;
} }
hlist_add_head(&link->tramp_hlist, &tr->progs_hlist[kind]); hlist_add_head(&link->tramp_hlist, &tr->progs_hlist[kind]);
@ -465,30 +454,44 @@ int bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_trampoline
hlist_del_init(&link->tramp_hlist); hlist_del_init(&link->tramp_hlist);
tr->progs_cnt[kind]--; tr->progs_cnt[kind]--;
} }
out: return err;
}
int bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr)
{
int err;
mutex_lock(&tr->mutex);
err = __bpf_trampoline_link_prog(link, tr);
mutex_unlock(&tr->mutex); mutex_unlock(&tr->mutex);
return err; return err;
} }
/* bpf_trampoline_unlink_prog() should never fail. */ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr)
int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr)
{ {
enum bpf_tramp_prog_type kind; enum bpf_tramp_prog_type kind;
int err; int err;
kind = bpf_attach_type_to_tramp(link->link.prog); kind = bpf_attach_type_to_tramp(link->link.prog);
mutex_lock(&tr->mutex);
if (kind == BPF_TRAMP_REPLACE) { if (kind == BPF_TRAMP_REPLACE) {
WARN_ON_ONCE(!tr->extension_prog); WARN_ON_ONCE(!tr->extension_prog);
err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP, err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP,
tr->extension_prog->bpf_func, NULL); tr->extension_prog->bpf_func, NULL);
tr->extension_prog = NULL; tr->extension_prog = NULL;
goto out; return err;
} }
hlist_del_init(&link->tramp_hlist); hlist_del_init(&link->tramp_hlist);
tr->progs_cnt[kind]--; tr->progs_cnt[kind]--;
err = bpf_trampoline_update(tr); return bpf_trampoline_update(tr);
out: }
/* bpf_trampoline_unlink_prog() should never fail. */
int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr)
{
int err;
mutex_lock(&tr->mutex);
err = __bpf_trampoline_unlink_prog(link, tr);
mutex_unlock(&tr->mutex); mutex_unlock(&tr->mutex);
return err; return err;
} }