From: Florian Lehner <dev@der-flo.net>
To: bpf@vger.kernel.org
Cc: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com,
andrii@kernel.org, martin.lau@linux.dev, eddyz87@gmail.com,
memxor@gmail.com, song@kernel.org, yonghong.song@linux.dev,
jolsa@kernel.org, shuah@kernel.org, davem@davemloft.net,
kuba@kernel.org, hawk@kernel.org, sdf@fomichev.me,
sun.jian.kdev@gmail.com, Florian Lehner <dev@der-flo.net>
Subject: [PATCH bpf-next 1/2 v3] bpf: Add LINK_DETACH support for perf link
Date: Fri, 1 May 2026 18:09:00 +0200 [thread overview]
Message-ID: <20260501160901.224134-2-dev@der-flo.net> (raw)
In-Reply-To: <20260501160901.224134-1-dev@der-flo.net>
Implement the .detach operation for bpf_perf_link, allowing BPF_LINK_DETACH
to release the perf event without destroying the link object. This mirrors
the existing behavior for xdp and cgroup links.
Introduce bpf_perf_link_mutext to guard perf_file against concurrent access
from BPF_OBJ_GET_INFO_BY_FD and /proc fdinfo: the detach path NULLs out
perf_file under the lock, while fill_link_info and show_fdinfo take a
get_file() reference under the same lock before dereferencing it.
Signed-off-by: Florian Lehner <dev@der-flo.net>
---
kernel/bpf/syscall.c | 87 +++++++++++++++++++++++++++++++++++++-------
1 file changed, 73 insertions(+), 14 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 3b1f0ba02f61..efd759970e10 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -3880,13 +3880,35 @@ struct bpf_perf_link {
struct file *perf_file;
};
+/* Serializes bpf_perf_link_release() against bpf_perf_link_fill_link_info()
+ * and bpf_perf_link_show_fdinfo() to prevent a use-after-free on perf_file
+ * when BPF_LINK_DETACH races with BPF_OBJ_GET_INFO_BY_FD or /proc fdinfo.
+ */
+static DEFINE_MUTEX(bpf_perf_link_mutex);
+
static void bpf_perf_link_release(struct bpf_link *link)
{
struct bpf_perf_link *perf_link = container_of(link, struct bpf_perf_link, link);
- struct perf_event *event = perf_link->perf_file->private_data;
+ struct perf_event *event;
+ struct file *perf_file;
+
+ mutex_lock(&bpf_perf_link_mutex);
+ perf_file = perf_link->perf_file;
+ perf_link->perf_file = NULL;
+ mutex_unlock(&bpf_perf_link_mutex);
+ if (!perf_file)
+ return;
+
+ event = perf_file->private_data;
perf_event_free_bpf_prog(event);
- fput(perf_link->perf_file);
+ fput(perf_file);
+}
+
+static int bpf_perf_link_detach(struct bpf_link *link)
+{
+ bpf_perf_link_release(link);
+ return 0;
}
static void bpf_perf_link_dealloc(struct bpf_link *link)
@@ -4095,22 +4117,42 @@ static int bpf_perf_link_fill_link_info(const struct bpf_link *link,
{
struct bpf_perf_link *perf_link;
const struct perf_event *event;
+ struct file *perf_file;
+ int ret;
perf_link = container_of(link, struct bpf_perf_link, link);
- event = perf_get_event(perf_link->perf_file);
- if (IS_ERR(event))
+
+ mutex_lock(&bpf_perf_link_mutex);
+ perf_file = perf_link->perf_file;
+ if (perf_file)
+ get_file(perf_file);
+ mutex_unlock(&bpf_perf_link_mutex);
+
+ if (!perf_file)
+ return 0;
+
+ event = perf_get_event(perf_file);
+ if (IS_ERR(event)) {
+ fput(perf_file);
return PTR_ERR(event);
+ }
switch (event->prog->type) {
case BPF_PROG_TYPE_PERF_EVENT:
- return bpf_perf_link_fill_perf_event(event, info);
+ ret = bpf_perf_link_fill_perf_event(event, info);
+ break;
case BPF_PROG_TYPE_TRACEPOINT:
- return bpf_perf_link_fill_tracepoint(event, info);
+ ret = bpf_perf_link_fill_tracepoint(event, info);
+ break;
case BPF_PROG_TYPE_KPROBE:
- return bpf_perf_link_fill_probe(event, info);
+ ret = bpf_perf_link_fill_probe(event, info);
+ break;
default:
- return -EOPNOTSUPP;
+ ret = -EOPNOTSUPP;
}
+
+ fput(perf_file);
+ return ret;
}
static void bpf_perf_event_link_show_fdinfo(const struct perf_event *event,
@@ -4163,26 +4205,43 @@ static void bpf_perf_link_show_fdinfo(const struct bpf_link *link,
{
struct bpf_perf_link *perf_link;
const struct perf_event *event;
+ struct file *perf_file;
perf_link = container_of(link, struct bpf_perf_link, link);
- event = perf_get_event(perf_link->perf_file);
- if (IS_ERR(event))
+
+ mutex_lock(&bpf_perf_link_mutex);
+ perf_file = perf_link->perf_file;
+ if (perf_file)
+ get_file(perf_file);
+ mutex_unlock(&bpf_perf_link_mutex);
+
+ if (!perf_file)
return;
+ event = perf_get_event(perf_file);
+ if (IS_ERR(event))
+ goto out;
+
switch (event->prog->type) {
case BPF_PROG_TYPE_PERF_EVENT:
- return bpf_perf_event_link_show_fdinfo(event, seq);
+ bpf_perf_event_link_show_fdinfo(event, seq);
+ break;
case BPF_PROG_TYPE_TRACEPOINT:
- return bpf_tracepoint_link_show_fdinfo(event, seq);
+ bpf_tracepoint_link_show_fdinfo(event, seq);
+ break;
case BPF_PROG_TYPE_KPROBE:
- return bpf_probe_link_show_fdinfo(event, seq);
+ bpf_probe_link_show_fdinfo(event, seq);
+ break;
default:
- return;
+ break;
}
+out:
+ fput(perf_file);
}
static const struct bpf_link_ops bpf_perf_link_lops = {
.release = bpf_perf_link_release,
+ .detach = bpf_perf_link_detach,
.dealloc = bpf_perf_link_dealloc,
.fill_link_info = bpf_perf_link_fill_link_info,
.show_fdinfo = bpf_perf_link_show_fdinfo,
--
2.53.0
next prev parent reply other threads:[~2026-05-01 16:16 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 16:08 [PATCH bpf-next 0/2 v3] bpf: Add LINK_DETACH for perf links Florian Lehner
2026-05-01 16:09 ` Florian Lehner [this message]
2026-05-01 16:52 ` [PATCH bpf-next 1/2 v3] bpf: Add LINK_DETACH support for perf link bot+bpf-ci
2026-05-01 16:59 ` sashiko-bot
2026-05-01 16:09 ` [PATCH bpf-next 2/2 v3] selftests/bpf: Test LINK_DETACH " Florian Lehner
2026-05-01 17:11 ` sashiko-bot
2026-05-03 13:14 ` Jiri Olsa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260501160901.224134-2-dev@der-flo.net \
--to=dev@der-flo.net \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=eddyz87@gmail.com \
--cc=hawk@kernel.org \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kuba@kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=sdf@fomichev.me \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=sun.jian.kdev@gmail.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.