aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-03-10 16:58:49 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-03-10 16:58:49 +0000
commit49622d784672bf2f7b2fe80589714cdef5adde0c (patch)
tree892bb79b0ef031d729e688d6be4950f6d17f13b9
parent4eb8b936cb0aeb27c3e12f9a93fc43aa1e9668f5 (diff)
downloadbusybox-w32-49622d784672bf2f7b2fe80589714cdef5adde0c.tar.gz
busybox-w32-49622d784672bf2f7b2fe80589714cdef5adde0c.tar.bz2
busybox-w32-49622d784672bf2f7b2fe80589714cdef5adde0c.zip
selinux support by Yuichi Nakamura <ynakam@hitachisoft.jp> (HitachiSoft)
-rw-r--r--coreutils/cp.c7
-rw-r--r--coreutils/id.c43
-rw-r--r--coreutils/install.c75
-rw-r--r--coreutils/libcoreutils/getopt_mk_fifo_nod.c20
-rw-r--r--coreutils/ls.c6
-rw-r--r--coreutils/mkdir.c20
-rw-r--r--coreutils/mv.c9
-rw-r--r--coreutils/stat.c169
-rw-r--r--include/applets.h2
-rw-r--r--include/libbb.h8
-rw-r--r--include/usage.h70
-rw-r--r--libbb/copy_file.c40
-rw-r--r--selinux/Config.in28
-rw-r--r--selinux/Kbuild2
14 files changed, 452 insertions, 47 deletions
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 7b0de477b..64cf63797 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -3,6 +3,7 @@
3 * Mini cp implementation for busybox 3 * Mini cp implementation for busybox
4 * 4 *
5 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
6 * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
6 * 7 *
7 * Licensed under GPL v2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
8 */ 9 */
@@ -50,6 +51,12 @@ int cp_main(int argc, char **argv)
50 if (flags & OPT_H) ... // deref command-line params only 51 if (flags & OPT_H) ... // deref command-line params only
51 */ 52 */
52 53
54#if ENABLE_SELINUX
55 if (flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) {
56 selinux_or_die();
57 }
58#endif
59
53 flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */ 60 flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */
54 61
55 if (optind + 2 > argc) { 62 if (optind + 2 > argc) {
diff --git a/coreutils/id.c b/coreutils/id.c
index 963ee0566..a0364675f 100644
--- a/coreutils/id.c
+++ b/coreutils/id.c
@@ -10,6 +10,7 @@
10/* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */ 10/* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
11/* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to 11/* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to
12 * be more similar to GNU id. 12 * be more similar to GNU id.
13 * -Z option support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
13 */ 14 */
14 15
15#include "busybox.h" 16#include "busybox.h"
@@ -17,14 +18,13 @@
17#include <unistd.h> 18#include <unistd.h>
18#include <sys/types.h> 19#include <sys/types.h>
19 20
20#ifdef CONFIG_SELINUX
21#include <selinux/selinux.h> /* for is_selinux_enabled() */
22#endif
23
24#define PRINT_REAL 1 21#define PRINT_REAL 1
25#define NAME_NOT_NUMBER 2 22#define NAME_NOT_NUMBER 2
26#define JUST_USER 4 23#define JUST_USER 4
27#define JUST_GROUP 8 24#define JUST_GROUP 8
25#if ENABLE_SELINUX
26#define JUST_CONTEXT 16
27#endif
28 28
29static short printf_full(unsigned int id, const char *arg, const char prefix) 29static short printf_full(unsigned int id, const char *arg, const char prefix)
30{ 30{
@@ -47,11 +47,13 @@ int id_main(int argc, char **argv)
47 gid_t gid; 47 gid_t gid;
48 unsigned long flags; 48 unsigned long flags;
49 short status; 49 short status;
50 50#if ENABLE_SELINUX
51 security_context_t scontext;
52#endif
51 /* Don't allow -n -r -nr -ug -rug -nug -rnug */ 53 /* Don't allow -n -r -nr -ug -rug -nug -rnug */
52 /* Don't allow more than one username */ 54 /* Don't allow more than one username */
53 opt_complementary = "?1:?:u--g:g--u:r?ug:n?ug"; 55 opt_complementary = "?1:?:u--g:g--u:r?ug:n?ug" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
54 flags = getopt32(argc, argv, "rnug"); 56 flags = getopt32(argc, argv, "rnug" USE_SELINUX("Z"));
55 57
56 /* This values could be overwritten later */ 58 /* This values could be overwritten later */
57 uid = geteuid(); 59 uid = geteuid();
@@ -69,14 +71,33 @@ int id_main(int argc, char **argv)
69 /* in this case PRINT_REAL is the same */ 71 /* in this case PRINT_REAL is the same */
70 } 72 }
71 73
72 if (flags & (JUST_GROUP | JUST_USER)) { 74 if (flags & (JUST_GROUP | JUST_USER USE_SELINUX(| JUST_CONTEXT))) {
73 /* JUST_GROUP and JUST_USER are mutually exclusive */ 75 /* JUST_GROUP and JUST_USER are mutually exclusive */
74 if (flags & NAME_NOT_NUMBER) { 76 if (flags & NAME_NOT_NUMBER) {
75 /* bb_getpwuid and bb_getgrgid exit on failure so puts cannot segfault */ 77 /* bb_getpwuid and bb_getgrgid exit on failure so puts cannot segfault */
76 puts((flags & JUST_USER) ? bb_getpwuid(NULL, uid, -1 ) : bb_getgrgid(NULL, gid, -1 )); 78 puts((flags & JUST_USER) ? bb_getpwuid(NULL, uid, -1 ) : bb_getgrgid(NULL, gid, -1 ));
77 } else { 79 } else {
78 printf("%u\n", (flags & JUST_USER) ? uid : gid); 80 if (flags & JUST_USER) {
79 } 81 printf("%u\n", uid);
82 }
83 if (flags & JUST_GROUP) {
84 printf("%u\n", gid);
85 }
86 }
87
88#if ENABLE_SELINUX
89 if (flags & JUST_CONTEXT) {
90 selinux_or_die();
91 if (argc - optind == 1) {
92 bb_error_msg_and_die("can't print security context when user specified");
93 }
94
95 if (getcon(&scontext)) {
96 bb_error_msg_and_die("can't get process context");
97 }
98 printf("%s\n", scontext);
99 }
100#endif
80 /* exit */ 101 /* exit */
81 fflush_stdout_and_exit(EXIT_SUCCESS); 102 fflush_stdout_and_exit(EXIT_SUCCESS);
82 } 103 }
@@ -88,7 +109,7 @@ int id_main(int argc, char **argv)
88 /* bb_getgrgid doesn't exit on failure here */ 109 /* bb_getgrgid doesn't exit on failure here */
89 status |= printf_full(gid, bb_getgrgid(NULL, gid, 0), 'g'); 110 status |= printf_full(gid, bb_getgrgid(NULL, gid, 0), 'g');
90 111
91#ifdef CONFIG_SELINUX 112#if ENABLE_SELINUX
92 if (is_selinux_enabled()) { 113 if (is_selinux_enabled()) {
93 security_context_t mysid; 114 security_context_t mysid;
94 const char *context; 115 const char *context;
diff --git a/coreutils/install.c b/coreutils/install.c
index c105addc5..83facad9d 100644
--- a/coreutils/install.c
+++ b/coreutils/install.c
@@ -21,10 +21,49 @@ static const struct option install_long_options[] = {
21 { "group", 0, NULL, 'g' }, 21 { "group", 0, NULL, 'g' },
22 { "mode", 0, NULL, 'm' }, 22 { "mode", 0, NULL, 'm' },
23 { "owner", 0, NULL, 'o' }, 23 { "owner", 0, NULL, 'o' },
24#if ENABLE_SELINUX
25 { "context", 1, NULL, 'Z' },
26 { "preserve_context", 0, NULL, 0xff },
27 { "preserve-context", 0, NULL, 0xff },
28#endif
24 { 0, 0, 0, 0 } 29 { 0, 0, 0, 0 }
25}; 30};
26#endif 31#endif
27 32
33
34#if ENABLE_SELINUX
35static bool use_default_selinux_context = 1;
36
37static void setdefaultfilecon(const char *path) {
38 struct stat s;
39 security_context_t scontext = NULL;
40
41 if (!is_selinux_enabled()) {
42 return;
43 }
44 if (lstat(path, &s) != 0) {
45 return;
46 }
47
48 if (matchpathcon(path, s.st_mode, &scontext) < 0) {
49 goto out;
50 }
51 if (strcmp(scontext, "<<none>>") == 0) {
52 goto out;
53 }
54
55 if (lsetfilecon(path, scontext) < 0) {
56 if (errno != ENOTSUP) {
57 bb_perror_msg("warning: failed to change context of %s to %s", path, scontext);
58 }
59 }
60
61 out:
62 freecon(scontext);
63}
64
65#endif
66
28int install_main(int argc, char **argv); 67int install_main(int argc, char **argv);
29int install_main(int argc, char **argv) 68int install_main(int argc, char **argv)
30{ 69{
@@ -37,7 +76,9 @@ int install_main(int argc, char **argv)
37 const char *mode_str; 76 const char *mode_str;
38 int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE; 77 int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
39 int ret = EXIT_SUCCESS, flags, i, isdir; 78 int ret = EXIT_SUCCESS, flags, i, isdir;
40 79#if ENABLE_SELINUX
80 security_context_t scontext;
81#endif
41 enum { 82 enum {
42 OPT_CMD = 0x1, 83 OPT_CMD = 0x1,
43 OPT_DIRECTORY = 0x2, 84 OPT_DIRECTORY = 0x2,
@@ -46,14 +87,35 @@ int install_main(int argc, char **argv)
46 OPT_GROUP = 0x10, 87 OPT_GROUP = 0x10,
47 OPT_MODE = 0x20, 88 OPT_MODE = 0x20,
48 OPT_OWNER = 0x40, 89 OPT_OWNER = 0x40,
90#if ENABLE_SELINUX
91 OPT_SET_SECURITY_CONTEXT = 0x80,
92 OPT_PRESERVE_SECURITY_CONTEXT = 0x100,
93#endif
49 }; 94 };
50 95
51#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS 96#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
52 applet_long_options = install_long_options; 97 applet_long_options = install_long_options;
53#endif 98#endif
54 opt_complementary = "?:s--d:d--s"; 99 opt_complementary = "?:s--d:d--s" USE_SELINUX(":Z--\xff:\xff--Z");
55 /* -c exists for backwards compatibility, its needed */ 100 /* -c exists for backwards compatibility, it's needed */
56 flags = getopt32(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); 101
102 flags = getopt32(argc, argv, "cdpsg:m:o:" USE_SELINUX("Z:"), &gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext));
103
104#if ENABLE_SELINUX
105 if (flags & OPT_PRESERVE_SECURITY_CONTEXT) {
106 use_default_selinux_context = 0;
107 copy_flags |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
108 selinux_or_die();
109 }
110 if (flags & OPT_SET_SECURITY_CONTEXT) {
111 selinux_or_die();
112 if (setfscreatecon(scontext) < 0) {
113 bb_error_msg_and_die("setfscreatecon(%s)", scontext); // perror?
114 }
115 use_default_selinux_context = 0;
116 copy_flags |= FILEUTILS_SET_SECURITY_CONTEXT;
117 }
118#endif
57 119
58 /* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */ 120 /* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */
59 if (flags & OPT_PRESERVE_TIME) { 121 if (flags & OPT_PRESERVE_TIME) {
@@ -117,7 +179,10 @@ int install_main(int argc, char **argv)
117 bb_perror_msg("cannot change permissions of %s", dest); 179 bb_perror_msg("cannot change permissions of %s", dest);
118 ret = EXIT_FAILURE; 180 ret = EXIT_FAILURE;
119 } 181 }
120 182#if ENABLE_SELINUX
183 if (use_default_selinux_context)
184 setdefaultfilecon(dest);
185#endif
121 /* Set the user and group id */ 186 /* Set the user and group id */
122 if ((flags & (OPT_OWNER|OPT_GROUP)) 187 if ((flags & (OPT_OWNER|OPT_GROUP))
123 && lchown(dest, uid, gid) == -1 188 && lchown(dest, uid, gid) == -1
diff --git a/coreutils/libcoreutils/getopt_mk_fifo_nod.c b/coreutils/libcoreutils/getopt_mk_fifo_nod.c
index 3a3d34118..2e0c27439 100644
--- a/coreutils/libcoreutils/getopt_mk_fifo_nod.c
+++ b/coreutils/libcoreutils/getopt_mk_fifo_nod.c
@@ -30,11 +30,25 @@ mode_t getopt_mk_fifo_nod(int argc, char **argv)
30{ 30{
31 mode_t mode = 0666; 31 mode_t mode = 0666;
32 char *smode = NULL; 32 char *smode = NULL;
33 33#if ENABLE_SELINUX
34 getopt32(argc, argv, "m:", &smode); 34 security_context_t scontext;
35 if(smode) { 35#endif
36 int opt;
37 opt = getopt32(argc, argv, "m:" USE_SELINUX("Z:"), &smode USE_SELINUX(,&scontext));
38 if (opt & 1) {
36 if (bb_parse_mode(smode, &mode)) 39 if (bb_parse_mode(smode, &mode))
37 umask(0); 40 umask(0);
38 } 41 }
42
43#if ENABLE_SELINUX
44 if (opt & 2) {
45 selinux_or_die();
46 if (setfscreatecon(scontext)) {
47 bb_error_msg_and_die("cannot set default file creation context "
48 "to %s", scontext);
49 }
50 }
51#endif
52
39 return mode; 53 return mode;
40} 54}
diff --git a/coreutils/ls.c b/coreutils/ls.c
index f902d382a..1c1544a34 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -716,7 +716,8 @@ static const char ls_options[] = "Cadil1gnsxAk"
716 USE_FEATURE_LS_RECURSIVE("R") 716 USE_FEATURE_LS_RECURSIVE("R")
717 USE_FEATURE_HUMAN_READABLE("h") 717 USE_FEATURE_HUMAN_READABLE("h")
718 USE_SELINUX("K") 718 USE_SELINUX("K")
719 USE_FEATURE_AUTOWIDTH("T:w:"); 719 USE_FEATURE_AUTOWIDTH("T:w:")
720 USE_SELINUX("Z");
720 721
721enum { 722enum {
722 LIST_MASK_TRIGGER = 0, 723 LIST_MASK_TRIGGER = 0,
@@ -769,6 +770,9 @@ static const unsigned opt_flags[] = {
769#if ENABLE_FEATURE_AUTOWIDTH 770#if ENABLE_FEATURE_AUTOWIDTH
770 0, 0, /* T, w - ignored */ 771 0, 0, /* T, w - ignored */
771#endif 772#endif
773#if ENABLE_SELINUX
774 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
775#endif
772 (1U<<31) 776 (1U<<31)
773}; 777};
774 778
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index 67819e784..93ded1dd5 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -16,6 +16,9 @@
16 * conjunction with -m. 16 * conjunction with -m.
17 */ 17 */
18 18
19/* Nov 28, 2006 Yoshinori Sato <ysato@users.sourceforge.jp>: Add SELinux Support.
20 */
21
19#include <stdlib.h> 22#include <stdlib.h>
20#include <unistd.h> 23#include <unistd.h>
21#include <getopt.h> /* struct option */ 24#include <getopt.h> /* struct option */
@@ -25,6 +28,9 @@
25static const struct option mkdir_long_options[] = { 28static const struct option mkdir_long_options[] = {
26 { "mode", 1, NULL, 'm' }, 29 { "mode", 1, NULL, 'm' },
27 { "parents", 0, NULL, 'p' }, 30 { "parents", 0, NULL, 'p' },
31#if ENABLE_SELINUX
32 { "context", 1, NULL, 'Z' },
33#endif
28 { 0, 0, 0, 0 } 34 { 0, 0, 0, 0 }
29}; 35};
30#endif 36#endif
@@ -37,11 +43,14 @@ int mkdir_main(int argc, char **argv)
37 int flags = 0; 43 int flags = 0;
38 unsigned opt; 44 unsigned opt;
39 char *smode; 45 char *smode;
46#if ENABLE_SELINUX
47 security_context_t scontext;
48#endif
40 49
41#if ENABLE_FEATURE_MKDIR_LONG_OPTIONS 50#if ENABLE_FEATURE_MKDIR_LONG_OPTIONS
42 applet_long_options = mkdir_long_options; 51 applet_long_options = mkdir_long_options;
43#endif 52#endif
44 opt = getopt32(argc, argv, "m:p", &smode); 53 opt = getopt32(argc, argv, "m:p" USE_SELINUX("Z:"), &smode USE_SELINUX(,&scontext));
45 if (opt & 1) { 54 if (opt & 1) {
46 mode = 0777; 55 mode = 0777;
47 if (!bb_parse_mode(smode, &mode)) { 56 if (!bb_parse_mode(smode, &mode)) {
@@ -50,6 +59,15 @@ int mkdir_main(int argc, char **argv)
50 } 59 }
51 if (opt & 2) 60 if (opt & 2)
52 flags |= FILEUTILS_RECUR; 61 flags |= FILEUTILS_RECUR;
62#if ENABLE_SELINUX
63 if (opt & 4) {
64 selinux_or_die();
65 if (setfscreatecon(scontext)) {
66 bb_error_msg_and_die("cannot set default file creation context "
67 "to %s", scontext);
68 }
69 }
70#endif
53 71
54 if (optind == argc) { 72 if (optind == argc) {
55 bb_show_usage(); 73 bb_show_usage();
diff --git a/coreutils/mv.c b/coreutils/mv.c
index 7d4905fc9..64cae965b 100644
--- a/coreutils/mv.c
+++ b/coreutils/mv.c
@@ -3,6 +3,7 @@
3 * Mini mv implementation for busybox 3 * Mini mv implementation for busybox
4 * 4 *
5 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
6 * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
6 * 7 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */ 9 */
@@ -44,6 +45,7 @@ int mv_main(int argc, char **argv)
44 unsigned long flags; 45 unsigned long flags;
45 int dest_exists; 46 int dest_exists;
46 int status = 0; 47 int status = 0;
48 int copy_flag = 0;
47 49
48#if ENABLE_FEATURE_MV_LONG_OPTIONS 50#if ENABLE_FEATURE_MV_LONG_OPTIONS
49 applet_long_options = mv_long_options; 51 applet_long_options = mv_long_options;
@@ -113,8 +115,11 @@ DO_MOVE:
113 goto RET_1; 115 goto RET_1;
114 } 116 }
115 } 117 }
116 if ((copy_file(*argv, dest, 118 copy_flag = FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS;
117 FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0) && 119#if ENABLE_SELINUX
120 copy_flag |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
121#endif
122 if ((copy_file(*argv, dest, copy_flag) >= 0) &&
118 (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)) { 123 (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)) {
119 goto RET_0; 124 goto RET_0;
120 } 125 }
diff --git a/coreutils/stat.c b/coreutils/stat.c
index 20ade9472..37a924057 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -5,6 +5,7 @@
5 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation. 5 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation.
6 * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org> 6 * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
7 * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org> 7 * Copyright (C) 2005 by Mike Frysinger <vapier@gentoo.org>
8 * Copyright (C) 2006 by Yoshinori Sato <ysato@users.sourceforge.jp>
8 * 9 *
9 * Written by Michael Meskes 10 * Written by Michael Meskes
10 * Taken from coreutils and turned into a busybox applet by Mike Frysinger 11 * Taken from coreutils and turned into a busybox applet by Mike Frysinger
@@ -17,6 +18,7 @@
17/* vars to control behavior */ 18/* vars to control behavior */
18#define OPT_TERSE 2 19#define OPT_TERSE 2
19#define OPT_DEREFERENCE 4 20#define OPT_DEREFERENCE 4
21#define OPT_SELINUX 8
20static long flags; 22static long flags;
21 23
22static char const *file_type(struct stat const *st) 24static char const *file_type(struct stat const *st)
@@ -114,7 +116,8 @@ static char const *human_fstype(long f_type)
114#ifdef CONFIG_FEATURE_STAT_FORMAT 116#ifdef CONFIG_FEATURE_STAT_FORMAT
115/* print statfs info */ 117/* print statfs info */
116static void print_statfs(char *pformat, size_t buf_len, char m, 118static void print_statfs(char *pformat, size_t buf_len, char m,
117 char const *filename, void const *data) 119 char const *filename, void const *data
120 USE_SELINUX(,security_context_t scontext) )
118{ 121{
119 struct statfs const *statfsbuf = data; 122 struct statfs const *statfsbuf = data;
120 123
@@ -164,6 +167,14 @@ static void print_statfs(char *pformat, size_t buf_len, char m,
164 strncat(pformat, "jd", buf_len); 167 strncat(pformat, "jd", buf_len);
165 printf(pformat, (intmax_t) (statfsbuf->f_ffree)); 168 printf(pformat, (intmax_t) (statfsbuf->f_ffree));
166 break; 169 break;
170#if ENABLE_SELINUX
171 case 'C':
172 if (flags & OPT_SELINUX) {
173 strncat(pformat, "s", buf_len);
174 printf(scontext);
175 }
176 break;
177#endif
167 default: 178 default:
168 strncat(pformat, "c", buf_len); 179 strncat(pformat, "c", buf_len);
169 printf(pformat, m); 180 printf(pformat, m);
@@ -173,7 +184,8 @@ static void print_statfs(char *pformat, size_t buf_len, char m,
173 184
174/* print stat info */ 185/* print stat info */
175static void print_stat(char *pformat, size_t buf_len, char m, 186static void print_stat(char *pformat, size_t buf_len, char m,
176 char const *filename, void const *data) 187 char const *filename, void const *data
188 USE_SELINUX(, security_context_t scontext))
177{ 189{
178#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) 190#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
179 struct stat *statbuf = (struct stat *) data; 191 struct stat *statbuf = (struct stat *) data;
@@ -301,6 +313,14 @@ static void print_stat(char *pformat, size_t buf_len, char m,
301 strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len); 313 strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len);
302 printf(pformat, (unsigned long int) statbuf->st_ctime); 314 printf(pformat, (unsigned long int) statbuf->st_ctime);
303 break; 315 break;
316#if ENABLE_SELINUX
317 case 'C':
318 if (flags & OPT_SELINUX) {
319 strncat(pformat, "s", buf_len);
320 printf(pformat, scontext);
321 }
322 break;
323#endif
304 default: 324 default:
305 strncat(pformat, "c", buf_len); 325 strncat(pformat, "c", buf_len);
306 printf(pformat, m); 326 printf(pformat, m);
@@ -309,8 +329,9 @@ static void print_stat(char *pformat, size_t buf_len, char m,
309} 329}
310 330
311static void print_it(char const *masterformat, char const *filename, 331static void print_it(char const *masterformat, char const *filename,
312 void (*print_func) (char *, size_t, char, char const *, void const *), 332 void (*print_func) (char *, size_t, char, char const *, void const *
313 void const *data) 333 USE_SELINUX(, security_context_t scontext)),
334 void const *data USE_SELINUX(, security_context_t scontext) )
314{ 335{
315 char *b; 336 char *b;
316 337
@@ -350,7 +371,7 @@ static void print_it(char const *masterformat, char const *filename,
350 putchar('%'); 371 putchar('%');
351 break; 372 break;
352 default: 373 default:
353 print_func(dest, n_alloc, *p, filename, data); 374 print_func(dest, n_alloc, *p, filename, data USE_SELINUX(,scontext));
354 break; 375 break;
355 } 376 }
356 } 377 }
@@ -365,6 +386,16 @@ static int do_statfs(char const *filename, char const *format)
365{ 386{
366 struct statfs statfsbuf; 387 struct statfs statfsbuf;
367 388
389#if ENABLE_SELINUX
390 security_context_t scontext = NULL;
391 if (flags & OPT_SELINUX) {
392 if ((flags & OPT_DEREFERENCE ? lgetfilecon(filename, scontext):
393 getfilecon(filename, scontext))< 0) {
394 bb_perror_msg(filename);
395 return 0;
396 }
397 }
398#endif
368 if (statfs(filename, &statfsbuf) != 0) { 399 if (statfs(filename, &statfsbuf) != 0) {
369 bb_perror_msg("cannot read file system information for '%s'", filename); 400 bb_perror_msg("cannot read file system information for '%s'", filename);
370 return 0; 401 return 0;
@@ -372,6 +403,7 @@ static int do_statfs(char const *filename, char const *format)
372 403
373#ifdef CONFIG_FEATURE_STAT_FORMAT 404#ifdef CONFIG_FEATURE_STAT_FORMAT
374 if (format == NULL) 405 if (format == NULL)
406#ifndef ENABLE_SELINUX
375 format = (flags & OPT_TERSE 407 format = (flags & OPT_TERSE
376 ? "%n %i %l %t %s %b %f %a %c %d\n" 408 ? "%n %i %l %t %s %b %f %a %c %d\n"
377 : " File: \"%n\"\n" 409 : " File: \"%n\"\n"
@@ -379,9 +411,27 @@ static int do_statfs(char const *filename, char const *format)
379 "Block size: %-10s\n" 411 "Block size: %-10s\n"
380 "Blocks: Total: %-10b Free: %-10f Available: %a\n" 412 "Blocks: Total: %-10b Free: %-10f Available: %a\n"
381 "Inodes: Total: %-10c Free: %d"); 413 "Inodes: Total: %-10c Free: %d");
382 print_it(format, filename, print_statfs, &statfsbuf); 414 print_it(format, filename, print_statfs, &statfsbuf USE_SELINUX(, scontext));
383#else 415#else
384 416 format = (flags & OPT_TERSE
417 ? (flags & OPT_SELINUX ? "%n %i %l %t %s %b %f %a %c %d %C\n":
418 "%n %i %l %t %s %b %f %a %c %d\n")
419 : (flags & OPT_SELINUX ?
420 " File: \"%n\"\n"
421 " ID: %-8i Namelen: %-7l Type: %T\n"
422 "Block size: %-10s\n"
423 "Blocks: Total: %-10b Free: %-10f Available: %a\n"
424 "Inodes: Total: %-10c Free: %d"
425 " S_context: %C\n":
426 " File: \"%n\"\n"
427 " ID: %-8i Namelen: %-7l Type: %T\n"
428 "Block size: %-10s\n"
429 "Blocks: Total: %-10b Free: %-10f Available: %a\n"
430 "Inodes: Total: %-10c Free: %d\n")
431 );
432 print_it(format, filename, print_statfs, &statfsbuf USE_SELINUX(, scontext));
433#endif /* SELINUX */
434#else /* FEATURE_STAT_FORMAT */
385 format = (flags & OPT_TERSE 435 format = (flags & OPT_TERSE
386 ? "%s %llx %lu " 436 ? "%s %llx %lu "
387 : " File: \"%s\"\n" 437 : " File: \"%s\"\n"
@@ -396,6 +446,7 @@ static int do_statfs(char const *filename, char const *format)
396 else 446 else
397 printf("Type: %s\n", human_fstype(statfsbuf.f_type)); 447 printf("Type: %s\n", human_fstype(statfsbuf.f_type));
398 448
449#if !ENABLE_SELINUX
399 format = (flags & OPT_TERSE 450 format = (flags & OPT_TERSE
400 ? "%lu %ld %ld %ld %ld %ld\n" 451 ? "%lu %ld %ld %ld %ld %ld\n"
401 : "Block size: %-10lu\n" 452 : "Block size: %-10lu\n"
@@ -408,8 +459,31 @@ static int do_statfs(char const *filename, char const *format)
408 (intmax_t) (statfsbuf.f_bavail), 459 (intmax_t) (statfsbuf.f_bavail),
409 (intmax_t) (statfsbuf.f_files), 460 (intmax_t) (statfsbuf.f_files),
410 (intmax_t) (statfsbuf.f_ffree)); 461 (intmax_t) (statfsbuf.f_ffree));
411#endif 462#else
463 format = (flags & OPT_TERSE
464 ? (flags & OPT_SELINUX ? "%lu %ld %ld %ld %ld %ld %C\n":
465 "%lu %ld %ld %ld %ld %ld\n")
466 : (flags & OPT_SELINUX ?
467 "Block size: %-10lu\n"
468 "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
469 "Inodes: Total: %-10jd Free: %jd"
470 "S_context: %C\n":
471 "Block size: %-10lu\n"
472 "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
473 "Inodes: Total: %-10jd Free: %jd\n"));
474 printf(format,
475 (unsigned long int) (statfsbuf.f_bsize),
476 (intmax_t) (statfsbuf.f_blocks),
477 (intmax_t) (statfsbuf.f_bfree),
478 (intmax_t) (statfsbuf.f_bavail),
479 (intmax_t) (statfsbuf.f_files),
480 (intmax_t) (statfsbuf.f_ffree),
481 scontext);
412 482
483 if (scontext)
484 freecon(scontext);
485#endif
486#endif /* FEATURE_STAT_FORMAT */
413 return 1; 487 return 1;
414} 488}
415 489
@@ -417,7 +491,16 @@ static int do_statfs(char const *filename, char const *format)
417static int do_stat(char const *filename, char const *format) 491static int do_stat(char const *filename, char const *format)
418{ 492{
419 struct stat statbuf; 493 struct stat statbuf;
420 494#if ENABLE_SELINUX
495 security_context_t scontext = NULL;
496 if (flags & OPT_SELINUX) {
497 if ((flags & OPT_DEREFERENCE ? lgetfilecon(filename, scontext):
498 getfilecon(filename, scontext))< 0) {
499 bb_perror_msg (filename);
500 return 0;
501 }
502 }
503#endif
421 if ((flags & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) { 504 if ((flags & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) {
422 bb_perror_msg("cannot stat '%s'", filename); 505 bb_perror_msg("cannot stat '%s'", filename);
423 return 0; 506 return 0;
@@ -425,6 +508,7 @@ static int do_stat(char const *filename, char const *format)
425 508
426#ifdef CONFIG_FEATURE_STAT_FORMAT 509#ifdef CONFIG_FEATURE_STAT_FORMAT
427 if (format == NULL) { 510 if (format == NULL) {
511#ifndef ENABLE_SELINUX
428 if (flags & OPT_TERSE) { 512 if (flags & OPT_TERSE) {
429 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o"; 513 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
430 } else { 514 } else {
@@ -445,11 +529,49 @@ static int do_stat(char const *filename, char const *format)
445 "Access: %x\n" "Modify: %y\n" "Change: %z\n"; 529 "Access: %x\n" "Modify: %y\n" "Change: %z\n";
446 } 530 }
447 } 531 }
448 }
449 print_it(format, filename, print_stat, &statbuf);
450#else 532#else
533 if (flags & OPT_TERSE) {
534 format = (flags & OPT_SELINUX ?
535 "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %C\n":
536 "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n");
537 } else {
538 if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
539 format = (flags & OPT_SELINUX ?
540 " File: \"%N\"\n"
541 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
542 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
543 " Device type: %t,%T\n"
544 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
545 " S_Context: %C\n"
546 "Access: %x\n" "Modify: %y\n" "Change: %z\n":
547 " File: \"%N\"\n"
548 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
549 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
550 " Device type: %t,%T\n"
551 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
552 "Access: %x\n" "Modify: %y\n" "Change: %z\n");
553 } else {
554 format = (flags & OPT_SELINUX ?
555 " File: \"%N\"\n"
556 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
557 "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
558 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
559 "S_Context: %C\n"
560 "Access: %x\n" "Modify: %y\n" "Change: %z\n":
561 " File: \"%N\"\n"
562 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
563 "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
564 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
565 "Access: %x\n" "Modify: %y\n" "Change: %z\n");
566 }
567 }
568#endif
569 }
570 print_it(format, filename, print_stat, &statbuf USE_SELINUX(, scontext));
571#else /* FEATURE_STAT_FORMAT */
451 if (flags & OPT_TERSE) { 572 if (flags & OPT_TERSE) {
452 printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu\n", 573 printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu"
574 SKIP_SELINUX("\n"),
453 filename, 575 filename,
454 (uintmax_t) (statbuf.st_size), 576 (uintmax_t) (statbuf.st_size),
455 (uintmax_t) statbuf.st_blocks, 577 (uintmax_t) statbuf.st_blocks,
@@ -466,6 +588,12 @@ static int do_stat(char const *filename, char const *format)
466 (unsigned long int) statbuf.st_ctime, 588 (unsigned long int) statbuf.st_ctime,
467 (unsigned long int) statbuf.st_blksize 589 (unsigned long int) statbuf.st_blksize
468 ); 590 );
591#if ENABLE_SELINUX
592 if (flags & OPT_SELINUX)
593 printf(" %lc\n", *scontext);
594 else
595 putchar('\n');
596#endif
469 } else { 597 } else {
470 char *linkname = NULL; 598 char *linkname = NULL;
471 599
@@ -499,19 +627,22 @@ static int do_stat(char const *filename, char const *format)
499 (unsigned long int) minor(statbuf.st_rdev)); 627 (unsigned long int) minor(statbuf.st_rdev));
500 else 628 else
501 putchar('\n'); 629 putchar('\n');
502 printf("Access: (%04lo/%10.10s) Uid: (%5lu/%8s) Gid: (%5lu/%8s)\n" 630 printf("Access: (%04lo/%10.10s) Uid: (%5lu/%8s) Gid: (%5lu/%8s)\n",
503 "Access: %s\n" "Modify: %s\n" "Change: %s\n",
504 (unsigned long int) (statbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)), 631 (unsigned long int) (statbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)),
505 bb_mode_string(statbuf.st_mode), 632 bb_mode_string(statbuf.st_mode),
506 (unsigned long int) statbuf.st_uid, 633 (unsigned long int) statbuf.st_uid,
507 (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN", 634 (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN",
508 (unsigned long int) statbuf.st_gid, 635 (unsigned long int) statbuf.st_gid,
509 (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN", 636 (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
637#if ENABLE_SELINUX
638 printf(" S_Context: %lc\n", *scontext);
639#endif
640 printf("Access: %s\n" "Modify: %s\n" "Change: %s\n",
510 human_time(statbuf.st_atime), 641 human_time(statbuf.st_atime),
511 human_time(statbuf.st_mtime), 642 human_time(statbuf.st_mtime),
512 human_time(statbuf.st_ctime)); 643 human_time(statbuf.st_ctime));
513 } 644 }
514#endif 645#endif /* FEATURE_STAT_FORMAT */
515 return 1; 646 return 1;
516} 647}
517 648
@@ -524,6 +655,7 @@ int stat_main(int argc, char **argv)
524 int (*statfunc)(char const *, char const *) = do_stat; 655 int (*statfunc)(char const *, char const *) = do_stat;
525 656
526 flags = getopt32(argc, argv, "ftL" 657 flags = getopt32(argc, argv, "ftL"
658 USE_SELINUX("Z")
527 USE_FEATURE_STAT_FORMAT("c:", &format) 659 USE_FEATURE_STAT_FORMAT("c:", &format)
528 ); 660 );
529 661
@@ -532,6 +664,11 @@ int stat_main(int argc, char **argv)
532 if (argc == optind) /* files */ 664 if (argc == optind) /* files */
533 bb_show_usage(); 665 bb_show_usage();
534 666
667#if ENABLE_SELINUX
668 if (flags & OPT_SELINUX) {
669 selinux_or_die();
670 }
671#endif /* ENABLE_SELINUX */
535 for (i = optind; i < argc; ++i) 672 for (i = optind; i < argc; ++i)
536 ok &= statfunc(argv[i], format); 673 ok &= statfunc(argv[i], format);
537 674
diff --git a/include/applets.h b/include/applets.h
index 214e63aa2..3aaf011eb 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -69,6 +69,7 @@ USE_CAL(APPLET(cal, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
69USE_CAT(APPLET(cat, _BB_DIR_BIN, _BB_SUID_NEVER)) 69USE_CAT(APPLET(cat, _BB_DIR_BIN, _BB_SUID_NEVER))
70USE_CATV(APPLET(catv, _BB_DIR_BIN, _BB_SUID_NEVER)) 70USE_CATV(APPLET(catv, _BB_DIR_BIN, _BB_SUID_NEVER))
71USE_CHATTR(APPLET(chattr, _BB_DIR_BIN, _BB_SUID_NEVER)) 71USE_CHATTR(APPLET(chattr, _BB_DIR_BIN, _BB_SUID_NEVER))
72USE_CHCON(APPLET(chcon, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
72USE_CHGRP(APPLET(chgrp, _BB_DIR_BIN, _BB_SUID_NEVER)) 73USE_CHGRP(APPLET(chgrp, _BB_DIR_BIN, _BB_SUID_NEVER))
73USE_CHMOD(APPLET(chmod, _BB_DIR_BIN, _BB_SUID_NEVER)) 74USE_CHMOD(APPLET(chmod, _BB_DIR_BIN, _BB_SUID_NEVER))
74USE_CHOWN(APPLET(chown, _BB_DIR_BIN, _BB_SUID_NEVER)) 75USE_CHOWN(APPLET(chown, _BB_DIR_BIN, _BB_SUID_NEVER))
@@ -249,6 +250,7 @@ USE_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_NEVER))
249USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER)) 250USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER))
250USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 251USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
251USE_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts)) 252USE_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts))
253USE_RUNCON(APPLET(runcon, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
252USE_RUNLEVEL(APPLET(runlevel, _BB_DIR_SBIN, _BB_SUID_NEVER)) 254USE_RUNLEVEL(APPLET(runlevel, _BB_DIR_SBIN, _BB_SUID_NEVER))
253USE_RUNSV(APPLET(runsv, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 255USE_RUNSV(APPLET(runsv, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
254USE_RUNSVDIR(APPLET(runsvdir, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 256USE_RUNSVDIR(APPLET(runsvdir, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
diff --git a/include/libbb.h b/include/libbb.h
index 93edbdc3f..e07fa7587 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -742,7 +742,7 @@ void *md5_end(void *resbuf, md5_ctx_t *ctx);
742uint32_t *crc32_filltable(int endian); 742uint32_t *crc32_filltable(int endian);
743 743
744 744
745enum { /* DO NOT CHANGE THESE VALUES! cp.c depends on them. */ 745enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */
746 FILEUTILS_PRESERVE_STATUS = 1, 746 FILEUTILS_PRESERVE_STATUS = 1,
747 FILEUTILS_DEREFERENCE = 2, 747 FILEUTILS_DEREFERENCE = 2,
748 FILEUTILS_RECUR = 4, 748 FILEUTILS_RECUR = 4,
@@ -750,9 +750,13 @@ enum { /* DO NOT CHANGE THESE VALUES! cp.c depends on them. */
750 FILEUTILS_INTERACTIVE = 0x10, 750 FILEUTILS_INTERACTIVE = 0x10,
751 FILEUTILS_MAKE_HARDLINK = 0x20, 751 FILEUTILS_MAKE_HARDLINK = 0x20,
752 FILEUTILS_MAKE_SOFTLINK = 0x40, 752 FILEUTILS_MAKE_SOFTLINK = 0x40,
753#if ENABLE_SELINUX
754 FILEUTILS_PRESERVE_SECURITY_CONTEXT = 0x80,
755 FILEUTILS_SET_SECURITY_CONTEXT = 0x100
756#endif
753}; 757};
754#define FILEUTILS_CP_OPTSTR "pdRfils"
755 758
759#define FILEUTILS_CP_OPTSTR "pdRfils" USE_SELINUX("c")
756extern const char *applet_name; 760extern const char *applet_name;
757extern const char BB_BANNER[]; 761extern const char BB_BANNER[];
758 762
diff --git a/include/usage.h b/include/usage.h
index 4d1ecb8f5..23703736f 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -198,6 +198,24 @@
198 " -R Recursively list subdirectories\n" \ 198 " -R Recursively list subdirectories\n" \
199 " -v Set the file's version/generation number" 199 " -v Set the file's version/generation number"
200 200
201#define chcon_trivial_usage \
202 "[OPTIONS] CONTEXT FILE...\n" \
203 " chcon [OPTIONS] [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE...\n" \
204 " chcon [OPTIONS] --reference=RFILE FILE...\n"
205#define chcon_full_usage \
206 "Change the security context of each FILE to CONTEXT\n\n" \
207 " -c, --changes Like verbose but report only when a change is made\n" \
208 " -h, --no-dereference Affect symbolic links instead of any referenced file\n" \
209 " (available only on systems with lchown system call)\n" \
210 " -f, --silent, --quiet Suppress most error messages\n" \
211 " --reference=RFILE Use RFILE's group instead of using a CONTEXT value\n" \
212 " -u, --user=USER Set user USER in the target security context\n" \
213 " -r, --role=ROLE Set role ROLE in the target security context\n" \
214 " -t, --type=TYPE Set type TYPE in the target security context\n" \
215 " -l, --range=RANGE Set range RANGE in the target security context\n" \
216 " -R, --recursive Recurse subdirs\n" \
217 " -v, --verbose Verbose mode" \
218
201#define chgrp_trivial_usage \ 219#define chgrp_trivial_usage \
202 "[-Rh"USE_DESKTOP("cvf")"]... GROUP FILE..." 220 "[-Rh"USE_DESKTOP("cvf")"]... GROUP FILE..."
203#define chgrp_full_usage \ 221#define chgrp_full_usage \
@@ -404,6 +422,9 @@
404 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY" \ 422 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY" \
405 "\n\nOptions:\n" \ 423 "\n\nOptions:\n" \
406 " -a Same as -dpR\n" \ 424 " -a Same as -dpR\n" \
425 USE_SELINUX( \
426 " -c Preserves security context\n" \
427 ) \
407 " -d,-P Preserve links\n" \ 428 " -d,-P Preserve links\n" \
408 " -H,-L Dereference all symlinks (implied by default)\n" \ 429 " -H,-L Dereference all symlinks (implied by default)\n" \
409 " -p Preserve file attributes if possible\n" \ 430 " -p Preserve file attributes if possible\n" \
@@ -1321,7 +1342,8 @@
1321 "Print information for USERNAME or the current user" \ 1342 "Print information for USERNAME or the current user" \
1322 "\n\nOptions:\n" \ 1343 "\n\nOptions:\n" \
1323 USE_SELINUX( \ 1344 USE_SELINUX( \
1324 " -c Prints only the security context\n") \ 1345 " -Z prints only the security context\n" \
1346 ) \
1325 " -g Prints only the group ID\n" \ 1347 " -g Prints only the group ID\n" \
1326 " -u Prints only the user ID\n" \ 1348 " -u Prints only the user ID\n" \
1327 " -n Print a name instead of a number\n" \ 1349 " -n Print a name instead of a number\n" \
@@ -1540,7 +1562,10 @@
1540 " -m Set permission modes\n" \ 1562 " -m Set permission modes\n" \
1541 " -o Set ownership\n" \ 1563 " -o Set ownership\n" \
1542 " -p Preserve date\n" \ 1564 " -p Preserve date\n" \
1543 " -s Strip symbol tables" 1565 " -s Strip symbol tables" \
1566 USE_SELINUX( \
1567 "\n -Z Set security context of copy" \
1568 )
1544 1569
1545#define ip_trivial_usage \ 1570#define ip_trivial_usage \
1546 "[OPTIONS] {address | link | route | tunnel | rule} {COMMAND}" 1571 "[OPTIONS] {address | link | route | tunnel | rule} {COMMAND}"
@@ -1850,7 +1875,9 @@
1850 USE_SELINUX( \ 1875 USE_SELINUX( \
1851 "\n -k Print security context") \ 1876 "\n -k Print security context") \
1852 USE_SELINUX( \ 1877 USE_SELINUX( \
1853 "\n -K Print security context in long format") 1878 "\n -K Print security context in long format") \
1879 USE_SELINUX( \
1880 "\n -Z Print security context and permission")
1854 1881
1855#define lsattr_trivial_usage \ 1882#define lsattr_trivial_usage \
1856 "[-Radlv] [files...]" 1883 "[-Radlv] [files...]"
@@ -1995,7 +2022,11 @@
1995 "Create the DIRECTORY(ies) if they do not already exist" \ 2022 "Create the DIRECTORY(ies) if they do not already exist" \
1996 "\n\nOptions:\n" \ 2023 "\n\nOptions:\n" \
1997 " -m Set permission mode (as in chmod), not rwxrwxrwx - umask\n" \ 2024 " -m Set permission mode (as in chmod), not rwxrwxrwx - umask\n" \
1998 " -p No error if existing, make parent directories as needed" 2025 " -p No error if existing, make parent directories as needed" \
2026 USE_SELINUX( \
2027 "\n -Z Set security context" \
2028 )
2029
1999#define mkdir_example_usage \ 2030#define mkdir_example_usage \
2000 "$ mkdir /tmp/foo\n" \ 2031 "$ mkdir /tmp/foo\n" \
2001 "$ mkdir /tmp/foo\n" \ 2032 "$ mkdir /tmp/foo\n" \
@@ -2040,7 +2071,10 @@
2040#define mkfifo_full_usage \ 2071#define mkfifo_full_usage \
2041 "Create a named pipe (identical to 'mknod name p')" \ 2072 "Create a named pipe (identical to 'mknod name p')" \
2042 "\n\nOptions:\n" \ 2073 "\n\nOptions:\n" \
2043 " -m Create the pipe using the specified mode (default a=rw)" 2074 " -m Create the pipe using the specified mode (default a=rw)" \
2075 USE_SELINUX( \
2076 "\n -Z Set security context" \
2077 )
2044 2078
2045#define mkfs_minix_trivial_usage \ 2079#define mkfs_minix_trivial_usage \
2046 "[-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]" 2080 "[-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]"
@@ -2062,7 +2096,11 @@
2062 "\n\nTYPEs include:\n" \ 2096 "\n\nTYPEs include:\n" \
2063 " b: Make a block (buffered) device\n" \ 2097 " b: Make a block (buffered) device\n" \
2064 " c or u: Make a character (un-buffered) device\n" \ 2098 " c or u: Make a character (un-buffered) device\n" \
2065 " p: Make a named pipe. MAJOR and MINOR are ignored for named pipes" 2099 " p: Make a named pipe. MAJOR and MINOR are ignored for named pipes" \
2100 USE_SELINUX( \
2101 "\n -Z Set security context" \
2102 )
2103
2066#define mknod_example_usage \ 2104#define mknod_example_usage \
2067 "$ mknod /dev/fd0 b 2 0\n" \ 2105 "$ mknod /dev/fd0 b 2 0\n" \
2068 "$ mknod -m 644 /tmp/pipe p\n" 2106 "$ mknod -m 644 /tmp/pipe p\n"
@@ -2698,6 +2736,20 @@
2698#define rpm2cpio_full_usage \ 2736#define rpm2cpio_full_usage \
2699 "Output a cpio archive of the rpm file" 2737 "Output a cpio archive of the rpm file"
2700 2738
2739#define runcon_trivial_usage \
2740 "[-c] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n" \
2741 " runcon CONTEXT COMMAND [args]"
2742#define runcon_full_usage \
2743 "runcon [-c] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n" \
2744 "runcon CONTEXT COMMAND [args]\n" \
2745 "Run a program in a different security context\n\n" \
2746 " CONTEXT Complete security context\n" \
2747 " -c, --compute Compute process transition context before modifying\n" \
2748 " -t, --type=TYPE Type (for same role as parent)\n" \
2749 " -u, --user=USER User identity\n" \
2750 " -r, --role=ROLE Role\n" \
2751 " -l, --range=RNG Levelrange" \
2752
2701#define run_parts_trivial_usage \ 2753#define run_parts_trivial_usage \
2702 "[-t] [-a ARG] [-u MASK] DIRECTORY" 2754 "[-t] [-a ARG] [-u MASK] DIRECTORY"
2703#define run_parts_full_usage \ 2755#define run_parts_full_usage \
@@ -2924,6 +2976,9 @@
2924 " -f Display filesystem status\n" \ 2976 " -f Display filesystem status\n" \
2925 " -L,-l Dereference links\n" \ 2977 " -L,-l Dereference links\n" \
2926 " -t Display info in terse form" \ 2978 " -t Display info in terse form" \
2979 USE_SELINUX( \
2980 "\n -Z Print security context" \
2981 ) \
2927 USE_FEATURE_STAT_FORMAT( \ 2982 USE_FEATURE_STAT_FORMAT( \
2928 "\n\nValid format sequences for files:\n" \ 2983 "\n\nValid format sequences for files:\n" \
2929 " %a Access rights in octal\n" \ 2984 " %a Access rights in octal\n" \
@@ -2958,6 +3013,9 @@
2958 " %c Total file nodes in file system\n" \ 3013 " %c Total file nodes in file system\n" \
2959 " %d Free file nodes in file system\n" \ 3014 " %d Free file nodes in file system\n" \
2960 " %f Free blocks in file system\n" \ 3015 " %f Free blocks in file system\n" \
3016 USE_SELINUX( \
3017 " %C Security context in SELinux\n" \
3018 ) \
2961 " %i File System ID in hex\n" \ 3019 " %i File System ID in hex\n" \
2962 " %l Maximum length of filenames\n" \ 3020 " %l Maximum length of filenames\n" \
2963 " %n File name\n" \ 3021 " %n File name\n" \
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index bd785b71c..6391824aa 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -3,6 +3,7 @@
3 * Mini copy_file implementation for busybox 3 * Mini copy_file implementation for busybox
4 * 4 *
5 * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu> 5 * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
6 * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
6 * 7 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 * 9 *
@@ -62,6 +63,26 @@ int copy_file(const char *source, const char *dest, int flags)
62 dest_exists = 1; 63 dest_exists = 1;
63 } 64 }
64 65
66#if ENABLE_SELINUX
67 if ((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) && is_selinux_enabled() > 0) {
68 security_context_t con;
69 if (lgetfilecon(source, &con) >= 0) {
70 if (setfscreatecon(con) < 0) {
71 bb_perror_msg("cannot set setfscreatecon %s", con);
72 freecon(con);
73 return -1;
74 }
75 } else {
76 if (errno == ENOTSUP || errno == ENODATA) {
77 setfscreatecon(NULL);
78 } else {
79 bb_perror_msg("cannot lgetfilecon %s", source);
80 return -1;
81 }
82 }
83 }
84#endif
85
65 if (S_ISDIR(source_stat.st_mode)) { 86 if (S_ISDIR(source_stat.st_mode)) {
66 DIR *dp; 87 DIR *dp;
67 struct dirent *d; 88 struct dirent *d;
@@ -204,6 +225,25 @@ int copy_file(const char *source, const char *dest, int flags)
204 } 225 }
205 } 226 }
206 227
228#if ENABLE_SELINUX
229 if (((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT)
230 || (flags & FILEUTILS_SET_SECURITY_CONTEXT))
231 && is_selinux_enabled() > 0) {
232 security_context_t con;
233 if (getfscreatecon(&con) == -1) {
234 bb_perror_msg("getfscreatecon");
235 return -1;
236 }
237 if (con) {
238 if(setfilecon(dest, con) == -1) {
239 bb_perror_msg("setfilecon:%s,%s", dest, con);
240 freecon(con);
241 return -1;
242 }
243 freecon(con);
244 }
245 }
246#endif
207 if (bb_copyfd_eof(src_fd, dst_fd) == -1) 247 if (bb_copyfd_eof(src_fd, dst_fd) == -1)
208 status = -1; 248 status = -1;
209 if (close(dst_fd) < 0) { 249 if (close(dst_fd) < 0) {
diff --git a/selinux/Config.in b/selinux/Config.in
index b078ee59e..6c08e51b7 100644
--- a/selinux/Config.in
+++ b/selinux/Config.in
@@ -6,6 +6,20 @@
6menu "Selinux Utilities" 6menu "Selinux Utilities"
7 depends on SELINUX 7 depends on SELINUX
8 8
9config CHCON
10 bool "chcon"
11 default n
12 depends on SELINUX
13 help
14 Enable support to change the security context of file.
15
16config FEATURE_CHCON_LONG_OPTIONS
17 bool "Enable long options"
18 default y
19 depends on CHCON && GETOPT_LONG
20 help
21 Support long options for the chcon applet.
22
9config GETENFORCE 23config GETENFORCE
10 bool "getenforce" 24 bool "getenforce"
11 default n 25 default n
@@ -28,6 +42,20 @@ config MATCHPATHCON
28 Enable support to get default security context of the 42 Enable support to get default security context of the
29 specified path from the file contexts configuration. 43 specified path from the file contexts configuration.
30 44
45config RUNCON
46 bool "runcon"
47 default n
48 depends on SELINUX
49 help
50 Enable support to run command in speficied security context.
51
52config FEATURE_RUNCON_LONG_OPTIONS
53 bool "Enable long options"
54 default y
55 depends on RUNCON && GETOPT_LONG
56 help
57 Support long options for the runcon applet.
58
31config SELINUXENABLED 59config SELINUXENABLED
32 bool "selinuxenabled" 60 bool "selinuxenabled"
33 default n 61 default n
diff --git a/selinux/Kbuild b/selinux/Kbuild
index 8371df8e4..398d1368d 100644
--- a/selinux/Kbuild
+++ b/selinux/Kbuild
@@ -6,8 +6,10 @@
6# Licensed under the GPL v2, see the file LICENSE in this tarball. 6# Licensed under the GPL v2, see the file LICENSE in this tarball.
7 7
8lib-y:= 8lib-y:=
9lib-$(CONFIG_CHCON) += chcon.o
9lib-$(CONFIG_GETENFORCE) += getenforce.o 10lib-$(CONFIG_GETENFORCE) += getenforce.o
10lib-$(CONFIG_GETSEBOOL) += getsebool.o 11lib-$(CONFIG_GETSEBOOL) += getsebool.o
11lib-$(CONFIG_MATCHPATHCON) += matchpathcon.o 12lib-$(CONFIG_MATCHPATHCON) += matchpathcon.o
13lib-$(CONFIG_RUNCON) += runcon.o
12lib-$(CONFIG_SELINUXENABLED) += selinuxenabled.o 14lib-$(CONFIG_SELINUXENABLED) += selinuxenabled.o
13lib-$(CONFIG_SETENFORCE) += setenforce.o 15lib-$(CONFIG_SETENFORCE) += setenforce.o