[PATCH bpf-next v2 4/9] bpf: trampoline: introduce bpf_tramp_multi_link

From: Menglong Dong
Date: Mon Mar 11 2024 - 05:36:30 EST


Introduce the struct bpf_tramp_multi_link, which is used to attach
a bpf_link to multi trampoline. Meanwhile, introduce corresponding
function bpf_trampoline_multi_{link,unlink}_prog.

Signed-off-by: Menglong Dong <dongmenglong.8@xxxxxxxxxxxxx>
---
include/linux/bpf.h | 14 ++++++++++++
kernel/bpf/trampoline.c | 47 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 2b5cd6100fc4..4e8f17d9f022 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -57,6 +57,7 @@ struct user_namespace;
struct super_block;
struct inode;
struct bpf_tramp_link;
+struct bpf_tramp_multi_link;

extern struct idr btf_idr;
extern spinlock_t btf_idr_lock;
@@ -1282,6 +1283,8 @@ struct bpf_trampoline *bpf_trampoline_get(u64 key,
struct bpf_attach_target_info *tgt_info);
void bpf_trampoline_put(struct bpf_trampoline *tr);
int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_funcs);
+int bpf_trampoline_multi_link_prog(struct bpf_tramp_multi_link *link);
+int bpf_trampoline_multi_unlink_prog(struct bpf_tramp_multi_link *link);

/*
* When the architecture supports STATIC_CALL replace the bpf_dispatcher_fn
@@ -1614,6 +1617,17 @@ struct bpf_shim_tramp_link {
struct bpf_trampoline *trampoline;
};

+struct bpf_tramp_multi_link_entry {
+ struct bpf_trampoline *trampoline;
+ struct bpf_tramp_link_conn conn;
+};
+
+struct bpf_tramp_multi_link {
+ struct bpf_link link;
+ u32 cnt;
+ struct bpf_tramp_multi_link_entry *entries;
+};
+
struct bpf_tracing_link {
struct bpf_tramp_link link;
enum bpf_attach_type attach_type;
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index cf9b84f785f3..2167aa3fe583 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -607,6 +607,53 @@ int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_trampolin
return err;
}

+static int __bpf_trampoline_multi_unlink_prog(struct bpf_tramp_multi_link *link,
+ u32 cnt)
+{
+ struct bpf_tramp_multi_link_entry *entry;
+ struct bpf_trampoline *tr;
+ int err = 0, i;
+
+ for (i = 0; i < cnt; i++) {
+ entry = &link->entries[i];
+ tr = entry->trampoline;
+ mutex_lock(&tr->mutex);
+ err = __bpf_trampoline_unlink_prog(&entry->conn,
+ entry->trampoline);
+ mutex_unlock(&tr->mutex);
+ if (err)
+ break;
+ }
+ return err;
+}
+
+int bpf_trampoline_multi_unlink_prog(struct bpf_tramp_multi_link *link)
+{
+ return __bpf_trampoline_multi_unlink_prog(link, link->cnt);
+}
+
+int bpf_trampoline_multi_link_prog(struct bpf_tramp_multi_link *link)
+{
+ struct bpf_tramp_multi_link_entry *entry;
+ struct bpf_trampoline *tr;
+ int err = 0, i;
+
+ for (i = 0; i < link->cnt; i++) {
+ entry = &link->entries[i];
+ tr = entry->trampoline;
+ mutex_lock(&tr->mutex);
+ err = __bpf_trampoline_link_prog(&entry->conn, tr);
+ mutex_unlock(&tr->mutex);
+ if (err)
+ goto unlink;
+ }
+
+ return 0;
+unlink:
+ __bpf_trampoline_multi_unlink_prog(link, i);
+ return err;
+}
+
#if defined(CONFIG_CGROUP_BPF) && defined(CONFIG_BPF_LSM)
static void bpf_shim_tramp_link_release(struct bpf_link *link)
{
--
2.39.2