[PATCH] selinux-testsuite: Add tests for extended socket classes.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add tests for the extended_socket_class policy capability.
This change includes the following tests:
- Test that ICMP datagram sockets are mapped to the new icmp_socket
class and not to rawip_socket for both IPv4 and IPv6.

- Test that SCTP stream and seqpacket sockets are mapped to the
new sctp_socket class and not to rawip_socket for both IPv4 and IPv6.

- Test that Bluetooth sockets are mapped to the new bluetooth_socket
class and not to socket.

- Test that AF_ALG sockets are mapped to the new alg_socket class
and not to socket.

The tests are only run if the extended_socket_class policy capability
is present and enabled in the kernel and the base policy, and only if
the new classes are defined in the base policy.  This avoids breaking
the testsuite on systems with older kernels, older policies, or
policies that do not enable the policy capability.

Signed-off-by: Stephen Smalley <sds@xxxxxxxxxxxxx>
---
 README                                   |  8 +++
 policy/Makefile                          |  4 ++
 policy/test_extended_socket_class.te     | 64 +++++++++++++++++++++++
 tests/Makefile                           |  4 ++
 tests/extended_socket_class/Makefile     |  4 ++
 tests/extended_socket_class/sockcreate.c | 89 ++++++++++++++++++++++++++++++++
 tests/extended_socket_class/test         | 76 +++++++++++++++++++++++++++
 7 files changed, 249 insertions(+)
 create mode 100644 policy/test_extended_socket_class.te
 create mode 100644 tests/extended_socket_class/Makefile
 create mode 100644 tests/extended_socket_class/sockcreate.c
 create mode 100755 tests/extended_socket_class/test

diff --git a/README b/README
index 8dbbbda..521e965 100644
--- a/README
+++ b/README
@@ -39,6 +39,14 @@ CONFIG_JFS_SECURITY=y
 CONFIG_XFS_SECURITY=y
 CONFIG_JFFS2_FS_SECURITY=y
 
+# Network protocol implementations.
+# These are enabled to test the extended socket classes in
+# tests/extended_socket_class; they are not required
+# for SELinux operation itself.
+CONFIG_IP_SCTP=m
+CONFIG_BT=m
+CONFIG_CRYPTO_USER_API=m
+
 Do not set CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX; it is an
 option for legacy distributions (Fedora 3 and 4).
 
