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, paul@paul-moore.com
Subject: Re: [PATCH V5 3/3] selinux-testsuite: Add BPF support to binder test
Date: Thu, 19 Sep 2019 16:15:31 -0400	[thread overview]
Message-ID: <03c9d67b-19e1-ce1a-1ed3-40f11ece482e@tycho.nsa.gov> (raw)
In-Reply-To: <20190919174655.17348-4-richard_c_haines@btinternet.com>

On 9/19/19 1:46 PM, Richard Haines wrote:
> Add BPF map & prog functions to test binder security_binder_transfer_file()

Thanks, all three applied.

> 
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
>   policy/Makefile                 |   2 +-
>   policy/test_binder_bpf.te       |  73 ++++++++++++++++++++
>   tests/binder/Makefile           |   5 ++
>   tests/binder/binder_common.c    |  10 +--
>   tests/binder/binder_common.h    |  17 ++++-
>   tests/binder/client.c           |  28 ++++++--
>   tests/binder/manager.c          |   2 +-
>   tests/binder/service_provider.c | 118 ++++++++++++++++++++++++--------
>   tests/bpf/Makefile              |   2 +-
>   tests/bpf/test                  |  84 ++++++++++++++++++++++-
>   10 files changed, 296 insertions(+), 45 deletions(-)
>   create mode 100644 policy/test_binder_bpf.te
> 
> diff --git a/policy/Makefile b/policy/Makefile
> index 4ca5486..d72eb62 100644
> --- a/policy/Makefile
> +++ b/policy/Makefile
> @@ -72,7 +72,7 @@ TARGETS += test_sctp.te
>   endif
>   
>   ifeq ($(shell grep -q bpf $(POLDEV)/include/support/all_perms.spt && echo true),true)
> -TARGETS += test_bpf.te test_fdreceive_bpf.te
> +TARGETS += test_bpf.te test_fdreceive_bpf.te test_binder_bpf.te
>   endif
>   
>   ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6))
> diff --git a/policy/test_binder_bpf.te b/policy/test_binder_bpf.te
> new file mode 100644
> index 0000000..c545846
> --- /dev/null
> +++ b/policy/test_binder_bpf.te
> @@ -0,0 +1,73 @@
> +####### Policy for testing BPF file descriptor transfers via binder #########
> +
> +attribute binderbpfdomain;
> +
> +#
> +################################## Manager ##################################
> +#
> +type test_binder_bpf_mgr_t;
> +domain_type(test_binder_bpf_mgr_t)
> +unconfined_runs_test(test_binder_bpf_mgr_t)
> +typeattribute test_binder_bpf_mgr_t testdomain;
> +typeattribute test_binder_bpf_mgr_t binderdomain;
> +allow test_binder_bpf_mgr_t test_binder_bpf_client_t:binder { transfer };
> +allow test_binder_bpf_mgr_t test_binder_client_no_bpf_perm_t:binder { transfer };
> +allow test_binder_bpf_mgr_t device_t:chr_file { ioctl open read write };
> +allow_map(test_binder_bpf_mgr_t, device_t, chr_file)
> +allow test_binder_bpf_mgr_t self:binder { set_context_mgr };
> +# For writing to flag file:
> +allow test_binder_bpf_mgr_t test_file_t:fifo_file { rw_file_perms };
> +
> +#
> +########################### Service Provider ################################
> +#
> +type test_binder_bpf_provider_t;
> +domain_type(test_binder_bpf_provider_t)
> +unconfined_runs_test(test_binder_bpf_provider_t)
> +typeattribute test_binder_bpf_provider_t testdomain;
> +typeattribute test_binder_bpf_provider_t binderbpfdomain;
> +allow test_binder_bpf_provider_t test_binder_bpf_mgr_t:binder { call transfer };
> +allow test_binder_bpf_provider_t device_t:chr_file { ioctl open read write };
> +allow_map(test_binder_bpf_provider_t, device_t, chr_file)
> +# For writing to flag file:
> +allow test_binder_bpf_provider_t test_file_t:fifo_file { rw_file_perms };
> +# For testing BPF map fd transfer:
> +allow test_binder_bpf_provider_t self:bpf { map_create map_read map_write prog_load prog_run };
> +allow test_binder_bpf_provider_t self:capability { sys_resource };
> +allow test_binder_bpf_provider_t self:process { setrlimit };
> +
> +#
> +################################# Client ####################################
> +#
> +type test_binder_bpf_client_t;
> +domain_type(test_binder_bpf_client_t)
> +unconfined_runs_test(test_binder_bpf_client_t)
> +typeattribute test_binder_bpf_client_t testdomain;
> +typeattribute test_binder_bpf_client_t binderbpfdomain;
> +allow test_binder_bpf_client_t test_binder_bpf_provider_t:binder { call impersonate };
> +allow test_binder_bpf_client_t test_binder_bpf_mgr_t:binder { call };
> +allow test_binder_bpf_client_t test_binder_bpf_provider_t:fd { use };
> +allow test_binder_bpf_client_t device_t:chr_file { getattr ioctl open read write };
> +allow_map(test_binder_bpf_client_t, device_t, chr_file)
> +# For testing BPF map fd transfer:
> +allow test_binder_bpf_client_t test_binder_bpf_provider_t:bpf { map_read map_write prog_load prog_run };
> +
> +#
> +######################## Client no BPF perms #############################
> +#
> +type test_binder_client_no_bpf_perm_t;
> +domain_type(test_binder_client_no_bpf_perm_t)
> +unconfined_runs_test(test_binder_client_no_bpf_perm_t)
> +typeattribute test_binder_client_no_bpf_perm_t testdomain;
> +typeattribute test_binder_client_no_bpf_perm_t binderbpfdomain;
> +allow test_binder_client_no_bpf_perm_t test_binder_bpf_provider_t:binder { call impersonate };
> +allow test_binder_client_no_bpf_perm_t test_binder_bpf_mgr_t:binder { call };
> +allow test_binder_client_no_bpf_perm_t test_binder_bpf_provider_t:fd { use };
> +allow test_binder_client_no_bpf_perm_t device_t:chr_file { getattr ioctl open read write };
> +allow_map(test_binder_client_no_bpf_perm_t, device_t, chr_file)
> +
> +#
> +########### Allow these domains to be entered from sysadm domain ############
> +#
> +miscfiles_domain_entry_test_files(binderbpfdomain)
> +userdom_sysadm_entry_spec_domtrans_to(binderbpfdomain)
> diff --git a/tests/binder/Makefile b/tests/binder/Makefile
> index 32f9a83..e78ad16 100644
> --- a/tests/binder/Makefile
> +++ b/tests/binder/Makefile
> @@ -10,6 +10,11 @@ CFLAGS += -DHAVE_BINDERFS
>   TARGETS += check_binderfs
>   endif
>   
> +ifneq (,$(findstring -DHAVE_BPF,$(CFLAGS)))
> +	DEPS += ../bpf/bpf_common.c ../bpf/bpf_common.h
> +	LDLIBS += -lbpf
> +endif
> +
>   all: $(TARGETS)
>   
>   clean:
> diff --git a/tests/binder/binder_common.c b/tests/binder/binder_common.c
> index a240453..224238b 100644
> --- a/tests/binder/binder_common.c
> +++ b/tests/binder/binder_common.c
> @@ -3,13 +3,15 @@
>    * the raw ioctl commands to test the SELinux binder permissions:
>    *     set_context_mgr, call, transfer, impersonate.
>    *
> + * If configured, the BPF permissions are also tested.
> + *
>    * Using binder test policy the following will be validated:
>    *    security_binder_set_context_mgr() binder { set_context_mgr }
>    *    security_binder_transaction()     binder { call impersonate }
>    *    security_binder_transfer_binder() binder { transfer }
>    *    security_binder_transfer_file()   fd { use }
> - *
> - * TODO security_binder_transfer_file() uses BPF if configured in kernel.
> + *					bpf { map_create map_read map_write };
> + *					bpf { prog_load prog_run };
>    */
>   
>   #include "binder_common.h"
> @@ -67,8 +69,8 @@ void print_trans_data(const struct binder_transaction_data *txn_in)
>   	case TEST_SERVICE_GET:
>   		printf("\tcode: TEST_SERVICE_GET\n");
>   		break;
> -	case TEST_SERVICE_SEND_CLIENT_SP_FD:
> -		printf("\tcode: TEST_SERVICE_SEND_CLIENT_SP_FD\n");
> +	case TEST_SERVICE_SEND_FD:
> +		printf("\tcode: TEST_SERVICE_SEND_FD\n");
>   		break;
>   	default:
>   		printf("Unknown binder_transaction_data->code: %x\n",
> diff --git a/tests/binder/binder_common.h b/tests/binder/binder_common.h
> index bcf9e0c..30edc75 100644
> --- a/tests/binder/binder_common.h
> +++ b/tests/binder/binder_common.h
> @@ -15,6 +15,9 @@
>   #if HAVE_BINDERFS
>   #include <linux/android/binderfs.h>
>   #endif
> +#if HAVE_BPF
> +#include "../bpf/bpf_common.h"
> +#endif
>   
>   #define BINDER_DEV "/dev/binder"
>   #define BINDERFS_DEV "/dev/binderfs"
> @@ -26,12 +29,20 @@
>   /* These are the Binder txn->code values used by the Service Provider, Client
>    * and Manager to request/retrieve a binder handle or file descriptor.
>    */
> -#define TEST_SERVICE_ADD		240616 /* Sent by Service Provider */
> -#define TEST_SERVICE_GET		290317 /* Sent by Client */
> -#define TEST_SERVICE_SEND_CLIENT_SP_FD	120419 /* Sent by Client */
> +#define TEST_SERVICE_ADD	240616 /* Sent by Service Provider */
> +#define TEST_SERVICE_GET	290317 /* Sent by Client */
> +#define TEST_SERVICE_SEND_FD	311019 /* Sent by Client */
>   
>   bool verbose;
>   
>   const char *cmd_name(uint32_t cmd);
>   void print_trans_data(const struct binder_transaction_data *txn_in);
>   int binder_write(int fd, void *data, size_t len);
> +
> +enum {
> +	BINDER_FD,
> +	BPF_MAP_FD,
> +	BPF_PROG_FD,
> +	BPF_TEST
> +} fd_type;
> +char *fd_type_str;
> diff --git a/tests/binder/client.c b/tests/binder/client.c
> index e4e2a61..4965563 100644
> --- a/tests/binder/client.c
> +++ b/tests/binder/client.c
> @@ -6,7 +6,7 @@ static int transactions_complete;
>   static void usage(char *progname)
>   {
>   	fprintf(stderr,
> -		"usage:  %s [-c] [-n] [-r replies] [-v]\n"
> +		"usage:  %s [-c] [-n] [-r replies] [-m|-p] [-v]\n"
>   		"Where:\n\t"
>   		"-c  Use the number of replies for the BR_TRANSACTION_COMPLETE"
>   		" count.\n\t"
> @@ -15,6 +15,8 @@ static void usage(char *progname)
>   		"    It can be the number of BR_TRANSACTION_COMPLETE if\n\t"
>   		"    the -c option is set or number of times to issue the\n\t"
>   		"    ioctl - BINDER_WRITE_READ command if -c not set.\n\t"
> +		"-m  Service Provider sending BPF map fd.\n\t"
> +		"-p  Service Provider sending BPF prog fd.\n\t"
>   		"-v  Print context and command information.\n\t"
>   		"\nNote: Ensure this boolean command is run when "
>   		"testing after a reboot:\n\t"
> @@ -67,8 +69,12 @@ static void extract_fd_and_respond(const struct binder_transaction_data *txn_in)
>   	}
>   
>   	if (verbose)
> -		printf("Client retrieved Service Providers fd: %d st_dev: %ld\n",
> -		       obj->fd, sb.st_dev);
> +		printf("Client retrieved %s fd: %d st_dev: %ld\n",
> +		       fd_type_str, obj->fd, sb.st_dev);
> +
> +	/* If testing BPF, then cannot do impersonate check */
> +	if (fd_type > BINDER_FD)
> +		return;
>   
>   	memset(&writebuf, 0, sizeof(writebuf));
>   	memset(readbuf, 0, sizeof(readbuf));
> @@ -141,7 +147,7 @@ static void request_service_provider_fd(int fd, uint32_t handle)
>   	writebuf.cmd = BC_TRANSACTION;
>   	writebuf.txn.target.handle = handle;
>   	writebuf.txn.cookie = 0;
> -	writebuf.txn.code = TEST_SERVICE_SEND_CLIENT_SP_FD;
> +	writebuf.txn.code = TEST_SERVICE_SEND_FD;
>   	writebuf.txn.flags = TF_ACCEPT_FDS;
>   
>   	writebuf.txn.data_size = 0;
> @@ -270,7 +276,7 @@ static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size)
>   			if (txn->code == TEST_SERVICE_GET)
>   				extract_handle_and_acquire(fd, txn);
>   
> -			if (txn->code == TEST_SERVICE_SEND_CLIENT_SP_FD)
> +			if (txn->code == TEST_SERVICE_SEND_FD)
>   				extract_fd_and_respond(txn);
>   
>   			ptr += sizeof(*txn);
> @@ -313,8 +319,10 @@ int main(int argc, char **argv)
>   	unsigned int readbuf[32];
>   
>   	transactions_complete = 0;
> +	fd_type = BINDER_FD;
> +	fd_type_str = "SP";
>   
> -	while ((opt = getopt(argc, argv, "cnr:v")) != -1) {
> +	while ((opt = getopt(argc, argv, "cnr:vmp")) != -1) {
>   		switch (opt) {
>   		case 'c':
>   			use_transactions_complete = true;
> @@ -328,6 +336,14 @@ int main(int argc, char **argv)
>   		case 'v':
>   			verbose = true;
>   			break;
> +		case 'm':
> +			fd_type = BPF_MAP_FD;
> +			fd_type_str = "BPF map";
> +			break;
> +		case 'p':
> +			fd_type = BPF_PROG_FD;
> +			fd_type_str = "BPF prog";
> +			break;
>   		default:
>   			usage(argv[0]);
>   		}
> diff --git a/tests/binder/manager.c b/tests/binder/manager.c
> index 9922183..8e5f446 100644
> --- a/tests/binder/manager.c
> +++ b/tests/binder/manager.c
> @@ -91,7 +91,7 @@ static void do_service_manager(int fd, struct binder_transaction_data *txn_in)
>   		reply_with_handle(fd, txn_in);
>   
>   		break;
> -	case TEST_SERVICE_SEND_CLIENT_SP_FD:
> +	case TEST_SERVICE_SEND_FD:
>   		if (verbose)
>   			printf("Manager Rx'ed SEND_CLIENT_YOUR_BINDER_FD for handle: %d\n",
>   			       txn_in->target.handle);
> diff --git a/tests/binder/service_provider.c b/tests/binder/service_provider.c
> index 2873af8..56d8a43 100644
> --- a/tests/binder/service_provider.c
> +++ b/tests/binder/service_provider.c
> @@ -6,11 +6,14 @@ static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size);
>   static void usage(char *progname)
>   {
>   	fprintf(stderr,
> -		"usage:  %s [-e expected_ctx] [-f file] [-n] [-v]\n"
> +		"usage:  %s -e expected_ctx] [-f file] [-n] [-m|-p|-t] [-v]\n"
>   		"Where:\n\t"
>   		"-e  Expected security context.\n\t"
>   		"-f  Write a line to the file when listening starts.\n\t"
>   		"-n  Use the /dev/binderfs name service.\n\t"
> +		"-m  Use BPF map fd for transfer.\n\t"
> +		"-p  Use BPF prog fd for transfer.\n\t"
> +		"-t  Test if BPF enabled.\n\t"
>   		"-v  Print context and command information.\n\t"
>   		"\nNote: Ensure this boolean command is run when "
>   		"testing after a reboot:\n\t"
> @@ -34,7 +37,7 @@ static void request_service_provider_fd(int fd,
>   	}
>   
>   	if (verbose)
> -		printf("Service Provider sending BC_REPLY with its FD\n");
> +		printf("Service Provider sending BC_REPLY with an FD\n");
>   
>   	memset(writebuf, 0, sizeof(writebuf));
>   	memset(&bwr, 0, sizeof(bwr));
> @@ -56,17 +59,47 @@ static void request_service_provider_fd(int fd,
>   	obj.pad_flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
>   #endif
>   	obj.cookie = txn->cookie;
> -	/* The Service Providers binder fd is used for testing as it allows
> +
> +	/*
> +	 * The Service Providers binder fd is used for testing as it allows
>   	 * policy to set whether the Service Provider and Client can be
>   	 * allowed access (fd use) or not.
>   	 * This also allows a check for the impersonate permission later as
>   	 * the Client will use the Service Provider fd to send a transaction.
> +	 *
> +	 * If a BPF fd is required, it is generated, however it cannot be
> +	 * used to check the impersonate permission.
>   	 */
> -	obj.fd = fd;
> +	switch (fd_type) {
> +	case BINDER_FD:
> +		obj.fd = fd;
> +		break;
> +#if HAVE_BPF
> +	case BPF_MAP_FD:
> +		obj.fd = create_bpf_map();
> +		if (obj.fd < 0)
> +			exit(70);
> +		break;
> +	case BPF_PROG_FD:
> +		obj.fd = create_bpf_prog();
> +		if (obj.fd < 0)
> +			exit(71);
> +		break;
> +#else
> +	case BPF_MAP_FD:
> +	case BPF_PROG_FD:
> +		fprintf(stderr, "BPF not supported - Service Provider\n");
> +		exit(72);
> +		break;
> +#endif
> +	default:
> +		fprintf(stderr, "Invalid fd_type: %d\n", fd_type);
> +		exit(73);
> +	}
>   
>   	if (verbose)
> -		printf("Service Provider handle: %d and its FD: %d\n",
> -		       txn->target.handle, fd);
> +		printf("Service Provider handle: %d and %s FD: %d\n",
> +		       txn->target.handle, fd_type_str, obj.fd);
>   
>   	txn->data_size = sizeof(obj);
>   	txn->data.ptr.buffer = (binder_uintptr_t)&obj;
> @@ -81,7 +114,7 @@ static void request_service_provider_fd(int fd,
>   		fprintf(stderr,
>   			"Service Provider ioctl BINDER_WRITE_READ error: %s\n",
>   			strerror(errno));
> -		exit(70);
> +		exit(74);
>   	}
>   }
>   
> @@ -119,7 +152,7 @@ static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size)
>   				print_trans_data(txn);
>   			}
>   
> -			if (txn->code == TEST_SERVICE_SEND_CLIENT_SP_FD)
> +			if (txn->code == TEST_SERVICE_SEND_FD)
>   				request_service_provider_fd(fd, txn);
>   
>   			ptr += sizeof(*txn);
> @@ -148,8 +181,7 @@ static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size)
>   				}
>   			}
>   
> -			if (txn_ctx->transaction_data.code ==
> -			    TEST_SERVICE_SEND_CLIENT_SP_FD)
> +			if (txn_ctx->transaction_data.code == TEST_SERVICE_SEND_FD)
>   				request_service_provider_fd(fd,
>   							    &txn_ctx->transaction_data);
>   
> @@ -209,8 +241,10 @@ int main(int argc, char **argv)
>   	unsigned int readbuf[32];
>   
>   	expected_ctx = NULL;
> +	fd_type = BINDER_FD;
> +	fd_type_str = "SP";
>   
> -	while ((opt = getopt(argc, argv, "e:f:nv")) != -1) {
> +	while ((opt = getopt(argc, argv, "e:f:nvmpt")) != -1) {
>   		switch (opt) {
>   		case 'e':
>   			expected_ctx = optarg;
> @@ -224,11 +258,37 @@ int main(int argc, char **argv)
>   		case 'v':
>   			verbose = true;
>   			break;
> +		case 'm':
> +			fd_type = BPF_MAP_FD;
> +			fd_type_str = "BPF map";
> +			break;
> +		case 'p':
> +			fd_type = BPF_PROG_FD;
> +			fd_type_str = "BPF prog";
> +			break;
> +		case 't':
> +			fd_type = BPF_TEST;
> +			break;
>   		default:
>   			usage(argv[0]);
>   		}
>   	}
>   
> +
> +#if HAVE_BPF
> +	if (fd_type == BPF_TEST)
> +		exit(0);
> +
> +	/* If BPF enabed, then need to set limits */
> +	if (fd_type == BPF_MAP_FD || fd_type == BPF_PROG_FD)
> +		bpf_setrlimit();
> +#else
> +	if (fd_type == BPF_TEST) {
> +		fprintf(stderr, "BPF not supported\n");
> +		exit(-1);
> +	}
> +#endif
> +
>   	/* Get our context and pid */
>   	result = getcon(&context);
>   	if (result < 0) {
> @@ -267,19 +327,6 @@ int main(int argc, char **argv)
>   		exit(63);
>   	}
>   
> -	if (flag_file) {
> -		flag_fd = fopen(flag_file, "w");
> -		if (!flag_fd) {
> -			fprintf(stderr,
> -				"Service Provider failed to open %s: %s\n",
> -				flag_file, strerror(errno));
> -			result = 64;
> -			goto brexit;
> -		}
> -		fprintf(flag_fd, "listening\n");
> -		fclose(flag_fd);
> -	}
> -
>   	memset(&writebuf, 0, sizeof(writebuf));
>   	memset(&obj, 0, sizeof(obj));
>   	memset(readbuf, 0, sizeof(readbuf));
> @@ -322,7 +369,7 @@ int main(int argc, char **argv)
>   		fprintf(stderr,
>   			"Service Provider ioctl BINDER_WRITE_READ error: %s\n",
>   			strerror(errno));
> -		result = 65;
> +		result = 64;
>   		goto brexit;
>   	}
>   
> @@ -338,7 +385,7 @@ int main(int argc, char **argv)
>   	    cmd == BR_DEAD_BINDER) {
>   		fprintf(stderr, "Service Provider %s() failing command %s, exiting.\n",
>   			__func__, cmd_name(cmd));
> -		result = 66;
> +		result = 65;
>   		goto brexit;
>   	}
>   
> @@ -358,10 +405,27 @@ int main(int argc, char **argv)
>   		fprintf(stderr,
>   			"Service Provider ioctl BINDER_WRITE_READ error: %s\n",
>   			strerror(errno));
> -		result = 67;
> +		result = 66;
>   		goto brexit;
>   	}
>   
> +	/*
> +	 * Ensure the Manager and Service Provider have completed the
> +	 * TEST_SERVICE_ADD sequence before the Client is allowed to start.
> +	 */
> +	if (flag_file) {
> +		flag_fd = fopen(flag_file, "w");
> +		if (!flag_fd) {
> +			fprintf(stderr,
> +				"Service Provider failed to open %s: %s\n",
> +				flag_file, strerror(errno));
> +			result = 67;
> +			goto brexit;
> +		}
> +		fprintf(flag_fd, "listening\n");
> +		fclose(flag_fd);
> +	}
> +
>   	while (true) {
>   		memset(readbuf, 0, sizeof(readbuf));
>   		bwr.read_size = sizeof(readbuf);
> diff --git a/tests/bpf/Makefile b/tests/bpf/Makefile
> index 3513179..6fb230d 100644
> --- a/tests/bpf/Makefile
> +++ b/tests/bpf/Makefile
> @@ -5,7 +5,7 @@ LDLIBS += -lselinux -lbpf
>   # export so that BPF_ENABLED entries get built correctly on local build
>   export CFLAGS += -DHAVE_BPF
>   
> -BPF_ENABLED = ../fdreceive
> +BPF_ENABLED = ../fdreceive ../binder
>   
>   all: $(TARGETS)
>   	@set -e; for i in $(BPF_ENABLED); do $(MAKE) -C $$i all ; done
> diff --git a/tests/bpf/test b/tests/bpf/test
> index b49918d..4c768be 100755
> --- a/tests/bpf/test
> +++ b/tests/bpf/test
> @@ -4,11 +4,14 @@ use Test::More;
>   BEGIN {
>       $basedir = $0;
>       $basedir =~ s|(.*)/[^/]*|$1|;
> -    $fdr_basedir = "$basedir/../fdreceive/";
> +    $fdr_basedir    = "$basedir/../fdreceive/";
> +    $binder_basedir = "$basedir/../binder/";
>   
>       $test_bpf_count       = 7;
>       $test_fdreceive_count = 4;
>   
> +    $test_count = $test_bpf_count + $test_fdreceive_count;
> +
>       # allow info to be shown during tests
>       $v = $ARGV[0];
>       if ($v) {
> @@ -20,7 +23,15 @@ BEGIN {
>           $v = " ";
>       }
>   
> -    plan tests => $test_bpf_count + $test_fdreceive_count;
> +    # Test if Binder is supported
> +    $test_binder = 0;
> +    $result      = system("$binder_basedir/check_binder $v 2>/dev/null");
> +    if ( $result >> 8 eq 0 ) {
> +        $test_binder = 1;
> +        $test_count += 4;
> +    }
> +
> +    plan tests => $test_count;
>   }
>   
>   #
> @@ -104,4 +115,73 @@ kill KILL, $pid;
>   # Clean up.
>   system "rm -rf $basedir/test_sock $basedir/flag";
>   
> +#
> +################ BPF Tests for binder #######################
> +#
> +sub service_start {
> +    my ( $service, $runcon_args, $args ) = @_;
> +    my $pid;
> +    my $flag = $service . "_flag";
> +
> +    system("mkfifo $basedir/$flag");
> +
> +    if ( ( $pid = fork() ) == 0 ) {
> +        exec
> +"runcon $runcon_args $binder_basedir/$service -f $basedir/$flag $args";
> +    }
> +
> +    # Wait for it to initialize.
> +    system("read -t 5 <>$basedir/$flag");
> +    return $pid;
> +}
> +
> +sub service_end {
> +    my ( $service, $pid ) = @_;
> +    my $flag = $service . "_flag";
> +
> +    kill KILL, $pid;
> +    waitpid $pid, 0;
> +    system("rm -f $basedir/$flag");
> +}
> +
> +if ($test_binder) {
> +    ### Test BPF map fd on transfer ##################
> +    $sm_pid = service_start( "manager", "-t test_binder_bpf_mgr_t", "$v" );
> +    $sp_pid =
> +      service_start( "service_provider", "-t test_binder_bpf_provider_t",
> +        "-m $v" );
> +
> +    # Verify that the BPF map fd can be transferred.
> +    $result =
> +      system
> +      "runcon -t test_binder_bpf_client_t $binder_basedir/client $v -m -r 1";
> +    ok( $result eq 0 );
> +
> +    # Verify BPF no map perms.
> +    $result = system
> +"runcon -t test_binder_client_no_bpf_perm_t $binder_basedir/client $v -m -r 2 2>&1";
> +    ok( $result >> 8 eq 141 );
> +
> +    ### Test BPF prog fd on transfer ##################
> +    service_end( "service_provider", $sp_pid );
> +    $sp_pid =
> +      service_start( "service_provider", "-t test_binder_bpf_provider_t",
> +        "-p $v" );
> +
> +    # Verify that the BPF prog fd can be transferred.
> +    $result =
> +      system
> +      "runcon -t test_binder_bpf_client_t $binder_basedir/client $v -p -r 1";
> +    ok( $result eq 0 );
> +
> +    # Verify BPF no prog perms.
> +    $result = system
> +"runcon -t test_binder_client_no_bpf_perm_t $binder_basedir/client $v -p -r 2 2>&1";
> +    ok( $result >> 8 eq 141 );
> +
> +    # Kill the service provider & manager.
> +    service_end( "service_provider", $sp_pid );
> +    service_end( "manager",          $sm_pid );
> +}
> +
>   exit;
> 


      reply	other threads:[~2019-09-19 20:15 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-19 17:46 [PATCH V5 0/3] selinux-testsuite: Add BPF tests Richard Haines
2019-09-19 17:46 ` [PATCH V5 1/3] " Richard Haines
2019-09-19 17:46 ` [PATCH V5 2/3] selinux-testsuite: Add BPF support to fdreceive test Richard Haines
2019-09-19 17:46 ` [PATCH V5 3/3] selinux-testsuite: Add BPF support to binder test Richard Haines
2019-09-19 20:15   ` 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=03c9d67b-19e1-ce1a-1ed3-40f11ece482e@tycho.nsa.gov \
    --to=sds@tycho.nsa.gov \
    --cc=paul@paul-moore.com \
    --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).