All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Haines <richard_c_haines@btinternet.com>
To: selinux@vger.kernel.org, paul@paul-moore.com
Cc: Richard Haines <richard_c_haines@btinternet.com>
Subject: [PATCH] selinux-testsuite: Add key and key_socket tests
Date: Mon,  9 Sep 2019 14:17:01 +0100	[thread overview]
Message-ID: <20190909131701.29588-1-richard_c_haines@btinternet.com> (raw)

Test all permissions associated with the key and key_socket classes.

Note that kernel 5.3 commit keys: Fix request_key() lack of Link perm
check on found key ("504b69eb3c95180bc59f1ae9096ad4b10bbbf254")
added an additional check for link perm on request_key(). The tests
will support earlier kernels.

Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
 README.md                   |   3 +-
 defconfig                   |   8 ++
 policy/Makefile             |   4 +
 policy/test_keys.te         | 161 ++++++++++++++++++++++++
 tests/Makefile              |   4 +
 tests/keys/.gitignore       |   3 +
 tests/keys/Makefile         |   8 ++
 tests/keys/key_sock.c       |  67 ++++++++++
 tests/keys/keyctl.c         | 241 ++++++++++++++++++++++++++++++++++++
 tests/keys/keyctl_relabel.c |  93 ++++++++++++++
 tests/keys/test             |  98 +++++++++++++++
 11 files changed, 689 insertions(+), 1 deletion(-)
 create mode 100644 policy/test_keys.te
 create mode 100644 tests/keys/.gitignore
 create mode 100644 tests/keys/Makefile
 create mode 100644 tests/keys/key_sock.c
 create mode 100644 tests/keys/keyctl.c
 create mode 100644 tests/keys/keyctl_relabel.c
 create mode 100755 tests/keys/test

diff --git a/README.md b/README.md
index 26784f8..fe72a91 100644
--- a/README.md
+++ b/README.md
@@ -65,7 +65,8 @@ following command:
 		netlabel_tools \
 		iptables \
 		lksctp-tools-devel \
-		attr
+		attr \
+		keyutils-libs-devel
 
 The testsuite requires a pre-existing base policy configuration of SELinux,
 using either the old example policy or the reference policy as the baseline.
diff --git a/defconfig b/defconfig
index d7f0ea5..c00e291 100644
--- a/defconfig
+++ b/defconfig
@@ -62,3 +62,11 @@ CONFIG_ANDROID_BINDER_IPC=y
 # This will configure the Dynamically Allocated Binder Devices added
 # to 5.0+ kernels:
 CONFIG_ANDROID_BINDERFS=y
+
+# Key implementations.
+# These are enabled to test the key and key_socket controls in
+# tests/keys; they are not required for SELinux operation itself.
+CONFIG_KEYS=y
+CONFIG_KEYS_COMPAT=y
+CONFIG_KEY_DH_OPERATIONS=y
+CONFIG_NET_KEY=m
diff --git a/policy/Makefile b/policy/Makefile
index 305b572..9258a93 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -71,6 +71,10 @@ ifeq ($(shell grep -q corenet_sctp_bind_all_nodes $(POLDEV)/include/kernel/coren
 TARGETS += test_sctp.te
 endif
 
+ifeq ($(shell grep -q key_socket $(POLDEV)/include/support/all_perms.spt && echo true),true)
+TARGETS += test_keys.te
+endif
+
 ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6))
 TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te, $(TARGETS))
 endif
