SELinux Archive on lore.kernel.org
 help / color / Atom feed
From: Richard Haines <richard_c_haines@btinternet.com>
To: selinux@vger.kernel.org
Cc: Richard Haines <richard_c_haines@btinternet.com>
Subject: [PATCH] selinux-testsuite: Add TUN/TAP driver tests
Date: Sun,  1 Dec 2019 16:58:20 +0000
Message-ID: <20191201165820.285680-1-richard_c_haines@btinternet.com> (raw)

Test TUN/TAP tun_socket permissions.

Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
Changes from RFC patch:
Remove BPF tests
Replace gen_require 'tun_tap_device_t' with corenet_rw_tun_tap_dev

 defconfig                   |   4 ++
 policy/Makefile             |   4 ++
 policy/test_tun_tap.te      | 113 ++++++++++++++++++++++++++++++++
 tests/Makefile              |   4 ++
 tests/tun_tap/.gitignore    |   2 +
 tests/tun_tap/Makefile      |  10 +++
 tests/tun_tap/test          |  88 +++++++++++++++++++++++++
 tests/tun_tap/tun_common.c  | 100 +++++++++++++++++++++++++++++
 tests/tun_tap/tun_common.h  |  22 +++++++
 tests/tun_tap/tun_relabel.c | 124 ++++++++++++++++++++++++++++++++++++
 tests/tun_tap/tun_tap.c     | 123 +++++++++++++++++++++++++++++++++++
 11 files changed, 594 insertions(+)
 create mode 100644 policy/test_tun_tap.te
 create mode 100644 tests/tun_tap/.gitignore
 create mode 100644 tests/tun_tap/Makefile
 create mode 100755 tests/tun_tap/test
 create mode 100644 tests/tun_tap/tun_common.c
 create mode 100644 tests/tun_tap/tun_common.h
 create mode 100644 tests/tun_tap/tun_relabel.c
 create mode 100644 tests/tun_tap/tun_tap.c

diff --git a/defconfig b/defconfig
index 0574f1d..abf8df4 100644
--- a/defconfig
+++ b/defconfig
@@ -78,3 +78,7 @@ CONFIG_KEY_DH_OPERATIONS=y
 # Test key management socket.
 # This is not required for SELinux operation itself.
 CONFIG_NET_KEY=m
