Commit 7ed9138a authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

perf: Ensure bpf_perf_link path is properly serialized



Ravi reported that the bpf_perf_link_attach() usage of
perf_event_set_bpf_prog() is not serialized by ctx->mutex, unlike the
PERF_EVENT_IOC_SET_BPF case.

Reported-by: default avatarRavi Bangoria <ravi.bangoria@amd.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarRavi Bangoria <ravi.bangoria@amd.com>
Link: https://lkml.kernel.org/r/20250307193305.486326750@infradead.org
parent 5dcba489
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -6239,6 +6239,9 @@ static int perf_event_set_output(struct perf_event *event,
static int perf_event_set_filter(struct perf_event *event, void __user *arg);
static int perf_copy_attr(struct perf_event_attr __user *uattr,
			  struct perf_event_attr *attr);
static int __perf_event_set_bpf_prog(struct perf_event *event,
				     struct bpf_prog *prog,
				     u64 bpf_cookie);

static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg)
{
@@ -6301,7 +6304,7 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
		if (IS_ERR(prog))
			return PTR_ERR(prog);

		err = perf_event_set_bpf_prog(event, prog, 0);
		err = __perf_event_set_bpf_prog(event, prog, 0);
		if (err) {
			bpf_prog_put(prog);
			return err;
@@ -11069,7 +11072,8 @@ static inline bool perf_event_is_tracing(struct perf_event *event)
	return false;
}

int perf_event_set_bpf_prog(struct perf_event *event, struct bpf_prog *prog,
static int __perf_event_set_bpf_prog(struct perf_event *event,
				     struct bpf_prog *prog,
				     u64 bpf_cookie)
{
	bool is_kprobe, is_uprobe, is_tracepoint, is_syscall_tp;
@@ -11108,6 +11112,20 @@ int perf_event_set_bpf_prog(struct perf_event *event, struct bpf_prog *prog,
	return perf_event_attach_bpf_prog(event, prog, bpf_cookie);
}

int perf_event_set_bpf_prog(struct perf_event *event,
			    struct bpf_prog *prog,
			    u64 bpf_cookie)
{
	struct perf_event_context *ctx;
	int ret;

	ctx = perf_event_ctx_lock(event);
	ret = __perf_event_set_bpf_prog(event, prog, bpf_cookie);
	perf_event_ctx_unlock(event, ctx);

	return ret;
}

void perf_event_free_bpf_prog(struct perf_event *event)
{
	if (!event->prog)
@@ -11130,7 +11148,15 @@ static void perf_event_free_filter(struct perf_event *event)
{
}

int perf_event_set_bpf_prog(struct perf_event *event, struct bpf_prog *prog,
static int __perf_event_set_bpf_prog(struct perf_event *event,
				     struct bpf_prog *prog,
				     u64 bpf_cookie)
{
	return -ENOENT;
}

int perf_event_set_bpf_prog(struct perf_event *event,
			    struct bpf_prog *prog,
			    u64 bpf_cookie)
{
	return -ENOENT;