next portion of selinux updates: chcon, runcon. From
Yuichi Nakamura <himainu-ynakam@miomio.jp> KaiGai Kohei <busybox@kaigai.gr.jp>
This commit is contained in:
		| @@ -89,7 +89,7 @@ int id_main(int argc, char **argv) | |||||||
|  		if (flags & JUST_CONTEXT) {         |  		if (flags & JUST_CONTEXT) {         | ||||||
| 			selinux_or_die(); | 			selinux_or_die(); | ||||||
|  			if (argc - optind == 1) { |  			if (argc - optind == 1) { | ||||||
|  				bb_error_msg_and_die("can't print security context when user specified"); |  				bb_error_msg_and_die("user name can't be passed with -Z"); | ||||||
|  			} |  			} | ||||||
| 			 | 			 | ||||||
|  			if (getcon(&scontext)) { |  			if (getcon(&scontext)) { | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| /* vi: set sw=4 ts=4: */ | /* vi: set sw=4 ts=4: */ | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2003 by Glenn McGrath <bug1@iinet.net.au> |  * Copyright (C) 2003 by Glenn McGrath <bug1@iinet.net.au> | ||||||
|  |  * SELinux support: by Yuichi Nakamura <ynakam@hitachisoft.jp> | ||||||
|  * |  * | ||||||
|  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ | |||||||
|  |  | ||||||
| #if ENABLE_SELINUX | #if ENABLE_SELINUX | ||||||
| #include <selinux/selinux.h> | #include <selinux/selinux.h> | ||||||
|  | #include <selinux/context.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if ENABLE_LOCALE_SUPPORT | #if ENABLE_LOCALE_SUPPORT | ||||||
| @@ -598,6 +599,8 @@ extern void run_shell(const char *shell, int loginshell, const char *command, co | |||||||
| #if ENABLE_SELINUX | #if ENABLE_SELINUX | ||||||
| extern void renew_current_security_context(void); | extern void renew_current_security_context(void); | ||||||
| extern void set_current_security_context(security_context_t sid); | extern void set_current_security_context(security_context_t sid); | ||||||
|  | extern context_t set_security_context_component(security_context_t cur_context, | ||||||
|  | 						char *user, char *role, char *type, char *range); | ||||||
| #endif | #endif | ||||||
| extern void selinux_or_die(void); | extern void selinux_or_die(void); | ||||||
| extern int restricted_shell(const char *shell); | extern int restricted_shell(const char *shell); | ||||||
|   | |||||||
| @@ -106,6 +106,7 @@ lib-$(CONFIG_SU) += correct_password.o | |||||||
| lib-$(CONFIG_LOGIN) += correct_password.o | lib-$(CONFIG_LOGIN) += correct_password.o | ||||||
| lib-$(CONFIG_DF) += find_mount_point.o | lib-$(CONFIG_DF) += find_mount_point.o | ||||||
| lib-$(CONFIG_MKFS_MINIX) += find_mount_point.o | lib-$(CONFIG_MKFS_MINIX) += find_mount_point.o | ||||||
|  | lib-$(CONFIG_SELINUX) += selinux_common.o | ||||||
|  |  | ||||||
| # We shouldn't build xregcomp.c if we don't need it - this ensures we don't | # We shouldn't build xregcomp.c if we don't need it - this ensures we don't | ||||||
| # require regex.h to be in the include dir even if we don't need it thereby | # require regex.h to be in the include dir even if we don't need it thereby | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								libbb/selinux_common.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								libbb/selinux_common.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | /* | ||||||
|  |  * libbb/selinux_common.c | ||||||
|  |  *   -- common SELinux utility functions | ||||||
|  |  *  | ||||||
|  |  * Copyright 2007 KaiGai Kohei <kaigai@kaigai.gr.jp> | ||||||
|  |  */ | ||||||
|  | #include "busybox.h" | ||||||
|  | #include <selinux/context.h> | ||||||
|  |  | ||||||
|  | context_t set_security_context_component(security_context_t cur_context, | ||||||
|  | 					 char *user, char *role, char *type, char *range) | ||||||
|  | { | ||||||
|  | 	context_t con = context_new(cur_context); | ||||||
|  | 	if (!con) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	if (user && context_user_set(con, user)) | ||||||
|  | 		goto error; | ||||||
|  | 	if (type && context_type_set(con, type)) | ||||||
|  | 		goto error; | ||||||
|  | 	if (range && context_range_set(con, range)) | ||||||
|  | 		goto error; | ||||||
|  | 	if (role && context_role_set(con, role)) | ||||||
|  | 		goto error; | ||||||
|  | 	return con; | ||||||
|  |  | ||||||
|  | error: | ||||||
|  | 	context_free(con); | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
							
								
								
									
										175
									
								
								selinux/chcon.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								selinux/chcon.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | |||||||
|  | /* | ||||||
|  |  * chcon -- change security context, based on coreutils-5.97-13 | ||||||
|  |  * | ||||||
|  |  * Port to busybox: KaiGai Kohei <kaigai@kaigai.gr.jp> | ||||||
|  |  *  | ||||||
|  |  * Copyright (C) 2006 - 2007 KaiGai Kohei <kaigai@kaigai.gr.jp> | ||||||
|  |  */ | ||||||
|  | #include "busybox.h" | ||||||
|  | #include <getopt.h> | ||||||
|  | #include <selinux/context.h> | ||||||
|  |  | ||||||
|  | #define OPT_RECURSIVE		(1<<0)	/* 'R' */ | ||||||
|  | #define OPT_CHANHES		(1<<1)	/* 'c' */ | ||||||
|  | #define OPT_NODEREFERENCE	(1<<2)	/* 'h' */ | ||||||
|  | #define OPT_QUIET		(1<<3)	/* 'f' */ | ||||||
|  | #define OPT_USER		(1<<4)	/* 'u' */ | ||||||
|  | #define OPT_ROLE		(1<<5)	/* 'r' */ | ||||||
|  | #define OPT_TYPE		(1<<6)	/* 't' */ | ||||||
|  | #define OPT_RANGE		(1<<7)	/* 'l' */ | ||||||
|  | #define OPT_VERBOSE		(1<<8)	/* 'v' */ | ||||||
|  | #define OPT_REFERENCE		((1<<9) * ENABLE_FEATURE_CHCON_LONG_OPTIONS) | ||||||
|  | #define OPT_COMPONENT_SPECIFIED	(OPT_USER | OPT_ROLE | OPT_TYPE | OPT_RANGE) | ||||||
|  |  | ||||||
|  | static char *user = NULL; | ||||||
|  | static char *role = NULL; | ||||||
|  | static char *type = NULL; | ||||||
|  | static char *range = NULL; | ||||||
|  | static char *specified_context = NULL; | ||||||
|  |  | ||||||
|  | static int change_filedir_context(const char *fname, struct stat *stbuf, void *userData, int depth) | ||||||
|  | { | ||||||
|  | 	context_t context = NULL; | ||||||
|  | 	security_context_t file_context = NULL; | ||||||
|  | 	security_context_t context_string; | ||||||
|  | 	int rc = FALSE; | ||||||
|  | 	int status = 0; | ||||||
|  |  | ||||||
|  | 	if (option_mask32 & OPT_NODEREFERENCE) { | ||||||
|  | 		status = lgetfilecon(fname, &file_context); | ||||||
|  | 	} else { | ||||||
|  | 		status = getfilecon(fname, &file_context); | ||||||
|  | 	} | ||||||
|  | 	if (status < 0 && errno != ENODATA) { | ||||||
|  | 		if ((option_mask32 & OPT_QUIET) == 0) | ||||||
|  | 			bb_error_msg("cannot obtain security context: %s", fname); | ||||||
|  | 		goto skip; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (file_context == NULL && specified_context == NULL) { | ||||||
|  | 		bb_error_msg("cannot apply partial context to unlabeled file %s", fname); | ||||||
|  | 		goto skip; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (specified_context == NULL) { | ||||||
|  | 		context = set_security_context_component(file_context, | ||||||
|  | 							 user, role, type, range); | ||||||
|  | 		if (!context) { | ||||||
|  | 			bb_error_msg("cannot compute security context from %s", file_context); | ||||||
|  | 			goto skip; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		context = context_new(specified_context); | ||||||
|  | 		if (!context) { | ||||||
|  | 			bb_error_msg("invalid context: %s", specified_context); | ||||||
|  | 			goto skip; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	context_string = context_str(context); | ||||||
|  | 	if (!context_string) { | ||||||
|  | 		bb_error_msg("cannot obtain security context in text expression"); | ||||||
|  | 		goto skip; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (file_context == NULL || strcmp(context_string, file_context) != 0) { | ||||||
|  | 		int fail; | ||||||
|  |  | ||||||
|  | 		if (option_mask32 & OPT_NODEREFERENCE) { | ||||||
|  | 			fail = lsetfilecon(fname, context_string); | ||||||
|  | 		} else { | ||||||
|  | 			fail = setfilecon(fname, context_string); | ||||||
|  | 		} | ||||||
|  | 		if ((option_mask32 & OPT_VERBOSE) || ((option_mask32 & OPT_CHANHES) && !fail)) { | ||||||
|  | 			printf(!fail | ||||||
|  | 			       ? "context of %s changed to %s\n" | ||||||
|  | 			       : "failed to change context of %s to %s\n", | ||||||
|  | 			       fname, context_string); | ||||||
|  | 		} | ||||||
|  | 		if (!fail) { | ||||||
|  | 			rc = TRUE; | ||||||
|  | 		} else if ((option_mask32 & OPT_QUIET) == 0) { | ||||||
|  | 			bb_error_msg("failed to change context of %s to %s", | ||||||
|  | 				     fname, context_string); | ||||||
|  | 		} | ||||||
|  | 	} else if (option_mask32 & OPT_VERBOSE) { | ||||||
|  | 		printf("context of %s retained as %s\n", fname, context_string); | ||||||
|  | 		rc = TRUE; | ||||||
|  | 	} | ||||||
|  | skip: | ||||||
|  | 	/* FIXME: aren't these work ok on NULL ptr? Remove if() then */ | ||||||
|  | 	if (context) | ||||||
|  | 		context_free(context); | ||||||
|  | 	if (file_context) | ||||||
|  | 		freecon(file_context); | ||||||
|  |  | ||||||
|  | 	return rc; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if ENABLE_FEATURE_CHCON_LONG_OPTIONS | ||||||
|  | static struct option chcon_options[] = { | ||||||
|  | 	{ "recursive",      0, NULL, 'R' }, | ||||||
|  | 	{ "changes",        0, NULL, 'c' }, | ||||||
|  | 	{ "no-dereference", 0, NULL, 'h' }, | ||||||
|  | 	{ "silent",         0, NULL, 'f' }, | ||||||
|  | 	{ "quiet",          0, NULL, 'f' }, | ||||||
|  | 	{ "user",           1, NULL, 'u' }, | ||||||
|  | 	{ "role",           1, NULL, 'r' }, | ||||||
|  | 	{ "type",           1, NULL, 't' }, | ||||||
|  | 	{ "range",          1, NULL, 'l' }, | ||||||
|  | 	{ "verbose",        0, NULL, 'v' }, | ||||||
|  | 	{ "reference",      1, NULL, 0xff }, /* no short option */ | ||||||
|  | 	{ NULL,             0, NULL, 0 }, | ||||||
|  | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | int chcon_main(int argc, char *argv[]); | ||||||
|  | int chcon_main(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	char *reference_file; | ||||||
|  | 	char *fname; | ||||||
|  | 	int i, errors = 0; | ||||||
|  |  | ||||||
|  | #if ENABLE_FEATURE_CHCON_LONG_OPTIONS | ||||||
|  | 	applet_long_options = chcon_options; | ||||||
|  | #endif | ||||||
|  | 	opt_complementary = "-1"    /* at least 1 param */ | ||||||
|  | 		":?:f--v:v--f"      /* 'verbose' and 'quiet' are exclusive */ | ||||||
|  | 		":\xff--urtl:u--\xff:r--\xff:t--\xff:l--\xff"; | ||||||
|  | 	getopt32(argc, argv, "Rchf:u:r:t:l:v", | ||||||
|  | 		&user, &role, &type, &range, &reference_file); | ||||||
|  | 	argv += optind; | ||||||
|  |  | ||||||
|  | #if ENABLE_FEATURE_CHCON_LONG_OPTIONS | ||||||
|  | 	if (option_mask32 & OPT_REFERENCE) { | ||||||
|  | 		/* FIXME: lgetfilecon() should be used when '-h' is specified. | ||||||
|  | 		   But current implementation follows the original one. */ | ||||||
|  | 		if (getfilecon(reference_file, &specified_context) < 0) | ||||||
|  | 			bb_perror_msg_and_die("getfilecon('%s') failed", reference_file); | ||||||
|  | 	} else | ||||||
|  | #endif | ||||||
|  | 	if ((option_mask32 & OPT_COMPONENT_SPECIFIED) == 0) { | ||||||
|  | 		specified_context = *argv++; | ||||||
|  | 		/* specified_context is never NULL - | ||||||
|  | 		 * "-1" in opt_complementary prevents this. */ | ||||||
|  | 		if (!argv[0]) | ||||||
|  | 			bb_error_msg_and_die("too few arguments"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (i = 0; (fname = argv[i]) != NULL; i++) { | ||||||
|  | 		int fname_len = strlen(fname); | ||||||
|  | 		while (fname_len > 1 && fname[fname_len - 1] == '/') | ||||||
|  | 			fname_len--; | ||||||
|  | 		fname[fname_len] = '\0'; | ||||||
|  |  | ||||||
|  | 		if (recursive_action(fname, | ||||||
|  | 				     option_mask32 & OPT_RECURSIVE, | ||||||
|  | 				     FALSE,	/* followLinks */ | ||||||
|  | 				     FALSE,	/* depthFirst */ | ||||||
|  | 				     change_filedir_context, | ||||||
|  | 				     change_filedir_context, | ||||||
|  | 				     NULL, 0) != TRUE) | ||||||
|  | 			errors = 1; | ||||||
|  | 	} | ||||||
|  | 	return errors; | ||||||
|  | } | ||||||
							
								
								
									
										137
									
								
								selinux/runcon.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								selinux/runcon.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | |||||||
|  | /* | ||||||
|  |  * runcon [ context | | ||||||
|  |  *         ( [ -c ] [ -r role ] [-t type] [ -u user ] [ -l levelrange ] ) | ||||||
|  |  *         command [arg1 [arg2 ...] ] | ||||||
|  |  * | ||||||
|  |  * attempt to run the specified command with the specified context. | ||||||
|  |  * | ||||||
|  |  * -r role  : use the current context with the specified role | ||||||
|  |  * -t type  : use the current context with the specified type | ||||||
|  |  * -u user  : use the current context with the specified user | ||||||
|  |  * -l level : use the current context with the specified level range | ||||||
|  |  * -c       : compute process transition context before modifying | ||||||
|  |  * | ||||||
|  |  * Contexts are interpreted as follows: | ||||||
|  |  * | ||||||
|  |  * Number of       MLS | ||||||
|  |  * components    system? | ||||||
|  |  * | ||||||
|  |  *     1            -         type | ||||||
|  |  *     2            -         role:type | ||||||
|  |  *     3            Y         role:type:range | ||||||
|  |  *     3            N         user:role:type | ||||||
|  |  *     4            Y         user:role:type:range | ||||||
|  |  *     4            N         error | ||||||
|  |  * | ||||||
|  |  * Port to busybox: KaiGai Kohei <kaigai@kaigai.gr.jp> | ||||||
|  |  *                  - based on coreutils-5.97 (in Fedora Core 6) | ||||||
|  |  */ | ||||||
|  | #include "busybox.h" | ||||||
|  | #include <getopt.h> | ||||||
|  | #include <selinux/context.h> | ||||||
|  | #include <selinux/flask.h> | ||||||
|  |  | ||||||
|  | static context_t runcon_compute_new_context(char *user, char *role, char *type, char *range, | ||||||
|  | 					    char *command, int compute_trans) | ||||||
|  | { | ||||||
|  | 	context_t con; | ||||||
|  | 	security_context_t cur_context; | ||||||
|  |  | ||||||
|  | 	if (getcon(&cur_context)) | ||||||
|  | 		bb_error_msg_and_die("cannot get current context"); | ||||||
|  |  | ||||||
|  | 	if (compute_trans) { | ||||||
|  | 		security_context_t file_context, new_context; | ||||||
|  |  | ||||||
|  | 		if (getfilecon(command, &file_context) < 0) | ||||||
|  | 			bb_error_msg_and_die("cannot retrieve attributes of '%s'", | ||||||
|  | 					     command); | ||||||
|  | 		if (security_compute_create(cur_context, file_context, | ||||||
|  | 					    SECCLASS_PROCESS, &new_context)) | ||||||
|  | 			bb_error_msg_and_die("unable to compute a new context"); | ||||||
|  | 		cur_context = new_context; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	con = context_new(cur_context); | ||||||
|  | 	if (!con) | ||||||
|  | 		bb_error_msg_and_die("'%s' is not a valid context", cur_context); | ||||||
|  | 	if (user && context_user_set(con, user)) | ||||||
|  | 		bb_error_msg_and_die("failed to set new user '%s'", user); | ||||||
|  | 	if (type && context_type_set(con, type)) | ||||||
|  | 		bb_error_msg_and_die("failed to set new type '%s'", type); | ||||||
|  | 	if (range && context_range_set(con, range)) | ||||||
|  | 		bb_error_msg_and_die("failed to set new range '%s'", range); | ||||||
|  | 	if (role && context_role_set(con, role)) | ||||||
|  | 		bb_error_msg_and_die("failed to set new role '%s'", role); | ||||||
|  |  | ||||||
|  | 	return con; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if ENABLE_FEATURE_RUNCON_LONG_OPTIONS | ||||||
|  | static const struct option runcon_options[] = { | ||||||
|  | 	{ "user",       1, NULL, 'u' }, | ||||||
|  | 	{ "role",       1, NULL, 'r' }, | ||||||
|  | 	{ "type",       1, NULL, 't' }, | ||||||
|  | 	{ "range",      1, NULL, 'l' }, | ||||||
|  | 	{ "compute",    0, NULL, 'c' }, | ||||||
|  | 	{ "help",       0, NULL, 'h' }, | ||||||
|  | 	{ NULL,         0, NULL, 0 }, | ||||||
|  | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define OPTS_ROLE	(1<<0)	/* r */ | ||||||
|  | #define OPTS_TYPE	(1<<1)	/* t */ | ||||||
|  | #define OPTS_USER	(1<<2)	/* u */ | ||||||
|  | #define OPTS_RANGE	(1<<3)	/* l */ | ||||||
|  | #define OPTS_COMPUTE	(1<<4)	/* c */ | ||||||
|  | #define OPTS_HELP	(1<<5)	/* h */ | ||||||
|  | #define OPTS_CONTEXT_COMPONENT		(OPTS_ROLE | OPTS_TYPE | OPTS_USER | OPTS_RANGE) | ||||||
|  |  | ||||||
|  | int runcon_main(int argc, char *argv[]); | ||||||
|  | int runcon_main(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	char *role = NULL; | ||||||
|  | 	char *range = NULL; | ||||||
|  | 	char *user = NULL; | ||||||
|  | 	char *type = NULL; | ||||||
|  | 	char *context = NULL; | ||||||
|  | 	unsigned opts; | ||||||
|  | 	context_t con; | ||||||
|  |  | ||||||
|  | 	selinux_or_die(); | ||||||
|  |  | ||||||
|  | #if ENABLE_FEATURE_RUNCON_LONG_OPTIONS | ||||||
|  | 	applet_long_options = runcon_options; | ||||||
|  | #endif | ||||||
|  | 	opt_complementary = "-1"; | ||||||
|  | 	opts = getopt32(argc, argv, "r:t:u:l:ch", &role, &type, &user, &range); | ||||||
|  | 	argv += optind; | ||||||
|  |  | ||||||
|  | 	if (!(opts & OPTS_CONTEXT_COMPONENT)) { | ||||||
|  | 		context = *argv++; | ||||||
|  | 		if (!argv[0]) | ||||||
|  | 			bb_error_msg_and_die("no command found"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (context) { | ||||||
|  | 		con = context_new(context); | ||||||
|  | 		if (!con) | ||||||
|  | 			bb_error_msg_and_die("'%s' is not a valid context", context); | ||||||
|  | 	} else { | ||||||
|  | 		con = runcon_compute_new_context(user, role, type, range, | ||||||
|  | 				argv[0], opts & OPTS_COMPUTE); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (security_check_context(context_str(con))) | ||||||
|  | 		bb_error_msg_and_die("'%s' is not a valid context", | ||||||
|  | 				     context_str(con)); | ||||||
|  |  | ||||||
|  | 	if (setexeccon(context_str(con))) | ||||||
|  | 		bb_error_msg_and_die("cannot set up security context '%s'", | ||||||
|  | 				     context_str(con)); | ||||||
|  |  | ||||||
|  | 	execvp(argv[0], argv); | ||||||
|  |  | ||||||
|  | 	bb_perror_msg_and_die("cannot execute '%s'", command); | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user