Changes in v3:
- mention "CAP_PERFMON or CAP_SYS_ADMIN" instead of sole CAP_PERFMON or
CAP_SYS_ADMIN capability in the docs and messages to support use case
of newer Perf tool on kernel w/o CAP_PERFMON
- reverted double new line in "No permission to enable %s event.\n\n"
- updated security.txt content with new messages wording
v2: https://lore.kernel.org/lkml/[email protected]/
Changes in v2:
- implemented minor doc and code changes to substitute CAP_SYS_ADMIN
with CAP_PERFMON capability;
- introduced Perf doc file with instructions on how to enable and use
perf_event LSM hooks for mandatory access control to perf_event_open()
syscall;
v1: https://lore.kernel.org/lkml/[email protected]/
repo: git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git perf/core
sha1: ee097e8ee56f8867cbbf45fe2a06f6b9e660c39c
Extend Perf tool with the check of /sys/fs/selinux/enforce value and notify
in case access to perf_event_open() syscall is restricted by the enforced
SELinux policy settings. See new added security.txt file for exact steps
how the changes look like and how to test the patch set.
---
Alexey Budankov (3):
perf docs: extend CAP_SYS_ADMIN with CAP_PERFMON where needed
perf tool: make Perf tool aware of SELinux access control
perf docs: introduce security.txt file to document related issues
tools/perf/Documentation/perf-intel-pt.txt | 2 +-
tools/perf/Documentation/security.txt | 237 +++++++++++++++++++++
tools/perf/util/cloexec.c | 4 +-
tools/perf/util/evsel.c | 39 ++--
4 files changed, 264 insertions(+), 18 deletions(-)
create mode 100644 tools/perf/Documentation/security.txt
--
2.24.1
Extend CAP_SYS_ADMIN with CAP_PERFMON in the docs.
Signed-off-by: Alexey Budankov <[email protected]>
---
tools/perf/Documentation/perf-intel-pt.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/Documentation/perf-intel-pt.txt b/tools/perf/Documentation/perf-intel-pt.txt
index 456fdcbf26ac..832408a54c1c 100644
--- a/tools/perf/Documentation/perf-intel-pt.txt
+++ b/tools/perf/Documentation/perf-intel-pt.txt
@@ -687,7 +687,7 @@ The v4.2 kernel introduced support for a context switch metadata event,
PERF_RECORD_SWITCH, which allows unprivileged users to see when their processes
are scheduled out and in, just not by whom, which is left for the
PERF_RECORD_SWITCH_CPU_WIDE, that is only accessible in system wide context,
-which in turn requires CAP_SYS_ADMIN.
+which in turn requires CAP_PERFMON or CAP_SYS_ADMIN.
Please see the 45ac1403f564 ("perf: Add PERF_RECORD_SWITCH to indicate context
switches") commit, that introduces these metadata events for further info.
--
2.24.1
Implement selinux sysfs check to see the system is in enforcing
mode and print warning message with pointer to check audit logs.
Signed-off-by: Alexey Budankov <[email protected]>
---
tools/perf/util/cloexec.c | 4 ++--
tools/perf/util/evsel.c | 39 ++++++++++++++++++++++++---------------
2 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index a12872f2856a..9c8ec816261b 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -65,7 +65,7 @@ static int perf_flag_probe(void)
return 1;
}
- WARN_ONCE(err != EINVAL && err != EBUSY,
+ WARN_ONCE(err != EINVAL && err != EBUSY && err != EACCES,
"perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
err, str_error_r(err, sbuf, sizeof(sbuf)));
@@ -83,7 +83,7 @@ static int perf_flag_probe(void)
if (fd >= 0)
close(fd);
- if (WARN_ONCE(fd < 0 && err != EBUSY,
+ if (WARN_ONCE(fd < 0 && err != EBUSY && err != EACCES,
"perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
err, str_error_r(err, sbuf, sizeof(sbuf))))
return -1;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9fa92649adb4..bf437c059c2b 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2514,32 +2514,41 @@ int perf_evsel__open_strerror(struct evsel *evsel, struct target *target,
int err, char *msg, size_t size)
{
char sbuf[STRERR_BUFSIZE];
- int printed = 0;
+ int printed = 0, enforced = 0;
switch (err) {
case EPERM:
case EACCES:
+ printed += scnprintf(msg + printed, size - printed,
+ "Access to performance monitoring and observability operations is limited.\n");
+
+ if (!sysfs__read_int("fs/selinux/enforce", &enforced)) {
+ if (enforced) {
+ printed += scnprintf(msg + printed, size - printed,
+ "Enforced MAC policy settings (SELinux) can limit access to performance\n"
+ "monitoring and observability operations. Inspect system audit records for\n"
+ "more perf_event access control information and adjusting the policy.\n");
+ }
+ }
+
if (err == EPERM)
- printed = scnprintf(msg, size,
+ printed += scnprintf(msg, size,
"No permission to enable %s event.\n\n",
perf_evsel__name(evsel));
return scnprintf(msg + printed, size - printed,
- "You may not have permission to collect %sstats.\n\n"
- "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n"
- "which controls use of the performance events system by\n"
- "unprivileged users (without CAP_PERFMON or CAP_SYS_ADMIN).\n\n"
- "The current value is %d:\n\n"
+ "Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open\n"
+ "access to performance monitoring and observability operations for users\n"
+ "without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.\n"
+ "perf_event_paranoid setting is %d:\n"
" -1: Allow use of (almost) all events by all users\n"
" Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK\n"
- ">= 0: Disallow ftrace function tracepoint by users without CAP_PERFMON or CAP_SYS_ADMIN\n"
- " Disallow raw tracepoint access by users without CAP_SYS_PERFMON or CAP_SYS_ADMIN\n"
- ">= 1: Disallow CPU event access by users without CAP_PERFMON or CAP_SYS_ADMIN\n"
- ">= 2: Disallow kernel profiling by users without CAP_PERFMON or CAP_SYS_ADMIN\n\n"
- "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n"
- " kernel.perf_event_paranoid = -1\n" ,
- target->system_wide ? "system-wide " : "",
- perf_event_paranoid());
+ ">= 0: Disallow raw and ftrace function tracepoint access\n"
+ ">= 1: Disallow CPU event access\n"
+ ">= 2: Disallow kernel profiling\n"
+ "To make the adjusted perf_event_paranoid setting permanent preserve it\n"
+ "in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)",
+ perf_event_paranoid());
case ENOENT:
return scnprintf(msg, size, "The %s event is not supported.",
perf_evsel__name(evsel));
--
2.24.1
Publish instructions on how to apply LSM hooks for access control
to perf_event_open() syscall on Fedora distro with Targeted SELinux
policy and then manage access to the syscall.
Signed-off-by: Alexey Budankov <[email protected]>
---
tools/perf/Documentation/security.txt | 237 ++++++++++++++++++++++++++
1 file changed, 237 insertions(+)
create mode 100644 tools/perf/Documentation/security.txt
diff --git a/tools/perf/Documentation/security.txt b/tools/perf/Documentation/security.txt
new file mode 100644
index 000000000000..4fe3b8b1958f
--- /dev/null
+++ b/tools/perf/Documentation/security.txt
@@ -0,0 +1,237 @@
+Overview
+========
+
+For general security related questions of perf_event_open() syscall usage,
+performance monitoring and observability operations by Perf see here:
+https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html
+
+Enabling LSM based mandatory access control (MAC) to perf_event_open() syscall
+==============================================================================
+
+LSM hooks for mandatory access control for perf_event_open() syscall can be
+used starting from Linux v5.3. Below are the steps to extend Fedora (v31) with
+Targeted policy with perf_event_open() access control capabilities:
+
+1. Download selinux-policy SRPM package (e.g. selinux-policy-3.14.4-48.fc31.src.rpm on FC31)
+ and install it so rpmbuild directory would exist in the current working directory:
+
+ # rpm -Uhv selinux-policy-3.14.4-48.fc31.src.rpm
+
+2. Get into rpmbuild/SPECS directory and unpack the source code:
+
+ # rpmbuild -bp selinux-policy.spec
+
+3. Place patch below at rpmbuild/BUILD/selinux-policy-b86eaaf4dbcf2d51dd4432df7185c0eaf3cbcc02
+ directory and apply it:
+
+ # patch -p1 < selinux-policy-perf-events-perfmon.patch
+ patching file policy/flask/access_vectors
+ patching file policy/flask/security_classes
+ # cat selinux-policy-perf-events-perfmon.patch
+diff -Nura a/policy/flask/access_vectors b/policy/flask/access_vectors
+--- a/policy/flask/access_vectors 2020-02-04 18:19:53.000000000 +0300
++++ b/policy/flask/access_vectors 2020-02-28 23:37:25.000000000 +0300
+@@ -174,6 +174,7 @@
+ wake_alarm
+ block_suspend
+ audit_read
++ perfmon
+ }
+
+ #
+@@ -1099,3 +1100,15 @@
+
+ class xdp_socket
+ inherits socket
++
++class perf_event
++{
++ open
++ cpu
++ kernel
++ tracepoint
++ read
++ write
++}
++
++
+diff -Nura a/policy/flask/security_classes b/policy/flask/security_classes
+--- a/policy/flask/security_classes 2020-02-04 18:19:53.000000000 +0300
++++ b/policy/flask/security_classes 2020-02-28 21:35:17.000000000 +0300
+@@ -200,4 +200,6 @@
+
+ class xdp_socket
+
++class perf_event
++
+ # FLASK
+
+4. Get into rpmbuild/SPECS directory and build policy packages from patched sources:
+
+ # rpmbuild --noclean --noprep -ba selinux-policy.spec
+
+ so you have this:
+
+ # ls -alh rpmbuild/RPMS/noarch/
+ total 33M
+ drwxr-xr-x. 2 root root 4.0K Mar 20 12:16 .
+ drwxr-xr-x. 3 root root 4.0K Mar 20 12:16 ..
+ -rw-r--r--. 1 root root 112K Mar 20 12:16 selinux-policy-3.14.4-48.fc31.noarch.rpm
+ -rw-r--r--. 1 root root 1.2M Mar 20 12:17 selinux-policy-devel-3.14.4-48.fc31.noarch.rpm
+ -rw-r--r--. 1 root root 2.3M Mar 20 12:17 selinux-policy-doc-3.14.4-48.fc31.noarch.rpm
+ -rw-r--r--. 1 root root 12M Mar 20 12:17 selinux-policy-minimum-3.14.4-48.fc31.noarch.rpm
+ -rw-r--r--. 1 root root 4.5M Mar 20 12:16 selinux-policy-mls-3.14.4-48.fc31.noarch.rpm
+ -rw-r--r--. 1 root root 111K Mar 20 12:16 selinux-policy-sandbox-3.14.4-48.fc31.noarch.rpm
+ -rw-r--r--. 1 root root 14M Mar 20 12:17 selinux-policy-targeted-3.14.4-48.fc31.noarch.rpm
+
+5. Install SELinux packages from Fedora repo, if not already done so, and
+ update with the patched rpms above:
+
+ # rpm -Uhv rpmbuild/RPMS/noarch/selinux-policy-*
+
+6. Enable SELinux Permissive mode for Targeted policy, if not already done so:
+
+ # cat /etc/selinux/config
+
+ # This file controls the state of SELinux on the system.
+ # SELINUX= can take one of these three values:
+ # enforcing - SELinux security policy is enforced.
+ # permissive - SELinux prints warnings instead of enforcing.
+ # disabled - No SELinux policy is loaded.
+ SELINUX=permissive
+ # SELINUXTYPE= can take one of these three values:
+ # targeted - Targeted processes are protected,
+ # minimum - Modification of targeted policy. Only selected processes are protected.
+ # mls - Multi Level Security protection.
+ SELINUXTYPE=targeted
+
+7. Enable filesystem SELinux labeling at the next reboot:
+
+ # touch /.autorelabel
+
+8. Reboot machine and it will label filesystems and load Targeted policy into the kernel;
+
+9. Login and check that dmesg output doesn't mention that perf_event class is unknown to SELinux subsystem;
+
+10. Check that SELinux is enabled and in Permissive mode
+
+ # getenforce
+ Permissive
+
+11. Turn SELinux into Enforcing mode:
+
+ # setenforce 1
+ # getenforce
+ Enforcing
+
+Opening access to perf_event_open() syscall on Fedora with SELinux
+==================================================================
+
+Access to performance monitoring and observability operations by Perf
+can be limited for superuser or CAP_PERFMON or CAP_SYS_ADMIN privileged
+processes. MAC policy settings (e.g. SELinux) can be loaded into the kernel
+and prevent unauthorized access to perf_event_open() syscall. In such case
+Perf tool provides a message similar to the one below:
+
+ # perf stat
+ Error:
+ Access to performance monitoring and observability operations is limited.
+ Enforced MAC policy settings (SELinux) can limit access to performance
+ monitoring and observability operations. Inspect system audit records for
+ more perf_event access control information and adjusting the policy.
+ Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open
+ access to performance monitoring and observability operations for users
+ without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.
+ perf_event_paranoid setting is -1:
+ -1: Allow use of (almost) all events by all users
+ Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
+ >= 0: Disallow raw and ftrace function tracepoint access
+ >= 1: Disallow CPU event access
+ >= 2: Disallow kernel profiling
+ To make the adjusted perf_event_paranoid setting permanent preserve it
+ in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)
+
+To make sure that access is limited by MAC policy settings inspect system
+audit records using journalctl command or /var/log/audit/audit.log so the
+output would contain AVC denied records related to perf_event:
+
+ # journalctl --reverse --no-pager | grep perf_event
+
+ python3[1318099]: SELinux is preventing perf from open access on the perf_event labeled unconfined_t.
+ If you believe that perf should be allowed open access on perf_event labeled unconfined_t by default.
+ setroubleshoot[1318099]: SELinux is preventing perf from open access on the perf_event labeled unconfined_t. For complete SELinux messages run: sealert -l 4595ce5b-e58f-462c-9d86-3bc2074935de
+ audit[1318098]: AVC avc: denied { open } for pid=1318098 comm="perf" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=perf_event permissive=0
+
+In order to open access to perf_event_open() syscall MAC policy settings can
+require to be extended. On SELinux system this can be done by loading a special
+policy module extending base policy settings. Perf related policy module can
+be generated using the system audit records about blocking perf_event access.
+Run the command below to generate my-perf.te policy extension file with
+perf_event related rules:
+
+ # ausearch -c 'perf' --raw | audit2allow -M my-perf && cat my-perf.te
+
+ module my-perf 1.0;
+
+ require {
+ type unconfined_t;
+ class perf_event { cpu kernel open read tracepoint write };
+ }
+
+ #============= unconfined_t ==============
+ allow unconfined_t self:perf_event { cpu kernel open read tracepoint write };
+
+Now compile, pack and load my-perf.pp extension module into the kernel:
+
+ # checkmodule -M -m -o my-perf.mod my-perf.te
+ # semodule_package -o my-perf.pp -m my-perf.mod
+ # semodule -X 300 -i my-perf.pp
+
+After all those taken steps above access to perf_event_open() syscall should
+now be allowed by the policy settings. Check access running Perf like this:
+
+ # perf stat
+ ^C
+ Performance counter stats for 'system wide':
+
+ 36,387.41 msec cpu-clock # 7.999 CPUs utilized
+ 2,629 context-switches # 0.072 K/sec
+ 57 cpu-migrations # 0.002 K/sec
+ 1 page-faults # 0.000 K/sec
+ 263,721,559 cycles # 0.007 GHz
+ 175,746,713 instructions # 0.67 insn per cycle
+ 19,628,798 branches # 0.539 M/sec
+ 1,259,201 branch-misses # 6.42% of all branches
+
+ 4.549061439 seconds time elapsed
+
+The generated perf-event.pp related policy extension module can be removed
+from the kernel using this command:
+
+ # semodule -X 300 -r my-perf
+
+Alternatively the module can be temporarily disabled and enabled back using
+these two commands:
+
+ # semodule -d my-perf
+ # semodule -e my-perf
+
+If something went wrong
+=======================
+
+To turn SELinux into Permissive mode:
+ # setenforce 0
+
+To fully disable SELinux during kernel boot [3] set kernel command line parameter selinux=0
+
+To remove SELinux labeling from local filesystems:
+ # find / -mount -print0 | xargs -0 setfattr -h -x security.selinux
+
+To fully turn SELinux off a machine set SELINUX=disabled at /etc/selinux/config file and reboot;
+
+Links
+=====
+
+[1] https://download-ib01.fedoraproject.org/pub/fedora/linux/updates/31/Everything/SRPMS/Packages/s/selinux-policy-3.14.4-49.fc31.src.rpm
+[2] https://docs.fedoraproject.org/en-US/Fedora/11/html/Security-Enhanced_Linux/sect-Security-Enhanced_Linux-Working_with_SELinux-Enabling_and_Disabling_SELinux.html
+[3] https://danwalsh.livejournal.com/10972.html
--
2.24.1
Hi,
Is there anything else that could be done from my side to move this forward?
Thanks,
Alexey
On 30.04.2020 10:06, Alexey Budankov wrote:
>
> Changes in v3:
> - mention "CAP_PERFMON or CAP_SYS_ADMIN" instead of sole CAP_PERFMON or
> CAP_SYS_ADMIN capability in the docs and messages to support use case
> of newer Perf tool on kernel w/o CAP_PERFMON
> - reverted double new line in "No permission to enable %s event.\n\n"
> - updated security.txt content with new messages wording
>
> v2: https://lore.kernel.org/lkml/[email protected]/
>
> Changes in v2:
> - implemented minor doc and code changes to substitute CAP_SYS_ADMIN
> with CAP_PERFMON capability;
> - introduced Perf doc file with instructions on how to enable and use
> perf_event LSM hooks for mandatory access control to perf_event_open()
> syscall;
>
> v1: https://lore.kernel.org/lkml/[email protected]/
>
> repo: git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git perf/core
> sha1: ee097e8ee56f8867cbbf45fe2a06f6b9e660c39c
>
>
> Extend Perf tool with the check of /sys/fs/selinux/enforce value and notify
> in case access to perf_event_open() syscall is restricted by the enforced
> SELinux policy settings. See new added security.txt file for exact steps
> how the changes look like and how to test the patch set.
>
> ---
> Alexey Budankov (3):
> perf docs: extend CAP_SYS_ADMIN with CAP_PERFMON where needed
> perf tool: make Perf tool aware of SELinux access control
> perf docs: introduce security.txt file to document related issues
>
> tools/perf/Documentation/perf-intel-pt.txt | 2 +-
> tools/perf/Documentation/security.txt | 237 +++++++++++++++++++++
> tools/perf/util/cloexec.c | 4 +-
> tools/perf/util/evsel.c | 39 ++--
> 4 files changed, 264 insertions(+), 18 deletions(-)
> create mode 100644 tools/perf/Documentation/security.txt
>
Em Thu, Apr 30, 2020 at 10:15:57AM +0300, Alexey Budankov escreveu:
>
> Implement selinux sysfs check to see the system is in enforcing
> mode and print warning message with pointer to check audit logs.
There were some changes in this area meanwhile, so I had to apply the
evsel.c by hand, when I push this please double check everything is ok,
- Arnaldo
> Signed-off-by: Alexey Budankov <[email protected]>
> ---
> tools/perf/util/cloexec.c | 4 ++--
> tools/perf/util/evsel.c | 39 ++++++++++++++++++++++++---------------
> 2 files changed, 26 insertions(+), 17 deletions(-)
>
> diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
> index a12872f2856a..9c8ec816261b 100644
> --- a/tools/perf/util/cloexec.c
> +++ b/tools/perf/util/cloexec.c
> @@ -65,7 +65,7 @@ static int perf_flag_probe(void)
> return 1;
> }
>
> - WARN_ONCE(err != EINVAL && err != EBUSY,
> + WARN_ONCE(err != EINVAL && err != EBUSY && err != EACCES,
> "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
> err, str_error_r(err, sbuf, sizeof(sbuf)));
>
> @@ -83,7 +83,7 @@ static int perf_flag_probe(void)
> if (fd >= 0)
> close(fd);
>
> - if (WARN_ONCE(fd < 0 && err != EBUSY,
> + if (WARN_ONCE(fd < 0 && err != EBUSY && err != EACCES,
> "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
> err, str_error_r(err, sbuf, sizeof(sbuf))))
> return -1;
> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index 9fa92649adb4..bf437c059c2b 100644
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c
> @@ -2514,32 +2514,41 @@ int perf_evsel__open_strerror(struct evsel *evsel, struct target *target,
> int err, char *msg, size_t size)
> {
> char sbuf[STRERR_BUFSIZE];
> - int printed = 0;
> + int printed = 0, enforced = 0;
>
> switch (err) {
> case EPERM:
> case EACCES:
> + printed += scnprintf(msg + printed, size - printed,
> + "Access to performance monitoring and observability operations is limited.\n");
> +
> + if (!sysfs__read_int("fs/selinux/enforce", &enforced)) {
> + if (enforced) {
> + printed += scnprintf(msg + printed, size - printed,
> + "Enforced MAC policy settings (SELinux) can limit access to performance\n"
> + "monitoring and observability operations. Inspect system audit records for\n"
> + "more perf_event access control information and adjusting the policy.\n");
> + }
> + }
> +
> if (err == EPERM)
> - printed = scnprintf(msg, size,
> + printed += scnprintf(msg, size,
> "No permission to enable %s event.\n\n",
> perf_evsel__name(evsel));
>
> return scnprintf(msg + printed, size - printed,
> - "You may not have permission to collect %sstats.\n\n"
> - "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n"
> - "which controls use of the performance events system by\n"
> - "unprivileged users (without CAP_PERFMON or CAP_SYS_ADMIN).\n\n"
> - "The current value is %d:\n\n"
> + "Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open\n"
> + "access to performance monitoring and observability operations for users\n"
> + "without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.\n"
> + "perf_event_paranoid setting is %d:\n"
> " -1: Allow use of (almost) all events by all users\n"
> " Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK\n"
> - ">= 0: Disallow ftrace function tracepoint by users without CAP_PERFMON or CAP_SYS_ADMIN\n"
> - " Disallow raw tracepoint access by users without CAP_SYS_PERFMON or CAP_SYS_ADMIN\n"
> - ">= 1: Disallow CPU event access by users without CAP_PERFMON or CAP_SYS_ADMIN\n"
> - ">= 2: Disallow kernel profiling by users without CAP_PERFMON or CAP_SYS_ADMIN\n\n"
> - "To make this setting permanent, edit /etc/sysctl.conf too, e.g.:\n\n"
> - " kernel.perf_event_paranoid = -1\n" ,
> - target->system_wide ? "system-wide " : "",
> - perf_event_paranoid());
> + ">= 0: Disallow raw and ftrace function tracepoint access\n"
> + ">= 1: Disallow CPU event access\n"
> + ">= 2: Disallow kernel profiling\n"
> + "To make the adjusted perf_event_paranoid setting permanent preserve it\n"
> + "in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)",
> + perf_event_paranoid());
> case ENOENT:
> return scnprintf(msg, size, "The %s event is not supported.",
> perf_evsel__name(evsel));
> --
> 2.24.1
>
>
--
- Arnaldo
Em Thu, Apr 30, 2020 at 10:16:34AM +0300, Alexey Budankov escreveu:
>
> Publish instructions on how to apply LSM hooks for access control
> to perf_event_open() syscall on Fedora distro with Targeted SELinux
> policy and then manage access to the syscall.
I'm fixing these up:
[acme@five perf]$ am /wb/1.patch
Applying: perf docs: introduce security.txt file to document related issues
.git/rebase-apply/patch:46: space before tab in indent.
wake_alarm
.git/rebase-apply/patch:47: space before tab in indent.
block_suspend
.git/rebase-apply/patch:48: space before tab in indent.
audit_read
.git/rebase-apply/patch:51: trailing whitespace.
.git/rebase-apply/patch:54: trailing whitespace.
> Signed-off-by: Alexey Budankov <[email protected]>
> ---
> tools/perf/Documentation/security.txt | 237 ++++++++++++++++++++++++++
> 1 file changed, 237 insertions(+)
> create mode 100644 tools/perf/Documentation/security.txt
>
> diff --git a/tools/perf/Documentation/security.txt b/tools/perf/Documentation/security.txt
> new file mode 100644
> index 000000000000..4fe3b8b1958f
> --- /dev/null
> +++ b/tools/perf/Documentation/security.txt
> @@ -0,0 +1,237 @@
> +Overview
> +========
> +
> +For general security related questions of perf_event_open() syscall usage,
> +performance monitoring and observability operations by Perf see here:
> +https://www.kernel.org/doc/html/latest/admin-guide/perf-security.html
> +
> +Enabling LSM based mandatory access control (MAC) to perf_event_open() syscall
> +==============================================================================
> +
> +LSM hooks for mandatory access control for perf_event_open() syscall can be
> +used starting from Linux v5.3. Below are the steps to extend Fedora (v31) with
> +Targeted policy with perf_event_open() access control capabilities:
> +
> +1. Download selinux-policy SRPM package (e.g. selinux-policy-3.14.4-48.fc31.src.rpm on FC31)
> + and install it so rpmbuild directory would exist in the current working directory:
> +
> + # rpm -Uhv selinux-policy-3.14.4-48.fc31.src.rpm
> +
> +2. Get into rpmbuild/SPECS directory and unpack the source code:
> +
> + # rpmbuild -bp selinux-policy.spec
> +
> +3. Place patch below at rpmbuild/BUILD/selinux-policy-b86eaaf4dbcf2d51dd4432df7185c0eaf3cbcc02
> + directory and apply it:
> +
> + # patch -p1 < selinux-policy-perf-events-perfmon.patch
> + patching file policy/flask/access_vectors
> + patching file policy/flask/security_classes
> + # cat selinux-policy-perf-events-perfmon.patch
> +diff -Nura a/policy/flask/access_vectors b/policy/flask/access_vectors
> +--- a/policy/flask/access_vectors 2020-02-04 18:19:53.000000000 +0300
> ++++ b/policy/flask/access_vectors 2020-02-28 23:37:25.000000000 +0300
> +@@ -174,6 +174,7 @@
> + wake_alarm
> + block_suspend
> + audit_read
> ++ perfmon
> + }
> +
> + #
> +@@ -1099,3 +1100,15 @@
> +
> + class xdp_socket
> + inherits socket
> ++
> ++class perf_event
> ++{
> ++ open
> ++ cpu
> ++ kernel
> ++ tracepoint
> ++ read
> ++ write
> ++}
> ++
> ++
> +diff -Nura a/policy/flask/security_classes b/policy/flask/security_classes
> +--- a/policy/flask/security_classes 2020-02-04 18:19:53.000000000 +0300
> ++++ b/policy/flask/security_classes 2020-02-28 21:35:17.000000000 +0300
> +@@ -200,4 +200,6 @@
> +
> + class xdp_socket
> +
> ++class perf_event
> ++
> + # FLASK
> +
> +4. Get into rpmbuild/SPECS directory and build policy packages from patched sources:
> +
> + # rpmbuild --noclean --noprep -ba selinux-policy.spec
> +
> + so you have this:
> +
> + # ls -alh rpmbuild/RPMS/noarch/
> + total 33M
> + drwxr-xr-x. 2 root root 4.0K Mar 20 12:16 .
> + drwxr-xr-x. 3 root root 4.0K Mar 20 12:16 ..
> + -rw-r--r--. 1 root root 112K Mar 20 12:16 selinux-policy-3.14.4-48.fc31.noarch.rpm
> + -rw-r--r--. 1 root root 1.2M Mar 20 12:17 selinux-policy-devel-3.14.4-48.fc31.noarch.rpm
> + -rw-r--r--. 1 root root 2.3M Mar 20 12:17 selinux-policy-doc-3.14.4-48.fc31.noarch.rpm
> + -rw-r--r--. 1 root root 12M Mar 20 12:17 selinux-policy-minimum-3.14.4-48.fc31.noarch.rpm
> + -rw-r--r--. 1 root root 4.5M Mar 20 12:16 selinux-policy-mls-3.14.4-48.fc31.noarch.rpm
> + -rw-r--r--. 1 root root 111K Mar 20 12:16 selinux-policy-sandbox-3.14.4-48.fc31.noarch.rpm
> + -rw-r--r--. 1 root root 14M Mar 20 12:17 selinux-policy-targeted-3.14.4-48.fc31.noarch.rpm
> +
> +5. Install SELinux packages from Fedora repo, if not already done so, and
> + update with the patched rpms above:
> +
> + # rpm -Uhv rpmbuild/RPMS/noarch/selinux-policy-*
> +
> +6. Enable SELinux Permissive mode for Targeted policy, if not already done so:
> +
> + # cat /etc/selinux/config
> +
> + # This file controls the state of SELinux on the system.
> + # SELINUX= can take one of these three values:
> + # enforcing - SELinux security policy is enforced.
> + # permissive - SELinux prints warnings instead of enforcing.
> + # disabled - No SELinux policy is loaded.
> + SELINUX=permissive
> + # SELINUXTYPE= can take one of these three values:
> + # targeted - Targeted processes are protected,
> + # minimum - Modification of targeted policy. Only selected processes are protected.
> + # mls - Multi Level Security protection.
> + SELINUXTYPE=targeted
> +
> +7. Enable filesystem SELinux labeling at the next reboot:
> +
> + # touch /.autorelabel
> +
> +8. Reboot machine and it will label filesystems and load Targeted policy into the kernel;
> +
> +9. Login and check that dmesg output doesn't mention that perf_event class is unknown to SELinux subsystem;
> +
> +10. Check that SELinux is enabled and in Permissive mode
> +
> + # getenforce
> + Permissive
> +
> +11. Turn SELinux into Enforcing mode:
> +
> + # setenforce 1
> + # getenforce
> + Enforcing
> +
> +Opening access to perf_event_open() syscall on Fedora with SELinux
> +==================================================================
> +
> +Access to performance monitoring and observability operations by Perf
> +can be limited for superuser or CAP_PERFMON or CAP_SYS_ADMIN privileged
> +processes. MAC policy settings (e.g. SELinux) can be loaded into the kernel
> +and prevent unauthorized access to perf_event_open() syscall. In such case
> +Perf tool provides a message similar to the one below:
> +
> + # perf stat
> + Error:
> + Access to performance monitoring and observability operations is limited.
> + Enforced MAC policy settings (SELinux) can limit access to performance
> + monitoring and observability operations. Inspect system audit records for
> + more perf_event access control information and adjusting the policy.
> + Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open
> + access to performance monitoring and observability operations for users
> + without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.
> + perf_event_paranoid setting is -1:
> + -1: Allow use of (almost) all events by all users
> + Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
> + >= 0: Disallow raw and ftrace function tracepoint access
> + >= 1: Disallow CPU event access
> + >= 2: Disallow kernel profiling
> + To make the adjusted perf_event_paranoid setting permanent preserve it
> + in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)
> +
> +To make sure that access is limited by MAC policy settings inspect system
> +audit records using journalctl command or /var/log/audit/audit.log so the
> +output would contain AVC denied records related to perf_event:
> +
> + # journalctl --reverse --no-pager | grep perf_event
> +
> + python3[1318099]: SELinux is preventing perf from open access on the perf_event labeled unconfined_t.
> + If you believe that perf should be allowed open access on perf_event labeled unconfined_t by default.
> + setroubleshoot[1318099]: SELinux is preventing perf from open access on the perf_event labeled unconfined_t. For complete SELinux messages run: sealert -l 4595ce5b-e58f-462c-9d86-3bc2074935de
> + audit[1318098]: AVC avc: denied { open } for pid=1318098 comm="perf" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=perf_event permissive=0
> +
> +In order to open access to perf_event_open() syscall MAC policy settings can
> +require to be extended. On SELinux system this can be done by loading a special
> +policy module extending base policy settings. Perf related policy module can
> +be generated using the system audit records about blocking perf_event access.
> +Run the command below to generate my-perf.te policy extension file with
> +perf_event related rules:
> +
> + # ausearch -c 'perf' --raw | audit2allow -M my-perf && cat my-perf.te
> +
> + module my-perf 1.0;
> +
> + require {
> + type unconfined_t;
> + class perf_event { cpu kernel open read tracepoint write };
> + }
> +
> + #============= unconfined_t ==============
> + allow unconfined_t self:perf_event { cpu kernel open read tracepoint write };
> +
> +Now compile, pack and load my-perf.pp extension module into the kernel:
> +
> + # checkmodule -M -m -o my-perf.mod my-perf.te
> + # semodule_package -o my-perf.pp -m my-perf.mod
> + # semodule -X 300 -i my-perf.pp
> +
> +After all those taken steps above access to perf_event_open() syscall should
> +now be allowed by the policy settings. Check access running Perf like this:
> +
> + # perf stat
> + ^C
> + Performance counter stats for 'system wide':
> +
> + 36,387.41 msec cpu-clock # 7.999 CPUs utilized
> + 2,629 context-switches # 0.072 K/sec
> + 57 cpu-migrations # 0.002 K/sec
> + 1 page-faults # 0.000 K/sec
> + 263,721,559 cycles # 0.007 GHz
> + 175,746,713 instructions # 0.67 insn per cycle
> + 19,628,798 branches # 0.539 M/sec
> + 1,259,201 branch-misses # 6.42% of all branches
> +
> + 4.549061439 seconds time elapsed
> +
> +The generated perf-event.pp related policy extension module can be removed
> +from the kernel using this command:
> +
> + # semodule -X 300 -r my-perf
> +
> +Alternatively the module can be temporarily disabled and enabled back using
> +these two commands:
> +
> + # semodule -d my-perf
> + # semodule -e my-perf
> +
> +If something went wrong
> +=======================
> +
> +To turn SELinux into Permissive mode:
> + # setenforce 0
> +
> +To fully disable SELinux during kernel boot [3] set kernel command line parameter selinux=0
> +
> +To remove SELinux labeling from local filesystems:
> + # find / -mount -print0 | xargs -0 setfattr -h -x security.selinux
> +
> +To fully turn SELinux off a machine set SELINUX=disabled at /etc/selinux/config file and reboot;
> +
> +Links
> +=====
> +
> +[1] https://download-ib01.fedoraproject.org/pub/fedora/linux/updates/31/Everything/SRPMS/Packages/s/selinux-policy-3.14.4-49.fc31.src.rpm
> +[2] https://docs.fedoraproject.org/en-US/Fedora/11/html/Security-Enhanced_Linux/sect-Security-Enhanced_Linux-Working_with_SELinux-Enabling_and_Disabling_SELinux.html
> +[3] https://danwalsh.livejournal.com/10972.html
> --
> 2.24.1
>
>
--
- Arnaldo
On 18.05.2020 18:58, Arnaldo Carvalho de Melo wrote:
> Em Thu, Apr 30, 2020 at 10:15:57AM +0300, Alexey Budankov escreveu:
>>
>> Implement selinux sysfs check to see the system is in enforcing
>> mode and print warning message with pointer to check audit logs.
>
> There were some changes in this area meanwhile, so I had to apply the
> evsel.c by hand, when I push this please double check everything is ok,
Will do. I appreciate your integrating effort.
Thanks,
Alexey
On 18.05.2020 18:59, Arnaldo Carvalho de Melo wrote:
> Em Thu, Apr 30, 2020 at 10:16:34AM +0300, Alexey Budankov escreveu:
>>
>> Publish instructions on how to apply LSM hooks for access control
>> to perf_event_open() syscall on Fedora distro with Targeted SELinux
>> policy and then manage access to the syscall.
>
> I'm fixing these up:
>
> [acme@five perf]$ am /wb/1.patch
> Applying: perf docs: introduce security.txt file to document related issues
> .git/rebase-apply/patch:46: space before tab in indent.
> wake_alarm
> .git/rebase-apply/patch:47: space before tab in indent.
> block_suspend
> .git/rebase-apply/patch:48: space before tab in indent.
> audit_read
> .git/rebase-apply/patch:51: trailing whitespace.
>
> .git/rebase-apply/patch:54: trailing whitespace.
This is output of diff utility.
Hopefully it is still applicable after fixes.
I will test this either jointly with the changes at 2/3.
Thanks,
Alexey
Em Mon, May 18, 2020 at 07:50:21PM +0300, Alexey Budankov escreveu:
>
> On 18.05.2020 18:59, Arnaldo Carvalho de Melo wrote:
> > Em Thu, Apr 30, 2020 at 10:16:34AM +0300, Alexey Budankov escreveu:
> >>
> >> Publish instructions on how to apply LSM hooks for access control
> >> to perf_event_open() syscall on Fedora distro with Targeted SELinux
> >> policy and then manage access to the syscall.
> >
> > I'm fixing these up:
> >
> > [acme@five perf]$ am /wb/1.patch
> > Applying: perf docs: introduce security.txt file to document related issues
> > .git/rebase-apply/patch:46: space before tab in indent.
> > wake_alarm
> > .git/rebase-apply/patch:47: space before tab in indent.
> > block_suspend
> > .git/rebase-apply/patch:48: space before tab in indent.
> > audit_read
> > .git/rebase-apply/patch:51: trailing whitespace.
> >
> > .git/rebase-apply/patch:54: trailing whitespace.
>
> This is output of diff utility.
> Hopefully it is still applicable after fixes.
> I will test this either jointly with the changes at 2/3.
So, I've pushed to the tmp.perf/core branch, after testing what is there
I'll move it to perf/core for 5.8,
- Arnaldo
On 18.05.2020 19:43, Alexey Budankov wrote:
>
> On 18.05.2020 18:58, Arnaldo Carvalho de Melo wrote:
>> Em Thu, Apr 30, 2020 at 10:15:57AM +0300, Alexey Budankov escreveu:
>>>
>>> Implement selinux sysfs check to see the system is in enforcing
>>> mode and print warning message with pointer to check audit logs.
>>
>> There were some changes in this area meanwhile, so I had to apply the
>> evsel.c by hand, when I push this please double check everything is ok,
>
> Will do. I appreciate your integrating effort.
Checked at tmp.perf/core branch. The message looks like this:
[root@nntvtune39 acme.tmp]# tools/perf/perf stat
Error:
Access to performance monitoring and observability operations is limited.
Enforced MAC policy settings (SELinux) can limit access to performance
monitoring and observability operations. Inspect system audit records for
more perf_event access control information and adjusting the policy.
Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open
access to performance monitoring and observability operations for users
without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.
perf_event_paranoid setting is 2:
-1: Allow use of (almost) all events by all users
Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
>= 0: Disallow raw and ftrace function tracepoint access
>= 1: Disallow CPU event access
>= 2: Disallow kernel profiling
To make the adjusted perf_event_paranoid setting permanent preserve it
in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)
Edited patch at security.txt didn't apply cleanly. It requires white space
prior tab in the first block for wake_alarm etc till perfmon:
---8<---
diff -Nura a/policy/flask/access_vectors b/policy/flask/access_vectors
--- a/policy/flask/access_vectors 2020-02-04 18:19:53.000000000 +0300
+++ b/policy/flask/access_vectors 2020-02-28 23:37:25.000000000 +0300
@@ -174,6 +174,7 @@
wake_alarm
block_suspend
audit_read
+ perfmon
}
#
@@ -1099,3 +1100,15 @@
class xdp_socket
inherits socket
+
+class perf_event
+{
+ open
+ cpu
+ kernel
+ tracepoint
+ read
+ write
+}
+
+
diff -Nura a/policy/flask/security_classes b/policy/flask/security_classes
--- a/policy/flask/security_classes 2020-02-04 18:19:53.000000000 +0300
+++ b/policy/flask/security_classes 2020-02-28 21:35:17.000000000 +0300
@@ -200,4 +200,6 @@
class xdp_socket
+class perf_event
+
# FLASK
---8<---
~Alexey
Em Tue, May 19, 2020 at 10:34:18AM +0300, Alexey Budankov escreveu:
>
> On 18.05.2020 19:43, Alexey Budankov wrote:
> >
> > On 18.05.2020 18:58, Arnaldo Carvalho de Melo wrote:
> >> Em Thu, Apr 30, 2020 at 10:15:57AM +0300, Alexey Budankov escreveu:
> >>>
> >>> Implement selinux sysfs check to see the system is in enforcing
> >>> mode and print warning message with pointer to check audit logs.
> >>
> >> There were some changes in this area meanwhile, so I had to apply the
> >> evsel.c by hand, when I push this please double check everything is ok,
> >
> > Will do. I appreciate your integrating effort.
>
> Checked at tmp.perf/core branch. The message looks like this:
>
> [root@nntvtune39 acme.tmp]# tools/perf/perf stat
> Error:
> Access to performance monitoring and observability operations is limited.
> Enforced MAC policy settings (SELinux) can limit access to performance
> monitoring and observability operations. Inspect system audit records for
> more perf_event access control information and adjusting the policy.
> Consider adjusting /proc/sys/kernel/perf_event_paranoid setting to open
> access to performance monitoring and observability operations for users
> without CAP_PERFMON or CAP_SYS_ADMIN Linux capability.
> perf_event_paranoid setting is 2:
> -1: Allow use of (almost) all events by all users
> Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
> >= 0: Disallow raw and ftrace function tracepoint access
> >= 1: Disallow CPU event access
> >= 2: Disallow kernel profiling
> To make the adjusted perf_event_paranoid setting permanent preserve it
> in /etc/sysctl.conf (e.g. kernel.perf_event_paranoid = <setting>)
>
> Edited patch at security.txt didn't apply cleanly. It requires white space
> prior tab in the first block for wake_alarm etc till perfmon:
I see, I'll leave it there then so that it applies cleanly to those
policy files.
> ---8<---
> diff -Nura a/policy/flask/access_vectors b/policy/flask/access_vectors
> --- a/policy/flask/access_vectors 2020-02-04 18:19:53.000000000 +0300
> +++ b/policy/flask/access_vectors 2020-02-28 23:37:25.000000000 +0300
> @@ -174,6 +174,7 @@
> wake_alarm
> block_suspend
> audit_read
> + perfmon
> }
>
> #
> @@ -1099,3 +1100,15 @@
>
> class xdp_socket
> inherits socket
> +
> +class perf_event
> +{
> + open
> + cpu
> + kernel
> + tracepoint
> + read
> + write
> +}
> +
> +
> diff -Nura a/policy/flask/security_classes b/policy/flask/security_classes
> --- a/policy/flask/security_classes 2020-02-04 18:19:53.000000000 +0300
> +++ b/policy/flask/security_classes 2020-02-28 21:35:17.000000000 +0300
> @@ -200,4 +200,6 @@
>
> class xdp_socket
>
> +class perf_event
> +
> # FLASK
>
> ---8<---
>
> ~Alexey
--
- Arnaldo