From: Marco Elver <elver@google.com>
To: elver@google.com, Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Jiri Olsa <jolsa@kernel.org>, Namhyung Kim <namhyung@kernel.org>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
kasan-dev@googlegroups.com, Dmitry Vyukov <dvyukov@google.com>,
Jann Horn <jannh@google.com>,
Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH] perf: Allow restricted kernel breakpoints on user addresses
Date: Fri, 2 Sep 2022 12:00:57 +0200 [thread overview]
Message-ID: <20220902100057.404817-1-elver@google.com> (raw)
Allow the creation of restricted breakpoint perf events that also fire
in the kernel (!exclude_kernel), if:
1. No sample information is requested; samples may contain IPs,
registers, or other information that may disclose kernel addresses.
2. The breakpoint (viz. data watchpoint) is on a user address.
The rules constrain the allowable perf events such that no sensitive
kernel information can be disclosed.
Despite no explicit kernel information disclosure, the following
questions may need answers:
1. Is obtaining information that the kernel accessed a particular
user's known memory location revealing new information?
Given the kernel's user space ABI, there should be no "surprise
accesses" to user space memory in the first place.
2. Does causing breakpoints on user memory accesses by the kernel
potentially impact timing in a sensitive way?
Since hardware breakpoints trigger regardless of the state of
perf_event_attr::exclude_kernel, but are filtered in the perf
subsystem, this possibility already exists independent of the
proposed change.
Signed-off-by: Marco Elver <elver@google.com>
---
Changelog
~~~~~~~~~
v1:
* Rebase.
RFC: https://lkml.kernel.org/r/20220601093502.364142-1-elver@google.com
---
include/linux/perf_event.h | 8 +-------
kernel/events/core.c | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index a784e055002e..907b0e3f1318 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1367,13 +1367,7 @@ static inline int perf_is_paranoid(void)
return sysctl_perf_event_paranoid > -1;
}
-static inline int perf_allow_kernel(struct perf_event_attr *attr)
-{
- if (sysctl_perf_event_paranoid > 1 && !perfmon_capable())
- return -EACCES;
-
- return security_perf_event_open(attr, PERF_SECURITY_KERNEL);
-}
+extern int perf_allow_kernel(struct perf_event_attr *attr);
static inline int perf_allow_cpu(struct perf_event_attr *attr)
{
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2621fd24ad26..75f5705b6892 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3176,6 +3176,12 @@ static int perf_event_modify_attr(struct perf_event *event,
return -EOPNOTSUPP;
}
+ if (!event->attr.exclude_kernel) {
+ err = perf_allow_kernel(attr);
+ if (err)
+ return err;
+ }
+
WARN_ON_ONCE(event->ctx->parent_ctx);
mutex_lock(&event->child_mutex);
@@ -12037,6 +12043,38 @@ perf_check_permission(struct perf_event_attr *attr, struct task_struct *task)
return is_capable || ptrace_may_access(task, ptrace_mode);
}
+/*
+ * Check if unprivileged users are allowed to set up breakpoints on user
+ * addresses that also count when the kernel accesses them.
+ */
+static bool perf_allow_kernel_breakpoint(struct perf_event_attr *attr)
+{
+ if (attr->type != PERF_TYPE_BREAKPOINT)
+ return false;
+
+ /*
+ * The sample may contain IPs, registers, or other information that may
+ * disclose kernel addresses or timing information. Disallow any kind of
+ * additional sample information.
+ */
+ if (attr->sample_type)
+ return false;
+
+ /*
+ * Only allow kernel breakpoints on user addresses.
+ */
+ return access_ok((void __user *)(unsigned long)attr->bp_addr, attr->bp_len);
+}
+
+int perf_allow_kernel(struct perf_event_attr *attr)
+{
+ if (sysctl_perf_event_paranoid > 1 && !perfmon_capable() &&
+ !perf_allow_kernel_breakpoint(attr))
+ return -EACCES;
+
+ return security_perf_event_open(attr, PERF_SECURITY_KERNEL);
+}
+
/**
* sys_perf_event_open - open a performance event, associate it to a task/cpu
*
--
2.37.2.789.g6183377224-goog
next reply other threads:[~2022-09-02 10:01 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-02 10:00 Marco Elver [this message]
2022-09-05 15:53 ` [PATCH] perf: Allow restricted kernel breakpoints on user addresses Dmitry Vyukov
2022-09-06 20:38 ` Peter Zijlstra
2022-09-07 7:40 ` Marco Elver
2022-09-07 12:39 ` Peter Zijlstra
2022-09-08 7:58 ` Marco Elver
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=20220902100057.404817-1-elver@google.com \
--to=elver@google.com \
--cc=acme@kernel.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=dvyukov@google.com \
--cc=jannh@google.com \
--cc=jolsa@kernel.org \
--cc=kasan-dev@googlegroups.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox