* [V4 PATCH 1/1] selinux-testsuite: Add perf_event tests
@ 2019-12-08 17:06 Richard Haines
2019-12-10 15:31 ` Stephen Smalley
0 siblings, 1 reply; 3+ messages in thread
From: Richard Haines @ 2019-12-08 17:06 UTC (permalink / raw)
To: selinux; +Cc: Richard Haines
Test perf_event permissions.
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
V2 Changes:
Remove neverallows from policy
Check /proc/sys/kernel/perf_event_paranoid, if < 2 then bypass the
capability { sys_admin } test.
V3 Changes:
Remove allow_map() and device_t:chr_file rules as not required.
V4 Change:
Correct policy module comment header.
defconfig | 6 ++
policy/Makefile | 4 +
policy/test_perf_event.te | 89 +++++++++++++++++
tests/Makefile | 4 +
tests/perf_event/.gitignore | 1 +
tests/perf_event/Makefile | 7 ++
tests/perf_event/perf_event.c | 178 ++++++++++++++++++++++++++++++++++
tests/perf_event/test | 93 ++++++++++++++++++
8 files changed, 382 insertions(+)
create mode 100644 policy/test_perf_event.te
create mode 100644 tests/perf_event/.gitignore
create mode 100644 tests/perf_event/Makefile
create mode 100644 tests/perf_event/perf_event.c
create mode 100755 tests/perf_event/test
diff --git a/defconfig b/defconfig
index 0574f1d..2d9c092 100644
--- a/defconfig
+++ b/defconfig
@@ -78,3 +78,9 @@ CONFIG_KEY_DH_OPERATIONS=y
# Test key management socket.
# This is not required for SELinux operation itself.
CONFIG_NET_KEY=m
+
+# Test perf events.
+# This is not required for SELinux operation itself.
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_EVENTS=y
+CONFIG_TRACEPOINTS=y
diff --git a/policy/Makefile b/policy/Makefile
index dda2e16..3f60991 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -101,6 +101,10 @@ ifeq ($(shell grep -q module_load $(POLDEV)/include/support/all_perms.spt && ech
TARGETS+=test_module_load.te
endif
+ifeq ($(shell grep -q perf_event $(POLDEV)/include/support/all_perms.spt && echo true),true)
+TARGETS += test_perf_event.te
+endif
+
ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6))
TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te test_ibpkey.te, $(TARGETS))
endif
diff --git a/policy/test_perf_event.te b/policy/test_perf_event.te
new file mode 100644
index 0000000..67250a4
--- /dev/null
+++ b/policy/test_perf_event.te
@@ -0,0 +1,89 @@
+#
+######### perf_event policy module ##########
+#
+attribute perfdomain;
+
+################# Allow perf_event { * } ##########################
+type test_perf_t;
+domain_type(test_perf_t)
+unconfined_runs_test(test_perf_t)
+typeattribute test_perf_t testdomain;
+typeattribute test_perf_t perfdomain;
+
+allow test_perf_t self:capability { sys_admin };
+allow test_perf_t self:perf_event { open cpu kernel tracepoint read write };
+
+################# Deny capability { sys_admin } ##########################
+type test_perf_no_admin_t;
+domain_type(test_perf_no_admin_t)
+unconfined_runs_test(test_perf_no_admin_t)
+typeattribute test_perf_no_admin_t testdomain;
+typeattribute test_perf_no_admin_t perfdomain;
+
+allow test_perf_no_admin_t self:perf_event { open cpu kernel tracepoint read write };
+
+################# Deny perf_event { open } ##########################
+type test_perf_no_open_t;
+domain_type(test_perf_no_open_t)
+unconfined_runs_test(test_perf_no_open_t)
+typeattribute test_perf_no_open_t testdomain;
+typeattribute test_perf_no_open_t perfdomain;
+
+allow test_perf_no_open_t self:capability { sys_admin };
+allow test_perf_no_open_t self:perf_event { cpu kernel tracepoint read write };
+
+################# Deny perf_event { cpu } ##########################
+type test_perf_no_cpu_t;
+domain_type(test_perf_no_cpu_t)
+unconfined_runs_test(test_perf_no_cpu_t)
+typeattribute test_perf_no_cpu_t testdomain;
+typeattribute test_perf_no_cpu_t perfdomain;
+
+allow test_perf_no_cpu_t self:capability { sys_admin };
+allow test_perf_no_cpu_t self:perf_event { open kernel tracepoint read write };
+
+################# Deny perf_event { kernel } ##########################
+type test_perf_no_kernel_t;
+domain_type(test_perf_no_kernel_t)
+unconfined_runs_test(test_perf_no_kernel_t)
+typeattribute test_perf_no_kernel_t testdomain;
+typeattribute test_perf_no_kernel_t perfdomain;
+
+allow test_perf_no_kernel_t self:capability { sys_admin };
+allow test_perf_no_kernel_t self:perf_event { open cpu tracepoint read write };
+
+################# Deny perf_event { tracepoint } ##########################
+type test_perf_no_tracepoint_t;
+domain_type(test_perf_no_tracepoint_t)
+unconfined_runs_test(test_perf_no_tracepoint_t)
+typeattribute test_perf_no_tracepoint_t testdomain;
+typeattribute test_perf_no_tracepoint_t perfdomain;
+
+allow test_perf_no_tracepoint_t self:capability { sys_admin };
+allow test_perf_no_tracepoint_t self:perf_event { open cpu kernel read write };
+
+################# Deny perf_event { read } ##########################
+type test_perf_no_read_t;
+domain_type(test_perf_no_read_t)
+unconfined_runs_test(test_perf_no_read_t)
+typeattribute test_perf_no_read_t testdomain;
+typeattribute test_perf_no_read_t perfdomain;
+
+allow test_perf_no_read_t self:capability { sys_admin };
+allow test_perf_no_read_t self:perf_event { open cpu kernel tracepoint write };
+
+################# Deny perf_event { write } ##########################
+type test_perf_no_write_t;
+domain_type(test_perf_no_write_t)
+unconfined_runs_test(test_perf_no_write_t)
+typeattribute test_perf_no_write_t testdomain;
+typeattribute test_perf_no_write_t perfdomain;
+
+allow test_perf_no_write_t self:capability { sys_admin };
+allow test_perf_no_write_t self:perf_event { open cpu kernel tracepoint read };
+
+#
+########### Allow these domains to be entered from sysadm domain ############
+#
+miscfiles_domain_entry_test_files(perfdomain)
+userdom_sysadm_entry_spec_domtrans_to(perfdomain)
diff --git a/tests/Makefile b/tests/Makefile
index 0d33fbf..8f66996 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -79,6 +79,10 @@ SUBDIRS+=module_load
endif
endif
+ifeq ($(shell grep -q perf_event $(POLDEV)/include/support/all_perms.spt && echo true),true)
+SUBDIRS += perf_event
+endif
+
ifeq ($(DISTRO),RHEL4)
SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap nnp_nosuid overlay unix_socket, $(SUBDIRS))
endif
diff --git a/tests/perf_event/.gitignore b/tests/perf_event/.gitignore
new file mode 100644
index 0000000..8c2f931
--- /dev/null
+++ b/tests/perf_event/.gitignore
@@ -0,0 +1 @@
+perf_event
diff --git a/tests/perf_event/Makefile b/tests/perf_event/Makefile
new file mode 100644
index 0000000..988424c
--- /dev/null
+++ b/tests/perf_event/Makefile
@@ -0,0 +1,7 @@
+TARGETS = perf_event
+LDLIBS += -lselinux
+
+all: $(TARGETS)
+
+clean:
+ rm -f $(TARGETS)
diff --git a/tests/perf_event/perf_event.c b/tests/perf_event/perf_event.c
new file mode 100644
index 0000000..8983f02
--- /dev/null
+++ b/tests/perf_event/perf_event.c
@@ -0,0 +1,178 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <asm/unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <linux/perf_event.h>
+#include <selinux/selinux.h>
+
+enum {
+ PERF_FILE_MMAP,
+ PERF_FILE,
+ PERF_MMAP
+} read_type;
+
+static void print_usage(char *progname)
+{
+ fprintf(stderr,
+ "usage: %s [-f|-m] [-v]\n"
+ "Where:\n\t"
+ "-f Read perf_event info using read(2)\n\t"
+ "-m Read perf_event info using mmap(2)\n\t"
+ " Default is to use read(2) and mmap(2)\n\t"
+ "-v Print information\n", progname);
+ exit(-1);
+}
+
+static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
+ int cpu, int group_fd, unsigned long flags)
+{
+ return syscall(__NR_perf_event_open, hw_event, pid, cpu,
+ group_fd, flags);
+}
+
+int main(int argc, char **argv)
+{
+ int opt, result, page_size, mmap_size, fd;
+ long long count;
+ bool verbose = false;
+ char *context;
+ void *base;
+ struct perf_event_attr pe_attr;
+ struct perf_event_mmap_page *pe_page;
+
+ read_type = PERF_FILE_MMAP;
+
+ while ((opt = getopt(argc, argv, "fmv")) != -1) {
+ switch (opt) {
+ case 'f':
+ read_type = PERF_FILE;
+ break;
+ case 'm':
+ read_type = PERF_MMAP;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ print_usage(argv[0]);
+ }
+ }
+
+ if (verbose) {
+ result = getcon(&context);
+ if (result < 0) {
+ fprintf(stderr, "Failed to obtain process context\n");
+ exit(-1);
+ }
+ printf("Process context:\n\t%s\n", context);
+ free(context);
+ }
+
+ /* Test perf_event { open cpu kernel tracepoint } */
+ memset(&pe_attr, 0, sizeof(struct perf_event_attr));
+ pe_attr.type = PERF_TYPE_HARDWARE | PERF_TYPE_TRACEPOINT;
+ pe_attr.size = sizeof(struct perf_event_attr);
+ pe_attr.config = PERF_COUNT_HW_INSTRUCTIONS;
+ pe_attr.disabled = 1;
+ pe_attr.exclude_hv = 1;
+
+ fd = perf_event_open(&pe_attr, -1, 1, -1, 0);
+ if (fd < 0) {
+ fprintf(stderr, "Failed perf_event_open(): %s\n",
+ strerror(errno));
+ if (errno == EACCES)
+ exit(1);
+ else
+ exit(-1);
+ }
+
+ /* Test perf_event { write }; */
+ result = ioctl(fd, PERF_EVENT_IOC_RESET, 0);
+ if (result < 0) {
+ fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_RESET): %s\n",
+ strerror(errno));
+ if (errno == EACCES)
+ result = 2;
+ goto err;
+ }
+
+ result = ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
+ if (result < 0) {
+ fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_ENABLE): %s\n",
+ strerror(errno));
+ if (errno == EACCES)
+ result = 3;
+ goto err;
+ }
+
+ result = ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
+ if (result < 0) {
+ fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_DISABLE): %s\n",
+ strerror(errno));
+ if (errno == EACCES)
+ result = 4;
+ goto err;
+ }
+
+ /* Test mmap(2) perf_event { read } */
+ if (read_type == PERF_MMAP || read_type == PERF_FILE_MMAP) {
+ page_size = sysconf(_SC_PAGESIZE);
+ if (page_size < 0) {
+ fprintf(stderr, "Failed sysconf(_SC_PAGESIZE): %s\n",
+ strerror(errno));
+ if (errno == EACCES)
+ result = 5;
+ else
+ result = -1;
+ goto err;
+ }
+ mmap_size = page_size * 2;
+
+ base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (base == MAP_FAILED) {
+ fprintf(stderr, "Failed mmap(): %s\n", strerror(errno));
+ if (errno == EACCES)
+ result = 6;
+ else
+ result = -1;
+ goto err;
+ }
+
+ if (verbose) {
+ pe_page = base;
+ printf("perf mmap(2) return value: %lld\n",
+ pe_page->offset);
+ }
+
+ munmap(base, mmap_size);
+ }
+
+ /* Test read(2) perf_event { read } */
+ if (read_type == PERF_FILE || read_type == PERF_FILE_MMAP) {
+ result = read(fd, &count, sizeof(long long));
+ if (result < 0) {
+ fprintf(stderr, "Failed read(): %s\n", strerror(errno));
+ if (errno == EACCES)
+ result = 7;
+ goto err;
+ }
+
+ if (verbose)
+ printf("perf read(2) return value: %lld\n", count);
+
+ close(fd);
+ }
+
+ return 0;
+
+err:
+ close(fd);
+ return result;
+}
diff --git a/tests/perf_event/test b/tests/perf_event/test
new file mode 100755
index 0000000..1c2e4a9
--- /dev/null
+++ b/tests/perf_event/test
@@ -0,0 +1,93 @@
+#!/usr/bin/perl
+use Test::More;
+
+BEGIN {
+ $basedir = $0;
+ $basedir =~ s|(.*)/[^/]*|$1|;
+
+ $test_count = 8;
+ $sys_admin = 0;
+
+ # allow info to be shown during tests
+ $v = $ARGV[0];
+ if ($v) {
+ if ( $v ne "-v" ) {
+ plan skip_all => "Invalid option (use -v)";
+ }
+ }
+ else {
+ $v = " ";
+ }
+
+ $level = `cat /proc/sys/kernel/perf_event_paranoid`;
+ chomp($level);
+ if ( $level >= 2 ) { # These tests require CAP_SYS_ADMIN
+ $test_count += 1;
+ $sys_admin = 1;
+ }
+
+ if ( $v eq "-v" ) {
+ print "Paranoid level: $level\n";
+ if ( $level < 0 ) {
+ print "\tNot paranoid\n";
+ }
+ elsif ( $level eq 0 ) {
+ print "\tDisallow raw tracepoint/ftrace without CAP_SYS_ADMIN\n";
+ }
+ elsif ( $level eq 1 ) {
+ print "\tDisallow CPU event access without CAP_SYS_ADMIN\n";
+ }
+ elsif ( $level eq 2 ) {
+ print "\tDisallow kernel profiling without CAP_SYS_ADMIN\n";
+ }
+ else {
+ print "\tUndefined level\n";
+ }
+ }
+
+ plan tests => $test_count;
+}
+
+# perf_event { open cpu kernel tracepoint read write };
+print "Test perf_event\n";
+$result = system "runcon -t test_perf_t $basedir/perf_event $v";
+ok( $result eq 0 );
+
+if ($sys_admin) {
+
+ # Deny capability { sys_admin } - EACCES perf_event_open(2)
+ $result =
+ system "runcon -t test_perf_no_admin_t $basedir/perf_event $v 2>&1";
+ ok( $result >> 8 eq 1 );
+}
+
+# Deny perf_event { open } - EACCES perf_event_open(2)
+$result = system "runcon -t test_perf_no_open_t $basedir/perf_event $v 2>&1";
+ok( $result >> 8 eq 1 );
+
+# Deny perf_event { cpu } - EACCES perf_event_open(2)
+$result = system "runcon -t test_perf_no_cpu_t $basedir/perf_event $v 2>&1";
+ok( $result >> 8 eq 1 );
+
+# Deny perf_event { kernel } - EACCES perf_event_open(2)
+$result = system "runcon -t test_perf_no_kernel_t $basedir/perf_event $v 2>&1";
+ok( $result >> 8 eq 1 );
+
+# Deny perf_event { tracepoint } - EACCES perf_event_open(2)
+$result =
+ system "runcon -t test_perf_no_tracepoint_t $basedir/perf_event $v 2>&1";
+ok( $result >> 8 eq 1 );
+
+# Deny perf_event { read } - EACCES mmap(2)
+$result = system "runcon -t test_perf_no_read_t $basedir/perf_event -m $v 2>&1";
+ok( $result >> 8 eq 6 );
+
+# Deny perf_event { read } - EACCES read(2)
+$result = system "runcon -t test_perf_no_read_t $basedir/perf_event -f $v 2>&1";
+ok( $result >> 8 eq 7 );
+
+# Deny perf_event { write } - EACCES ioctl(2) write
+$result = system "runcon -t test_perf_no_write_t $basedir/perf_event $v 2>&1";
+ok( $result >> 8 eq 2 );
+
+exit;
--
2.23.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [V4 PATCH 1/1] selinux-testsuite: Add perf_event tests
2019-12-08 17:06 [V4 PATCH 1/1] selinux-testsuite: Add perf_event tests Richard Haines
@ 2019-12-10 15:31 ` Stephen Smalley
2019-12-10 17:01 ` Stephen Smalley
0 siblings, 1 reply; 3+ messages in thread
From: Stephen Smalley @ 2019-12-10 15:31 UTC (permalink / raw)
To: Richard Haines, selinux
On 12/8/19 12:06 PM, Richard Haines wrote:
> Test perf_event permissions.
>
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
I'll fix the merge conflict.
> ---
> V2 Changes:
> Remove neverallows from policy
> Check /proc/sys/kernel/perf_event_paranoid, if < 2 then bypass the
> capability { sys_admin } test.
> V3 Changes:
> Remove allow_map() and device_t:chr_file rules as not required.
> V4 Change:
> Correct policy module comment header.
>
> defconfig | 6 ++
> policy/Makefile | 4 +
> policy/test_perf_event.te | 89 +++++++++++++++++
> tests/Makefile | 4 +
> tests/perf_event/.gitignore | 1 +
> tests/perf_event/Makefile | 7 ++
> tests/perf_event/perf_event.c | 178 ++++++++++++++++++++++++++++++++++
> tests/perf_event/test | 93 ++++++++++++++++++
> 8 files changed, 382 insertions(+)
> create mode 100644 policy/test_perf_event.te
> create mode 100644 tests/perf_event/.gitignore
> create mode 100644 tests/perf_event/Makefile
> create mode 100644 tests/perf_event/perf_event.c
> create mode 100755 tests/perf_event/test
>
> diff --git a/defconfig b/defconfig
> index 0574f1d..2d9c092 100644
> --- a/defconfig
> +++ b/defconfig
> @@ -78,3 +78,9 @@ CONFIG_KEY_DH_OPERATIONS=y
> # Test key management socket.
> # This is not required for SELinux operation itself.
> CONFIG_NET_KEY=m
> +
> +# Test perf events.
> +# This is not required for SELinux operation itself.
> +CONFIG_HAVE_PERF_EVENTS=y
> +CONFIG_PERF_EVENTS=y
> +CONFIG_TRACEPOINTS=y
> diff --git a/policy/Makefile b/policy/Makefile
> index dda2e16..3f60991 100644
> --- a/policy/Makefile
> +++ b/policy/Makefile
> @@ -101,6 +101,10 @@ ifeq ($(shell grep -q module_load $(POLDEV)/include/support/all_perms.spt && ech
> TARGETS+=test_module_load.te
> endif
>
> +ifeq ($(shell grep -q perf_event $(POLDEV)/include/support/all_perms.spt && echo true),true)
> +TARGETS += test_perf_event.te
> +endif
> +
> ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6))
> TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te test_ibpkey.te, $(TARGETS))
> endif
> diff --git a/policy/test_perf_event.te b/policy/test_perf_event.te
> new file mode 100644
> index 0000000..67250a4
> --- /dev/null
> +++ b/policy/test_perf_event.te
> @@ -0,0 +1,89 @@
> +#
> +######### perf_event policy module ##########
> +#
> +attribute perfdomain;
> +
> +################# Allow perf_event { * } ##########################
> +type test_perf_t;
> +domain_type(test_perf_t)
> +unconfined_runs_test(test_perf_t)
> +typeattribute test_perf_t testdomain;
> +typeattribute test_perf_t perfdomain;
> +
> +allow test_perf_t self:capability { sys_admin };
> +allow test_perf_t self:perf_event { open cpu kernel tracepoint read write };
> +
> +################# Deny capability { sys_admin } ##########################
> +type test_perf_no_admin_t;
> +domain_type(test_perf_no_admin_t)
> +unconfined_runs_test(test_perf_no_admin_t)
> +typeattribute test_perf_no_admin_t testdomain;
> +typeattribute test_perf_no_admin_t perfdomain;
> +
> +allow test_perf_no_admin_t self:perf_event { open cpu kernel tracepoint read write };
> +
> +################# Deny perf_event { open } ##########################
> +type test_perf_no_open_t;
> +domain_type(test_perf_no_open_t)
> +unconfined_runs_test(test_perf_no_open_t)
> +typeattribute test_perf_no_open_t testdomain;
> +typeattribute test_perf_no_open_t perfdomain;
> +
> +allow test_perf_no_open_t self:capability { sys_admin };
> +allow test_perf_no_open_t self:perf_event { cpu kernel tracepoint read write };
> +
> +################# Deny perf_event { cpu } ##########################
> +type test_perf_no_cpu_t;
> +domain_type(test_perf_no_cpu_t)
> +unconfined_runs_test(test_perf_no_cpu_t)
> +typeattribute test_perf_no_cpu_t testdomain;
> +typeattribute test_perf_no_cpu_t perfdomain;
> +
> +allow test_perf_no_cpu_t self:capability { sys_admin };
> +allow test_perf_no_cpu_t self:perf_event { open kernel tracepoint read write };
> +
> +################# Deny perf_event { kernel } ##########################
> +type test_perf_no_kernel_t;
> +domain_type(test_perf_no_kernel_t)
> +unconfined_runs_test(test_perf_no_kernel_t)
> +typeattribute test_perf_no_kernel_t testdomain;
> +typeattribute test_perf_no_kernel_t perfdomain;
> +
> +allow test_perf_no_kernel_t self:capability { sys_admin };
> +allow test_perf_no_kernel_t self:perf_event { open cpu tracepoint read write };
> +
> +################# Deny perf_event { tracepoint } ##########################
> +type test_perf_no_tracepoint_t;
> +domain_type(test_perf_no_tracepoint_t)
> +unconfined_runs_test(test_perf_no_tracepoint_t)
> +typeattribute test_perf_no_tracepoint_t testdomain;
> +typeattribute test_perf_no_tracepoint_t perfdomain;
> +
> +allow test_perf_no_tracepoint_t self:capability { sys_admin };
> +allow test_perf_no_tracepoint_t self:perf_event { open cpu kernel read write };
> +
> +################# Deny perf_event { read } ##########################
> +type test_perf_no_read_t;
> +domain_type(test_perf_no_read_t)
> +unconfined_runs_test(test_perf_no_read_t)
> +typeattribute test_perf_no_read_t testdomain;
> +typeattribute test_perf_no_read_t perfdomain;
> +
> +allow test_perf_no_read_t self:capability { sys_admin };
> +allow test_perf_no_read_t self:perf_event { open cpu kernel tracepoint write };
> +
> +################# Deny perf_event { write } ##########################
> +type test_perf_no_write_t;
> +domain_type(test_perf_no_write_t)
> +unconfined_runs_test(test_perf_no_write_t)
> +typeattribute test_perf_no_write_t testdomain;
> +typeattribute test_perf_no_write_t perfdomain;
> +
> +allow test_perf_no_write_t self:capability { sys_admin };
> +allow test_perf_no_write_t self:perf_event { open cpu kernel tracepoint read };
> +
> +#
> +########### Allow these domains to be entered from sysadm domain ############
> +#
> +miscfiles_domain_entry_test_files(perfdomain)
> +userdom_sysadm_entry_spec_domtrans_to(perfdomain)
> diff --git a/tests/Makefile b/tests/Makefile
> index 0d33fbf..8f66996 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -79,6 +79,10 @@ SUBDIRS+=module_load
> endif
> endif
>
> +ifeq ($(shell grep -q perf_event $(POLDEV)/include/support/all_perms.spt && echo true),true)
> +SUBDIRS += perf_event
> +endif
> +
> ifeq ($(DISTRO),RHEL4)
> SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap nnp_nosuid overlay unix_socket, $(SUBDIRS))
> endif
> diff --git a/tests/perf_event/.gitignore b/tests/perf_event/.gitignore
> new file mode 100644
> index 0000000..8c2f931
> --- /dev/null
> +++ b/tests/perf_event/.gitignore
> @@ -0,0 +1 @@
> +perf_event
> diff --git a/tests/perf_event/Makefile b/tests/perf_event/Makefile
> new file mode 100644
> index 0000000..988424c
> --- /dev/null
> +++ b/tests/perf_event/Makefile
> @@ -0,0 +1,7 @@
> +TARGETS = perf_event
> +LDLIBS += -lselinux
> +
> +all: $(TARGETS)
> +
> +clean:
> + rm -f $(TARGETS)
> diff --git a/tests/perf_event/perf_event.c b/tests/perf_event/perf_event.c
> new file mode 100644
> index 0000000..8983f02
> --- /dev/null
> +++ b/tests/perf_event/perf_event.c
> @@ -0,0 +1,178 @@
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <stdbool.h>
> +#include <asm/unistd.h>
> +#include <sys/mman.h>
> +#include <sys/ioctl.h>
> +#include <linux/perf_event.h>
> +#include <selinux/selinux.h>
> +
> +enum {
> + PERF_FILE_MMAP,
> + PERF_FILE,
> + PERF_MMAP
> +} read_type;
> +
> +static void print_usage(char *progname)
> +{
> + fprintf(stderr,
> + "usage: %s [-f|-m] [-v]\n"
> + "Where:\n\t"
> + "-f Read perf_event info using read(2)\n\t"
> + "-m Read perf_event info using mmap(2)\n\t"
> + " Default is to use read(2) and mmap(2)\n\t"
> + "-v Print information\n", progname);
> + exit(-1);
> +}
> +
> +static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
> + int cpu, int group_fd, unsigned long flags)
> +{
> + return syscall(__NR_perf_event_open, hw_event, pid, cpu,
> + group_fd, flags);
> +}
> +
> +int main(int argc, char **argv)
> +{
> + int opt, result, page_size, mmap_size, fd;
> + long long count;
> + bool verbose = false;
> + char *context;
> + void *base;
> + struct perf_event_attr pe_attr;
> + struct perf_event_mmap_page *pe_page;
> +
> + read_type = PERF_FILE_MMAP;
> +
> + while ((opt = getopt(argc, argv, "fmv")) != -1) {
> + switch (opt) {
> + case 'f':
> + read_type = PERF_FILE;
> + break;
> + case 'm':
> + read_type = PERF_MMAP;
> + break;
> + case 'v':
> + verbose = true;
> + break;
> + default:
> + print_usage(argv[0]);
> + }
> + }
> +
> + if (verbose) {
> + result = getcon(&context);
> + if (result < 0) {
> + fprintf(stderr, "Failed to obtain process context\n");
> + exit(-1);
> + }
> + printf("Process context:\n\t%s\n", context);
> + free(context);
> + }
> +
> + /* Test perf_event { open cpu kernel tracepoint } */
> + memset(&pe_attr, 0, sizeof(struct perf_event_attr));
> + pe_attr.type = PERF_TYPE_HARDWARE | PERF_TYPE_TRACEPOINT;
> + pe_attr.size = sizeof(struct perf_event_attr);
> + pe_attr.config = PERF_COUNT_HW_INSTRUCTIONS;
> + pe_attr.disabled = 1;
> + pe_attr.exclude_hv = 1;
> +
> + fd = perf_event_open(&pe_attr, -1, 1, -1, 0);
> + if (fd < 0) {
> + fprintf(stderr, "Failed perf_event_open(): %s\n",
> + strerror(errno));
> + if (errno == EACCES)
> + exit(1);
> + else
> + exit(-1);
> + }
> +
> + /* Test perf_event { write }; */
> + result = ioctl(fd, PERF_EVENT_IOC_RESET, 0);
> + if (result < 0) {
> + fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_RESET): %s\n",
> + strerror(errno));
> + if (errno == EACCES)
> + result = 2;
> + goto err;
> + }
> +
> + result = ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
> + if (result < 0) {
> + fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_ENABLE): %s\n",
> + strerror(errno));
> + if (errno == EACCES)
> + result = 3;
> + goto err;
> + }
> +
> + result = ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
> + if (result < 0) {
> + fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_DISABLE): %s\n",
> + strerror(errno));
> + if (errno == EACCES)
> + result = 4;
> + goto err;
> + }
> +
> + /* Test mmap(2) perf_event { read } */
> + if (read_type == PERF_MMAP || read_type == PERF_FILE_MMAP) {
> + page_size = sysconf(_SC_PAGESIZE);
> + if (page_size < 0) {
> + fprintf(stderr, "Failed sysconf(_SC_PAGESIZE): %s\n",
> + strerror(errno));
> + if (errno == EACCES)
> + result = 5;
> + else
> + result = -1;
> + goto err;
> + }
> + mmap_size = page_size * 2;
> +
> + base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
> + MAP_SHARED, fd, 0);
> + if (base == MAP_FAILED) {
> + fprintf(stderr, "Failed mmap(): %s\n", strerror(errno));
> + if (errno == EACCES)
> + result = 6;
> + else
> + result = -1;
> + goto err;
> + }
> +
> + if (verbose) {
> + pe_page = base;
> + printf("perf mmap(2) return value: %lld\n",
> + pe_page->offset);
> + }
> +
> + munmap(base, mmap_size);
> + }
> +
> + /* Test read(2) perf_event { read } */
> + if (read_type == PERF_FILE || read_type == PERF_FILE_MMAP) {
> + result = read(fd, &count, sizeof(long long));
> + if (result < 0) {
> + fprintf(stderr, "Failed read(): %s\n", strerror(errno));
> + if (errno == EACCES)
> + result = 7;
> + goto err;
> + }
> +
> + if (verbose)
> + printf("perf read(2) return value: %lld\n", count);
> +
> + close(fd);
> + }
> +
> + return 0;
> +
> +err:
> + close(fd);
> + return result;
> +}
> diff --git a/tests/perf_event/test b/tests/perf_event/test
> new file mode 100755
> index 0000000..1c2e4a9
> --- /dev/null
> +++ b/tests/perf_event/test
> @@ -0,0 +1,93 @@
> +#!/usr/bin/perl
> +use Test::More;
> +
> +BEGIN {
> + $basedir = $0;
> + $basedir =~ s|(.*)/[^/]*|$1|;
> +
> + $test_count = 8;
> + $sys_admin = 0;
> +
> + # allow info to be shown during tests
> + $v = $ARGV[0];
> + if ($v) {
> + if ( $v ne "-v" ) {
> + plan skip_all => "Invalid option (use -v)";
> + }
> + }
> + else {
> + $v = " ";
> + }
> +
> + $level = `cat /proc/sys/kernel/perf_event_paranoid`;
> + chomp($level);
> + if ( $level >= 2 ) { # These tests require CAP_SYS_ADMIN
> + $test_count += 1;
> + $sys_admin = 1;
> + }
> +
> + if ( $v eq "-v" ) {
> + print "Paranoid level: $level\n";
> + if ( $level < 0 ) {
> + print "\tNot paranoid\n";
> + }
> + elsif ( $level eq 0 ) {
> + print "\tDisallow raw tracepoint/ftrace without CAP_SYS_ADMIN\n";
> + }
> + elsif ( $level eq 1 ) {
> + print "\tDisallow CPU event access without CAP_SYS_ADMIN\n";
> + }
> + elsif ( $level eq 2 ) {
> + print "\tDisallow kernel profiling without CAP_SYS_ADMIN\n";
> + }
> + else {
> + print "\tUndefined level\n";
> + }
> + }
> +
> + plan tests => $test_count;
> +}
> +
> +# perf_event { open cpu kernel tracepoint read write };
> +print "Test perf_event\n";
> +$result = system "runcon -t test_perf_t $basedir/perf_event $v";
> +ok( $result eq 0 );
> +
> +if ($sys_admin) {
> +
> + # Deny capability { sys_admin } - EACCES perf_event_open(2)
> + $result =
> + system "runcon -t test_perf_no_admin_t $basedir/perf_event $v 2>&1";
> + ok( $result >> 8 eq 1 );
> +}
> +
> +# Deny perf_event { open } - EACCES perf_event_open(2)
> +$result = system "runcon -t test_perf_no_open_t $basedir/perf_event $v 2>&1";
> +ok( $result >> 8 eq 1 );
> +
> +# Deny perf_event { cpu } - EACCES perf_event_open(2)
> +$result = system "runcon -t test_perf_no_cpu_t $basedir/perf_event $v 2>&1";
> +ok( $result >> 8 eq 1 );
> +
> +# Deny perf_event { kernel } - EACCES perf_event_open(2)
> +$result = system "runcon -t test_perf_no_kernel_t $basedir/perf_event $v 2>&1";
> +ok( $result >> 8 eq 1 );
> +
> +# Deny perf_event { tracepoint } - EACCES perf_event_open(2)
> +$result =
> + system "runcon -t test_perf_no_tracepoint_t $basedir/perf_event $v 2>&1";
> +ok( $result >> 8 eq 1 );
> +
> +# Deny perf_event { read } - EACCES mmap(2)
> +$result = system "runcon -t test_perf_no_read_t $basedir/perf_event -m $v 2>&1";
> +ok( $result >> 8 eq 6 );
> +
> +# Deny perf_event { read } - EACCES read(2)
> +$result = system "runcon -t test_perf_no_read_t $basedir/perf_event -f $v 2>&1";
> +ok( $result >> 8 eq 7 );
> +
> +# Deny perf_event { write } - EACCES ioctl(2) write
> +$result = system "runcon -t test_perf_no_write_t $basedir/perf_event $v 2>&1";
> +ok( $result >> 8 eq 2 );
> +
> +exit;
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [V4 PATCH 1/1] selinux-testsuite: Add perf_event tests
2019-12-10 15:31 ` Stephen Smalley
@ 2019-12-10 17:01 ` Stephen Smalley
0 siblings, 0 replies; 3+ messages in thread
From: Stephen Smalley @ 2019-12-10 17:01 UTC (permalink / raw)
To: Richard Haines, selinux
On 12/10/19 10:31 AM, Stephen Smalley wrote:
> On 12/8/19 12:06 PM, Richard Haines wrote:
>> Test perf_event permissions.
>>
>> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
>
> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
>
> I'll fix the merge conflict.
Thanks, merged.
>
>> ---
>> V2 Changes:
>> Remove neverallows from policy
>> Check /proc/sys/kernel/perf_event_paranoid, if < 2 then bypass the
>> capability { sys_admin } test.
>> V3 Changes:
>> Remove allow_map() and device_t:chr_file rules as not required.
>> V4 Change:
>> Correct policy module comment header.
>>
>> defconfig | 6 ++
>> policy/Makefile | 4 +
>> policy/test_perf_event.te | 89 +++++++++++++++++
>> tests/Makefile | 4 +
>> tests/perf_event/.gitignore | 1 +
>> tests/perf_event/Makefile | 7 ++
>> tests/perf_event/perf_event.c | 178 ++++++++++++++++++++++++++++++++++
>> tests/perf_event/test | 93 ++++++++++++++++++
>> 8 files changed, 382 insertions(+)
>> create mode 100644 policy/test_perf_event.te
>> create mode 100644 tests/perf_event/.gitignore
>> create mode 100644 tests/perf_event/Makefile
>> create mode 100644 tests/perf_event/perf_event.c
>> create mode 100755 tests/perf_event/test
>>
>> diff --git a/defconfig b/defconfig
>> index 0574f1d..2d9c092 100644
>> --- a/defconfig
>> +++ b/defconfig
>> @@ -78,3 +78,9 @@ CONFIG_KEY_DH_OPERATIONS=y
>> # Test key management socket.
>> # This is not required for SELinux operation itself.
>> CONFIG_NET_KEY=m
>> +
>> +# Test perf events.
>> +# This is not required for SELinux operation itself.
>> +CONFIG_HAVE_PERF_EVENTS=y
>> +CONFIG_PERF_EVENTS=y
>> +CONFIG_TRACEPOINTS=y
>> diff --git a/policy/Makefile b/policy/Makefile
>> index dda2e16..3f60991 100644
>> --- a/policy/Makefile
>> +++ b/policy/Makefile
>> @@ -101,6 +101,10 @@ ifeq ($(shell grep -q module_load
>> $(POLDEV)/include/support/all_perms.spt && ech
>> TARGETS+=test_module_load.te
>> endif
>> +ifeq ($(shell grep -q perf_event
>> $(POLDEV)/include/support/all_perms.spt && echo true),true)
>> +TARGETS += test_perf_event.te
>> +endif
>> +
>> ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6))
>> TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te
>> test_ibpkey.te, $(TARGETS))
>> endif
>> diff --git a/policy/test_perf_event.te b/policy/test_perf_event.te
>> new file mode 100644
>> index 0000000..67250a4
>> --- /dev/null
>> +++ b/policy/test_perf_event.te
>> @@ -0,0 +1,89 @@
>> +#
>> +######### perf_event policy module ##########
>> +#
>> +attribute perfdomain;
>> +
>> +################# Allow perf_event { * } ##########################
>> +type test_perf_t;
>> +domain_type(test_perf_t)
>> +unconfined_runs_test(test_perf_t)
>> +typeattribute test_perf_t testdomain;
>> +typeattribute test_perf_t perfdomain;
>> +
>> +allow test_perf_t self:capability { sys_admin };
>> +allow test_perf_t self:perf_event { open cpu kernel tracepoint read
>> write };
>> +
>> +################# Deny capability { sys_admin }
>> ##########################
>> +type test_perf_no_admin_t;
>> +domain_type(test_perf_no_admin_t)
>> +unconfined_runs_test(test_perf_no_admin_t)
>> +typeattribute test_perf_no_admin_t testdomain;
>> +typeattribute test_perf_no_admin_t perfdomain;
>> +
>> +allow test_perf_no_admin_t self:perf_event { open cpu kernel
>> tracepoint read write };
>> +
>> +################# Deny perf_event { open } ##########################
>> +type test_perf_no_open_t;
>> +domain_type(test_perf_no_open_t)
>> +unconfined_runs_test(test_perf_no_open_t)
>> +typeattribute test_perf_no_open_t testdomain;
>> +typeattribute test_perf_no_open_t perfdomain;
>> +
>> +allow test_perf_no_open_t self:capability { sys_admin };
>> +allow test_perf_no_open_t self:perf_event { cpu kernel tracepoint
>> read write };
>> +
>> +################# Deny perf_event { cpu } ##########################
>> +type test_perf_no_cpu_t;
>> +domain_type(test_perf_no_cpu_t)
>> +unconfined_runs_test(test_perf_no_cpu_t)
>> +typeattribute test_perf_no_cpu_t testdomain;
>> +typeattribute test_perf_no_cpu_t perfdomain;
>> +
>> +allow test_perf_no_cpu_t self:capability { sys_admin };
>> +allow test_perf_no_cpu_t self:perf_event { open kernel tracepoint
>> read write };
>> +
>> +################# Deny perf_event { kernel } ##########################
>> +type test_perf_no_kernel_t;
>> +domain_type(test_perf_no_kernel_t)
>> +unconfined_runs_test(test_perf_no_kernel_t)
>> +typeattribute test_perf_no_kernel_t testdomain;
>> +typeattribute test_perf_no_kernel_t perfdomain;
>> +
>> +allow test_perf_no_kernel_t self:capability { sys_admin };
>> +allow test_perf_no_kernel_t self:perf_event { open cpu tracepoint
>> read write };
>> +
>> +################# Deny perf_event { tracepoint }
>> ##########################
>> +type test_perf_no_tracepoint_t;
>> +domain_type(test_perf_no_tracepoint_t)
>> +unconfined_runs_test(test_perf_no_tracepoint_t)
>> +typeattribute test_perf_no_tracepoint_t testdomain;
>> +typeattribute test_perf_no_tracepoint_t perfdomain;
>> +
>> +allow test_perf_no_tracepoint_t self:capability { sys_admin };
>> +allow test_perf_no_tracepoint_t self:perf_event { open cpu kernel
>> read write };
>> +
>> +################# Deny perf_event { read } ##########################
>> +type test_perf_no_read_t;
>> +domain_type(test_perf_no_read_t)
>> +unconfined_runs_test(test_perf_no_read_t)
>> +typeattribute test_perf_no_read_t testdomain;
>> +typeattribute test_perf_no_read_t perfdomain;
>> +
>> +allow test_perf_no_read_t self:capability { sys_admin };
>> +allow test_perf_no_read_t self:perf_event { open cpu kernel
>> tracepoint write };
>> +
>> +################# Deny perf_event { write } ##########################
>> +type test_perf_no_write_t;
>> +domain_type(test_perf_no_write_t)
>> +unconfined_runs_test(test_perf_no_write_t)
>> +typeattribute test_perf_no_write_t testdomain;
>> +typeattribute test_perf_no_write_t perfdomain;
>> +
>> +allow test_perf_no_write_t self:capability { sys_admin };
>> +allow test_perf_no_write_t self:perf_event { open cpu kernel
>> tracepoint read };
>> +
>> +#
>> +########### Allow these domains to be entered from sysadm domain
>> ############
>> +#
>> +miscfiles_domain_entry_test_files(perfdomain)
>> +userdom_sysadm_entry_spec_domtrans_to(perfdomain)
>> diff --git a/tests/Makefile b/tests/Makefile
>> index 0d33fbf..8f66996 100644
>> --- a/tests/Makefile
>> +++ b/tests/Makefile
>> @@ -79,6 +79,10 @@ SUBDIRS+=module_load
>> endif
>> endif
>> +ifeq ($(shell grep -q perf_event
>> $(POLDEV)/include/support/all_perms.spt && echo true),true)
>> +SUBDIRS += perf_event
>> +endif
>> +
>> ifeq ($(DISTRO),RHEL4)
>> SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap
>> nnp_nosuid overlay unix_socket, $(SUBDIRS))
>> endif
>> diff --git a/tests/perf_event/.gitignore b/tests/perf_event/.gitignore
>> new file mode 100644
>> index 0000000..8c2f931
>> --- /dev/null
>> +++ b/tests/perf_event/.gitignore
>> @@ -0,0 +1 @@
>> +perf_event
>> diff --git a/tests/perf_event/Makefile b/tests/perf_event/Makefile
>> new file mode 100644
>> index 0000000..988424c
>> --- /dev/null
>> +++ b/tests/perf_event/Makefile
>> @@ -0,0 +1,7 @@
>> +TARGETS = perf_event
>> +LDLIBS += -lselinux
>> +
>> +all: $(TARGETS)
>> +
>> +clean:
>> + rm -f $(TARGETS)
>> diff --git a/tests/perf_event/perf_event.c
>> b/tests/perf_event/perf_event.c
>> new file mode 100644
>> index 0000000..8983f02
>> --- /dev/null
>> +++ b/tests/perf_event/perf_event.c
>> @@ -0,0 +1,178 @@
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <unistd.h>
>> +#include <string.h>
>> +#include <unistd.h>
>> +#include <errno.h>
>> +#include <stdbool.h>
>> +#include <asm/unistd.h>
>> +#include <sys/mman.h>
>> +#include <sys/ioctl.h>
>> +#include <linux/perf_event.h>
>> +#include <selinux/selinux.h>
>> +
>> +enum {
>> + PERF_FILE_MMAP,
>> + PERF_FILE,
>> + PERF_MMAP
>> +} read_type;
>> +
>> +static void print_usage(char *progname)
>> +{
>> + fprintf(stderr,
>> + "usage: %s [-f|-m] [-v]\n"
>> + "Where:\n\t"
>> + "-f Read perf_event info using read(2)\n\t"
>> + "-m Read perf_event info using mmap(2)\n\t"
>> + " Default is to use read(2) and mmap(2)\n\t"
>> + "-v Print information\n", progname);
>> + exit(-1);
>> +}
>> +
>> +static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
>> + int cpu, int group_fd, unsigned long flags)
>> +{
>> + return syscall(__NR_perf_event_open, hw_event, pid, cpu,
>> + group_fd, flags);
>> +}
>> +
>> +int main(int argc, char **argv)
>> +{
>> + int opt, result, page_size, mmap_size, fd;
>> + long long count;
>> + bool verbose = false;
>> + char *context;
>> + void *base;
>> + struct perf_event_attr pe_attr;
>> + struct perf_event_mmap_page *pe_page;
>> +
>> + read_type = PERF_FILE_MMAP;
>> +
>> + while ((opt = getopt(argc, argv, "fmv")) != -1) {
>> + switch (opt) {
>> + case 'f':
>> + read_type = PERF_FILE;
>> + break;
>> + case 'm':
>> + read_type = PERF_MMAP;
>> + break;
>> + case 'v':
>> + verbose = true;
>> + break;
>> + default:
>> + print_usage(argv[0]);
>> + }
>> + }
>> +
>> + if (verbose) {
>> + result = getcon(&context);
>> + if (result < 0) {
>> + fprintf(stderr, "Failed to obtain process context\n");
>> + exit(-1);
>> + }
>> + printf("Process context:\n\t%s\n", context);
>> + free(context);
>> + }
>> +
>> + /* Test perf_event { open cpu kernel tracepoint } */
>> + memset(&pe_attr, 0, sizeof(struct perf_event_attr));
>> + pe_attr.type = PERF_TYPE_HARDWARE | PERF_TYPE_TRACEPOINT;
>> + pe_attr.size = sizeof(struct perf_event_attr);
>> + pe_attr.config = PERF_COUNT_HW_INSTRUCTIONS;
>> + pe_attr.disabled = 1;
>> + pe_attr.exclude_hv = 1;
>> +
>> + fd = perf_event_open(&pe_attr, -1, 1, -1, 0);
>> + if (fd < 0) {
>> + fprintf(stderr, "Failed perf_event_open(): %s\n",
>> + strerror(errno));
>> + if (errno == EACCES)
>> + exit(1);
>> + else
>> + exit(-1);
>> + }
>> +
>> + /* Test perf_event { write }; */
>> + result = ioctl(fd, PERF_EVENT_IOC_RESET, 0);
>> + if (result < 0) {
>> + fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_RESET): %s\n",
>> + strerror(errno));
>> + if (errno == EACCES)
>> + result = 2;
>> + goto err;
>> + }
>> +
>> + result = ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
>> + if (result < 0) {
>> + fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_ENABLE): %s\n",
>> + strerror(errno));
>> + if (errno == EACCES)
>> + result = 3;
>> + goto err;
>> + }
>> +
>> + result = ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
>> + if (result < 0) {
>> + fprintf(stderr, "Failed ioctl(PERF_EVENT_IOC_DISABLE): %s\n",
>> + strerror(errno));
>> + if (errno == EACCES)
>> + result = 4;
>> + goto err;
>> + }
>> +
>> + /* Test mmap(2) perf_event { read } */
>> + if (read_type == PERF_MMAP || read_type == PERF_FILE_MMAP) {
>> + page_size = sysconf(_SC_PAGESIZE);
>> + if (page_size < 0) {
>> + fprintf(stderr, "Failed sysconf(_SC_PAGESIZE): %s\n",
>> + strerror(errno));
>> + if (errno == EACCES)
>> + result = 5;
>> + else
>> + result = -1;
>> + goto err;
>> + }
>> + mmap_size = page_size * 2;
>> +
>> + base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
>> + MAP_SHARED, fd, 0);
>> + if (base == MAP_FAILED) {
>> + fprintf(stderr, "Failed mmap(): %s\n", strerror(errno));
>> + if (errno == EACCES)
>> + result = 6;
>> + else
>> + result = -1;
>> + goto err;
>> + }
>> +
>> + if (verbose) {
>> + pe_page = base;
>> + printf("perf mmap(2) return value: %lld\n",
>> + pe_page->offset);
>> + }
>> +
>> + munmap(base, mmap_size);
>> + }
>> +
>> + /* Test read(2) perf_event { read } */
>> + if (read_type == PERF_FILE || read_type == PERF_FILE_MMAP) {
>> + result = read(fd, &count, sizeof(long long));
>> + if (result < 0) {
>> + fprintf(stderr, "Failed read(): %s\n", strerror(errno));
>> + if (errno == EACCES)
>> + result = 7;
>> + goto err;
>> + }
>> +
>> + if (verbose)
>> + printf("perf read(2) return value: %lld\n", count);
>> +
>> + close(fd);
>> + }
>> +
>> + return 0;
>> +
>> +err:
>> + close(fd);
>> + return result;
>> +}
>> diff --git a/tests/perf_event/test b/tests/perf_event/test
>> new file mode 100755
>> index 0000000..1c2e4a9
>> --- /dev/null
>> +++ b/tests/perf_event/test
>> @@ -0,0 +1,93 @@
>> +#!/usr/bin/perl
>> +use Test::More;
>> +
>> +BEGIN {
>> + $basedir = $0;
>> + $basedir =~ s|(.*)/[^/]*|$1|;
>> +
>> + $test_count = 8;
>> + $sys_admin = 0;
>> +
>> + # allow info to be shown during tests
>> + $v = $ARGV[0];
>> + if ($v) {
>> + if ( $v ne "-v" ) {
>> + plan skip_all => "Invalid option (use -v)";
>> + }
>> + }
>> + else {
>> + $v = " ";
>> + }
>> +
>> + $level = `cat /proc/sys/kernel/perf_event_paranoid`;
>> + chomp($level);
>> + if ( $level >= 2 ) { # These tests require CAP_SYS_ADMIN
>> + $test_count += 1;
>> + $sys_admin = 1;
>> + }
>> +
>> + if ( $v eq "-v" ) {
>> + print "Paranoid level: $level\n";
>> + if ( $level < 0 ) {
>> + print "\tNot paranoid\n";
>> + }
>> + elsif ( $level eq 0 ) {
>> + print "\tDisallow raw tracepoint/ftrace without
>> CAP_SYS_ADMIN\n";
>> + }
>> + elsif ( $level eq 1 ) {
>> + print "\tDisallow CPU event access without CAP_SYS_ADMIN\n";
>> + }
>> + elsif ( $level eq 2 ) {
>> + print "\tDisallow kernel profiling without CAP_SYS_ADMIN\n";
>> + }
>> + else {
>> + print "\tUndefined level\n";
>> + }
>> + }
>> +
>> + plan tests => $test_count;
>> +}
>> +
>> +# perf_event { open cpu kernel tracepoint read write };
>> +print "Test perf_event\n";
>> +$result = system "runcon -t test_perf_t $basedir/perf_event $v";
>> +ok( $result eq 0 );
>> +
>> +if ($sys_admin) {
>> +
>> + # Deny capability { sys_admin } - EACCES perf_event_open(2)
>> + $result =
>> + system "runcon -t test_perf_no_admin_t $basedir/perf_event $v
>> 2>&1";
>> + ok( $result >> 8 eq 1 );
>> +}
>> +
>> +# Deny perf_event { open } - EACCES perf_event_open(2)
>> +$result = system "runcon -t test_perf_no_open_t $basedir/perf_event
>> $v 2>&1";
>> +ok( $result >> 8 eq 1 );
>> +
>> +# Deny perf_event { cpu } - EACCES perf_event_open(2)
>> +$result = system "runcon -t test_perf_no_cpu_t $basedir/perf_event $v
>> 2>&1";
>> +ok( $result >> 8 eq 1 );
>> +
>> +# Deny perf_event { kernel } - EACCES perf_event_open(2)
>> +$result = system "runcon -t test_perf_no_kernel_t $basedir/perf_event
>> $v 2>&1";
>> +ok( $result >> 8 eq 1 );
>> +
>> +# Deny perf_event { tracepoint } - EACCES perf_event_open(2)
>> +$result =
>> + system "runcon -t test_perf_no_tracepoint_t $basedir/perf_event $v
>> 2>&1";
>> +ok( $result >> 8 eq 1 );
>> +
>> +# Deny perf_event { read } - EACCES mmap(2)
>> +$result = system "runcon -t test_perf_no_read_t $basedir/perf_event
>> -m $v 2>&1";
>> +ok( $result >> 8 eq 6 );
>> +
>> +# Deny perf_event { read } - EACCES read(2)
>> +$result = system "runcon -t test_perf_no_read_t $basedir/perf_event
>> -f $v 2>&1";
>> +ok( $result >> 8 eq 7 );
>> +
>> +# Deny perf_event { write } - EACCES ioctl(2) write
>> +$result = system "runcon -t test_perf_no_write_t $basedir/perf_event
>> $v 2>&1";
>> +ok( $result >> 8 eq 2 );
>> +
>> +exit;
>>
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-12-10 17:01 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-08 17:06 [V4 PATCH 1/1] selinux-testsuite: Add perf_event tests Richard Haines
2019-12-10 15:31 ` Stephen Smalley
2019-12-10 17:01 ` Stephen Smalley
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.