selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Smalley <sds@tycho.nsa.gov>
To: Richard Haines <richard_c_haines@btinternet.com>,
	selinux@vger.kernel.org
Subject: Re: [PATCH] selinux-testsuite: Add TUN/TAP driver tests
Date: Thu, 5 Dec 2019 08:28:23 -0500	[thread overview]
Message-ID: <cbabad82-d5d3-c73a-a6da-6824d8e6c26c@tycho.nsa.gov> (raw)
In-Reply-To: <20191201165820.285680-1-richard_c_haines@btinternet.com>

On 12/1/19 11:58 AM, Richard Haines wrote:
> Test TUN/TAP tun_socket permissions.
> 
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>

Thanks, applied.

> ---
> 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;
> +}
> 


      parent reply	other threads:[~2019-12-05 13:28 UTC|newest]

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

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=cbabad82-d5d3-c73a-a6da-6824d8e6c26c@tycho.nsa.gov \
    --to=sds@tycho.nsa.gov \
    --cc=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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).