1 diff -Nur coreutils-5.0/README coreutils-5.0.new/README
2 --- coreutils-5.0/README 2003-03-29 15:24:00.000000000 +0100
3 +++ coreutils-5.0.new/README 2003-06-20 12:10:09.000000000 +0200
6 The programs that can be built with this package are:
8 - basename cat chgrp chmod chown chroot cksum comm cp csplit cut date dd
9 + basename cat chcon chgrp chmod chown chroot cksum comm cp csplit cut date dd
10 df dir dircolors dirname du echo env expand expr factor false fmt fold
11 ginstall groups head hostid hostname id join kill link ln logname ls
12 md5sum mkdir mkfifo mknod mv nice nl nohup od paste pathchk pinky pr
13 - printenv printf ptx pwd readlink rm rmdir seq sha1sum shred sleep sort
14 + printenv printf ptx pwd readlink rm rmdir runcon seq sha1sum shred sleep sort
15 split stat stty su sum sync tac tail tee test touch tr true tsort tty
16 uname unexpand uniq unlink uptime users vdir wc who whoami yes
18 diff -Nur coreutils-5.0/man/Makefile.am coreutils-5.0.new/man/Makefile.am
19 --- coreutils-5.0/man/Makefile.am 2003-06-20 12:00:57.000000000 +0200
20 +++ coreutils-5.0.new/man/Makefile.am 2003-06-20 12:12:08.000000000 +0200
22 rm.1 rmdir.1 seq.1 sha1sum.1 shred.1 sleep.1 sort.1 split.1 stat.1 stty.1 \
23 su.1 sum.1 sync.1 tac.1 tail.1 tee.1 test.1 touch.1 tr.1 true.1 tsort.1 \
24 tty.1 uname.1 unexpand.1 uniq.1 unlink.1 uptime.1 users.1 vdir.1 wc.1 \
25 - who.1 whoami.1 yes.1
26 + who.1 whoami.1 yes.1 chcon.1 runcon.1
29 man_aux = $(dist_man_MANS:.1=.x)
31 who.1: $(common_dep) $(srcdir)/who.x ../src/who.c
32 whoami.1: $(common_dep) $(srcdir)/whoami.x ../src/whoami.c
33 yes.1: $(common_dep) $(srcdir)/yes.x ../src/yes.c
34 +chcon.1: $(common_dep) $(srcdir)/chcon.x ../src/chcon.c
35 +runcon.1: $(common_dep) $(srcdir)/runcon.x ../src/runcon.c
39 diff -Nur coreutils-5.0/man/chcon.x coreutils-5.0.new/man/chcon.x
40 --- coreutils-5.0/man/chcon.x 1970-01-01 01:00:00.000000000 +0100
41 +++ coreutils-5.0.new/man/chcon.x 2003-06-20 12:10:08.000000000 +0200
44 +chcon \- change file security context
46 +.\" Add any additional description here
47 diff -Nur coreutils-5.0/man/runcon.x coreutils-5.0.new/man/runcon.x
48 --- coreutils-5.0/man/runcon.x 1970-01-01 01:00:00.000000000 +0100
49 +++ coreutils-5.0.new/man/runcon.x 2003-06-20 12:10:08.000000000 +0200
52 +.\" Add any additional description here
53 diff -Nur coreutils-5.0/src/Makefile.am coreutils-5.0.new/src/Makefile.am
54 --- coreutils-5.0/src/Makefile.am 2003-06-20 12:00:57.000000000 +0200
55 +++ coreutils-5.0.new/src/Makefile.am 2003-06-20 12:11:21.000000000 +0200
59 bin_SCRIPTS = groups @OPTIONAL_BIN_ZCRIPTS@
60 -bin_PROGRAMS = chgrp chown chmod cp dd dircolors du \
61 +bin_PROGRAMS = chgrp chown chmod chcon cp dd dircolors du \
62 ginstall link ln dir vdir ls mkdir \
63 mkfifo mknod mv readlink rm rmdir shred stat sync touch unlink \
64 cat cksum comm csplit cut expand fmt fold head join md5sum \
65 nl od paste pr ptx sha1sum sort split sum tac tail tr tsort unexpand uniq wc \
66 basename date dirname echo env expr factor false getgid \
67 - hostname id kill logname pathchk printenv printf pwd seq sleep tee \
68 + hostname id kill logname pathchk printenv printf pwd runcon seq sleep tee \
69 test true tty whoami yes \
70 @OPTIONAL_BIN_PROGS@ @DF_PROG@
73 groups.sh nohup.sh wheel-gen.pl
74 CLEANFILES = $(SCRIPTS) su
76 -INCLUDES = -I.. -I$(srcdir) -I$(top_srcdir)/lib -I../lib
77 -DEFS = -DLOCALEDIR=\"$(localedir)\" -DSHAREDIR=\"$(datadir)\" @DEFS@
78 +INCLUDES = -I.. -I$(srcdir) -I$(top_srcdir)/lib -I../lib
79 +DEFS = -DLOCALEDIR=\"$(localedir)\" -DSHAREDIR=\"$(datadir)\" -DWITH_SELINUX @DEFS@
81 # Sometimes, the expansion of @LIBINTL@ includes -lc which may
82 # include modules defining variables like `optind', so libfetish.a
83 # must precede @LIBINTL@ in order to ensure we use GNU getopt.
84 # But libfetish.a must also follow @LIBINTL@, since libintl uses
85 # replacement functions defined in libfetish.a.
86 -LDADD = ../lib/libfetish.a @LIBINTL@ ../lib/libfetish.a
87 +LDADD = ../lib/libfetish.a @LIBINTL@ ../lib/libfetish.a -lselinux -lattr
89 dir_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@
90 ls_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@
91 diff -Nur coreutils-5.0/src/chcon.c coreutils-5.0.new/src/chcon.c
92 --- coreutils-5.0/src/chcon.c 1970-01-01 01:00:00.000000000 +0100
93 +++ coreutils-5.0.new/src/chcon.c 2003-06-20 12:10:08.000000000 +0200
95 +/* chcontext -- change security context of a pathname */
99 +#include <sys/types.h>
102 +#include <selinux/selinux.h>
106 +#include "savedir.h"
107 +#include "group-member.h"
113 + CH_NO_CHANGE_REQUESTED
118 + /* Print a message for each file that is processed. */
121 + /* Print a message for each file whose attributes we change. */
124 + /* Do not be verbose. This is the default. */
128 +static int change_dir_context PARAMS ((const char *dir, security_context_t context,
129 + const struct stat *statp));
131 +/* The name the program was run with. */
134 +/* If nonzero, and the systems has support for it, change the context
135 + of symbolic links rather than any files they point to. */
136 +static int change_symlinks;
138 +/* If nonzero, change the context of directories recursively. */
141 +/* If nonzero, force silence (no error messages). */
142 +static int force_silent;
144 +/* Level of verbosity. */
145 +static enum Verbosity verbosity = V_off;
147 +/* The name of the context file is being given. */
148 +static const char *contextname;
150 +/* The argument to the --reference option. Use the context of this file.
151 + This file must exist. */
152 +static char *reference_file;
154 +/* If nonzero, display usage information and exit. */
155 +static int show_help;
157 +/* If nonzero, print the version on standard output and exit. */
158 +static int show_version;
160 +static struct option const long_options[] =
162 + {"recursive", no_argument, 0, 'R'},
163 + {"changes", no_argument, 0, 'c'},
164 + {"no-dereference", no_argument, 0, 'h'},
165 + {"silent", no_argument, 0, 'f'},
166 + {"quiet", no_argument, 0, 'f'},
167 + {"reference", required_argument, 0, CHAR_MAX + 1},
168 + {"context", required_argument, 0, CHAR_MAX + 2},
169 + {"verbose", no_argument, 0, 'v'},
170 + {"help", no_argument, &show_help, 1},
171 + {"version", no_argument, &show_version, 1},
175 +/* Tell the user how/if the context of FILE has been changed.
176 + CHANGED describes what (if anything) has happened. */
179 +describe_change (const char *file, enum Change_status changed)
185 + fmt = _("context of %s changed to %s\n");
188 + fmt = _("failed to change context of %s to %s\n");
190 + case CH_NO_CHANGE_REQUESTED:
191 + fmt = _("context of %s retained as %s\n");
196 + printf (fmt, file, contextname);
199 +/* Change the context of FILE to CONTEXT.
200 + If it is a directory and -R is given, recurse.
201 + Return 0 if successful, 1 if errors occurred. */
204 +change_file_context (const char *file, security_context_t context)
206 + struct stat file_stats;
207 + security_context_t file_context=NULL;
210 + if ((lgetfilecon(file, &file_context)<0) && (errno != ENODATA))
213 + if (force_silent == 0)
214 + error (0, errno, "%s", file);
218 + if ((file_context==NULL) || strcmp(context,file_context)!=0)
222 + if (change_symlinks)
223 + fail = lsetfilecon (file, context);
225 + fail = setfilecon (file, context);
227 + if (verbosity == V_high || (verbosity == V_changes_only && !fail))
228 + describe_change (file, (fail ? CH_FAILED : CH_SUCCEEDED));
233 + if (force_silent == 0)
235 + error (0, errno, "%s", file);
239 + else if (verbosity == V_high)
241 + describe_change (file, CH_NO_CHANGE_REQUESTED);
244 + freecon(file_context);
247 + if (lstat(file, &file_stats)==0)
248 + if (S_ISDIR (file_stats.st_mode))
249 + errors |= change_dir_context (file, context, &file_stats);
254 +/* Recursively change context of the files in directory DIR
255 + to CONTEXT CONTEXT.
256 + STATP points to the results of lstat on DIR.
257 + Return 0 if successful, 1 if errors occurred. */
260 +change_dir_context (const char *dir, security_context_t context, const struct stat *statp)
262 + char *name_space, *namep;
263 + char *path; /* Full path of each entry to process. */
264 + unsigned dirlength; /* Length of `dir' and '\0'. */
265 + unsigned filelength; /* Length of each pathname to process. */
266 + unsigned pathlength; /* Bytes allocated for `path'. */
270 + name_space = savedir (dir);
271 + if (name_space == NULL)
275 + if (force_silent == 0)
276 + error (0, errno, "%s", dir);
280 + error (1, 0, _("virtual memory exhausted"));
283 + dirlength = strlen (dir) + 1; /* + 1 is for the trailing '/'. */
284 + pathlength = dirlength + 1;
285 + /* Give `path' a dummy value; it will be reallocated before first use. */
286 + path = xmalloc (pathlength);
287 + strcpy (path, dir);
288 + path[dirlength - 1] = '/';
290 + for (namep = name_space; *namep; namep += filelength - dirlength)
292 + filelength = dirlength + strlen (namep) + 1;
293 + if (filelength > pathlength)
295 + pathlength = filelength * 2;
296 + path = xrealloc (path, pathlength);
298 + strcpy (path + dirlength, namep);
299 + errors |= change_file_context (path, context);
310 + fprintf (stderr, _("Try `%s --help' for more information.\n"),
315 +Usage: %s [OPTION]... CONTEXT FILE...\n\
316 + or: %s [OPTION]... --reference=RFILE FILE...\n\
318 + program_name, program_name, program_name);
320 +Change the security context of each FILE to CONTEXT.\n\
322 + -c, --changes like verbose but report only when a change is made\n\
323 + -h, --no-dereference affect symbolic links instead of any referenced file\n\
324 + (available only on systems with lchown system call)\n\
325 + -f, --silent, --quiet suppress most error messages\n\
326 + --reference=RFILE use RFILE's group instead of using a CONTEXT value\n\
327 + -R, --recursive change files and directories recursively\n\
328 + -v, --verbose output a diagnostic for every file processed\n\
329 + --help display this help and exit\n\
330 + --version output version information and exit\n\
338 +main (int argc, char **argv)
340 + security_context_t context = NULL;
341 + security_context_t ref_context = NULL;
345 + program_name = argv[0];
346 + setlocale (LC_ALL, "");
347 + bindtextdomain (PACKAGE, LOCALEDIR);
348 + textdomain (PACKAGE);
350 + recurse = force_silent = 0;
352 + while ((optc = getopt_long (argc, argv, "Rcfhv", long_options, NULL)) != -1)
359 + reference_file = optarg;
365 + verbosity = V_changes_only;
371 + change_symlinks = 1;
374 + verbosity = V_high;
383 + printf ("chcon (%s) %s\n", GNU_PACKAGE, VERSION);
391 + if (argc - optind + ( (reference_file || ( context > 0 ) ) ? 1 : 0) <= 1)
393 + error (0, 0, _("too few arguments"));
397 + if (reference_file)
399 + if (getfilecon (reference_file, &ref_context)<0)
400 + error (1, errno, "%s", reference_file);
402 + context = ref_context;
405 + context = argv[optind++];
407 + for (; optind < argc; ++optind)
408 + errors |= change_file_context (argv[optind], context);
410 + if (verbosity != V_off)
412 + if (ref_context != NULL)
413 + freecon(ref_context);
416 diff -Nur coreutils-5.0/src/copy.c coreutils-5.0.new/src/copy.c
417 --- coreutils-5.0/src/copy.c 2003-06-20 12:01:02.000000000 +0200
418 +++ coreutils-5.0.new/src/copy.c 2003-06-20 12:10:08.000000000 +0200
421 #include "xreadlink.h"
424 +#include <selinux/selinux.h> /* for is_selinux_enabled() */
427 #define DO_CHOWN(Chown, File, New_uid, New_gid) \
428 (Chown (File, New_uid, New_gid) \
429 /* If non-root uses -p, it's ok if we can't preserve ownership. \
430 @@ -1233,6 +1237,26 @@
431 In such cases, set this variable to zero. */
432 preserve_metadata = 1;
435 + if (x->preserve_security_context)
437 + security_context_t con;
439 + if (lgetfilecon (src_path, &con) < 0)
441 + error (0, errno, _("cannot lgetfilecon %s"), quote (src_path));
444 + if (setfscreatecon(con) < 0)
447 + error (0, errno, _("cannot set setfscreatecon %s"), quote (con));
454 if (S_ISDIR (src_mode))
456 struct dir_list *dir;
457 @@ -1302,8 +1326,13 @@
460 /* Are we crossing a file system boundary? */
461 - if (x->one_file_system && device != 0 && device != src_sb.st_dev)
462 + if (x->one_file_system && device != 0 && device != src_sb.st_dev) {
464 + if (x->preserve_security_context)
465 + setfscreatecon(NULL);
470 /* Copy the contents of the directory. */
472 @@ -1442,6 +1471,11 @@
477 + if (x->preserve_security_context)
478 + setfscreatecon(NULL);
481 /* There's no need to preserve timestamps or permissions. */
482 preserve_metadata = 0;
484 @@ -1474,7 +1508,7 @@
485 if (command_line_arg)
486 record_file (x->dest_info, dst_path, NULL);
488 - if ( ! preserve_metadata)
489 + if ( ! preserve_metadata)
492 /* POSIX says that `cp -p' must restore the following:
493 @@ -1576,6 +1610,11 @@
498 + if (x->preserve_security_context)
499 + setfscreatecon(NULL);
502 /* We have failed to create the destination file.
503 If we've just added a dev/ino entry via the remember_copied
504 call above (i.e., unless we've just failed to create a hard link),
505 diff -Nur coreutils-5.0/src/copy.h coreutils-5.0.new/src/copy.h
506 --- coreutils-5.0/src/copy.h 2003-06-20 12:01:02.000000000 +0200
507 +++ coreutils-5.0.new/src/copy.h 2003-06-20 12:10:08.000000000 +0200
509 int preserve_ownership;
511 int preserve_timestamps;
513 + int preserve_security_context;
516 /* Enabled for mv, and for cp by the --preserve=links option.
517 If nonzero, attempt to preserve in the destination files any
518 diff -Nur coreutils-5.0/src/cp.c coreutils-5.0.new/src/cp.c
519 --- coreutils-5.0/src/cp.c 2003-06-20 12:01:02.000000000 +0200
520 +++ coreutils-5.0.new/src/cp.c 2003-06-20 12:10:08.000000000 +0200
523 #define AUTHORS N_ ("Torbjorn Granlund, David MacKenzie, and Jim Meyering")
526 +#include <selinux/selinux.h> /* for is_selinux_enabled() */
529 #ifndef _POSIX_VERSION
533 {"update", no_argument, NULL, 'u'},
534 {"verbose", no_argument, NULL, 'v'},
535 {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */
537 + {"context", required_argument, NULL, 'X'},
539 {GETOPT_HELP_OPTION_DECL},
540 {GETOPT_VERSION_OPTION_DECL},
543 additional attributes: links, all\n\
546 + -c same as --preserve=context\n\
549 --no-preserve=ATTR_LIST don't preserve the specified attributes\n\
550 --parents append source path to DIRECTORY\n\
551 -P same as `--no-dereference'\n\
553 destination file is missing\n\
554 -v, --verbose explain what is being done\n\
555 -x, --one-file-system stay on this file system\n\
556 + -X, --context=CONTEXT set security context of copy to CONTEXT\n\
558 fputs (HELP_OPTION_DESCRIPTION, stdout);
559 fputs (VERSION_OPTION_DESCRIPTION, stdout);
562 new_dest = (char *) dest;
565 - return copy (source, new_dest, new_dst, x, &unused, NULL);
566 + ret=copy (source, new_dest, new_dst, x, &unused, NULL);
572 x->preserve_mode = 0;
573 x->preserve_timestamps = 0;
576 + x->preserve_security_context = 0;
579 x->require_preserve = 0;
581 x->sparse_mode = SPARSE_AUTO;
582 @@ -808,19 +823,20 @@
589 static enum File_attribute const preserve_vals[] =
591 PRESERVE_MODE, PRESERVE_TIMESTAMPS,
592 - PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL
593 + PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_CONTEXT, PRESERVE_ALL
596 /* Valid arguments to the `--preserve' option. */
597 static char const* const preserve_args[] =
599 "mode", "timestamps",
600 - "ownership", "links", "all", 0
601 + "ownership", "links", "context", "all", 0
604 char *arg_writable = xstrdup (arg);
605 @@ -855,11 +871,16 @@
606 x->preserve_links = on_off;
609 + case PRESERVE_CONTEXT:
610 + x->preserve_security_context = on_off;
614 x->preserve_mode = on_off;
615 x->preserve_timestamps = on_off;
616 x->preserve_ownership = on_off;
617 x->preserve_links = on_off;
618 + x->preserve_security_context = on_off;
624 int copy_contents = 0;
625 char *target_directory = NULL;
627 + security_context_t scontext = NULL;
628 + int is_selinux_enabled_flag= is_selinux_enabled();
631 program_name = argv[0];
632 setlocale (LC_ALL, "");
634 we'll actually use backup_suffix_string. */
635 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
638 + while ((c = getopt_long (argc, argv, "abcdfHilLprsuvxPRS:V:X:Z:", long_opts, NULL))
640 while ((c = getopt_long (argc, argv, "abdfHilLprsuvxPRS:V:", long_opts, NULL))
645 @@ -987,6 +1016,36 @@
646 x.preserve_timestamps = 1;
647 x.require_preserve = 1;
651 + if ( scontext != NULL ) {
652 + (void) fprintf(stderr, "%s: cannot force target context <-- %s and preserve it\n", argv[0], scontext);
655 + else if (is_selinux_enabled_flag)
656 + x.preserve_security_context = 1;
660 + /* politely decline if we're not on a selinux-enabled kernel. */
661 + if( !is_selinux_enabled_flag ) {
662 + fprintf( stderr, "Warning: ignoring --context (-X). "
663 + "It requires a SELinux enabled kernel.\n" );
666 + if ( x.preserve_security_context ) {
667 + (void) fprintf(stderr, "%s: cannot force target context to '%s' and preserve it\n", argv[0], optarg);
671 + /* if there's a security_context given set new path
672 + components to that context, too */
673 + if ( setfscreatecon(scontext) < 0 ) {
674 + (void) fprintf(stderr, _("cannot set default security context %s"), scontext);
682 diff -Nur coreutils-5.0/src/id.c coreutils-5.0.new/src/id.c
683 --- coreutils-5.0/src/id.c 2003-03-27 23:39:46.000000000 +0100
684 +++ coreutils-5.0.new/src/id.c 2003-06-20 12:10:08.000000000 +0200
690 +#include <selinux/selinux.h>
691 +static void print_context PARAMS ((char* context));
692 +/* Print the SELinux context */
694 +print_context(char *context)
696 + printf ("%s", context);
699 +/* If nonzero, output only the SELinux context. -c */
700 +static int just_context = 0;
703 static void print_user (uid_t uid);
704 static void print_group (gid_t gid);
705 static void print_group_list (const char *username);
707 /* The number of errors encountered so far. */
708 static int problems = 0;
710 +/* The SELinux context */
711 +/* Set `context' to a known invalid value so print_full_info() will *
712 + * know when `context' has not been set to a meaningful value. */
713 +static security_context_t context=NULL;
715 static struct option const longopts[] =
717 + {"context", no_argument, NULL, 'c'},
718 {"group", no_argument, NULL, 'g'},
719 {"groups", no_argument, NULL, 'G'},
720 {"name", no_argument, NULL, 'n'},
722 Print information for USERNAME, or the current user.\n\
724 -a ignore, for compatibility with other versions\n\
725 + -c, --context print only the context\n\
726 -g, --group print only the effective group ID\n\
727 -G, --groups print all group IDs\n\
728 -n, --name print a name instead of a number, for -ugG\n\
730 main (int argc, char **argv)
733 + int is_selinux_enabled_flag=is_selinux_enabled();
735 /* If nonzero, output the list of all group IDs. -G */
736 int just_group_list = 0;
739 atexit (close_stdout);
741 - while ((optc = getopt_long (argc, argv, "agnruG", longopts, NULL)) != -1)
742 + while ((optc = getopt_long (argc, argv, "acgnrsuG", longopts, NULL)) != -1)
748 /* Ignore -a, for compatibility with SVR4. */
752 + /* politely decline if we're not on a selinux-enabled kernel. */
753 + if( !is_selinux_enabled_flag ) {
754 + fprintf( stderr, "Sorry, --context (-c) can be used only on "
755 + "a selinux-enabled kernel.\n" );
768 - if (just_user + just_group + just_group_list > 1)
769 - error (EXIT_FAILURE, 0, _("cannot print only user and only group"));
771 + if (argc - optind == 1)
772 + is_selinux_enabled_flag = 0;
774 + if( just_context && !is_selinux_enabled_flag)
776 +cannot display context when selinux not enabled or when displaying the id\n\
777 +of a different user"));
779 + /* If we are on a selinux-enabled kernel, get our context. *
780 + * Otherwise, leave the context variable alone - it has *
781 + * been initialized known invalid value; if we see this invalid *
782 + * value later, we will know we are on a non-selinux kernel. */
783 + if( is_selinux_enabled_flag )
785 + if (getcon(&context))
786 + error (1, 0, "can't get process context");
790 + if (just_user + just_group + just_group_list + just_context > 1)
791 + error (EXIT_FAILURE, 0, _("cannot print \"only\" of more than one choice"));
793 if (just_user + just_group + just_group_list == 0 && (use_real || use_name))
794 error (EXIT_FAILURE, 0,
796 print_group (use_real ? rgid : egid);
797 else if (just_group_list)
798 print_group_list (argv[optind]);
800 + else if (just_context)
801 + print_context (context);
804 print_full_info (argv[optind]);
809 #endif /* HAVE_GETGROUPS */
811 + if ( context != NULL ) {
812 + printf(" context=%s",context);
816 diff -Nur coreutils-5.0/src/install.c coreutils-5.0.new/src/install.c
817 --- coreutils-5.0/src/install.c 2003-06-20 12:01:02.000000000 +0200
818 +++ coreutils-5.0.new/src/install.c 2003-06-20 12:10:08.000000000 +0200
820 # include <sys/wait.h>
824 +#include <selinux/selinux.h> /* for is_selinux_enabled() */
827 struct passwd *getpwnam ();
828 struct group *getgrnam ();
830 @@ -126,11 +130,17 @@
831 static struct option const long_options[] =
833 {"backup", optional_argument, NULL, 'b'},
835 + {"context", required_argument, NULL, 'X'},
837 {"directory", no_argument, NULL, 'd'},
838 {"group", required_argument, NULL, 'g'},
839 {"mode", required_argument, NULL, 'm'},
840 {"owner", required_argument, NULL, 'o'},
841 {"preserve-timestamps", no_argument, NULL, 'p'},
843 + {"preserve_context", no_argument, NULL, 'P'},
845 {"strip", no_argument, NULL, 's'},
846 {"suffix", required_argument, NULL, 'S'},
847 {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */
853 + x->preserve_security_context = 0;
863 + security_context_t scontext = NULL;
864 + /* set iff kernel has extra selinux system calls */
865 + int is_selinux_enabled_flag = is_selinux_enabled();
868 program_name = argv[0];
869 setlocale (LC_ALL, "");
871 we'll actually use backup_suffix_string. */
872 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
875 + while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pPX:vV:S:Z:", long_options,
877 while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pvV:S:", long_options,
884 backup_suffix_string = optarg;
888 + /* politely decline if we're not on a selinux-enabled kernel. */
889 + if( !is_selinux_enabled_flag ) {
890 + fprintf( stderr, "Warning: ignoring --preserve_context (-P) "
891 + "because the kernel is not selinux-enabled.\n" );
894 + if ( scontext!=NULL ) { /* scontext could be NULL because of calloc() failure */
895 + (void) fprintf(stderr, "%s: cannot force target context to '%s' and preserve it\n", argv[0], scontext);
898 + x.preserve_security_context = 1;
901 + /* politely decline if we're not on a selinux-enabled kernel. */
902 + if( !is_selinux_enabled_flag ) {
903 + fprintf( stderr, "Warning: ignoring --context (-X) "
904 + "because the kernel is not selinux-enabled.\n" );
907 + if ( x.preserve_security_context ) {
909 + (void) fprintf(stderr, "%s: cannot force target context == '%s' and preserve it\n", argv[0], optarg);
913 + if (setfscreatecon(scontext)) {
914 + (void) fprintf(stderr, "%s: cannot setup default context == '%s'\n", argv[0], scontext);
919 case_GETOPT_HELP_CHAR;
920 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
923 -S, --suffix=SUFFIX override the usual backup suffix\n\
924 -v, --verbose print the name of each directory as it is created\n\
927 + -P, --preserve_context (Selinux) Preserve security context\n\
928 + -X, --context=CONTEXT (Selinux) Set security context of files and directories\n\
931 fputs (HELP_OPTION_DESCRIPTION, stdout);
932 fputs (VERSION_OPTION_DESCRIPTION, stdout);
934 diff -Nur coreutils-5.0/src/ls.c coreutils-5.0.new/src/ls.c
935 --- coreutils-5.0/src/ls.c 2003-06-20 12:01:02.000000000 +0200
936 +++ coreutils-5.0.new/src/ls.c 2003-06-20 12:10:08.000000000 +0200
939 #define AUTHORS N_ ("Richard Stallman and David MacKenzie")
942 +#include <selinux/selinux.h>
943 +int is_selinux_enabled_flag= 0;
944 +static int print_scontext = 0;
947 #define obstack_chunk_alloc malloc
948 #define obstack_chunk_free free
951 /* For long listings, true if the file has an access control list. */
956 + security_context_t scontext;
960 #if HAVE_ACL || USE_ACL
962 static void sort_files (void);
963 static void parse_ls_color (void);
964 void usage (int status);
966 +static void print_scontext_format PARAMS ((const struct fileinfo *f));
969 /* The name the program was run with, stripped of any leading path. */
972 one_per_line, /* -1 */
973 many_per_line, /* -C */
975 - with_commas /* -m */
977 + with_commas, /* -m */
980 + with_commas /* -m */
984 static enum format format;
986 SHOW_CONTROL_CHARS_OPTION,
998 {"time-style", required_argument, 0, TIME_STYLE_OPTION},
999 {"color", optional_argument, 0, COLOR_OPTION},
1000 {"block-size", required_argument, 0, BLOCK_SIZE_OPTION},
1001 +#ifdef WITH_SELINUX
1002 + {"context", no_argument, 0, CONTEXT_OPTION},
1003 + {"lcontext", no_argument, 0, LCONTEXT_OPTION},
1004 + {"scontext", no_argument, 0, SCONTEXT_OPTION},
1006 {"author", no_argument, 0, AUTHOR_OPTION},
1007 {GETOPT_HELP_OPTION_DECL},
1008 {GETOPT_VERSION_OPTION_DECL},
1009 @@ -752,12 +780,19 @@
1010 static char const *const format_args[] =
1012 "verbose", "long", "commas", "horizontal", "across",
1013 - "vertical", "single-column", 0
1014 + "vertical", "single-column",
1015 +#ifdef WITH_SELINUX
1021 static enum format const format_types[] =
1023 long_format, long_format, with_commas, horizontal, horizontal,
1024 +#ifdef WITH_SELINUX
1027 many_per_line, one_per_line
1030 @@ -1121,6 +1156,9 @@
1032 format_needs_stat = sort_type == sort_time || sort_type == sort_size
1033 || format == long_format
1034 +#ifdef WITH_SELINUX
1035 + || format == security_format || print_scontext
1037 || dereference == DEREF_ALWAYS
1038 || print_block_size || print_inode;
1039 format_needs_type = (format_needs_stat == 0
1040 @@ -1243,6 +1281,11 @@
1041 /* Record whether there is an option specifying sort type. */
1042 int sort_type_specified = 0;
1044 +#ifdef WITH_SELINUX
1045 + /* 1 iff kernel has new selinux system calls */
1046 + is_selinux_enabled_flag= is_selinux_enabled();
1049 qmark_funny_chars = 0;
1051 /* initialize all switches to default settings */
1052 @@ -1293,6 +1336,9 @@
1054 really_all_files = 0;
1055 ignore_patterns = 0;
1056 +#ifdef WITH_SELINUX
1057 + print_scontext = 0;
1060 /* FIXME: put this in a function. */
1062 @@ -1656,6 +1702,31 @@
1064 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1066 +#ifdef WITH_SELINUX
1068 +#define check_selinux() if (!is_selinux_enabled_flag) { \
1069 + fprintf( stderr, "Sorry, this option can only be used " \
1070 + "on a SELinux kernel.\n" ); \
1071 + exit( EXIT_FAILURE ); \
1074 + case CONTEXT_OPTION: /* new security format */
1076 + print_scontext = 1;
1077 + format = security_format;
1079 + case LCONTEXT_OPTION: /* long format plus security context */
1081 + print_scontext = 1;
1082 + format = long_format;
1084 + case SCONTEXT_OPTION: /* short form of new security format */
1086 + print_scontext = 0;
1087 + format = security_format;
1092 usage (EXIT_FAILURE);
1094 @@ -2301,6 +2372,10 @@
1095 free (files[i].name);
1096 if (files[i].linkname)
1097 free (files[i].linkname);
1098 +#ifdef WITH_SELINUX
1099 + if (files[i].scontext)
1100 + freecon (files[i].scontext);
1105 @@ -2372,6 +2447,11 @@
1108 err = stat (path, &files[files_index].stat);
1109 +#ifdef WITH_SELINUX
1111 + if (is_selinux_enabled_flag)
1112 + getfilecon(path, &files[files_index].scontext);
1115 if (dereference == DEREF_COMMAND_LINE_ARGUMENTS)
1117 @@ -2390,6 +2470,12 @@
1119 default: /* DEREF_NEVER */
1120 err = lstat (path, &files[files_index].stat);
1121 +#ifdef WITH_SELINUX
1123 + if (is_selinux_enabled_flag)
1124 + lgetfilecon(path, &files[files_index].scontext);
1130 @@ -2819,6 +2905,16 @@
1131 DIRED_PUTCHAR ('\n');
1135 +#ifdef WITH_SELINUX
1136 + case security_format:
1137 + for (i = 0; i < files_index; i++)
1139 + print_scontext_format (files + i);
1140 + DIRED_PUTCHAR ('\n');
1147 @@ -3082,6 +3178,14 @@
1151 +#ifdef WITH_SELINUX
1153 + if ( print_scontext ) {
1154 + sprintf (p, "%-32s ", f->scontext);
1160 DIRED_FPUTS (buf, stdout, p - buf);
1161 print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok,
1162 @@ -3874,6 +3978,16 @@
1163 -X sort alphabetically by entry extension\n\
1164 -1 list one file per line\n\
1166 +#ifdef WITH_SELINUX
1167 +printf(_("SELINUX options:\n\n\
1168 + --lcontext Display security context. Enable -l. Lines\n\
1169 + will probably be too wide for most displays.\n\
1170 + --context Display security context so it fits on most\n\
1171 + displays. Displays only mode, user, group,\n\
1172 + security context and file name.\n\
1173 + --scontext Display only security context and file name.\n\
1176 fputs (HELP_OPTION_DESCRIPTION, stdout);
1177 fputs (VERSION_OPTION_DESCRIPTION, stdout);
1179 @@ -3892,3 +4006,79 @@
1184 +#ifdef WITH_SELINUX
1187 +print_scontext_format (const struct fileinfo *f)
1191 + /* 7 fields that may require LONGEST_HUMAN_READABLE bytes,
1192 + 1 10-byte mode string,
1193 + 9 spaces, one following each of these fields, and
1194 + 1 trailing NUL byte. */
1196 + char init_bigbuf[7 * LONGEST_HUMAN_READABLE + 10 + 9 + 1];
1197 + char *buf = init_bigbuf;
1198 + size_t bufsize = sizeof (init_bigbuf);
1209 + if ( print_scontext ) { /* zero means terse listing */
1210 + mode_string (f->stat.st_mode, modebuf);
1211 + modebuf[10] = (FILE_HAS_ACL (f) ? '+' : ' ');
1212 + modebuf[11] = '\0';
1216 + (void) sprintf (p, "%s ", modebuf);
1219 + /* print standard user and group */
1221 + user_name = (numeric_ids ? NULL : getuser (f->stat.st_uid));
1223 + (void) sprintf (p, "%-8.8s ", user_name);
1225 + (void) sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid);
1228 + if ( print_group ) {
1229 + group_name = (numeric_ids ? NULL : getgroup (f->stat.st_gid));
1231 + (void) sprintf (p, "%-8.8s ", group_name);
1233 + (void) sprintf (p, "%-8u ", (unsigned int) f->stat.st_gid);
1238 + (void) sprintf (p, "%-32s ", f->scontext);
1242 + DIRED_FPUTS (buf, stdout, p - buf);
1243 + print_name_with_quoting (f->name, f->stat.st_mode, f->linkok, &dired_obstack);
1245 + if (f->filetype == symbolic_link) {
1246 + if (f->linkname) {
1247 + DIRED_FPUTS_LITERAL (" -> ", stdout);
1248 + print_name_with_quoting (f->linkname, f->linkmode, f->linkok - 1, NULL);
1249 + if (indicator_style != none)
1250 + print_type_indicator (f->linkmode);
1254 + if (indicator_style != none)
1255 + print_type_indicator (f->stat.st_mode);
1259 diff -Nur coreutils-5.0/src/mkdir.c coreutils-5.0.new/src/mkdir.c
1260 --- coreutils-5.0/src/mkdir.c 2002-09-23 09:35:27.000000000 +0200
1261 +++ coreutils-5.0.new/src/mkdir.c 2003-06-20 12:10:08.000000000 +0200
1264 #define AUTHORS "David MacKenzie"
1266 +#ifdef WITH_SELINUX
1267 +#include <selinux/selinux.h> /* for is_selinux_enabled() */
1270 /* The name this program was run with. */
1275 static struct option const longopts[] =
1277 +#ifdef WITH_SELINUX
1278 + {"context", required_argument, NULL, 'c'},
1280 {"mode", required_argument, NULL, 'm'},
1281 {"parents", no_argument, NULL, 'p'},
1282 {"verbose", no_argument, NULL, 'v'},
1284 Create the DIRECTORY(ies), if they do not already exist.\n\
1287 +#ifdef WITH_SELINUX
1289 + -c, --context=CONTEXT (Selinux) set security context to CONTEXT\n\
1293 Mandatory arguments to long options are mandatory for short options too.\n\
1299 +#ifdef WITH_SELINUX
1300 + while ((optc = getopt_long (argc, argv, "pm:s:c:v", longopts, NULL)) != -1)
1302 while ((optc = getopt_long (argc, argv, "pm:v", longopts, NULL)) != -1)
1307 @@ -112,6 +128,20 @@
1308 case 'v': /* --verbose */
1309 verbose_fmt_string = _("created directory %s");
1311 +#ifdef WITH_SELINUX
1313 + /* politely decline if we're not on a selinux-enabled kernel. */
1314 + if( !is_selinux_enabled()) {
1315 + fprintf( stderr, "Sorry, --context (-c) can be used only on "
1316 + "a selinux-enabled kernel.\n" );
1319 + if (setfscreatecon(optarg)) {
1320 + fprintf( stderr, "Sorry, cannot set default context to %s.\n", optarg);
1325 case_GETOPT_HELP_CHAR;
1326 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1328 diff -Nur coreutils-5.0/src/mkfifo.c coreutils-5.0.new/src/mkfifo.c
1329 --- coreutils-5.0/src/mkfifo.c 2002-08-31 09:29:21.000000000 +0200
1330 +++ coreutils-5.0.new/src/mkfifo.c 2003-06-20 12:10:08.000000000 +0200
1333 #define AUTHORS "David MacKenzie"
1335 +#ifdef WITH_SELINUX
1336 +#include <selinux/selinux.h> /* for is_selinux_enabled() */
1339 /* The name this program was run with. */
1342 static struct option const longopts[] =
1344 +#ifdef WITH_SELINUX
1345 + {"context", required_argument, NULL, 'c'},
1347 {"mode", required_argument, NULL, 'm'},
1348 {GETOPT_HELP_OPTION_DECL},
1349 {GETOPT_VERSION_OPTION_DECL},
1351 Create named pipes (FIFOs) with the given NAMEs.\n\
1354 +#ifdef WITH_SELINUX
1356 + -c, --context=CONTEXT set security context (quoted string)\n\
1360 Mandatory arguments to long options are mandatory for short options too.\n\
1364 error (4, 0, _("fifo files not supported"));
1366 +#ifdef WITH_SELINUX
1367 + while ((optc = getopt_long (argc, argv, "m:c:", longopts, NULL)) != -1)
1369 while ((optc = getopt_long (argc, argv, "m:", longopts, NULL)) != -1)
1374 @@ -101,6 +117,19 @@
1376 specified_mode = optarg;
1378 +#ifdef WITH_SELINUX
1380 + if( !is_selinux_enabled()) {
1381 + fprintf( stderr, "Sorry, --context (-c) can be used only on "
1382 + "a selinux-enabled kernel.\n" );
1385 + if (setfscreatecon(optarg)) {
1386 + fprintf( stderr, "Sorry, cannot set default context to %s.\n", optarg);
1391 case_GETOPT_HELP_CHAR;
1392 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1394 diff -Nur coreutils-5.0/src/mknod.c coreutils-5.0.new/src/mknod.c
1395 --- coreutils-5.0/src/mknod.c 2002-12-14 15:14:59.000000000 +0100
1396 +++ coreutils-5.0.new/src/mknod.c 2003-06-20 12:10:08.000000000 +0200
1398 /* The name this program was run with. */
1401 +#ifdef WITH_SELINUX
1402 +#include <selinux/selinux.h>
1405 static struct option const longopts[] =
1407 +#ifdef WITH_SELINUX
1408 + {"context", required_argument, NULL, 'c'},
1410 {"mode", required_argument, NULL, 'm'},
1411 {GETOPT_HELP_OPTION_DECL},
1412 {GETOPT_VERSION_OPTION_DECL},
1414 Create the special file NAME of the given TYPE.\n\
1417 +#ifdef WITH_SELINUX
1419 + -c, --context=CONTEXT set security context (quoted string)\n\
1423 Mandatory arguments to long options are mandatory for short options too.\n\
1425 @@ -102,7 +114,11 @@
1427 specified_mode = NULL;
1429 +#ifdef WITH_SELINUX
1430 + while ((optc = getopt_long (argc, argv, "m:s:c:", longopts, NULL)) != -1)
1432 while ((optc = getopt_long (argc, argv, "m:", longopts, NULL)) != -1)
1437 @@ -111,6 +127,20 @@
1439 specified_mode = optarg;
1441 +#ifdef WITH_SELINUX
1443 + /* politely decline if we're not on a selinux-enabled kernel. */
1444 + if( !is_selinux_enabled()) {
1445 + fprintf( stderr, "Sorry, --context (-c) can be used only on "
1446 + "a selinux-enabled kernel.\n" );
1449 + if (setfscreatecon(optarg)) {
1450 + fprintf( stderr, "Sorry, cannot set default context to %s.\n", optarg);
1455 case_GETOPT_HELP_CHAR;
1456 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1458 diff -Nur coreutils-5.0/src/mv.c coreutils-5.0.new/src/mv.c
1459 --- coreutils-5.0/src/mv.c 2003-06-20 12:01:02.000000000 +0200
1460 +++ coreutils-5.0.new/src/mv.c 2003-06-20 12:10:08.000000000 +0200
1462 #include "path-concat.h"
1465 +#ifdef WITH_SELINUX
1466 +#include <selinux/selinux.h> /* for is_selinux_enabled() */
1469 /* The official name of this program (e.g., no `g' prefix). */
1470 #define PROGRAM_NAME "mv"
1475 +#ifdef WITH_SELINUX
1476 + x->preserve_security_context = 0;
1479 x->dest_info = NULL;
1481 @@ -324,6 +330,10 @@
1482 equivalent to --reply=query\n\
1485 + -c preserve security context when source and\n\
1486 + destination are on different file systems\n\
1489 --reply={yes,no,query} specify how to handle the prompt about an\n\
1490 existing destination file\n\
1491 --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\
1492 @@ -387,7 +397,11 @@
1496 +#ifdef WITH_SELINUX
1497 + while ((c = getopt_long (argc, argv, "bcfiuvS:V:", long_options, NULL)) != -1)
1499 while ((c = getopt_long (argc, argv, "bfiuvS:V:", long_options, NULL)) != -1)
1504 @@ -406,6 +420,15 @@
1506 version_control_string = optarg;
1508 +#ifdef WITH_SELINUX
1510 + if (is_selinux_enabled())
1511 + x.preserve_security_context = 1;
1513 + fprintf( stderr, "Warning: ignoring -c. "
1514 + "It requires a SELinux enabled kernel.\n" );
1518 x.interactive = I_ALWAYS_YES;
1520 diff -Nur coreutils-5.0/src/runcon.c coreutils-5.0.new/src/runcon.c
1521 --- coreutils-5.0/src/runcon.c 1970-01-01 01:00:00.000000000 +0100
1522 +++ coreutils-5.0.new/src/runcon.c 2003-06-20 12:10:08.000000000 +0200
1525 + * runcon [ context |
1526 + * ( [ -r role ] [-t type] [ -u user ] [ -l levelrange ] )
1527 + * command [arg1 [arg2 ...] ]
1529 + * attempt to run the specified command with the specified context.
1531 + * -r role : use the current context with the specified role
1532 + * -t type : use the current context with the specified type
1533 + * -u user : use the current context with the specified user
1534 + * -l level : use the current context with the specified level range
1536 + * Contexts are interpreted as follows:
1539 + * components system?
1543 + * 3 Y role:type:range
1544 + * 3 N user:role:type
1545 + * 4 Y user:role:type:range
1549 +#include <unistd.h>
1551 +#include <getopt.h>
1552 +#include <selinux/context.h>
1553 +#include <selinux/selinux.h>
1557 +/* The name the program was run with. */
1558 +char *program_name;
1563 + printf("Usage: %s [OPTION]... command [args]\n"
1564 + "Run a program in a different security context.\n\n"
1565 + " context Complete security context\n"
1566 + " -t type (for same role as parent)\n"
1567 + " -u user identity\n"
1569 + " -l levelrange\n"
1570 + " --help display this help and exit\n",
1576 +main(int argc,char **argv,char **envp )
1582 + char *context = NULL;
1583 + security_context_t cur_context = NULL;
1587 + program_name = argv[0];
1591 + int this_option_optind = optind ? optind : 1;
1592 + int option_index = 0;
1593 + static struct option long_options[] = {
1594 + { "role", 1, 0, 'r' },
1595 + { "type", 1, 0, 't' },
1596 + { "user", 1, 0, 'u' },
1597 + { "range", 1, 0, 'l' },
1598 + { "help", 0, 0, '?' },
1601 + c = getopt_long(argc, argv, "s:r:t:u:l:?", long_options, &option_index);
1608 + fprintf(stderr,"multiple roles\n");
1615 + fprintf(stderr,"multiple types\n");
1622 + fprintf(stderr,"multiple users\n");
1629 + fprintf(stderr,"multiple levelranges\n");
1635 + fprintf(stderr,"unrecognised option %c\n",c);
1641 + if ( !(user || role || type || range)) {
1642 + if ( optind >= argc ) {
1643 + usage("must specify -t, -u, -l, -r, or context");
1645 + context = argv[optind++];
1648 + if ( optind >= argc ) {
1649 + usage("no command found");
1653 + con = context_new(context);
1655 + fprintf(stderr,"%s is not a valid context\n", context);
1660 + getcon(&cur_context);
1661 + con = context_new(cur_context);
1663 + fprintf(stderr,"%s is not a valid context\n", context);
1667 + context_user_set(con,user);
1670 + context_type_set(con,type);
1673 + context_range_set(con,range);
1676 + context_role_set(con,role);
1680 + if (setexeccon(context_str(con))!=0) {
1681 + fprintf(stderr,"unable to setup security context %s\n", context_str(con));
1684 + if (cur_context!=NULL)
1685 + freecon(cur_context);
1687 + if ( execvp(argv[optind],argv+optind) ) {
1691 + return 1; /* can't reach this statement.... */
1693 diff -Nur coreutils-5.0/tests/cp/Makefile.am coreutils-5.0.new/tests/cp/Makefile.am
1694 --- coreutils-5.0/tests/cp/Makefile.am 2003-02-02 21:08:59.000000000 +0100
1695 +++ coreutils-5.0.new/tests/cp/Makefile.am 2003-06-20 12:10:09.000000000 +0200
1699 preserve-2 r-vs-symlink link-preserve \
1700 - backup-1 no-deref-link1 no-deref-link2 no-deref-link3 backup-is-src \
1701 - same-file cp-mv-backup symlink-slash slink-2-slink fail-perm dir-slash \
1702 + backup-1 backup-is-src \
1703 + cp-mv-backup symlink-slash slink-2-slink fail-perm dir-slash \
1704 perm cp-HL special-bits link dir-rm-dest cp-parents deref-slink \
1705 dir-vs-file into-self
1706 EXTRA_DIST = $(TESTS)