diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-10 16:58:49 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-10 16:58:49 +0000 |
commit | 49622d784672bf2f7b2fe80589714cdef5adde0c (patch) | |
tree | 892bb79b0ef031d729e688d6be4950f6d17f13b9 | |
parent | 4eb8b936cb0aeb27c3e12f9a93fc43aa1e9668f5 (diff) | |
download | busybox-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.c | 7 | ||||
-rw-r--r-- | coreutils/id.c | 43 | ||||
-rw-r--r-- | coreutils/install.c | 75 | ||||
-rw-r--r-- | coreutils/libcoreutils/getopt_mk_fifo_nod.c | 20 | ||||
-rw-r--r-- | coreutils/ls.c | 6 | ||||
-rw-r--r-- | coreutils/mkdir.c | 20 | ||||
-rw-r--r-- | coreutils/mv.c | 9 | ||||
-rw-r--r-- | coreutils/stat.c | 169 | ||||
-rw-r--r-- | include/applets.h | 2 | ||||
-rw-r--r-- | include/libbb.h | 8 | ||||
-rw-r--r-- | include/usage.h | 70 | ||||
-rw-r--r-- | libbb/copy_file.c | 40 | ||||
-rw-r--r-- | selinux/Config.in | 28 | ||||
-rw-r--r-- | selinux/Kbuild | 2 |
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 | ||
29 | static short printf_full(unsigned int id, const char *arg, const char prefix) | 29 | static 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 | ||
35 | static bool use_default_selinux_context = 1; | ||
36 | |||
37 | static 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 | |||
28 | int install_main(int argc, char **argv); | 67 | int install_main(int argc, char **argv); |
29 | int install_main(int argc, char **argv) | 68 | int 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 | ||
721 | enum { | 722 | enum { |
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 @@ | |||
25 | static const struct option mkdir_long_options[] = { | 28 | static 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 | ||
20 | static long flags; | 22 | static long flags; |
21 | 23 | ||
22 | static char const *file_type(struct stat const *st) | 24 | static 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 */ |
116 | static void print_statfs(char *pformat, size_t buf_len, char m, | 118 | static 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 */ |
175 | static void print_stat(char *pformat, size_t buf_len, char m, | 186 | static 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 | ||
311 | static void print_it(char const *masterformat, char const *filename, | 331 | static 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) | |||
417 | static int do_stat(char const *filename, char const *format) | 491 | static 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)) | |||
69 | USE_CAT(APPLET(cat, _BB_DIR_BIN, _BB_SUID_NEVER)) | 69 | USE_CAT(APPLET(cat, _BB_DIR_BIN, _BB_SUID_NEVER)) |
70 | USE_CATV(APPLET(catv, _BB_DIR_BIN, _BB_SUID_NEVER)) | 70 | USE_CATV(APPLET(catv, _BB_DIR_BIN, _BB_SUID_NEVER)) |
71 | USE_CHATTR(APPLET(chattr, _BB_DIR_BIN, _BB_SUID_NEVER)) | 71 | USE_CHATTR(APPLET(chattr, _BB_DIR_BIN, _BB_SUID_NEVER)) |
72 | USE_CHCON(APPLET(chcon, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | ||
72 | USE_CHGRP(APPLET(chgrp, _BB_DIR_BIN, _BB_SUID_NEVER)) | 73 | USE_CHGRP(APPLET(chgrp, _BB_DIR_BIN, _BB_SUID_NEVER)) |
73 | USE_CHMOD(APPLET(chmod, _BB_DIR_BIN, _BB_SUID_NEVER)) | 74 | USE_CHMOD(APPLET(chmod, _BB_DIR_BIN, _BB_SUID_NEVER)) |
74 | USE_CHOWN(APPLET(chown, _BB_DIR_BIN, _BB_SUID_NEVER)) | 75 | USE_CHOWN(APPLET(chown, _BB_DIR_BIN, _BB_SUID_NEVER)) |
@@ -249,6 +250,7 @@ USE_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_NEVER)) | |||
249 | USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER)) | 250 | USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER)) |
250 | USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 251 | USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
251 | USE_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts)) | 252 | USE_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts)) |
253 | USE_RUNCON(APPLET(runcon, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | ||
252 | USE_RUNLEVEL(APPLET(runlevel, _BB_DIR_SBIN, _BB_SUID_NEVER)) | 254 | USE_RUNLEVEL(APPLET(runlevel, _BB_DIR_SBIN, _BB_SUID_NEVER)) |
253 | USE_RUNSV(APPLET(runsv, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 255 | USE_RUNSV(APPLET(runsv, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
254 | USE_RUNSVDIR(APPLET(runsvdir, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 256 | USE_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); | |||
742 | uint32_t *crc32_filltable(int endian); | 742 | uint32_t *crc32_filltable(int endian); |
743 | 743 | ||
744 | 744 | ||
745 | enum { /* DO NOT CHANGE THESE VALUES! cp.c depends on them. */ | 745 | enum { /* 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") | ||
756 | extern const char *applet_name; | 760 | extern const char *applet_name; |
757 | extern const char BB_BANNER[]; | 761 | extern 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 @@ | |||
6 | menu "Selinux Utilities" | 6 | menu "Selinux Utilities" |
7 | depends on SELINUX | 7 | depends on SELINUX |
8 | 8 | ||
9 | config CHCON | ||
10 | bool "chcon" | ||
11 | default n | ||
12 | depends on SELINUX | ||
13 | help | ||
14 | Enable support to change the security context of file. | ||
15 | |||
16 | config 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 | |||
9 | config GETENFORCE | 23 | config 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 | ||
45 | config RUNCON | ||
46 | bool "runcon" | ||
47 | default n | ||
48 | depends on SELINUX | ||
49 | help | ||
50 | Enable support to run command in speficied security context. | ||
51 | |||
52 | config 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 | |||
31 | config SELINUXENABLED | 59 | config 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 | ||
8 | lib-y:= | 8 | lib-y:= |
9 | lib-$(CONFIG_CHCON) += chcon.o | ||
9 | lib-$(CONFIG_GETENFORCE) += getenforce.o | 10 | lib-$(CONFIG_GETENFORCE) += getenforce.o |
10 | lib-$(CONFIG_GETSEBOOL) += getsebool.o | 11 | lib-$(CONFIG_GETSEBOOL) += getsebool.o |
11 | lib-$(CONFIG_MATCHPATHCON) += matchpathcon.o | 12 | lib-$(CONFIG_MATCHPATHCON) += matchpathcon.o |
13 | lib-$(CONFIG_RUNCON) += runcon.o | ||
12 | lib-$(CONFIG_SELINUXENABLED) += selinuxenabled.o | 14 | lib-$(CONFIG_SELINUXENABLED) += selinuxenabled.o |
13 | lib-$(CONFIG_SETENFORCE) += setenforce.o | 15 | lib-$(CONFIG_SETENFORCE) += setenforce.o |