diff --git a/policy/test_keys.te b/policy/test_keys.te
new file mode 100644
index 0000000..9c65ec8
--- /dev/null
+++ b/policy/test_keys.te
@@ -0,0 +1,161 @@
+#
+################# KEY selinux-testsuite policy module ######################
+#
+attribute keydomain;
+
+#
+############################## Define Macro ################################
+#
+# Do not use domain_type() macro as it has allow 'key { link search }'
+# in base module so 'allow domain self:key ~{ link search };' will not work
+# here. Add these instead to allow key perms to be controlled by this module:
+#
+define(`key_domain_type',`
+	allow $1 proc_t:dir { search };
+	allow $1 proc_t:lnk_file { read };
+	allow $1 self:dir { search };
+	allow $1 self:file { open read write };
+')
+
+#
+####################### Main key class tests #####################
+#
+type test_key_t;
+key_domain_type(test_key_t)
+unconfined_runs_test(test_key_t)
+typeattribute test_key_t testdomain;
+typeattribute test_key_t keydomain;
+
+allow test_key_t self:process { setkeycreate };
+allow test_key_t self:key { create write search read view link setattr };
+
+# Set new context on a keyring:
+type test_newcon_key_t;
+key_domain_type(test_newcon_key_t)
+unconfined_runs_test(test_newcon_key_t)
+typeattribute test_newcon_key_t testdomain;
+typeattribute test_newcon_key_t keydomain;
+
+allow test_key_t test_newcon_key_t:key { create write search view };
+
+################# Deny process { setkeycreate } #######################
+type test_no_setkeycreate_t;
+key_domain_type(test_no_setkeycreate_t)
+unconfined_runs_test(test_no_setkeycreate_t)
+typeattribute test_no_setkeycreate_t testdomain;
+typeattribute test_no_setkeycreate_t keydomain;
+
+###################### Deny key { create } ###########################
+type test_key_no_create_t;
+key_domain_type(test_key_no_create_t)
+unconfined_runs_test(test_key_no_create_t)
+typeattribute test_key_no_create_t testdomain;
+typeattribute test_key_no_create_t keydomain;
+
+allow test_key_no_create_t self:process { setkeycreate };
+allow test_key_no_create_t self:key { write search read view link setattr };
+
+###################### Deny key { write } ###########################
+type test_key_no_write_t;
+key_domain_type(test_key_no_write_t)
+unconfined_runs_test(test_key_no_write_t)
+typeattribute test_key_no_write_t testdomain;
+typeattribute test_key_no_write_t keydomain;
+
+allow test_key_no_write_t self:process { setkeycreate };
+allow test_key_no_write_t self:key { create search read view link setattr };
+
+###################### Deny key { search } ###########################
+type test_key_no_search_t;
+key_domain_type(test_key_no_search_t)
+unconfined_runs_test(test_key_no_search_t)
+typeattribute test_key_no_search_t testdomain;
+typeattribute test_key_no_search_t keydomain;
+
+allow test_key_no_search_t self:process { setkeycreate };
+allow test_key_no_search_t self:key { create write read view link setattr };
+
+###################### Deny key { view } ###########################
+type test_key_no_view_t;
+key_domain_type(test_key_no_view_t)
+unconfined_runs_test(test_key_no_view_t)
+typeattribute test_key_no_view_t testdomain;
+typeattribute test_key_no_view_t keydomain;
+
+allow test_key_no_view_t self:process { setkeycreate };
+allow test_key_no_view_t self:key { create write search read link setattr };
+
+###################### Deny key { read } ###########################
+type test_key_no_read_t;
+key_domain_type(test_key_no_read_t)
+unconfined_runs_test(test_key_no_read_t)
+typeattribute test_key_no_read_t testdomain;
+typeattribute test_key_no_read_t keydomain;
+
+allow test_key_no_read_t self:process { setkeycreate };
+allow test_key_no_read_t self:key { create write search view link setattr };
+
+###################### Deny key { link } ###########################
+type test_key_no_link_t;
+key_domain_type(test_key_no_link_t)
+unconfined_runs_test(test_key_no_link_t)
+typeattribute test_key_no_link_t testdomain;
+typeattribute test_key_no_link_t keydomain;
+
+allow test_key_no_link_t self:process { setkeycreate };
+allow test_key_no_link_t self:key { create write search read view setattr };
+
+###################### Deny key { setattr } ###########################
+type test_key_no_setattr_t;
+key_domain_type(test_key_no_setattr_t)
+unconfined_runs_test(test_key_no_setattr_t)
+typeattribute test_key_no_setattr_t testdomain;
+typeattribute test_key_no_setattr_t keydomain;
+
+allow test_key_no_setattr_t self:process { setkeycreate };
+allow test_key_no_setattr_t self:key { create write search read view link };
+
+#
+######################## Test key_socket class ###########################
+#
+type test_key_sock_t;
+domain_type(test_key_sock_t)
+unconfined_runs_test(test_key_sock_t)
+typeattribute test_key_sock_t testdomain;
+typeattribute test_key_sock_t keydomain;
+
+# key_socket rules:
+allow test_key_sock_t self:rawip_socket { create };
+allow test_key_sock_t self:capability { net_admin };
+allow test_key_sock_t self:key_socket { create write };
+# For CONFIG_NET_KEY=m
+allow test_key_sock_t kernel_t:system { module_request };
+
+################## Deny capability { net_admin } ##########################
+type test_key_sock_no_net_admin_t;
+domain_type(test_key_sock_no_net_admin_t)
+unconfined_runs_test(test_key_sock_no_net_admin_t)
+typeattribute test_key_sock_no_net_admin_t testdomain;
+typeattribute test_key_sock_no_net_admin_t keydomain;
+
+# key_socket rules:
+allow test_key_sock_no_net_admin_t self:rawip_socket { create };
+allow test_key_sock_no_net_admin_t self:key_socket { create write };
+
+####################### Deny key_socket { create } ##########################
+type test_key_sock_no_create_t;
+domain_type(test_key_sock_no_create_t)
+unconfined_runs_test(test_key_sock_no_create_t)
+typeattribute test_key_sock_no_create_t testdomain;
+typeattribute test_key_sock_no_create_t keydomain;
+
+# key_socket rules:
+allow test_key_sock_no_create_t self:rawip_socket { create };
+allow test_key_sock_no_create_t self:capability { net_admin };
+allow test_key_sock_no_create_t self:key_socket { write };
+
+#
+########### Allow these domains to be entered from sysadm domain ############
+#
+miscfiles_domain_entry_test_files(keydomain)
+userdom_sysadm_entry_spec_domtrans_to(keydomain)
diff --git a/tests/Makefile b/tests/Makefile
index 63aa325..d1dbf38 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -42,6 +42,10 @@ ifeq ($(shell grep -q binder $(POLDEV)/include/support/all_perms.spt && test -e
 SUBDIRS += binder
 endif
 
+ifeq ($(shell grep -q key_socket $(POLDEV)/include/support/all_perms.spt && test -e $(INCLUDEDIR)/keyutils.h && echo true),true)
+SUBDIRS += keys
+endif
+
 ifeq ($(shell grep "^SELINUX_INFINIBAND_ENDPORT_TEST=" infiniband_endport/ibendport_test.conf | cut -d'=' -f 2),1)
 SUBDIRS += infiniband_endport
 endif
diff --git a/tests/keys/.gitignore b/tests/keys/.gitignore
new file mode 100644
index 0000000..4a0a48d
--- /dev/null
+++ b/tests/keys/.gitignore
@@ -0,0 +1,3 @@
+keyctl
+keyctl_relabel
+key_sock
diff --git a/tests/keys/Makefile b/tests/keys/Makefile
new file mode 100644
index 0000000..3a00df5
--- /dev/null
+++ b/tests/keys/Makefile
@@ -0,0 +1,8 @@
+TARGETS = keyctl key_sock keyctl_relabel
+
+LDLIBS += -lselinux -lkeyutils
+
+all: $(TARGETS)
+
+clean:
+	rm -f $(TARGETS)
diff --git a/tests/keys/key_sock.c b/tests/keys/key_sock.c
new file mode 100644
index 0000000..8ac1f45
--- /dev/null
+++ b/tests/keys/key_sock.c
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <linux/pfkeyv2.h>
+#include <selinux/selinux.h>
+
+static void usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-v]\n"
+		"Where:\n\t"
+		"-v  Print information.\n", progname);
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	char *context;
+	int opt, sock, result;
+	bool verbose = false;
+
+	while ((opt = getopt(argc, argv, "v")) != -1) {
+		switch (opt) {
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	result = getcon(&context);
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain process context\n");
+		exit(-1);
+	}
+	if (verbose)
+		printf("Process context: %s\n", context);
+
+	sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+	if (sock < 0) {
+		fprintf(stderr, "Failed to open PF_KEY socket: %s\n",
+			strerror(errno));
+		exit(errno);
+	}
+	if (verbose)
+		printf("Opened PF_KEY socket\n");
+
+	/* Write nothing to socket for test, expect EMSGSIZE error */
+	result = write(sock, NULL, 0);
+	if (result < 0 && errno == EMSGSIZE) {
+		result = 0;
+		if (verbose)
+			printf("Written to PF_KEY socket\n");
+	} else if (result < 0 && errno != EMSGSIZE) {
+		result = -1;
+		fprintf(stderr, "Failed write to PF_KEY socket: %s\n",
+			strerror(errno));
+	}
+
+	close(sock);
+	return result;
+}
diff --git a/tests/keys/keyctl.c b/tests/keys/keyctl.c
new file mode 100644
index 0000000..6d85be7
--- /dev/null
+++ b/tests/keys/keyctl.c
@@ -0,0 +1,241 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <keyutils.h>
+#include <selinux/selinux.h>
+
+/* This is used as the payload for each add_key() */
+static const char payload[] =
+	" -----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDN4FHsPjlJf03r9KfNt1Ma9/D6\nQDEiR/cfhZrNUPgHRrC+E4dj52VJSonPFJ6HaLlUi5pZq2t1LqPNrMfFKCNn12m+\nWw4aduBJM7u1RUPSNxrlfDAJZkdtNALOO/ds3U93hZrxOYNetzbnjILDu5JT1nbI\n4aC60SkdlCw1TxmvXwIDAQAB\n-----END PUBLIC KEY-----\n";
+
+static void usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-v]\n"
+		"Where:\n\t"
+		"-v  Print information.\n", progname);
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	int opt, result;
+	char *context, *keycreate_con;
+	char r_con[256];
+	bool verbose = false;
+	key_serial_t retrieved, search, link, compute, newring,
+		     private, prime, base, test_key;
+	struct keyctl_dh_params params;
+
+	while ((opt = getopt(argc, argv, "v")) != -1) {
+		switch (opt) {
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	result = getcon(&context);
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain process context\n");
+		exit(1);
+	}
+	if (verbose)
+		printf("Process context: %s\n", context);
+
+	result = getkeycreatecon(&keycreate_con);
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain keycreate context\n");
+		exit(2);
+	}
+	if (verbose)
+		printf("Current keycreate context: %s\n", keycreate_con);
+	free(keycreate_con);
+
+	/* Set context requires process { setkeycreate } and key { create } */
+	result = setkeycreatecon(context);
+	if (result < 0) {
+		fprintf(stderr, "Failed setkeycreatecon(): %s\n",
+			strerror(errno));
+		exit(3);
+	}
+	if (verbose)
+		printf("Set keycreate context: %s\n", context);
+	free(context);
+
+	result = getkeycreatecon(&keycreate_con);
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain keycreate context\n");
+		exit(4);
+	}
+	if (verbose)
+		printf("New keycreate context: %s\n", keycreate_con);
+	free(keycreate_con);
+
+	/*
+	 * Add three keys as these will be required by the
+	 * keyctl(KEYCTL_DH_COMPUTE, ..) function.
+	 * These require key { create write } permissions.
+	 */
+	private = add_key("user", "private", payload, strlen(payload),
+			  KEY_SPEC_PROCESS_KEYRING);
+	if (private < 0) {
+		fprintf(stderr, "Failed add_key(private): %s\n",
+			strerror(errno));
+		exit(5);
+	}
+
+	prime = add_key("user", "prime", payload, strlen(payload),
+			KEY_SPEC_PROCESS_KEYRING);
+	if (prime < 0) {
+		fprintf(stderr, "Failed add_key(prime): %s\n",
+			strerror(errno));
+		exit(6);
+	}
+
+	base = add_key("user", "base", payload, strlen(payload),
+		       KEY_SPEC_PROCESS_KEYRING);
+	if (base < 0) {
+		fprintf(stderr, "Failed add_key(base): %s\n",
+			strerror(errno));
+		exit(7);
+	}
+
+	if (verbose) {
+		printf("Private key ID: 0x%x\n", private);
+		printf("Prime key ID:   0x%x\n", prime);
+		printf("Base key ID:    0x%x\n", base);
+	}
+
+	/* Requires key { search }. From kernel 5.3 also requires { link } */
+	retrieved = request_key("user", "private", NULL,
+				KEY_SPEC_PROCESS_KEYRING);
+	if (retrieved < 0) {
+		fprintf(stderr, "Failed to request 'private' key: %s\n",
+			strerror(errno));
+		exit(8);
+	}
+
+	/* Requires key { search } */
+	search = keyctl(KEYCTL_SEARCH, KEY_SPEC_PROCESS_KEYRING, "user",
+			"base", 0);
+	if (search < 0) {
+		fprintf(stderr, "Failed to find 'base' key: %s\n",
+			strerror(errno));
+		exit(9);
+	}
+
+	/* Requires key { view } */
+	result = keyctl(KEYCTL_GET_SECURITY, search, r_con, sizeof(r_con));
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain key context: %s\n",
+			strerror(errno));
+		exit(10);
+	}
+
+	if (verbose) {
+		printf("Requested 'private' key ID: 0x%x\n", retrieved);
+		printf("Searched 'base' key ID:     0x%x\n", search);
+		printf("Searched 'base' key context:\n\t%s\n", r_con);
+	}
+
+	/* Compute DH key, only obtain the length for test, not the key. */
+	params.priv = private;
+	params.prime = prime;
+	params.base = base;
+
+	/* Requires key { create read write } */
+	compute = keyctl(KEYCTL_DH_COMPUTE, &params, NULL, 0, 0);
+	if (compute < 0) {
+		fprintf(stderr, "Failed KEYCTL_DH_COMPUTE: %s\n",
+			strerror(errno));
+		exit(11);
+	}
+	if (verbose)
+		printf("KEYCTL_DH_COMPUTE key ID size: %d\n", compute);
+
+	/* To test key { link }, need to generate a new keyring ID first */
+	newring = add_key("keyring", "my-keyring", NULL, 0,
+			  KEY_SPEC_THREAD_KEYRING);
+	if (newring < 0) {
+		fprintf(stderr, "Failed to add new keyring: %s\n",
+			strerror(errno));
+		exit(12);
+	}
+	if (verbose)
+		printf("New keyring ID: 0x%x\n", newring);
+
+	/* Requires key { write link } */
+	link = keyctl(KEYCTL_LINK, base, newring);
+	if (link < 0) {
+		fprintf(stderr, "Failed KEYCTL_LINK: %s\n",
+			strerror(errno));
+		exit(13);
+	}
+	if (verbose)
+		printf("Link key ID:    0x%x\n", newring);
+
+	/* Requires key { setattr } */
+	link = keyctl(KEYCTL_RESTRICT_KEYRING, newring, NULL, NULL);
+	if (link < 0) {
+		fprintf(stderr, "Failed KEYCTL_RESTRICT_KEYRING: %s\n",
+			strerror(errno));
+		exit(14);
+	}
+	if (verbose)
+		printf("Restricted keyring\n");
+
+	/* Requires key { search } from 5.X key { inval } */
+	test_key = keyctl(KEYCTL_INVALIDATE, private);
+	if (test_key < 0) {
+		fprintf(stderr, "Failed KEYCTL_INVALIDATE(private): %s\n",
+			strerror(errno));
+		exit(15);
+	}
+	if (verbose)
+		printf("Invalidated 'private' key\n");
+
+	/* Requires key { write setattr } from 5.X key { revoke } */
+	test_key = keyctl(KEYCTL_REVOKE, prime);
+	if (test_key < 0) {
+		fprintf(stderr, "Failed KEYCTL_REVOKE(prime): %s\n",
+			strerror(errno));
+		exit(16);
+	}
+	if (verbose)
+		printf("Revoked 'prime' key\n");
+
+	/* Requires key { write } from 5.X key { clear } */
+	test_key = keyctl(KEYCTL_CLEAR, newring);
+	if (test_key < 0) {
+		fprintf(stderr, "Failed KEYCTL_CLEAR(newring): %s\n",
+			strerror(errno));
+		exit(17);
+	}
+	if (verbose)
+		printf("Cleared 'newring' keyring\n");
+
+	/* To test key { join }, need to join session first */
+	test_key = keyctl(KEYCTL_JOIN_SESSION_KEYRING, "user");
+	if (test_key < 0) {
+		fprintf(stderr, "Failed KEYCTL_JOIN_SESSION_KEYRING,: %s\n",
+			strerror(errno));
+		exit(18);
+	}
+	/* Requires key { link } from 5.X key { join } */
+	test_key = keyctl(KEYCTL_SESSION_TO_PARENT);
+	if (test_key < 0) {
+		fprintf(stderr, "Failed KEYCTL_SESSION_TO_PARENT: %s\n",
+			strerror(errno));
+		exit(19);
+	}
+	if (verbose)
+		printf("Joined session to parent\n");
+
+	return 0;
+}
diff --git a/tests/keys/keyctl_relabel.c b/tests/keys/keyctl_relabel.c
new file mode 100644
index 0000000..0276c7a
--- /dev/null
+++ b/tests/keys/keyctl_relabel.c
@@ -0,0 +1,93 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <keyutils.h>
+#include <selinux/selinux.h>
+
+static void usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-v] newcon\n"
+		"Where:\n\t"
+		"-v      Print information.\n\t"
+		"newcon  New keyring context.\n", progname);
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	int opt, result;
+	char *context, *keycreate_con;
+	char r_con[256];
+	bool verbose = false;
+	key_serial_t newring;
+
+	while ((opt = getopt(argc, argv, "v")) != -1) {
+		switch (opt) {
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	if (optind >= argc)
+		usage(argv[0]);
+
+	result = getcon(&context);
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain process context\n");
+		exit(1);
+	}
+	if (verbose)
+		printf("Process context: %s\n", context);
+	free(context);
+
+	result = setkeycreatecon(argv[optind]);
+	if (result < 0) {
+		fprintf(stderr, "Failed setkeycreatecon(): %s\n",
+			strerror(errno));
+		exit(2);
+	}
+
+	result = getkeycreatecon(&keycreate_con);
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain keycreate context\n");
+		exit(3);
+	}
+	if (verbose)
+		printf("New keycreate context: %s\n", keycreate_con);
+	free(keycreate_con);
+
+	newring = add_key("keyring", "my-keyring", NULL, 0,
+			  KEY_SPEC_THREAD_KEYRING);
+	if (newring < 0) {
+		fprintf(stderr, "Failed to add new keyring: %s\n",
+			strerror(errno));
+		exit(4);
+	}
+
+	result = keyctl(KEYCTL_GET_SECURITY, newring, r_con, sizeof(r_con));
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain key context: %s\n",
+			strerror(errno));
+		exit(5);
+	}
+
+	if (strcmp(argv[optind], r_con)) {
+		fprintf(stderr, "Relabel error - expected: %s got: %s\n",
+			argv[optind], r_con);
+		exit(6);
+	}
+
+	if (verbose) {
+		printf("'my-keyring' key ID: 0x%x\n", newring);
+		printf("'my-keyring' context:\n\t%s\n", r_con);
+	}
+
+	return 0;
+}
diff --git a/tests/keys/test b/tests/keys/test
new file mode 100755
index 0000000..4916e7c
--- /dev/null
+++ b/tests/keys/test
@@ -0,0 +1,98 @@
+#!/usr/bin/perl
+use Test::More;
+
+BEGIN {
+    $basedir = $0;
+    $basedir =~ s|(.*)/[^/]*|$1|;
+
+    $test_count = 13;
+
+    # 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 = " ";
+    }
+
+    # From kernel 5.3 request_key() requires additional check of key { link }
+    $kvercur = `uname -r`;
+    chomp($kvercur);
+    $kverminstream = "5.3";
+    $test_link_53  = 0;
+
+    $result = `$basedir/../kvercmp $kvercur $kverminstream`;
+    if ( $result >= 0 ) {
+        $test_link_53 = 1;
+    }
+
+    plan tests => $test_count;
+}
+
+############ Test keyctl #############
+print "Test key class permissions\n";
+$result = system "runcon -t test_key_t $basedir/keyctl $v";
+ok( $result eq 0 );
+
+# Deny process { setkeycreate }
+$result = system "runcon -t test_no_setkeycreate_t $basedir/keyctl $v 2>&1";
+ok( $result >> 8 eq 3 );
+
+# Deny key { create }
+$result = system "runcon -t test_key_no_create_t $basedir/keyctl $v 2>&1";
+ok( $result >> 8 eq 3 );
+
+# Deny key { write }
+$result = system "runcon -t test_key_no_write_t $basedir/keyctl $v 2>&1";
+ok( $result >> 8 eq 5 );
+
+# Deny key { search }
+$result = system "runcon -t test_key_no_search_t $basedir/keyctl $v 2>&1";
+ok( $result >> 8 eq 8 );
+
+# Deny key { view }
+$result = system "runcon -t test_key_no_view_t $basedir/keyctl $v 2>&1";
+ok( $result >> 8 eq 10 );
+
+# Deny key { read }
+$result = system "runcon -t test_key_no_read_t $basedir/keyctl $v 2>&1";
+ok( $result >> 8 eq 11 );
+
+# Deny key { link }
+$result = system "runcon -t test_key_no_link_t $basedir/keyctl $v 2>&1";
+if ($test_link_53) {
+    ok( $result >> 8 eq 8 );
+}
+else {
+    ok( $result >> 8 eq 13 );
+}
+
+# Deny key { setattr }
+$result = system "runcon -t test_key_no_setattr_t $basedir/keyctl $v 2>&1";
+ok( $result >> 8 eq 14 );
+
+########### Change keyring context ##############
+print "Change keyring context\n";
+$result = system
+"runcon -t test_key_t $basedir/keyctl_relabel $v system_u:system_r:test_newcon_key_t:s0";
+ok( $result eq 0 );
+
+############ Test key_socket #############
+print "Test key_socket class\n";
+$result = system "runcon -t test_key_sock_t $basedir/key_sock $v";
+ok( $result eq 0 );
+
+# Deny capability { net_admin } - EPERM
+$result =
+  system "runcon -t test_key_sock_no_net_admin_t $basedir/key_sock $v 2>&1";
+ok( $result >> 8 eq 1 );
+
+# Deny key_socket { create } - EACCES
+$result =
+  system "runcon -t test_key_sock_no_create_t $basedir/key_sock $v 2>&1";
+ok( $result >> 8 eq 13 );
+
+exit;
-- 
2.21.0


             reply	other threads:[~2019-09-09 13:17 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-09 13:17 Richard Haines [this message]
2019-09-16 17:58 ` [PATCH] selinux-testsuite: Add key and key_socket tests Stephen Smalley
2019-09-16 18:55   ` Richard Haines
2019-09-16 19:11     ` Stephen Smalley
2019-09-16 19:23       ` Richard Haines
2019-09-16 19:39         ` Stephen Smalley
2019-09-17  7:04 ` Ondrej Mosnacek
2019-09-19 16:29   ` Richard Haines

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=20190909131701.29588-1-richard_c_haines@btinternet.com \
    --to=richard_c_haines@btinternet.com \
    --cc=paul@paul-moore.com \
    --cc=selinux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.