* [PATCH 7/8] busybox -- SELinux option support for coreutils: ver3
@ 2007-02-23 8:48 Yuichi Nakamura
[not found] ` <200702241601.12758.vda.linux@googlemail.com>
0 siblings, 1 reply; 3+ messages in thread
From: Yuichi Nakamura @ 2007-02-23 8:48 UTC (permalink / raw)
To: busybox; +Cc: busybox, vda.linux, selinux
[-- Attachment #1: Type: text/plain, Size: 143 bytes --]
[7/8] busybox-coreutils-07-chcon.v3.patch
- chcon - change security context of file.
Signed-off-by: KaiGai Kohei <kaigai@kaigai.gr.jp>
[-- Attachment #2: busybox-coreutils-chcon-07.v3.patch --]
[-- Type: application/octet-stream, Size: 6322 bytes --]
Index: selinux/chcon.c
===================================================================
--- selinux/chcon.c (revision 0)
+++ selinux/chcon.c (revision 0)
@@ -0,0 +1,216 @@
+/*
+ * chcon -- based on coreutils-5.97-13
+ *
+ * Author: ????
+ * Port to busybox: KaiGai Kohei <kaigai@kaigai.gr.jp>
+ *
+ * Copyright (C) 2006 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_REFERENCE (1<<4) /* '\n' */
+#define OPT_USER (1<<5) /* 'u' */
+#define OPT_ROLE (1<<6) /* 'r' */
+#define OPT_TYPE (1<<7) /* 't' */
+#define OPT_RANGE (1<<8) /* 'l' */
+#define OPT_VERBOSE (1<<9) /* 'v' */
+#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_dir_context(const char *dir_name, unsigned int opts);
+
+static context_t compute_context_from_mask(security_context_t context, unsigned int opts)
+{
+ context_t new_context = context_new(context);
+ if (!new_context)
+ return NULL;
+
+ if ((opts & OPT_USER) && context_user_set(new_context, user))
+ goto error;
+ if ((opts & OPT_RANGE) && context_range_set(new_context, range))
+ goto error;
+ if ((opts & OPT_ROLE) && context_role_set(new_context, role))
+ goto error;
+ if ((opts & OPT_TYPE) && context_type_set(new_context, type))
+ goto error;
+
+ return new_context;
+error:
+ context_free (new_context);
+ return NULL;
+}
+
+static int change_file_context(const char *fname, unsigned long opts)
+{
+ security_context_t file_context = NULL;
+ security_context_t context_string;
+ context_t context;
+ int errors = 0;
+ int status = 0;
+
+ if (opts & OPT_NODEREFERENCE) {
+ status = lgetfilecon(fname, &file_context);
+ } else {
+ status = getfilecon(fname, &file_context);
+ }
+ if (status < 0 && errno != ENODATA) {
+ if (!(opts & OPT_QUIET) == 0)
+ bb_error_msg("could not obtain security context: %s", fname);
+ return 1;
+ }
+
+ if (file_context == NULL && specified_context == NULL) {
+ bb_error_msg("could not apply partial context to unlabeled file %s", fname);
+ return 1;
+ }
+
+ if (specified_context == NULL) {
+ context = compute_context_from_mask(file_context, opts);
+ if (!context) {
+ bb_error_msg("couldn't compute security context from %s", file_context);
+ return 1;
+ }
+ } else {
+ context = context_new(specified_context);
+ if (!context) {
+ bb_error_msg("invalid context: %s", specified_context);
+ return 1;
+ }
+ }
+
+ context_string = context_str(context);
+ if (file_context == NULL || strcmp(context_string, file_context) != 0) {
+ int fail = 0;
+
+ if (opts & OPT_NODEREFERENCE) {
+ fail = lsetfilecon (fname, context_string);
+ } else {
+ fail = setfilecon (fname, context_string);
+ }
+ if ((opts & OPT_VERBOSE)
+ || ((opts & 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) {
+ errors = 1;
+ if ((opts & OPT_QUIET) == 0)
+ bb_error_msg("failed to change context of %s to %s",
+ fname, context_string);
+ }
+ } else if (opts & OPT_VERBOSE) {
+ printf("context of %s retained as %s\n", fname, context_string);
+ }
+ context_free(context);
+ freecon(file_context);
+
+ if (opts & OPT_RECURSIVE) {
+ struct stat file_stats;
+ if (lstat(fname, &file_stats) == 0
+ && S_ISDIR(file_stats.st_mode))
+ errors |= change_dir_context(fname, opts);
+ }
+ return errors;
+}
+
+static int change_dir_context(const char *dir_name, unsigned int opts)
+{
+ DIR *dir;
+ struct dirent *dent;
+ char buffer[PATH_MAX];
+ int len, rc = 0;
+
+ dir = opendir(dir_name);
+ if (!dir) {
+ if (!(opts & OPT_QUIET))
+ bb_error_msg("failed to open directory '%s'", dir_name);
+ return 1;
+ }
+
+ while ((dent = readdir(dir))) {
+ if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+ continue;
+ len = snprintf(buffer, sizeof(buffer), "%s/%s", dir_name, dent->d_name);
+ if (len > sizeof(buffer)) {
+ bb_error_msg("name too long: %s/%s", dir_name, dent->d_name);
+ continue;
+ }
+ rc |= change_file_context(buffer, opts);
+ }
+
+ closedir(dir);
+
+ return rc;
+}
+
+#ifdef CONFIG_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'},
+ {"reference", 1, NULL, '\n' }, /* no short option */
+ {"user", 1, NULL, 'u' },
+ {"role", 1, NULL, 'r' },
+ {"type", 1, NULL, 't' },
+ {"range", 1, NULL, 'l' },
+ {"verbose", 0, NULL, 'v' },
+ {NULL, 0, NULL, 0 },
+};
+#endif
+
+int chcon_main(int argc, char *argv[]);
+int chcon_main(int argc, char *argv[])
+{
+ char *reference_file;
+ char **target_files;
+ int i, opts, errors = 0;
+
+#ifdef CONFIG_FEATURE_CHCON_LONG_OPTIONS
+ applet_long_options = chcon_options;
+#endif
+ opt_complementary = "-1" /* at least 1 param */
+ ":q--v:v--q"; /* 'verbose' and 'quiet' are exclusive */
+ opts = getopt32(argc, argv, "Rchf\n:u:r:t:l:v",
+ &reference_file, &user, &role, &type, &range);
+ if (opts & OPT_REFERENCE) {
+ if (opts & OPT_COMPONENT_SPECIFIED)
+ bb_error_msg_and_die("conflicting security context specifiers given");
+
+ /* FIXME: lgetfilecon() should be used when '-h' is specified. */
+ if (getfilecon(reference_file, &specified_context) < 0)
+ bb_perror_msg_and_die("getfilecon('%s') failed", reference_file);
+ } else if ((opts & OPT_COMPONENT_SPECIFIED) == 0) {
+ specified_context = argv[optind++];
+ if (!specified_context)
+ bb_error_msg_and_die("too few arguments");
+ }
+ target_files = argv + optind;
+ if (!target_files[0])
+ bb_error_msg_and_die("too few arguments");
+
+ for (i=0; target_files[i]; i++) {
+ char *fname = target_files[i];
+ int fname_len = strlen(fname);
+ while (fname_len > 1 && fname[fname_len - 1] == '/')
+ fname_len--;
+ fname[fname_len] = '\0';
+ errors |= change_file_context(fname, opts);
+
+ }
+ return errors;
+}
^ permalink raw reply [flat|nested] 3+ messages in thread[parent not found: <200702241601.12758.vda.linux@googlemail.com>]
* Re: [PATCH 7/8] busybox -- SELinux option support for coreutils: ver3 [not found] ` <200702241601.12758.vda.linux@googlemail.com> @ 2007-02-26 17:40 ` KaiGai Kohei [not found] ` <20070308132308.GE32231@aon.at> 0 siblings, 1 reply; 3+ messages in thread From: KaiGai Kohei @ 2007-02-26 17:40 UTC (permalink / raw) To: Denis Vlasenko; +Cc: Yuichi Nakamura, busybox, selinux, busybox [-- Attachment #1: Type: text/plain, Size: 2025 bytes --] Hi, Denis. Thanks for your reviews. Denis Vlasenko wrote: > On Friday 23 February 2007 09:48, Yuichi Nakamura wrote: >> [7/8] busybox-coreutils-07-chcon.v3.patch >> - chcon - change security context of file. >> >> Signed-off-by: KaiGai Kohei <kaigai@kaigai.gr.jp> > > +#define OPT_QUIET (1<<3) /* 'f' */ > +#define OPT_REFERENCE (1<<4) /* '\n' */ > +#define OPT_USER (1<<5) /* 'u' */ > > ... > > > + {"quiet", 0, NULL, 'f'}, > + {"reference", 1, NULL, '\n' }, /* no short option */ > + {"user", 1, NULL, 'u' }, > + {"role", 1, NULL, 'r' }, > + {"type", 1, NULL, 't' }, > + {"range", 1, NULL, 'l' }, > + {"verbose", 0, NULL, 'v' }, > + {NULL, 0, NULL, 0 }, > +}; > +#endif > + > +int chcon_main(int argc, char *argv[]); > +int chcon_main(int argc, char *argv[]) > +{ > + char *reference_file; > + char **target_files; > + int i, opts, errors = 0; > + > +#ifdef CONFIG_FEATURE_CHCON_LONG_OPTIONS > + applet_long_options = chcon_options; > +#endif > + opt_complementary = "-1" /* at least 1 param */ > + ":q--v:v--q"; /* 'verbose' and 'quiet' are exclusive */ > + opts = getopt32(argc, argv, "Rchf\n:u:r:t:l:v", > + &reference_file, &user, &role, &type, &range); > + if (opts & OPT_REFERENCE) { > + if (opts & OPT_COMPONENT_SPECIFIED) > + bb_error_msg_and_die("conflicting security context specifiers given"); > > > Again see wget.c how to not pass '\n' to getopt32. > > You can make OPT_REFERENCE and OPT_COMPONENT_SPECIFIED > exclusive by using suitable opt_complementary. OK, fixed. * '\n' was replaced by '0xff' * Checks for exclusive options were added. chcon applet will will abort if --reference and '-u','-r','-t','-l' are appeared concurrently, Thanks, -- KaiGai Kohei <kaigai@kaigai.gr.jp> [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: busybox-coreutils-chcon-07.v4.patch --] [-- Type: text/x-patch; name="busybox-coreutils-chcon-07.v4.patch", Size: 6357 bytes --] Index: selinux/chcon.c =================================================================== --- selinux/chcon.c (リビジョン 0) +++ selinux/chcon.c (リビジョン 0) @@ -0,0 +1,214 @@ +/* + * 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_REFERENCE (1<<4) /* 0xff */ +#define OPT_USER (1<<5) /* 'u' */ +#define OPT_ROLE (1<<6) /* 'r' */ +#define OPT_TYPE (1<<7) /* 't' */ +#define OPT_RANGE (1<<8) /* 'l' */ +#define OPT_VERBOSE (1<<9) /* 'v' */ +#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_dir_context(const char *dir_name, unsigned int opts); + +static context_t compute_context_from_mask(security_context_t context, unsigned int opts) +{ + context_t new_context = context_new(context); + if (!new_context) + return NULL; + + if ((opts & OPT_USER) && context_user_set(new_context, user)) + goto error; + if ((opts & OPT_RANGE) && context_range_set(new_context, range)) + goto error; + if ((opts & OPT_ROLE) && context_role_set(new_context, role)) + goto error; + if ((opts & OPT_TYPE) && context_type_set(new_context, type)) + goto error; + + return new_context; +error: + context_free (new_context); + return NULL; +} + +static int change_file_context(const char *fname, unsigned long opts) +{ + security_context_t file_context = NULL; + security_context_t context_string; + context_t context; + int errors = 0; + int status = 0; + + if (opts & OPT_NODEREFERENCE) { + status = lgetfilecon(fname, &file_context); + } else { + status = getfilecon(fname, &file_context); + } + if (status < 0 && errno != ENODATA) { + if (!(opts & OPT_QUIET) == 0) + bb_error_msg("could not obtain security context: %s", fname); + return 1; + } + + if (file_context == NULL && specified_context == NULL) { + bb_error_msg("could not apply partial context to unlabeled file %s", fname); + return 1; + } + + if (specified_context == NULL) { + context = compute_context_from_mask(file_context, opts); + if (!context) { + bb_error_msg("couldn't compute security context from %s", file_context); + return 1; + } + } else { + context = context_new(specified_context); + if (!context) { + bb_error_msg("invalid context: %s", specified_context); + return 1; + } + } + + context_string = context_str(context); + if (file_context == NULL || strcmp(context_string, file_context) != 0) { + int fail = 0; + + if (opts & OPT_NODEREFERENCE) { + fail = lsetfilecon (fname, context_string); + } else { + fail = setfilecon (fname, context_string); + } + if ((opts & OPT_VERBOSE) + || ((opts & 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) { + errors = 1; + if ((opts & OPT_QUIET) == 0) + bb_error_msg("failed to change context of %s to %s", + fname, context_string); + } + } else if (opts & OPT_VERBOSE) { + printf("context of %s retained as %s\n", fname, context_string); + } + context_free(context); + freecon(file_context); + + if (opts & OPT_RECURSIVE) { + struct stat file_stats; + if (lstat(fname, &file_stats) == 0 + && S_ISDIR(file_stats.st_mode)) + errors |= change_dir_context(fname, opts); + } + return errors; +} + +static int change_dir_context(const char *dir_name, unsigned int opts) +{ + DIR *dir; + struct dirent *dent; + char buffer[PATH_MAX]; + int len, rc = 0; + + dir = opendir(dir_name); + if (!dir) { + if (!(opts & OPT_QUIET)) + bb_error_msg("failed to open directory '%s'", dir_name); + return 1; + } + + while ((dent = readdir(dir))) { + if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) + continue; + len = snprintf(buffer, sizeof(buffer), "%s/%s", dir_name, dent->d_name); + if (len > sizeof(buffer)) { + bb_error_msg("name too long: %s/%s", dir_name, dent->d_name); + continue; + } + rc |= change_file_context(buffer, opts); + } + + closedir(dir); + + return rc; +} + +#ifdef CONFIG_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'}, + {"reference", 1, NULL, 0xff }, /* no short option */ + {"user", 1, NULL, 'u' }, + {"role", 1, NULL, 'r' }, + {"type", 1, NULL, 't' }, + {"range", 1, NULL, 'l' }, + {"verbose", 0, NULL, 'v' }, + {NULL, 0, NULL, 0 }, +}; +#endif + +int chcon_main(int argc, char *argv[]); +int chcon_main(int argc, char *argv[]) +{ + char *reference_file; + char **target_files; + int i, opts, errors = 0; + +#ifdef CONFIG_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"; + opts = getopt32(argc, argv, "Rchf\xff:u:r:t:l:v", + &reference_file, &user, &role, &type, &range); + if (opts & 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 if ((opts & OPT_COMPONENT_SPECIFIED) == 0) { + specified_context = argv[optind++]; + if (!specified_context) + bb_error_msg_and_die("too few arguments"); + } + target_files = argv + optind; + if (!target_files[0]) + bb_error_msg_and_die("too few arguments"); + + for (i=0; target_files[i]; i++) { + char *fname = target_files[i]; + int fname_len = strlen(fname); + while (fname_len > 1 && fname[fname_len - 1] == '/') + fname_len--; + fname[fname_len] = '\0'; + errors |= change_file_context(fname, opts); + + } + return errors; +} ^ permalink raw reply [flat|nested] 3+ messages in thread
[parent not found: <20070308132308.GE32231@aon.at>]
* Ver.6 (Re: [PATCH 7/8] busybox -- SELinux option support for coreutils: ver3) [not found] ` <20070308132308.GE32231@aon.at> @ 2007-03-10 5:43 ` KaiGai Kohei 0 siblings, 0 replies; 3+ messages in thread From: KaiGai Kohei @ 2007-03-10 5:43 UTC (permalink / raw) To: busybox; +Cc: Denis Vlasenko, busybox, selinux [-- Attachment #1: Type: text/plain, Size: 2896 bytes --] Hello, Thanks for your reviewing. >> * '\n' was replaced by '0xff' >> * Checks for exclusive options were added. chcon applet will will abort >> if --reference and '-u','-r','-t','-l' are appeared concurrently, > > Please move the change_dir_context() function around to remove the > forward decl. I replaced change_dir_context() function by recursive_action(), not only its declaration. > +static context_t compute_context_from_mask(security_context_t context, > + context_free (new_context); > > surplus space > Smaller if you goto ret where > ret: > return NULL; > } As you say, we can share the above function between runcon and chcon, so I removed the compute_context_from_mask() and added a new function in libbb/selinux_common.c. See, busybox-coreutils-libbb-09.v6.patch > + context_string = context_str(context); > + if (file_context == NULL || strcmp(context_string, file_context) != 0) { > > Can context_str() return NULL? Yes, it can return NULL, if malloc() used internally didn't succeed. So, I added the following check: + context_string = context_str(context); + if (!context_string) { + bb_error_msg("couldn't obtain security context in text expression"); + goto skip; + } > + int fail = 0; > > superfluous set. Remove initialization to 0 Fixed, > + > + if (opts & OPT_NODEREFERENCE) { > + fail = lsetfilecon (fname, context_string); > + } else { > + fail = setfilecon (fname, context_string); > + } > + if ((opts & OPT_VERBOSE) > + || ((opts & OPT_CHANHES) && !fail)) { > + printf(!fail > > bb_perror_msg() instead of printf? bb_perror_msg() prints a message into stderr, although upstreamed chcon prints a message into stdout. It will make an incompatibility. So, I didn't use bb_error_msg() here. > + ? "context of %s changed to %s\n" > + : "failed to change context of %s to > %s\n", > + fname, context_string); > + } > > change_dir_context() sounds a bit overdone. Don't we have an opendir > wrapper with diagnostics? Perhaps this is a candidate for > recursive_action() It was replaced by recursive_action(). > Manually inlining compute_context_from_mask() smaller? It was moved into libbb/selinux_common.o to share with 'runcon'. > Smaller to resuse the global option_mask32 rather than using opts in > chcon_main() ? I replaced any local 'opts' by option_mask32. > + ":?:f--v:v--f" /* 'verbose' and 'quiet' are exclusive */ > Sounds like there is the word mutual missing. '-f' is a option for the silent purpose. It is a definition of upstreamed chcon. Thanks, -- KaiGai Kohei <kaigai@kaigai.gr.jp> [-- Attachment #2: busybox-coreutils-libbb-09.v6.patch --] [-- Type: text/x-diff, Size: 2083 bytes --] Index: include/libbb.h =================================================================== --- include/libbb.h (revision 18056) +++ include/libbb.h (working copy) @@ -41,6 +41,7 @@ #if ENABLE_SELINUX #include <selinux/selinux.h> +#include <selinux/context.h> #endif #if ENABLE_LOCALE_SUPPORT @@ -598,6 +599,8 @@ #if ENABLE_SELINUX extern void renew_current_security_context(void); 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 extern void selinux_or_die(void); extern int restricted_shell(const char *shell); Index: libbb/Kbuild =================================================================== --- libbb/Kbuild (revision 18056) +++ libbb/Kbuild (working copy) @@ -106,6 +106,7 @@ lib-$(CONFIG_LOGIN) += correct_password.o lib-$(CONFIG_DF) += 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 # require regex.h to be in the include dir even if we don't need it thereby Index: libbb/selinux_common.c =================================================================== --- libbb/selinux_common.c (revision 0) +++ libbb/selinux_common.c (revision 0) @@ -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; +} [-- Attachment #3: busybox-coreutils-runcon-08.v6.patch --] [-- Type: text/x-diff, Size: 4150 bytes --] Index: selinux/runcon.c =================================================================== --- selinux/runcon.c (revision 0) +++ selinux/runcon.c (revision 0) @@ -0,0 +1,131 @@ +/* + * 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> + +#ifdef CONFIG_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) + +static context_t +runcon_compute_new_context(char *user, char *role, char *type, char *range, char *command) +{ + context_t con; + security_context_t cur_context; + + if (getcon(&cur_context)) + bb_error_msg_and_die("could not get current context."); + + if (option_mask32 & OPTS_COMPUTE) { + security_context_t file_context, new_context; + + if (getfilecon(command, &file_context) < 0) + bb_error_msg_and_die("unable to 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 = set_security_context_component(cur_context, user, role, type, range); + if (!con) + bb_error_msg_and_die("failed to set new context"); + + return con; +} + +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; + char *command; + char **command_args; + context_t con; + + selinux_or_die(); + +#ifdef CONFIG_FEATURE_RUNCON_LONG_OPTIONS + applet_long_options = runcon_options; +#endif + opt_complementary="-1"; /* need at least one non-option parm */ + getopt32(argc, argv, "r:t:u:l:ch", &role, &type, &user, &range); + + if (!(option_mask32 & OPTS_CONTEXT_COMPONENT)) + context = argv[optind++]; + + if (optind >= argc) + bb_error_msg_and_die((option_mask32 & OPTS_CONTEXT_COMPONENT) + ? "no command found" + : "must specify -c, -t, -u, -l, -r, or context"); + command = argv[optind]; + command_args = argv + optind; + + 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, command); + } + + 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("unable to set up security context '%s'", + context_str(con)); + + execvp(command, command_args); + + bb_perror_msg_and_die("unable to execute '%s'", command); + return 1; +} [-- Attachment #4: busybox-coreutils-chcon-07.v6.patch --] [-- Type: text/x-diff, Size: 5322 bytes --] Index: selinux/chcon.c =================================================================== --- selinux/chcon.c (revision 0) +++ selinux/chcon.c (revision 0) @@ -0,0 +1,171 @@ +/* + * 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_REFERENCE (1<<4) /* 0xff */ +#define OPT_USER (1<<5) /* 'u' */ +#define OPT_ROLE (1<<6) /* 'r' */ +#define OPT_TYPE (1<<7) /* 't' */ +#define OPT_RANGE (1<<8) /* 'l' */ +#define OPT_VERBOSE (1<<9) /* 'v' */ +#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("could not obtain security context: %s", fname); + goto skip; + } + + if (file_context == NULL && specified_context == NULL) { + bb_error_msg("could not 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("couldn't 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("couldn't 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: + if (context) + context_free(context); + if (file_context) + freecon(file_context); + + return rc; +} + +#ifdef CONFIG_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'}, + {"reference", 1, NULL, 0xff }, /* no short option */ + {"user", 1, NULL, 'u' }, + {"role", 1, NULL, 'r' }, + {"type", 1, NULL, 't' }, + {"range", 1, NULL, 'l' }, + {"verbose", 0, NULL, 'v' }, + {NULL, 0, NULL, 0 }, +}; +#endif + +int chcon_main(int argc, char *argv[]); +int chcon_main(int argc, char *argv[]) +{ + char *reference_file; + char **target_files; + int i, errors = 0; + +#ifdef CONFIG_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\xff:u:r:t:l:v", + &reference_file, &user, &role, &type, &range); + 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 if ((option_mask32 & OPT_COMPONENT_SPECIFIED) == 0) { + specified_context = argv[optind++]; + if (!specified_context) + bb_error_msg_and_die("too few arguments"); + } + target_files = argv + optind; + if (!target_files[0]) + bb_error_msg_and_die("too few arguments"); + + for (i=0; target_files[i]; i++) { + char *fname = target_files[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 ? TRUE : FALSE), + FALSE, /* followLinks */ + FALSE, /* depthFirst */ + change_filedir_context, + change_filedir_context, + NULL, 0) != TRUE) + errors = 1; + } + return errors; +} ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2007-03-10 5:43 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-02-23 8:48 [PATCH 7/8] busybox -- SELinux option support for coreutils: ver3 Yuichi Nakamura
[not found] ` <200702241601.12758.vda.linux@googlemail.com>
2007-02-26 17:40 ` KaiGai Kohei
[not found] ` <20070308132308.GE32231@aon.at>
2007-03-10 5:43 ` Ver.6 (Re: [PATCH 7/8] busybox -- SELinux option support for coreutils: ver3) KaiGai Kohei
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.