aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-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
8 files changed, 310 insertions, 39 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