+
+# Test TUN/TAP driver support.
+# This is not required for SELinux operation itself.
+CONFIG_TUN=m
diff --git a/policy/Makefile b/policy/Makefile
index 87b2856..46a6ab4 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 tun_socket $(POLDEV)/include/support/all_perms.spt && echo true),true)
+TARGETS += test_tun_tap.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_tun_tap.te b/policy/test_tun_tap.te
new file mode 100644
index 0000000..e1731ff
--- /dev/null
+++ b/policy/test_tun_tap.te
@@ -0,0 +1,113 @@
+#
+########### Test TUN/TAP device driver support - 'tun_socket' ##############
+#
+attribute tuntapdomain;
+
+# For CONFIG_TUN=m
+kernel_request_load_module(tuntapdomain)
+
+type test_tun_tap_t;
+domain_type(test_tun_tap_t)
+unconfined_runs_test(test_tun_tap_t)
+typeattribute test_tun_tap_t testdomain;
+typeattribute test_tun_tap_t tuntapdomain;
+
+# tun_socket rules:
+allow test_tun_tap_t self:capability { net_admin };
+corenet_rw_tun_tap_dev(test_tun_tap_t)
+allow test_tun_tap_t self:tun_socket { create attach_queue };
+
+################## Deny capability { net_admin } ##########################
+#
+# Note that when capability { net_admin } is removed for the test
+# there will not be an audit message in the log as the Fedora policy
+# is built with 'hide_broken_symptoms' that adds the following:
+#   dontaudit test_tun_tap_no_net_admin_t self:capability { net_admin sys_module };
+#
+type test_tun_tap_no_net_admin_t;
+domain_type(test_tun_tap_no_net_admin_t)
+unconfined_runs_test(test_tun_tap_no_net_admin_t)
+typeattribute test_tun_tap_no_net_admin_t testdomain;
+typeattribute test_tun_tap_no_net_admin_t tuntapdomain;
+
+neverallow test_tun_tap_t self:capability { net_admin };
+corenet_rw_tun_tap_dev(test_tun_tap_no_net_admin_t)
+allow test_tun_tap_no_net_admin_t self:tun_socket { create write read setopt };
+
+####################### Deny tun_socket { create } ##########################
+type test_tun_tap_no_create_t;
+domain_type(test_tun_tap_no_create_t)
+unconfined_runs_test(test_tun_tap_no_create_t)
+typeattribute test_tun_tap_no_create_t testdomain;
+typeattribute test_tun_tap_no_create_t tuntapdomain;
+
+allow test_tun_tap_no_create_t self:capability { net_admin };
+corenet_rw_tun_tap_dev(test_tun_tap_no_create_t)
+neverallow test_tun_tap_no_create_t self:tun_socket { create };
+
+################## Deny tun_socket { attach_queue } ########################
+type test_tun_tap_no_queue_t;
+domain_type(test_tun_tap_no_queue_t)
+unconfined_runs_test(test_tun_tap_no_queue_t)
+typeattribute test_tun_tap_no_queue_t testdomain;
+typeattribute test_tun_tap_no_queue_t tuntapdomain;
+
+allow test_tun_tap_no_queue_t self:capability { net_admin };
+corenet_rw_tun_tap_dev(test_tun_tap_no_queue_t)
+allow test_tun_tap_no_queue_t self:tun_socket { create };
+neverallow test_tun_tap_no_queue_t self:tun_socket { attach_queue };
+
+#
+############ Test relabelto/relabelfrom via new context #####################
+type test_newcon_tun_tap_t;
+domain_type(test_newcon_tun_tap_t)
+unconfined_runs_test(test_newcon_tun_tap_t)
+typeattribute test_newcon_tun_tap_t testdomain;
+typeattribute test_newcon_tun_tap_t keydomain;
+
+allow test_tun_tap_t test_newcon_tun_tap_t:process { dyntransition };
+corenet_rw_tun_tap_dev(test_newcon_tun_tap_t)
+allow test_newcon_tun_tap_t test_tun_tap_t:tun_socket { relabelfrom };
+allow test_newcon_tun_tap_t self:tun_socket { relabelto };
+
+# For error handling when switching back to original context:
+allow test_newcon_tun_tap_t test_tun_tap_t:fd use;
+allow test_newcon_tun_tap_t test_tun_tap_t:process dyntransition;
+
+############ Deny relabelto via new context #####################
+type test_newcon_no_to_tun_tap_t;
+domain_type(test_newcon_no_to_tun_tap_t)
+unconfined_runs_test(test_newcon_no_to_tun_tap_t)
+typeattribute test_newcon_no_to_tun_tap_t testdomain;
+typeattribute test_newcon_no_to_tun_tap_t keydomain;
+
+allow test_tun_tap_t test_newcon_no_to_tun_tap_t:process { dyntransition };
+allow test_tun_tap_t test_newcon_no_to_tun_tap_t:fd { use };
+corenet_rw_tun_tap_dev(test_newcon_no_to_tun_tap_t)
+allow test_newcon_no_to_tun_tap_t test_tun_tap_t:tun_socket { relabelfrom };
+neverallow test_newcon_no_to_tun_tap_t self:tun_socket { relabelto };
+
+# For switch back on error:
+allow test_newcon_no_to_tun_tap_t test_tun_tap_t:process { dyntransition };
+
+############ Deny relabelfrom via new context #####################
+type test_newcon_no_from_tun_tap_t;
+domain_type(test_newcon_no_from_tun_tap_t)
+unconfined_runs_test(test_newcon_no_from_tun_tap_t)
+typeattribute test_newcon_no_from_tun_tap_t testdomain;
+typeattribute test_newcon_no_from_tun_tap_t keydomain;
+
+allow test_tun_tap_t test_newcon_no_from_tun_tap_t:process { dyntransition };
+corenet_rw_tun_tap_dev(test_newcon_no_from_tun_tap_t)
+neverallow test_newcon_no_from_tun_tap_t test_tun_tap_t:tun_socket { relabelfrom };
+allow test_newcon_no_from_tun_tap_t self:tun_socket { relabelto };
+
+# For switch back on error:
+allow test_tun_tap_t test_newcon_no_from_tun_tap_t:fd { use };
+allow test_newcon_no_from_tun_tap_t test_tun_tap_t:process { dyntransition };
+
+#
+########### Allow these domains to be entered from sysadm domain ############
+#
+miscfiles_domain_entry_test_files(tuntapdomain)
+userdom_sysadm_entry_spec_domtrans_to(tuntapdomain)
diff --git a/tests/Makefile b/tests/Makefile
index 1cdb1ac..df79099 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -78,6 +78,10 @@ SUBDIRS+=module_load
 endif
 endif
 