diff --git a/policy/Makefile b/policy/Makefile
index 16ab3b9..992278b 100644
--- a/policy/Makefile
+++ b/policy/Makefile
@@ -30,6 +30,10 @@ ifeq ($(shell grep -q cap_userns $(POLDEV)/include/support/all_perms.spt && echo
 TARGETS += test_cap_userns.te
 endif
 
+ifeq ($(shell grep -q icmp_socket $(POLDEV)/include/support/all_perms.spt && echo true),true)
+TARGETS += test_extended_socket_class.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_extended_socket_class.te b/policy/test_extended_socket_class.te
new file mode 100644
index 0000000..4f30c9f
--- /dev/null
+++ b/policy/test_extended_socket_class.te
@@ -0,0 +1,64 @@
+########################################
+#
+# Policy for testing the new socket classes
+# introduced when the extended_socket_class
+# policy capability is enabled in policy and
+# supported by the kernel.
+
+attribute extsocktestdomain;
+
+#
+# extended_socket_test(newclass, oldclass)
+#
+# Generate a pair of test domains and rules to test
+# that when the extended_socket_class policy capability
+# is enabled, the kernel checks permission against the
+# 'newclass' security class rather than the 'oldclass'
+# security class.
+#
+define(`extended_socket_class_test', `
+# Domain that is allowed to create $1_socket.
+type test_$1_t;
+domain_type(test_$1_t)
+unconfined_runs_test(test_$1_t)
+typeattribute test_$1_t extsocktestdomain;
+typeattribute test_$1_t testdomain;
+
+# Allow $1 but not $2.
+# This is to ensure that the kernel is checking the right class.
+allow test_$1_t self:$1 create_socket_perms;
+
+# Domain that is not allowed to create $1.
+type test_no_$1_t;
+domain_type(test_no_$1_t)
+unconfined_runs_test(test_no_$1_t)
+typeattribute test_no_$1_t extsocktestdomain;
+typeattribute test_no_$1_t testdomain;
+
+# Allow $2 but not $1.
+# This is to ensure that the kernel is checking the right class.
+allow test_no_$1_t self:$2 create_socket_perms;
+')
+
+# Test use of icmp_socket class for ICMP datagram sockets instead of rawip_socket.
+extended_socket_class_test(icmp_socket, rawip_socket)
+
+# Test use of sctp_socket class for SCTP sockets instead of rawip_socket.
+extended_socket_class_test(sctp_socket, rawip_socket)
+
+# Test use of bluetooth_socket for Bluetooth sockets instead of socket.
+extended_socket_class_test(bluetooth_socket, socket)
+
+# Test use of alg_socket for Alg (Crypto API) sockets instead of socket.
+extended_socket_class_test(alg_socket, socket)
+
+#
+# Common rules for all extended_socket_class test domains.
+#
+
+# Trigger kernel module auto-loading of the network protocol implementations.
+kernel_request_load_module(extsocktestdomain)
+
+# Entry into the test domains via the test program.
+miscfiles_domain_entry_test_files(extsocktestdomain)
+userdom_sysadm_entry_spec_domtrans_to(extsocktestdomain)
diff --git a/tests/Makefile b/tests/Makefile
index 57a5d12..228b764 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -16,6 +16,10 @@ ifeq ($(shell grep -q cap_userns $(POLDEV)/include/support/all_perms.spt && echo
 SUBDIRS += cap_userns
 endif
 
+ifeq ($(shell grep -q icmp_socket $(POLDEV)/include/support/all_perms.spt && grep -q 1 /sys/fs/selinux/policy_capabilities/extended_socket_class && echo true),true)
+SUBDIRS += extended_socket_class
+endif
+
 ifeq ($(DISTRO),RHEL4)
     SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap nnp overlay unix_socket, $(SUBDIRS))
 endif
diff --git a/tests/extended_socket_class/Makefile b/tests/extended_socket_class/Makefile
new file mode 100644
index 0000000..8dce555
--- /dev/null
+++ b/tests/extended_socket_class/Makefile
@@ -0,0 +1,4 @@
+TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+all: $(TARGETS)
+clean:
+	rm -f $(TARGETS)
diff --git a/tests/extended_socket_class/sockcreate.c b/tests/extended_socket_class/sockcreate.c
new file mode 100644
index 0000000..c5802ae
--- /dev/null
+++ b/tests/extended_socket_class/sockcreate.c
@@ -0,0 +1,89 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+struct nameval {
+	const char *name;
+	const int value;
+};
+
+static struct nameval domains[] = {
+	{ "inet", AF_INET },
+	{ "inet6", AF_INET6 },
+	{ "bluetooth", AF_BLUETOOTH },
+	{ "alg", AF_ALG },
+	{ NULL, 0 }
+};
+
+static struct nameval types[] = {
+	{ "stream", SOCK_STREAM },
+	{ "dgram", SOCK_DGRAM },
+	{ "seqpacket", SOCK_SEQPACKET },
+	{ "raw", SOCK_RAW },
+	{ NULL, 0 }
+};
+
+static struct nameval protocols[] = {
+	{ "icmp", IPPROTO_ICMP },
+	{ "icmpv6", IPPROTO_ICMPV6 },
+	{ "sctp", IPPROTO_SCTP },
+	{ "default", 0 },
+	{ NULL, 0 }
+};
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static int lookup_value(const char *name, const struct nameval *nvlist)
+{
+	const struct nameval *nv;
+
+	for (nv = nvlist; nv->name; nv++) {
+		if (!strcmp(nv->name, name))
+			return nv->value;
+	}
+	return -1;
+}
+
+int main(int argc, char **argv)
+{
+	int sock;
+	int domain, type, protocol;
+
+	if (argc != 4) {
+		fprintf(stderr, "usage: %s domain type protocol\n", argv[0]);
+		exit(1);
+	}
+
+	domain = lookup_value(argv[1], domains);
+	if (domain < 0) {
+		fprintf(stderr, "%s: unknown domain %s\n", argv[0], argv[1]);
+		exit(1);
+	}
+
+	type = lookup_value(argv[2], types);
+	if (type < 0) {
+		fprintf(stderr, "%s: unknown type %s\n", argv[0], argv[2]);
+		exit(1);
+	}
+
+	protocol = lookup_value(argv[3], protocols);
+	if (protocol < 0) {
+		fprintf(stderr, "%s: unknown protocol %s\n", argv[0], argv[3]);
+		exit(1);
+	}
+
+	sock = socket(domain, type, protocol);
+	if (sock < 0) {
+		fprintf(stderr, "%s: socket(%s/%d, %s/%d, %s/%d): %s\n",
+			argv[0], argv[1], domain, argv[2], type,
+			argv[3], protocol, strerror(errno));
+		exit(1);
+	}
+	close(sock);
+	exit(0);
+}
diff --git a/tests/extended_socket_class/test b/tests/extended_socket_class/test
new file mode 100755
index 0000000..eb100ee
--- /dev/null
+++ b/tests/extended_socket_class/test
@@ -0,0 +1,76 @@
+#!/usr/bin/perl
+
+use Test;
+BEGIN { plan tests => 16 };
+
+$basedir = $0;  $basedir =~ s|(.*)/[^/]*|$1|;
+
+# Enable gid 0 to create ICMP sockets for testing.
+system("echo 0 0 > /proc/sys/net/ipv4/ping_group_range");
+
+# Verify that test_icmp_socket_t can create an ICMP socket.
+$result = system("runcon -t test_icmp_socket_t -- $basedir/sockcreate inet dgram icmp 2>&1");
+ok($result, 0);
+
+# Verify that test_no_icmp_socket_t cannot create an ICMP socket.
+$result = system("runcon -t test_no_icmp_socket_t -- $basedir/sockcreate inet dgram icmp 2>&1");
+ok($result);
+
+# Verify that test_icmp_socket_t can create an ICMPv6 socket.
+$result = system("runcon -t test_icmp_socket_t -- $basedir/sockcreate inet6 dgram icmpv6 2>&1");
+ok($result, 0);
+
+# Verify that test_no_icmp_socket_t cannot create an ICMPv6 socket.
+$result = system("runcon -t test_no_icmp_socket_t -- $basedir/sockcreate inet6 dgram icmpv6 2>&1");
+ok($result);
+
+# Restore to the kernel defaults - no one allowed to create ICMP sockets.
+system("echo 1 0 > /proc/sys/net/ipv4/ping_group_range");
+
+# Verify that test_sctp_socket_t can create an IPv4 stream SCTP socket.
+$result = system("runcon -t test_sctp_socket_t -- $basedir/sockcreate inet stream sctp 2>&1");
+ok($result, 0);
+
+# Verify that test_no_sctp_socket_t cannot create an IPv4 stream SCTP socket.
+$result = system("runcon -t test_no_sctp_socket_t -- $basedir/sockcreate inet stream sctp 2>&1");
+ok($result);
+
+# Verify that test_sctp_socket_t can create an IPv4 seqpacket SCTP socket.
+$result = system("runcon -t test_sctp_socket_t -- $basedir/sockcreate inet seqpacket sctp 2>&1");
+ok($result, 0);
+
+# Verify that test_no_sctp_socket_t cannot create an IPv4 seqpacket SCTP socket.
+$result = system("runcon -t test_no_sctp_socket_t -- $basedir/sockcreate inet seqpacket sctp 2>&1");
+ok($result);
+
+# Verify that test_sctp_socket_t can create an IPv6 stream SCTP socket.
+$result = system("runcon -t test_sctp_socket_t -- $basedir/sockcreate inet6 stream sctp 2>&1");
+ok($result, 0);
+
+# Verify that test_no_sctp_socket_t cannot create an IPv6 stream SCTP socket.
+$result = system("runcon -t test_no_sctp_socket_t -- $basedir/sockcreate inet6 stream sctp 2>&1");
+ok($result);
+
+# Verify that test_sctp_socket_t can create an IPv6 seqpacket SCTP socket.
+$result = system("runcon -t test_sctp_socket_t -- $basedir/sockcreate inet6 seqpacket sctp 2>&1");
+ok($result, 0);
+
+# Verify that test_no_sctp_socket_t cannot create an IPv6 seqpacket SCTP socket.
+$result = system("runcon -t test_no_sctp_socket_t -- $basedir/sockcreate inet6 seqpacket sctp 2>&1");
+ok($result);
+
+# Verify that test_bluetooth_socket_t can create a Bluetooth socket.
+$result = system("runcon -t test_bluetooth_socket_t -- $basedir/sockcreate bluetooth stream default 2>&1");
+ok($result, 0);
+
+# Verify that test_no_bluetooth_socket_t cannot create a Bluetooth socket.
+$result = system("runcon -t test_no_bluetooth_socket_t -- $basedir/sockcreate bluetooth stream default 2>&1");
+ok($result);
+
+# Verify that test_alg_socket_t can create a Crypto API socket.
+$result = system("runcon -t test_alg_socket_t -- $basedir/sockcreate alg seqpacket default 2>&1");
+ok($result, 0);
+
+# Verify that test_no_alg_socket_t cannot create a Crypto API socket.
+$result = system("runcon -t test_no_alg_socket_t -- $basedir/sockcreate alg seqpacket default 2>&1");
+ok($result);
-- 
2.7.4

_______________________________________________
Selinux mailing list
Selinux@xxxxxxxxxxxxx
To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx.
To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.



[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux