From 4aca87515a5083ae0e31ce3177189fd43b6d05ac Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 3 Jan 2015 13:58:15 +0100 Subject: patch to Vanilla Tomato 1.28 --- release/src/router/busybox/selinux/chcon.c | 179 +++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 release/src/router/busybox/selinux/chcon.c (limited to 'release/src/router/busybox/selinux/chcon.c') diff --git a/release/src/router/busybox/selinux/chcon.c b/release/src/router/busybox/selinux/chcon.c new file mode 100644 index 00000000..55c2522f --- /dev/null +++ b/release/src/router/busybox/selinux/chcon.c @@ -0,0 +1,179 @@ +/* + * chcon -- change security context, based on coreutils-5.97-13 + * + * Port to busybox: KaiGai Kohei + * + * Copyright (C) 2006 - 2007 KaiGai Kohei + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ +#include +#include + +#include "libbb.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 FAST_FUNC change_filedir_context( + const char *fname, + struct stat *stbuf UNUSED_PARAM, + void *userData UNUSED_PARAM, + int depth UNUSED_PARAM) +{ + 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: + context_free(context); + freecon(file_context); + + return rc; +} + +#if ENABLE_FEATURE_CHCON_LONG_OPTIONS +static const char chcon_longopts[] ALIGN1 = + "recursive\0" No_argument "R" + "changes\0" No_argument "c" + "no-dereference\0" No_argument "h" + "silent\0" No_argument "f" + "quiet\0" No_argument "f" + "user\0" Required_argument "u" + "role\0" Required_argument "r" + "type\0" Required_argument "t" + "range\0" Required_argument "l" + "verbose\0" No_argument "v" + "reference\0" Required_argument "\xff" /* no short option */ + ; +#endif + +int chcon_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int chcon_main(int argc UNUSED_PARAM, char **argv) +{ + char *reference_file; + char *fname; + int i, errors = 0; + +#if ENABLE_FEATURE_CHCON_LONG_OPTIONS + applet_long_options = chcon_longopts; +#endif + opt_complementary = "-1" /* at least 1 param */ + ":?" /* error if exclusivity constraints are violated */ +#if ENABLE_FEATURE_CHCON_LONG_OPTIONS + ":\xff--urtl:u--\xff:r--\xff:t--\xff:l--\xff" +#endif + ":f--v:v--f"; /* 'verbose' and 'quiet' are exclusive */ + getopt32(argv, "Rchfu: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, + 1<