+ifeq ($(shell grep -q tun_socket $(POLDEV)/include/support/all_perms.spt && echo true),true)
+SUBDIRS += tun_tap
+endif
+
 ifeq ($(DISTRO),RHEL4)
     SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap nnp_nosuid overlay unix_socket, $(SUBDIRS))
 endif
diff --git a/tests/tun_tap/.gitignore b/tests/tun_tap/.gitignore
new file mode 100644
index 0000000..0c0c5e7
--- /dev/null
+++ b/tests/tun_tap/.gitignore
@@ -0,0 +1,2 @@
+tun_tap
+tun_relabel
diff --git a/tests/tun_tap/Makefile b/tests/tun_tap/Makefile
new file mode 100644
index 0000000..11f5b03
--- /dev/null
+++ b/tests/tun_tap/Makefile
@@ -0,0 +1,10 @@
+TARGETS = tun_tap tun_relabel
+DEPS = tun_common.c tun_common.h
+LDLIBS += -lselinux
+
+all: $(TARGETS)
+
+clean:
+	rm -f $(TARGETS)
+
+$(TARGETS): $(DEPS)
diff --git a/tests/tun_tap/test b/tests/tun_tap/test
new file mode 100755
index 0000000..3daf2eb
--- /dev/null
+++ b/tests/tun_tap/test
@@ -0,0 +1,88 @@
+#!/usr/bin/perl
+use Test::More;
+
+BEGIN {
+    $basedir = $0;
+    $basedir =~ s|(.*)/[^/]*|$1|;
+
+    # 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 = " ";
+    }
+
+    plan tests => 14;
+}
+
+############ Test tun_socket TUN #############
+print "Test TUN device driver support - 'tun_socket'\n";
+$result = system "runcon -t test_tun_tap_t $basedir/tun_tap $v -s";
+ok( $result eq 0 );
+
+# Deny capability { net_admin } - EPERM
+$result =
+  system "runcon -t test_tun_tap_no_net_admin_t $basedir/tun_tap $v 2>&1";
+ok( $result >> 8 eq 1 );
+
+# Deny tun_socket { create } - EACCES
+$result = system "runcon -t test_tun_tap_no_create_t $basedir/tun_tap $v 2>&1";
+ok( $result >> 8 eq 13 );
+
+# Deny tun_socket { attach_queue } - EACCES
+$result = system "runcon -t test_tun_tap_no_queue_t $basedir/tun_tap $v 2>&1";
+ok( $result >> 8 eq 13 );
+
+$result = system
+  "runcon -t test_tun_tap_t $basedir/tun_relabel $v test_newcon_tun_tap_t";
+ok( $result eq 0 );
+
+# Deny tun_socket { relabelto } - EACCES
+$result = system
+"runcon -t test_tun_tap_t $basedir/tun_relabel $v test_newcon_no_to_tun_tap_t 2>&1";
+ok( $result >> 8 eq 13 );
+
+# Deny tun_socket { relabelfrom } - EACCES
+$result = system
+"runcon -t test_tun_tap_t $basedir/tun_relabel $v test_newcon_no_from_tun_tap_t 2>&1";
+ok( $result >> 8 eq 13 );
+
+############ Test tun_socket TAP #############
+print "Test TAP device driver support - 'tun_socket'\n";
+$result = system "runcon -t test_tun_tap_t $basedir/tun_tap -p $v";
+ok( $result eq 0 );
+
+# Deny capability { net_admin } - EPERM
+$result =
+  system "runcon -t test_tun_tap_no_net_admin_t $basedir/tun_tap -p $v 2>&1";
+ok( $result >> 8 eq 1 );
+
+# Deny tun_socket { create } - EACCES
+$result =
+  system "runcon -t test_tun_tap_no_create_t $basedir/tun_tap -p $v 2>&1";
+ok( $result >> 8 eq 13 );
+
+# Deny tun_socket { attach_queue } - EACCES
+$result =
+  system "runcon -t test_tun_tap_no_queue_t $basedir/tun_tap -p $v 2>&1";
+ok( $result >> 8 eq 13 );
+
+$result = system
+  "runcon -t test_tun_tap_t $basedir/tun_relabel -p $v test_newcon_tun_tap_t";
+ok( $result eq 0 );
+
+# Deny tun_socket { relabelto } - EACCES
+$result = system
+"runcon -t test_tun_tap_t $basedir/tun_relabel -p $v test_newcon_no_to_tun_tap_t 2>&1";
+ok( $result >> 8 eq 13 );
+
+# Deny tun_socket { relabelfrom } - EACCES
+$result = system
+"runcon -t test_tun_tap_t $basedir/tun_relabel -p $v test_newcon_no_from_tun_tap_t 2>&1";
+ok( $result >> 8 eq 13 );
+
+exit;
diff --git a/tests/tun_tap/tun_common.c b/tests/tun_tap/tun_common.c
new file mode 100644
index 0000000..5a4a5ee
--- /dev/null
+++ b/tests/tun_tap/tun_common.c
@@ -0,0 +1,100 @@
+#include "tun_common.h"
+
+int open_dev(int *fd, char *test_str, bool verbose)
+{
+	char *tun_dev = "/dev/net/tun";
+
+	*fd = open(tun_dev, O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "Failed to open device: %s\n",
+			strerror(errno));
+		return errno;
+	}
+	if (verbose)
+		printf("Opened: %s and testing %s service.\n",
+		       tun_dev, test_str);
+
+	return 0;
+}
+
+int setiff(int fd, struct ifreq *ifr, bool verbose)
+{
+	int result;
+
+	result = ioctl(fd, TUNSETIFF, ifr);
+	if (result < 0) {
+		fprintf(stderr, "Failed ioctl(TUNSETIFF): %s\n",
+			strerror(errno));
+		return errno;
+	}
+	if (verbose)
+		printf("ioctl(TUNSETIFF) name: %s\n", ifr->ifr_name);
+
+	return 0;
+}
+
+int persist(int fd, int op, char *name, bool verbose)
+{
+	int result;
+
+	result = ioctl(fd, TUNSETPERSIST, op);
+	if (result < 0) {
+		fprintf(stderr, "Failed ioctl(TUNSETPERSIST %s): %s\n",
+			op ? "Set" : "Unset", strerror(errno));
+		return errno;
+	}
+	if (verbose)
+		printf("%s ioctl(TUNSETPERSIST) name: %s\n",
+		       op ? "Set" : "Unset", name);
+
+	return 0;
+}
+
+int tunsetqueue(int fd, int op, char *name, bool verbose)
+{
+	int result;
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(ifr));
+	ifr.ifr_flags = (op ? IFF_ATTACH_QUEUE : IFF_DETACH_QUEUE);
+	result = ioctl(fd, TUNSETQUEUE, &ifr);
+	if (result < 0) {
+		fprintf(stderr, "Failed ioctl(TUNSETQUEUE %s): %s\n",
+			op ? "IFF_ATTACH_QUEUE" : "IFF_DETACH_QUEUE",
+			strerror(errno));
+		return errno;
+	}
+	if (verbose)
+		printf("ioctl(TUNSETQUEUE) %s name: %s\n",
+		       op ? "IFF_ATTACH_QUEUE" : "IFF_DETACH_QUEUE", name);
+
+	return 0;
+}
+
+int switch_context(char *newcon, bool verbose)
+{
+	int result;
+
+	result = setcon(newcon);
+	if (result < 0) {
+		fprintf(stderr, "setcon() failed to set new process context:\n\t%s\n",
+			newcon);
+		return -1;
+	}
+
+	if (verbose)
+		printf("New process context:\n\t%s\n", newcon);
+
+	free(newcon);
+
+	return 0;
+}
+
+void del_tuntap_name(int fd, char *context, char *name, bool verbose)
+{
+	if (verbose)
+		printf("Switching back to orig context to remove persistent name: %s\n",
+		       name);
+	switch_context(context, verbose);
+	persist(fd, 0, name, verbose);
+}
diff --git a/tests/tun_tap/tun_common.h b/tests/tun_tap/tun_common.h
new file mode 100644
index 0000000..0259563
--- /dev/null
+++ b/tests/tun_tap/tun_common.h
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <linux/if_tun.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+
+extern int open_dev(int *fd, char *test_str, bool verbose);
+extern int setiff(int fd, struct ifreq *ifr, bool verbose);
+/* Persistent state 'op': 0 = unset, 1 = set */
+extern int persist(int fd, int op, char *name, bool verbose);
+/* Queue state 'op': 0 = IFF_DETACH_QUEUE, 1 = IFF_ATTACH_QUEUE */
+extern int tunsetqueue(int fd, int op, char *name, bool verbose);
+extern int switch_context(char *newcon, bool verbose);
+extern void del_tuntap_name(int fd, char *context, char *name, bool verbose);
diff --git a/tests/tun_tap/tun_relabel.c b/tests/tun_tap/tun_relabel.c
new file mode 100644
index 0000000..7aeabd1
--- /dev/null
+++ b/tests/tun_tap/tun_relabel.c
@@ -0,0 +1,124 @@
+#include "tun_common.h"
+
+static void print_usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-v] newcon\n"
+		"Where:\n\t"
+		"-p      Test TAP driver, default is TUN driver.\n\t"
+		"-v      Print information.\n\t"
+		"newcon  New process context.\n", progname);
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	char *origcon, *newcon, *test_str;
+	char alloc_name[IFNAMSIZ];
+	int opt, result, test, fd1, fd2;
+	bool verbose = false;
+	context_t con_t;
+	struct ifreq ifr;
+
+	test = IFF_TUN;
+	test_str = "TUN";
+
+	while ((opt = getopt(argc, argv, "pv")) != -1) {
+		switch (opt) {
+		case 'p':
+			test = IFF_TAP;
+			test_str = "TAP";
+			break;
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			print_usage(argv[0]);
+		}
+	}
+
+	if (optind >= argc)
+		print_usage(argv[0]);
+
+	/*
+	 * Need to keep a copy of this to switch back when testing deny
+	 * relabelto/from in newcon. This will allow the removal of the
+	 * allocated TUN/TAP name.
+	 */
+	result = getcon(&origcon);
+	if (result < 0) {
+		fprintf(stderr, "Failed to obtain process context\n");
+		exit(-1);
+	}
+	if (verbose)
+		printf("Current process context:\n\t%s\n", origcon);
+
+	/* Build new context for transition */
+	con_t = context_new(origcon);
+	if (!con_t) {
+		fprintf(stderr, "Unable to create context structure\n");
+		exit(-1);
+	}
+
+	if (context_type_set(con_t, argv[optind])) {
+		fprintf(stderr, "Unable to set new type\n");
+		exit(-1);
+	}
+
+	newcon = context_str(con_t);
+	if (!newcon) {
+		fprintf(stderr, "Unable to obtain new context string\n");
+		exit(-1);
+	}
+
+	/* Start TUN/TAP */
+	result = open_dev(&fd1, test_str, verbose);
+	if (result != 0)
+		exit(result);
+
+	/* Let TUNSETIFF allocate the ifr_name for later use */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	ifr.ifr_flags = test | IFF_MULTI_QUEUE;
+	result = setiff(fd1, &ifr, verbose);
+	if (result != 0)
+		goto err1;
+
+	strcpy(alloc_name, ifr.ifr_name);
+
+	/* Make this name persist */
+	result = persist(fd1, 1, alloc_name, verbose);
+	if (result != 0)
+		goto err1;
+
+	/* Switch to new context for relabel tests */
+	result = switch_context(newcon, verbose);
+	if (result < 0) { /* If fail remove the persistent one */
+		del_tuntap_name(fd1, origcon, alloc_name, verbose);
+		goto err1;
+	}
+
+	/* Start TUN/TAP in new context */
+	result = open_dev(&fd2, test_str, verbose);
+	if (result != 0) {
+		del_tuntap_name(fd1, origcon, alloc_name, verbose);
+		goto err1;
+	}
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	ifr.ifr_flags = test | IFF_MULTI_QUEUE;
+	/* Use the TUN/TAP name allocated initially */
+	strcpy(ifr.ifr_name, alloc_name);
+	result = setiff(fd2, &ifr, verbose);
+	if (result != 0) {
+		del_tuntap_name(fd1, origcon, alloc_name, verbose);
+		goto now_ok;
+	}
+
+	persist(fd2, 0, alloc_name, verbose);
+now_ok:
+	close(fd2);
+err1:
+	close(fd1);
+
+	return result;
+}
diff --git a/tests/tun_tap/tun_tap.c b/tests/tun_tap/tun_tap.c
new file mode 100644
index 0000000..a3db6c9
--- /dev/null
+++ b/tests/tun_tap/tun_tap.c
@@ -0,0 +1,123 @@
+#include "tun_common.h"
+
+static void print_usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-p] [-s ] [-v]\n"
+		"Where:\n\t"
+		"-p  Test TAP driver, default is TUN driver.\n\t"
+		"-s  If -v, then show TUN/TAP Features.\n\t"
+		"-v  Print information.\n", progname);
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	char *context, *test_str;
+	int opt, result, fd, bit, count, test;
+	unsigned int features, f_switch;
+	bool verbose = false, show = false;
+	struct ifreq ifr;
+
+	test = IFF_TUN;
+	test_str = "TUN";
+
+	while ((opt = getopt(argc, argv, "psv")) != -1) {
+		switch (opt) {
+		case 'p':
+			test = IFF_TAP;
+			test_str = "TAP";
+			break;
+		case 's':
+			show = true;
+			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);
+	}
+
+	/* Start TUN/TAP */
+	result = open_dev(&fd, test_str, verbose);
+	if (result != 0)
+		exit(result);
+
+	if (verbose && show) {
+		result = ioctl(fd, TUNGETFEATURES, &features);
+		if (result < 0) {
+			fprintf(stderr, "Failed ioctl(TUNGETFEATURES): %s\n",
+				strerror(errno));
+			exit(-1);
+		}
+
+		bit = 1;
+		count = 0xffff;
+		printf("TUN/TAP supported features:\n");
+		while (count) {
+			f_switch = bit & features;
+			switch (f_switch) {
+			case IFF_TUN:
+				printf("\tIFF_TUN\n");
+				break;
+			case IFF_TAP:
+				printf("\tIFF_TAP\n");
+				break;
+			case IFF_NAPI:
+				printf("\tIFF_NAPI\n");
+				break;
+			case IFF_NAPI_FRAGS:
+				printf("\tIFF_NAPI_FRAGS\n");
+				break;
+			case IFF_NO_PI:
+				printf("\tIFF_NO_PI\n");
+				break;
+			case IFF_ONE_QUEUE:
+				printf("\tIFF_ONE_QUEUE\n");
+				break;
+			case IFF_VNET_HDR:
+				printf("\tIFF_VNET_HDR\n");
+				break;
+			/* Added in kernel 3.8 */
+			case IFF_MULTI_QUEUE:
+				printf("\tIFF_MULTI_QUEUE\n");
+				break;
+			}
+			bit <<= 1;
+			count >>= 1;
+		}
+	}
+
+	/* Let TUNSETIFF allocate the ifr_name */
+	memset(&ifr, 0, sizeof(struct ifreq));
+	ifr.ifr_flags = test | IFF_MULTI_QUEUE;
+	result = setiff(fd, &ifr, verbose);
+	if (result != 0)
+		goto err;
+
+	/*
+	 * Test 'tun_socket { attach_queue }' permission by removing
+	 * the queue. Adding it back then generates the call to:
+	 *     selinux_tun_dev_attach_queue().
+	 */
+	result = tunsetqueue(fd, 0, ifr.ifr_name, verbose);
+	if (result != 0)
+		goto err;
+
+	result = tunsetqueue(fd, 1, ifr.ifr_name, verbose);
+err:
+	close(fd);
+	return result;
+}
-- 
2.23.0


             reply index

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-01 16:58 Richard Haines [this message]
2019-12-04 14:44 ` Stephen Smalley
2019-12-05 13:28 ` Stephen Smalley

Reply instructions:

You may reply publically 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=20191201165820.285680-1-richard_c_haines@btinternet.com \
    --to=richard_c_haines@btinternet.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

SELinux Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/selinux/0 selinux/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 selinux selinux/ https://lore.kernel.org/selinux \
		selinux@vger.kernel.org
	public-inbox-index selinux

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.selinux


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git