selinux support by Yuichi Nakamura <ynakam@hitachisoft.jp> (HitachiSoft)
authorDenis Vlasenko <vda.linux@googlemail.com>
Sat, 10 Mar 2007 16:58:49 +0000 (16:58 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sat, 10 Mar 2007 16:58:49 +0000 (16:58 -0000)
14 files changed:
coreutils/cp.c
coreutils/id.c
coreutils/install.c
coreutils/libcoreutils/getopt_mk_fifo_nod.c
coreutils/ls.c
coreutils/mkdir.c
coreutils/mv.c
coreutils/stat.c
include/applets.h
include/libbb.h
include/usage.h
libbb/copy_file.c
selinux/Config.in
selinux/Kbuild

index 7b0de47..64cf637 100644 (file)
@@ -3,6 +3,7 @@
  * Mini cp implementation for busybox
  *
  * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
  *
  * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
  */
@@ -50,6 +51,12 @@ int cp_main(int argc, char **argv)
        if (flags & OPT_H) ... // deref command-line params only
        */
 
+#if ENABLE_SELINUX 
+       if (flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) {
+               selinux_or_die();
+       }
+#endif
+
        flags ^= FILEUTILS_DEREFERENCE;         /* The sense of this flag was reversed. */
 
        if (optind + 2 > argc) {
index 963ee05..a036467 100644 (file)
@@ -10,6 +10,7 @@
 /* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
 /* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to
  * be more similar to GNU id.
+ * -Z option support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
  */
 
 #include "busybox.h"
 #include <unistd.h>
 #include <sys/types.h>
 
-#ifdef CONFIG_SELINUX
-#include <selinux/selinux.h>          /* for is_selinux_enabled() */
-#endif
-
 #define PRINT_REAL        1
 #define NAME_NOT_NUMBER   2
 #define JUST_USER         4
 #define JUST_GROUP        8
+#if ENABLE_SELINUX
+#define JUST_CONTEXT    16
+#endif
 
 static short printf_full(unsigned int id, const char *arg, const char prefix)
 {
@@ -47,11 +47,13 @@ int id_main(int argc, char **argv)
        gid_t gid;
        unsigned long flags;
        short status;
-
+#if ENABLE_SELINUX
+       security_context_t scontext;
+#endif
        /* Don't allow -n -r -nr -ug -rug -nug -rnug */
        /* Don't allow more than one username */
-       opt_complementary = "?1:?:u--g:g--u:r?ug:n?ug";
-       flags = getopt32(argc, argv, "rnug");
+       opt_complementary = "?1:?:u--g:g--u:r?ug:n?ug" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
+       flags = getopt32(argc, argv, "rnug" USE_SELINUX("Z"));
 
        /* This values could be overwritten later */
        uid = geteuid();
@@ -69,14 +71,33 @@ int id_main(int argc, char **argv)
                /* in this case PRINT_REAL is the same */
        }
 
-       if (flags & (JUST_GROUP | JUST_USER)) {
+       if (flags & (JUST_GROUP | JUST_USER USE_SELINUX(| JUST_CONTEXT))) {
                /* JUST_GROUP and JUST_USER are mutually exclusive */
                if (flags & NAME_NOT_NUMBER) {
                        /* bb_getpwuid and bb_getgrgid exit on failure so puts cannot segfault */
                        puts((flags & JUST_USER) ? bb_getpwuid(NULL, uid, -1 ) : bb_getgrgid(NULL, gid, -1 ));
                } else {
-                       printf("%u\n", (flags & JUST_USER) ? uid : gid);
-               }
+                       if (flags & JUST_USER) {
+                               printf("%u\n", uid);
+                       }
+                       if (flags & JUST_GROUP) {
+                               printf("%u\n", gid);
+                       }
+               }
+               
+#if ENABLE_SELINUX
+               if (flags & JUST_CONTEXT) {        
+                       selinux_or_die();
+                       if (argc - optind == 1) {
+                               bb_error_msg_and_die("can't print security context when user specified");
+                       }
+                       
+                       if (getcon(&scontext)) {
+                               bb_error_msg_and_die("can't get process context");              
+                       }
+                       printf("%s\n", scontext);
+               }
+#endif 
                /* exit */
                fflush_stdout_and_exit(EXIT_SUCCESS);
        }
@@ -88,7 +109,7 @@ int id_main(int argc, char **argv)
        /* bb_getgrgid doesn't exit on failure here */
        status |= printf_full(gid, bb_getgrgid(NULL, gid, 0), 'g');
 
-#ifdef CONFIG_SELINUX
+#if ENABLE_SELINUX
        if (is_selinux_enabled()) {
                security_context_t mysid;
                const char *context;
index c105add..83facad 100644 (file)
@@ -21,10 +21,49 @@ static const struct option install_long_options[] = {
        { "group",               0, NULL, 'g' },
        { "mode",                0, NULL, 'm' },
        { "owner",               0, NULL, 'o' },
+#if ENABLE_SELINUX
+       { "context",             1, NULL, 'Z' },
+       { "preserve_context",    0, NULL, 0xff },
+       { "preserve-context",    0, NULL, 0xff },
+#endif
        { 0, 0, 0, 0 }
 };
 #endif
 
+
+#if ENABLE_SELINUX
+static bool use_default_selinux_context = 1;
+
+static void setdefaultfilecon(const char *path) {
+       struct stat s;
+       security_context_t scontext = NULL;
+
+       if (!is_selinux_enabled()) {
+               return;
+       }       
+       if (lstat(path, &s) != 0) {
+               return;
+       }
+
+       if (matchpathcon(path, s.st_mode, &scontext) < 0) {
+               goto out;
+       }
+       if (strcmp(scontext, "<<none>>") == 0) {
+               goto out;
+       }
+
+       if (lsetfilecon(path, scontext) < 0) {
+               if (errno != ENOTSUP) {
+                       bb_perror_msg("warning: failed to change context of %s to %s", path, scontext);
+               }
+       }
+
+ out:
+       freecon(scontext);
+}
+
+#endif
+
 int install_main(int argc, char **argv);
 int install_main(int argc, char **argv)
 {
@@ -37,7 +76,9 @@ int install_main(int argc, char **argv)
        const char *mode_str;
        int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
        int ret = EXIT_SUCCESS, flags, i, isdir;
-
+#if ENABLE_SELINUX
+       security_context_t scontext;
+#endif
        enum {
                OPT_CMD           =  0x1,
                OPT_DIRECTORY     =  0x2,
@@ -46,14 +87,35 @@ int install_main(int argc, char **argv)
                OPT_GROUP         = 0x10,
                OPT_MODE          = 0x20,
                OPT_OWNER         = 0x40,
+#if ENABLE_SELINUX
+               OPT_SET_SECURITY_CONTEXT = 0x80,
+               OPT_PRESERVE_SECURITY_CONTEXT = 0x100,
+#endif
        };
 
 #if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
        applet_long_options = install_long_options;
 #endif
-       opt_complementary = "?:s--d:d--s";
-       /* -c exists for backwards compatibility, its needed */
-       flags = getopt32(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str);
+       opt_complementary = "?:s--d:d--s" USE_SELINUX(":Z--\xff:\xff--Z");
+       /* -c exists for backwards compatibility, it's needed */
+
+       flags = getopt32(argc, argv, "cdpsg:m:o:" USE_SELINUX("Z:"), &gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext));
+       
+#if ENABLE_SELINUX
+       if (flags & OPT_PRESERVE_SECURITY_CONTEXT) {
+               use_default_selinux_context = 0;
+               copy_flags |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
+               selinux_or_die();
+       }
+       if (flags & OPT_SET_SECURITY_CONTEXT) {
+               selinux_or_die();
+               if (setfscreatecon(scontext) < 0) {
+                       bb_error_msg_and_die("setfscreatecon(%s)", scontext); // perror?
+               }
+               use_default_selinux_context = 0;
+               copy_flags |= FILEUTILS_SET_SECURITY_CONTEXT;
+       }
+#endif
 
        /* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */
        if (flags & OPT_PRESERVE_TIME) {
@@ -117,7 +179,10 @@ int install_main(int argc, char **argv)
                        bb_perror_msg("cannot change permissions of %s", dest);
                        ret = EXIT_FAILURE;
                }
-
+#if ENABLE_SELINUX
+               if (use_default_selinux_context)
+                       setdefaultfilecon(dest);
+#endif
                /* Set the user and group id */
                if ((flags & (OPT_OWNER|OPT_GROUP))
                 && lchown(dest, uid, gid) == -1
index 3a3d341..2e0c274 100644 (file)
@@ -30,11 +30,25 @@ mode_t getopt_mk_fifo_nod(int argc, char **argv)
 {
        mode_t mode = 0666;
        char *smode = NULL;
-
-       getopt32(argc, argv, "m:", &smode);
-       if(smode) {
+#if ENABLE_SELINUX
+       security_context_t scontext;
+#endif
+       int opt;
+       opt = getopt32(argc, argv, "m:" USE_SELINUX("Z:"), &smode USE_SELINUX(,&scontext));
+       if (opt & 1) {
                if (bb_parse_mode(smode, &mode))
                        umask(0);
        }
+
+#if ENABLE_SELINUX
+       if (opt & 2) {
+               selinux_or_die();
+               if (setfscreatecon(scontext)) {
+                       bb_error_msg_and_die("cannot set default file creation context "
+                                             "to %s", scontext);
+               }
+       }
+#endif
+
        return mode;
 }
index f902d38..1c1544a 100644 (file)
@@ -716,7 +716,8 @@ static const char ls_options[] = "Cadil1gnsxAk"
        USE_FEATURE_LS_RECURSIVE("R")
        USE_FEATURE_HUMAN_READABLE("h")
        USE_SELINUX("K")
-       USE_FEATURE_AUTOWIDTH("T:w:");
+       USE_FEATURE_AUTOWIDTH("T:w:")
+       USE_SELINUX("Z");
 
 enum {
        LIST_MASK_TRIGGER       = 0,
@@ -769,6 +770,9 @@ static const unsigned opt_flags[] = {
 #if ENABLE_FEATURE_AUTOWIDTH
        0, 0,                       /* T, w - ignored */
 #endif
+#if ENABLE_SELINUX     
+       LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
+#endif
        (1U<<31)
 };
 
index 67819e7..93ded1d 100644 (file)
@@ -16,6 +16,9 @@
  * conjunction with -m.
  */
 
+/* Nov 28, 2006      Yoshinori Sato <ysato@users.sourceforge.jp>: Add SELinux Support.
+ */
+
 #include <stdlib.h>
 #include <unistd.h>
 #include <getopt.h> /* struct option */
@@ -25,6 +28,9 @@
 static const struct option mkdir_long_options[] = {
        { "mode", 1, NULL, 'm' },
        { "parents", 0, NULL, 'p' },
+#if ENABLE_SELINUX
+       { "context", 1, NULL, 'Z' },
+#endif
        { 0, 0, 0, 0 }
 };
 #endif
@@ -37,11 +43,14 @@ int mkdir_main(int argc, char **argv)
        int flags = 0;
        unsigned opt;
        char *smode;
+#if ENABLE_SELINUX
+       security_context_t scontext;
+#endif
 
 #if ENABLE_FEATURE_MKDIR_LONG_OPTIONS
        applet_long_options = mkdir_long_options;
 #endif
-       opt = getopt32(argc, argv, "m:p", &smode);
+       opt = getopt32(argc, argv, "m:p" USE_SELINUX("Z:"), &smode USE_SELINUX(,&scontext));
        if (opt & 1) {
                mode = 0777;
                if (!bb_parse_mode(smode, &mode)) {
@@ -50,6 +59,15 @@ int mkdir_main(int argc, char **argv)
        }
        if (opt & 2)
                flags |= FILEUTILS_RECUR;
+#if ENABLE_SELINUX
+       if (opt & 4) {
+               selinux_or_die();
+               if (setfscreatecon(scontext)) {
+                       bb_error_msg_and_die("cannot set default file creation context "
+                                             "to %s", scontext);
+               }
+       }
+#endif
 
        if (optind == argc) {
                bb_show_usage();
index 7d4905f..64cae96 100644 (file)
@@ -3,6 +3,7 @@
  * Mini mv implementation for busybox
  *
  * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
  *
  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
@@ -44,6 +45,7 @@ int mv_main(int argc, char **argv)
        unsigned long flags;
        int dest_exists;
        int status = 0;
+       int copy_flag = 0;
 
 #if ENABLE_FEATURE_MV_LONG_OPTIONS
        applet_long_options = mv_long_options;
@@ -113,8 +115,11 @@ DO_MOVE:
                                                goto RET_1;
                                        }
                                }
-                               if ((copy_file(*argv, dest,
-                                       FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0) &&
+                               copy_flag = FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS;
+#if ENABLE_SELINUX
+                               copy_flag |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
+#endif                         
+                               if ((copy_file(*argv, dest, copy_flag) >= 0) &&
                                        (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)) {
                                        goto RET_0;
                                }
index 20ade94..37a9240 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation.
  * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
  * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org>
+ * Copyright (C) 2006 by Yoshinori Sato <ysato@users.sourceforge.jp>
  *
  * Written by Michael Meskes
  * Taken from coreutils and turned into a busybox applet by Mike Frysinger
@@ -17,6 +18,7 @@
 /* vars to control behavior */
 #define OPT_TERSE 2
 #define OPT_DEREFERENCE 4
+#define OPT_SELINUX 8
 static long flags;
 
 static char const *file_type(struct stat const *st)
@@ -114,7 +116,8 @@ static char const *human_fstype(long f_type)
 #ifdef CONFIG_FEATURE_STAT_FORMAT
 /* print statfs info */
 static void print_statfs(char *pformat, size_t buf_len, char m,
-                        char const *filename, void const *data)
+                        char const *filename, void const *data
+                                                USE_SELINUX(,security_context_t scontext) )
 {
        struct statfs const *statfsbuf = data;
 
@@ -164,6 +167,14 @@ static void print_statfs(char *pformat, size_t buf_len, char m,
                strncat(pformat, "jd", buf_len);
                printf(pformat, (intmax_t) (statfsbuf->f_ffree));
                break;
+#if ENABLE_SELINUX
+       case 'C':
+               if (flags & OPT_SELINUX) {
+                       strncat(pformat, "s", buf_len);
+                       printf(scontext);
+               }
+               break;
+#endif
        default:
                strncat(pformat, "c", buf_len);
                printf(pformat, m);
@@ -173,7 +184,8 @@ static void print_statfs(char *pformat, size_t buf_len, char m,
 
 /* print stat info */
 static void print_stat(char *pformat, size_t buf_len, char m,
-                      char const *filename, void const *data)
+                      char const *filename, void const *data
+                          USE_SELINUX(, security_context_t scontext))
 {
 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
        struct stat *statbuf = (struct stat *) data;
@@ -301,6 +313,14 @@ static void print_stat(char *pformat, size_t buf_len, char m,
                strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len);
                printf(pformat, (unsigned long int) statbuf->st_ctime);
                break;
+#if ENABLE_SELINUX
+       case 'C':
+               if (flags & OPT_SELINUX) {
+                       strncat(pformat, "s", buf_len);
+                       printf(pformat, scontext);
+               }
+               break;
+#endif
        default:
                strncat(pformat, "c", buf_len);
                printf(pformat, m);
@@ -309,8 +329,9 @@ static void print_stat(char *pformat, size_t buf_len, char m,
 }
 
 static void print_it(char const *masterformat, char const *filename,
-                    void (*print_func) (char *, size_t, char, char const *, void const *),
-                    void const *data)
+                    void (*print_func) (char *, size_t, char, char const *, void const *
+                                                                USE_SELINUX(, security_context_t scontext)),
+                                        void const *data USE_SELINUX(, security_context_t scontext) )
 {
        char *b;
 
@@ -350,7 +371,7 @@ static void print_it(char const *masterformat, char const *filename,
                        putchar('%');
                        break;
                default:
-                       print_func(dest, n_alloc, *p, filename, data);
+                       print_func(dest, n_alloc, *p, filename, data USE_SELINUX(,scontext));
                        break;
                }
        }
@@ -365,6 +386,16 @@ static int do_statfs(char const *filename, char const *format)
 {
        struct statfs statfsbuf;
 
+#if ENABLE_SELINUX
+       security_context_t scontext = NULL;
+       if (flags & OPT_SELINUX) {
+               if ((flags & OPT_DEREFERENCE ? lgetfilecon(filename, scontext):
+                    getfilecon(filename, scontext))< 0) {
+                       bb_perror_msg(filename);
+                       return 0;
+               }
+       }
+#endif
        if (statfs(filename, &statfsbuf) != 0) {
                bb_perror_msg("cannot read file system information for '%s'", filename);
                return 0;
@@ -372,6 +403,7 @@ static int do_statfs(char const *filename, char const *format)
 
 #ifdef CONFIG_FEATURE_STAT_FORMAT
        if (format == NULL)
+#ifndef ENABLE_SELINUX
                format = (flags & OPT_TERSE
                        ? "%n %i %l %t %s %b %f %a %c %d\n"
                        : "  File: \"%n\"\n"
@@ -379,9 +411,27 @@ static int do_statfs(char const *filename, char const *format)
                          "Block size: %-10s\n"
                          "Blocks: Total: %-10b Free: %-10f Available: %a\n"
                          "Inodes: Total: %-10c Free: %d");
-       print_it(format, filename, print_statfs, &statfsbuf);
+       print_it(format, filename, print_statfs, &statfsbuf USE_SELINUX(, scontext));
 #else
-
+       format = (flags & OPT_TERSE
+                       ? (flags & OPT_SELINUX ? "%n %i %l %t %s %b %f %a %c %d %C\n":
+                       "%n %i %l %t %s %b %f %a %c %d\n")
+                       : (flags & OPT_SELINUX ? 
+                       "  File: \"%n\"\n"
+                       "    ID: %-8i Namelen: %-7l Type: %T\n"
+                       "Block size: %-10s\n"
+                       "Blocks: Total: %-10b Free: %-10f Available: %a\n"
+                       "Inodes: Total: %-10c Free: %d"
+                       "  S_context: %C\n":
+                       "  File: \"%n\"\n"
+                       "    ID: %-8i Namelen: %-7l Type: %T\n"
+                       "Block size: %-10s\n"
+                       "Blocks: Total: %-10b Free: %-10f Available: %a\n"
+                       "Inodes: Total: %-10c Free: %d\n")
+                       );
+       print_it(format, filename, print_statfs, &statfsbuf USE_SELINUX(, scontext));
+#endif /* SELINUX */
+#else /* FEATURE_STAT_FORMAT */
        format = (flags & OPT_TERSE
                ? "%s %llx %lu "
                : "  File: \"%s\"\n"
@@ -396,6 +446,7 @@ static int do_statfs(char const *filename, char const *format)
        else
                printf("Type: %s\n", human_fstype(statfsbuf.f_type));
 
+#if !ENABLE_SELINUX
        format = (flags & OPT_TERSE
                ? "%lu %ld %ld %ld %ld %ld\n"
                : "Block size: %-10lu\n"
@@ -408,8 +459,31 @@ static int do_statfs(char const *filename, char const *format)
               (intmax_t) (statfsbuf.f_bavail),
               (intmax_t) (statfsbuf.f_files),
               (intmax_t) (statfsbuf.f_ffree));
-#endif
+#else
+       format = (flags & OPT_TERSE
+               ? (flags & OPT_SELINUX ? "%lu %ld %ld %ld %ld %ld %C\n":
+               "%lu %ld %ld %ld %ld %ld\n")
+               : (flags & OPT_SELINUX ?
+               "Block size: %-10lu\n"
+               "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
+               "Inodes: Total: %-10jd Free: %jd"
+               "S_context: %C\n":
+               "Block size: %-10lu\n"
+               "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
+               "Inodes: Total: %-10jd Free: %jd\n"));
+       printf(format,
+              (unsigned long int) (statfsbuf.f_bsize),
+              (intmax_t) (statfsbuf.f_blocks),
+              (intmax_t) (statfsbuf.f_bfree),
+              (intmax_t) (statfsbuf.f_bavail),
+              (intmax_t) (statfsbuf.f_files),
+              (intmax_t) (statfsbuf.f_ffree),
+               scontext);
 
+       if (scontext)
+               freecon(scontext);
+#endif
+#endif /* FEATURE_STAT_FORMAT */
        return 1;
 }
 
@@ -417,7 +491,16 @@ static int do_statfs(char const *filename, char const *format)
 static int do_stat(char const *filename, char const *format)
 {
        struct stat statbuf;
-
+#if ENABLE_SELINUX
+       security_context_t scontext = NULL;
+       if (flags & OPT_SELINUX) {
+               if ((flags & OPT_DEREFERENCE ? lgetfilecon(filename, scontext):
+                    getfilecon(filename, scontext))< 0) {
+                       bb_perror_msg (filename);
+                       return 0;
+               }
+       }
+#endif
        if ((flags & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) {
                bb_perror_msg("cannot stat '%s'", filename);
                return 0;
@@ -425,6 +508,7 @@ static int do_stat(char const *filename, char const *format)
 
 #ifdef CONFIG_FEATURE_STAT_FORMAT
        if (format == NULL) {
+#ifndef ENABLE_SELINUX
                if (flags & OPT_TERSE) {
                        format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
                } else {
@@ -445,11 +529,49 @@ static int do_stat(char const *filename, char const *format)
                                        "Access: %x\n" "Modify: %y\n" "Change: %z\n";
                        }
                }
-       }
-       print_it(format, filename, print_stat, &statbuf);
 #else
+               if (flags & OPT_TERSE) {
+                       format = (flags & OPT_SELINUX ? 
+                                 "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %C\n":
+                                 "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n");
+               } else {
+                       if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
+                               format = (flags & OPT_SELINUX ?
+                                         "  File: \"%N\"\n"
+                                         "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+                                         "Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
+                                         " Device type: %t,%T\n"
+                                         "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
+                                         "   S_Context: %C\n"
+                                         "Access: %x\n" "Modify: %y\n" "Change: %z\n":
+                                         "  File: \"%N\"\n"
+                                         "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+                                         "Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
+                                         " Device type: %t,%T\n"
+                                         "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
+                                         "Access: %x\n" "Modify: %y\n" "Change: %z\n");
+                       } else {
+                               format = (flags & OPT_SELINUX ?
+                                         "  File: \"%N\"\n"
+                                         "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+                                         "Device: %Dh/%dd\tInode: %-10i  Links: %h\n"
+                                         "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
+                                         "S_Context: %C\n"
+                                         "Access: %x\n" "Modify: %y\n" "Change: %z\n":
+                                         "  File: \"%N\"\n"
+                                         "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+                                         "Device: %Dh/%dd\tInode: %-10i  Links: %h\n"
+                                         "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
+                                         "Access: %x\n" "Modify: %y\n" "Change: %z\n");
+                       }
+               }
+#endif
+       }
+       print_it(format, filename, print_stat, &statbuf USE_SELINUX(, scontext));
+#else  /* FEATURE_STAT_FORMAT */
        if (flags & OPT_TERSE) {
-               printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu\n",
+               printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu"
+                      SKIP_SELINUX("\n"),
                       filename,
                       (uintmax_t) (statbuf.st_size),
                       (uintmax_t) statbuf.st_blocks,
@@ -466,6 +588,12 @@ static int do_stat(char const *filename, char const *format)
                       (unsigned long int) statbuf.st_ctime,
                       (unsigned long int) statbuf.st_blksize
                );
+#if ENABLE_SELINUX
+               if (flags & OPT_SELINUX)
+                       printf(" %lc\n", *scontext);
+               else
+                       putchar('\n');
+#endif
        } else {
                char *linkname = NULL;
 
@@ -499,19 +627,22 @@ static int do_stat(char const *filename, char const *format)
                               (unsigned long int) minor(statbuf.st_rdev));
                else
                        putchar('\n');
-               printf("Access: (%04lo/%10.10s)  Uid: (%5lu/%8s)   Gid: (%5lu/%8s)\n"
-                      "Access: %s\n" "Modify: %s\n" "Change: %s\n",
+               printf("Access: (%04lo/%10.10s)  Uid: (%5lu/%8s)   Gid: (%5lu/%8s)\n",
                       (unsigned long int) (statbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)),
                       bb_mode_string(statbuf.st_mode),
                       (unsigned long int) statbuf.st_uid,
                       (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN",
                       (unsigned long int) statbuf.st_gid,
-                      (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN",
+                      (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
+#if ENABLE_SELINUX
+               printf("   S_Context: %lc\n", *scontext);
+#endif
+               printf("Access: %s\n" "Modify: %s\n" "Change: %s\n",
                       human_time(statbuf.st_atime),
                       human_time(statbuf.st_mtime),
                       human_time(statbuf.st_ctime));
        }
-#endif
+#endif /* FEATURE_STAT_FORMAT */
        return 1;
 }
 
@@ -524,6 +655,7 @@ int stat_main(int argc, char **argv)
        int (*statfunc)(char const *, char const *) = do_stat;
 
        flags = getopt32(argc, argv, "ftL"
+               USE_SELINUX("Z")
                USE_FEATURE_STAT_FORMAT("c:", &format)
        );
 
@@ -532,6 +664,11 @@ int stat_main(int argc, char **argv)
        if (argc == optind)           /* files */
                bb_show_usage();
 
+#if ENABLE_SELINUX
+       if (flags & OPT_SELINUX) {
+               selinux_or_die();
+       }
+#endif /* ENABLE_SELINUX */
        for (i = optind; i < argc; ++i)
                ok &= statfunc(argv[i], format);
 
index 214e63a..3aaf011 100644 (file)
@@ -69,6 +69,7 @@ USE_CAL(APPLET(cal, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_CAT(APPLET(cat, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_CATV(APPLET(catv, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_CHATTR(APPLET(chattr, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CHCON(APPLET(chcon, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_CHGRP(APPLET(chgrp, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_CHMOD(APPLET(chmod, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_CHOWN(APPLET(chown, _BB_DIR_BIN, _BB_SUID_NEVER))
@@ -249,6 +250,7 @@ USE_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts))
+USE_RUNCON(APPLET(runcon, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_RUNLEVEL(APPLET(runlevel, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_RUNSV(APPLET(runsv, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_RUNSVDIR(APPLET(runsvdir, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
index 93edbdc..e07fa75 100644 (file)
@@ -742,7 +742,7 @@ void *md5_end(void *resbuf, md5_ctx_t *ctx);
 uint32_t *crc32_filltable(int endian);
 
 
-enum { /* DO NOT CHANGE THESE VALUES!  cp.c depends on them. */
+enum { /* DO NOT CHANGE THESE VALUES!  cp.c, mv.c, install.c depend on them. */
        FILEUTILS_PRESERVE_STATUS = 1,
        FILEUTILS_DEREFERENCE = 2,
        FILEUTILS_RECUR = 4,
@@ -750,9 +750,13 @@ enum {     /* DO NOT CHANGE THESE VALUES!  cp.c depends on them. */
        FILEUTILS_INTERACTIVE = 0x10,
        FILEUTILS_MAKE_HARDLINK = 0x20,
        FILEUTILS_MAKE_SOFTLINK = 0x40,
+#if ENABLE_SELINUX
+       FILEUTILS_PRESERVE_SECURITY_CONTEXT = 0x80,
+       FILEUTILS_SET_SECURITY_CONTEXT = 0x100
+#endif
 };
-#define FILEUTILS_CP_OPTSTR "pdRfils"
 
+#define FILEUTILS_CP_OPTSTR "pdRfils" USE_SELINUX("c")
 extern const char *applet_name;
 extern const char BB_BANNER[];
 
index 4d1ecb8..2370373 100644 (file)
        "       -R      Recursively list subdirectories\n" \
        "       -v      Set the file's version/generation number"
 
+#define chcon_trivial_usage \
+       "[OPTIONS] CONTEXT FILE...\n" \
+       "       chcon [OPTIONS] [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE...\n" \
+       "       chcon [OPTIONS] --reference=RFILE FILE...\n"
+#define chcon_full_usage \
+       "Change the security context of each FILE to CONTEXT\n\n" \
+       "       -c, --changes           Like verbose but report only when a change is made\n" \
+       "       -h, --no-dereference    Affect symbolic links instead of any referenced file\n" \
+       "                               (available only on systems with lchown system call)\n" \
+       "       -f, --silent, --quiet   Suppress most error messages\n" \
+       "       --reference=RFILE       Use RFILE's group instead of using a CONTEXT value\n" \
+       "       -u, --user=USER         Set user USER in the target security context\n" \
+       "       -r, --role=ROLE         Set role ROLE in the target security context\n" \
+       "       -t, --type=TYPE         Set type TYPE in the target security context\n" \
+       "       -l, --range=RANGE       Set range RANGE in the target security context\n" \
+       "       -R, --recursive         Recurse subdirs\n" \
+       "       -v, --verbose           Verbose mode" \
+
 #define chgrp_trivial_usage \
        "[-Rh"USE_DESKTOP("cvf")"]... GROUP FILE..."
 #define chgrp_full_usage \
        "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY" \
        "\n\nOptions:\n" \
        "       -a      Same as -dpR\n" \
+       USE_SELINUX( \
+       "       -c      Preserves security context\n" \
+       ) \
        "       -d,-P   Preserve links\n" \
        "       -H,-L   Dereference all symlinks (implied by default)\n" \
        "       -p      Preserve file attributes if possible\n" \
        "Print information for USERNAME or the current user" \
        "\n\nOptions:\n" \
        USE_SELINUX( \
-       "       -c      Prints only the security context\n") \
+       "       -Z      prints only the security context\n" \
+       ) \
        "       -g      Prints only the group ID\n" \
        "       -u      Prints only the user ID\n" \
        "       -n      Print a name instead of a number\n" \
        "       -m      Set permission modes\n" \
        "       -o      Set ownership\n" \
        "       -p      Preserve date\n" \
-       "       -s      Strip symbol tables"
+       "       -s      Strip symbol tables" \
+       USE_SELINUX( \
+       "\n     -Z      Set security context of copy" \
+       )
 
 #define ip_trivial_usage \
        "[OPTIONS] {address | link | route | tunnel | rule} {COMMAND}"
        USE_SELINUX( \
        "\n     -k      Print security context") \
        USE_SELINUX( \
-       "\n     -K      Print security context in long format")
+       "\n     -K      Print security context in long format") \
+       USE_SELINUX( \
+       "\n     -Z      Print security context and permission")
 
 #define lsattr_trivial_usage \
        "[-Radlv] [files...]"
        "Create the DIRECTORY(ies) if they do not already exist" \
        "\n\nOptions:\n" \
        "       -m      Set permission mode (as in chmod), not rwxrwxrwx - umask\n" \
-       "       -p      No error if existing, make parent directories as needed"
+       "       -p      No error if existing, make parent directories as needed" \
+       USE_SELINUX( \
+       "\n     -Z      Set security context" \
+       )
+
 #define mkdir_example_usage \
        "$ mkdir /tmp/foo\n" \
        "$ mkdir /tmp/foo\n" \
 #define mkfifo_full_usage \
        "Create a named pipe (identical to 'mknod name p')" \
        "\n\nOptions:\n" \
-       "       -m      Create the pipe using the specified mode (default a=rw)"
+       "       -m      Create the pipe using the specified mode (default a=rw)" \
+       USE_SELINUX( \
+       "\n     -Z      Set security context" \
+       )
 
 #define mkfs_minix_trivial_usage \
        "[-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]"
        "\n\nTYPEs include:\n" \
        "       b:      Make a block (buffered) device\n" \
        "       c or u: Make a character (un-buffered) device\n" \
-       "       p:      Make a named pipe. MAJOR and MINOR are ignored for named pipes"
+       "       p:      Make a named pipe. MAJOR and MINOR are ignored for named pipes" \
+       USE_SELINUX( \
+       "\n     -Z      Set security context" \
+       )
+
 #define mknod_example_usage \
        "$ mknod /dev/fd0 b 2 0\n" \
        "$ mknod -m 644 /tmp/pipe p\n"
 #define rpm2cpio_full_usage \
        "Output a cpio archive of the rpm file"
 
+#define runcon_trivial_usage \
+       "[-c] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n" \
+       "       runcon CONTEXT COMMAND [args]"
+#define runcon_full_usage \
+       "runcon [-c] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n" \
+       "runcon CONTEXT COMMAND [args]\n" \
+       "Run a program in a different security context\n\n" \
+       "       CONTEXT         Complete security context\n" \
+       "       -c, --compute   Compute process transition context before modifying\n" \
+       "       -t, --type=TYPE Type (for same role as parent)\n" \
+       "       -u, --user=USER User identity\n" \
+       "       -r, --role=ROLE Role\n" \
+       "       -l, --range=RNG Levelrange" \
+
 #define run_parts_trivial_usage \
        "[-t] [-a ARG] [-u MASK] DIRECTORY"
 #define run_parts_full_usage \
        "       -f      Display filesystem status\n" \
        "       -L,-l   Dereference links\n" \
        "       -t      Display info in terse form" \
+       USE_SELINUX( \
+       "\n     -Z      Print security context" \
+       ) \
        USE_FEATURE_STAT_FORMAT( \
        "\n\nValid format sequences for files:\n" \
        " %a    Access rights in octal\n" \
        " %c    Total file nodes in file system\n" \
        " %d    Free file nodes in file system\n" \
        " %f    Free blocks in file system\n" \
+       USE_SELINUX( \
+       " %C    Security context in SELinux\n" \
+       ) \
        " %i    File System ID in hex\n" \
        " %l    Maximum length of filenames\n" \
        " %n    File name\n" \
index bd785b7..6391824 100644 (file)
@@ -3,6 +3,7 @@
  * Mini copy_file implementation for busybox
  *
  * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
  *
  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  *
@@ -62,6 +63,26 @@ int copy_file(const char *source, const char *dest, int flags)
                dest_exists = 1;
        }
 
+#if ENABLE_SELINUX
+       if ((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) && is_selinux_enabled() > 0) {
+               security_context_t con;
+               if (lgetfilecon(source, &con) >= 0) {
+                       if (setfscreatecon(con) < 0) {
+                               bb_perror_msg("cannot set setfscreatecon %s", con);
+                               freecon(con);
+                               return -1;
+                       }
+               } else {
+                       if (errno == ENOTSUP || errno == ENODATA) {
+                               setfscreatecon(NULL);
+                       } else {
+                               bb_perror_msg("cannot lgetfilecon %s", source);
+                               return -1;
+                       }
+               }
+       }
+#endif
+
        if (S_ISDIR(source_stat.st_mode)) {
                DIR *dp;
                struct dirent *d;
@@ -204,6 +225,25 @@ int copy_file(const char *source, const char *dest, int flags)
                        }
                }
 
+#if ENABLE_SELINUX
+               if (((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT)
+                   || (flags & FILEUTILS_SET_SECURITY_CONTEXT))
+                && is_selinux_enabled() > 0) {
+                       security_context_t con;  
+                       if (getfscreatecon(&con) == -1) {
+                               bb_perror_msg("getfscreatecon");
+                               return -1;
+                       }                               
+                       if (con) {
+                               if(setfilecon(dest, con) == -1) {
+                                       bb_perror_msg("setfilecon:%s,%s", dest, con);
+                                       freecon(con);
+                                       return -1;
+                               }
+                               freecon(con);
+                       }
+               }
+#endif
                if (bb_copyfd_eof(src_fd, dst_fd) == -1)
                        status = -1;
                if (close(dst_fd) < 0) {
index b078ee5..6c08e51 100644 (file)
@@ -6,6 +6,20 @@
 menu "Selinux Utilities"
        depends on SELINUX
 
+config CHCON
+       bool "chcon"
+       default n
+       depends on SELINUX
+       help
+         Enable support to change the security context of file.
+
+config FEATURE_CHCON_LONG_OPTIONS
+       bool "Enable long options"
+       default y
+       depends on CHCON && GETOPT_LONG
+       help
+         Support long options for the chcon applet.
+
 config GETENFORCE
        bool "getenforce"
        default n
@@ -28,6 +42,20 @@ config MATCHPATHCON
          Enable support to get default security context of the
          specified path from the file contexts configuration.
 
+config RUNCON
+       bool "runcon"
+       default n
+       depends on SELINUX
+       help
+         Enable support to run command in speficied security context.
+
+config FEATURE_RUNCON_LONG_OPTIONS
+       bool "Enable long options"
+       default y
+       depends on RUNCON && GETOPT_LONG
+       help
+         Support long options for the runcon applet.
+
 config SELINUXENABLED
        bool "selinuxenabled"
        default n
index 8371df8..398d136 100644 (file)
@@ -6,8 +6,10 @@
 # Licensed under the GPL v2, see the file LICENSE in this tarball.
 
 lib-y:=
+lib-$(CONFIG_CHCON)            += chcon.o
 lib-$(CONFIG_GETENFORCE)       += getenforce.o
 lib-$(CONFIG_GETSEBOOL)                += getsebool.o
 lib-$(CONFIG_MATCHPATHCON)     += matchpathcon.o
+lib-$(CONFIG_RUNCON)           += runcon.o
 lib-$(CONFIG_SELINUXENABLED)   += selinuxenabled.o
 lib-$(CONFIG_SETENFORCE)       += setenforce.o