diff -Nur coreutils-5.0/lib/Makefile.am coreutils-5.0.new/lib/Makefile.am --- coreutils-5.0/lib/Makefile.am 2003-04-02 12:16:19.000000000 +0200 +++ coreutils-5.0.new/lib/Makefile.am 2003-06-06 03:01:11.000000000 +0200 @@ -20,8 +20,8 @@ noinst_LIBRARIES = libfetish.a -INCLUDES = -I.. -I$(srcdir) -DEFS = -DLIBDIR=\"$(libdir)\" @DEFS@ +INCLUDES = -I.. -I$(srcdir) -I/usr/include/selinux +DEFS = -DLIBDIR=\"$(libdir)\" -DFLASK_LINUX @DEFS@ ## Put relatively complex files at the beginning of the list so ## that parallel compiles finish a tiny bit sooner. I don't see diff -Nur coreutils-5.0/lib/makepath.c coreutils-5.0.new/lib/makepath.c --- coreutils-5.0/lib/makepath.c 2003-03-04 22:19:25.000000000 +0100 +++ coreutils-5.0.new/lib/makepath.c 2003-06-06 03:01:11.000000000 +0200 @@ -39,6 +39,9 @@ #include #include #include +#ifdef FLASK_LINUX +#include +#endif #if HAVE_UNISTD_H # include #endif @@ -139,6 +142,24 @@ } \ while (0) +#ifdef FLASK_LINUX +static security_id_t Sid = -1; +#endif + +#ifdef FLASK_LINUX +int +make_dir_s (const char *dir, + const char *dirpath, + mode_t mode, + int *created_dir_p, + security_id_t sid) +{ + Sid = sid; + return( make_dir(dir, dirpath,mode, created_dir_p)); +} +#endif + + /* Attempt to create directory DIR (aka DIRPATH) with the specified MODE. If CREATED_DIR_P is non-NULL, set *CREATED_DIR_P to non-zero if this function creates DIR and to zero otherwise. Give a diagnostic and @@ -153,6 +174,11 @@ int fail = 0; int created_dir; +#ifdef FLASK_LINUX + if ( (int) Sid > 0 ) + created_dir = (mkdir_secure (dir, mode, Sid) == 0); + else +#endif created_dir = (mkdir (dir, mode) == 0); if (!created_dir) @@ -191,6 +217,24 @@ return fail; } + +#ifdef FLASK_LINUX +int +make_path_s (const char *argpath, + int mode, + int parent_mode, + uid_t owner, + gid_t group, + int preserve_existing, + const char *verbose_fmt_string, + security_id_t sid) +{ + Sid = sid; + return( make_path(argpath, mode, parent_mode, owner, group, preserve_existing, verbose_fmt_string) ); +} +#endif + + /* Ensure that the directory ARGPATH exists. Create any leading directories that don't already exist, with diff -Nur coreutils-5.0/man/chcon.x coreutils-5.0.new/man/chcon.x --- coreutils-5.0/man/chcon.x 1970-01-01 01:00:00.000000000 +0100 +++ coreutils-5.0.new/man/chcon.x 2003-06-06 03:01:11.000000000 +0200 @@ -0,0 +1,4 @@ +[NAME] +chcon \- change file security context +[DESCRIPTION] +.\" Add any additional description here diff -Nur coreutils-5.0/man/Makefile.am coreutils-5.0.new/man/Makefile.am --- coreutils-5.0/man/Makefile.am 2003-06-06 02:58:53.000000000 +0200 +++ coreutils-5.0.new/man/Makefile.am 2003-06-06 03:04:25.000000000 +0200 @@ -9,7 +9,7 @@ rm.1 rmdir.1 seq.1 sha1sum.1 shred.1 sleep.1 sort.1 split.1 stat.1 stty.1 \ su.1 sum.1 sync.1 tac.1 tail.1 tee.1 test.1 touch.1 tr.1 true.1 tsort.1 \ tty.1 uname.1 unexpand.1 uniq.1 unlink.1 uptime.1 users.1 vdir.1 wc.1 \ - who.1 whoami.1 yes.1 + who.1 whoami.1 yes.1 chcon.1 runas.1 man_MANS = getgid.1 man_aux = $(dist_man_MANS:.1=.x) @@ -111,6 +111,8 @@ who.1: $(common_dep) $(srcdir)/who.x ../src/who.c whoami.1: $(common_dep) $(srcdir)/whoami.x ../src/whoami.c yes.1: $(common_dep) $(srcdir)/yes.x ../src/yes.c +chcon.1: $(common_dep) $(srcdir)/chcon.x ../src/chcon.c +runas.1: $(common_dep) $(srcdir)/runas.x ../src/runas.c SUFFIXES = .x .1 diff -Nur coreutils-5.0/man/runas.x coreutils-5.0.new/man/runas.x --- coreutils-5.0/man/runas.x 1970-01-01 01:00:00.000000000 +0100 +++ coreutils-5.0.new/man/runas.x 2003-06-06 03:01:11.000000000 +0200 @@ -0,0 +1,2 @@ +[DESCRIPTION] +.\" Add any additional description here diff -Nur coreutils-5.0/README coreutils-5.0.new/README --- coreutils-5.0/README 2003-03-29 15:24:00.000000000 +0100 +++ coreutils-5.0.new/README 2003-06-06 03:01:11.000000000 +0200 @@ -7,11 +7,11 @@ The programs that can be built with this package are: - basename cat chgrp chmod chown chroot cksum comm cp csplit cut date dd + basename cat chcon chgrp chmod chown chroot cksum comm cp csplit cut date dd df dir dircolors dirname du echo env expand expr factor false fmt fold ginstall groups head hostid hostname id join kill link ln logname ls md5sum mkdir mkfifo mknod mv nice nl nohup od paste pathchk pinky pr - printenv printf ptx pwd readlink rm rmdir seq sha1sum shred sleep sort + printenv printf ptx pwd readlink rm rmdir runas seq sha1sum shred sleep sort split stat stty su sum sync tac tail tee test touch tr true tsort tty uname unexpand uniq unlink uptime users vdir wc who whoami yes diff -Nur coreutils-5.0/src/chcon.c coreutils-5.0.new/src/chcon.c --- coreutils-5.0/src/chcon.c 1970-01-01 01:00:00.000000000 +0100 +++ coreutils-5.0.new/src/chcon.c 2003-06-06 03:01:11.000000000 +0200 @@ -0,0 +1,334 @@ +/* chcontext -- change security context of a pathname */ + +#include +#include +#include +#include +#include +#include + +#include "system.h" +#include "error.h" +#include "savedir.h" +#include "group-member.h" + +enum Change_status +{ + CH_SUCCEEDED, + CH_FAILED, + CH_NO_CHANGE_REQUESTED +}; + +enum Verbosity +{ + /* Print a message for each file that is processed. */ + V_high, + + /* Print a message for each file whose attributes we change. */ + V_changes_only, + + /* Do not be verbose. This is the default. */ + V_off +}; + +static int change_dir_context PARAMS ((const char *dir, int sid, + const struct stat *statp)); + +/* The name the program was run with. */ +char *program_name; + +/* If nonzero, and the systems has support for it, change the context + of symbolic links rather than any files they point to. */ +static int change_symlinks; + +/* If nonzero, change the context of directories recursively. */ +static int recurse; + +/* If nonzero, force silence (no error messages). */ +static int force_silent; + +/* Level of verbosity. */ +static enum Verbosity verbosity = V_off; + +/* The name of the context the file is being given. */ +static const char *contextname; + +/* The argument to the --reference option. Use the context SID of this file. + This file must exist. */ +static char *reference_file; + +/* If nonzero, display usage information and exit. */ +static int show_help; + +/* If nonzero, print the version on standard output and exit. */ +static int show_version; + +static struct option const long_options[] = +{ + {"recursive", no_argument, 0, 'R'}, + {"changes", no_argument, 0, 'c'}, + {"no-dereference", no_argument, 0, 'h'}, + {"silent", no_argument, 0, 'f'}, + {"quiet", no_argument, 0, 'f'}, + {"reference", required_argument, 0, CHAR_MAX + 1}, + {"sid", required_argument, 0, CHAR_MAX + 2}, + {"verbose", no_argument, 0, 'v'}, + {"help", no_argument, &show_help, 1}, + {"version", no_argument, &show_version, 1}, + {0, 0, 0, 0} +}; + +/* Tell the user how/if the context of FILE has been changed. + CHANGED describes what (if anything) has happened. */ + +static void +describe_change (const char *file, enum Change_status changed) +{ + const char *fmt; + switch (changed) + { + case CH_SUCCEEDED: + fmt = _("context of %s changed to %s\n"); + break; + case CH_FAILED: + fmt = _("failed to change context of %s to %s\n"); + break; + case CH_NO_CHANGE_REQUESTED: + fmt = _("context of %s retained as %s\n"); + break; + default: + abort (); + } + printf (fmt, file, contextname); +} + +/* Change the context of FILE to SID CONTEXT. + If it is a directory and -R is given, recurse. + Return 0 if successful, 1 if errors occurred. */ + +static int +change_file_context (const char *file, int sid) +{ + struct stat file_stats; + security_id_t file_sid; + int errors = 0; + + if (lstat_secure (file, &file_stats, &file_sid)) + { + if (force_silent == 0) + error (0, errno, "%s", file); + return 1; + } + + if (sid != file_sid) + { + int fail; + + if (change_symlinks) + fail = lchsid (file, sid); + else + fail = chsid (file, sid); + + if (verbosity == V_high || (verbosity == V_changes_only && !fail)) + describe_change (file, (fail ? CH_FAILED : CH_SUCCEEDED)); + + if (fail) + { + errors = 1; + if (force_silent == 0) + { + error (0, errno, "%s", file); + } + } + } + else if (verbosity == V_high) + { + describe_change (file, CH_NO_CHANGE_REQUESTED); + } + + if (recurse && S_ISDIR (file_stats.st_mode)) + errors |= change_dir_context (file, sid, &file_stats); + + return errors; +} + +/* Recursively change context of the files in directory DIR + to SID CONTEXT. + STATP points to the results of lstat on DIR. + Return 0 if successful, 1 if errors occurred. */ + +static int +change_dir_context (const char *dir, int sid, const struct stat *statp) +{ + char *name_space, *namep; + char *path; /* Full path of each entry to process. */ + unsigned dirlength; /* Length of `dir' and '\0'. */ + unsigned filelength; /* Length of each pathname to process. */ + unsigned pathlength; /* Bytes allocated for `path'. */ + int errors = 0; + + errno = 0; + name_space = savedir (dir); + if (name_space == NULL) + { + if (errno) + { + if (force_silent == 0) + error (0, errno, "%s", dir); + return 1; + } + else + error (1, 0, _("virtual memory exhausted")); + } + + dirlength = strlen (dir) + 1; /* + 1 is for the trailing '/'. */ + pathlength = dirlength + 1; + /* Give `path' a dummy value; it will be reallocated before first use. */ + path = xmalloc (pathlength); + strcpy (path, dir); + path[dirlength - 1] = '/'; + + for (namep = name_space; *namep; namep += filelength - dirlength) + { + filelength = dirlength + strlen (namep) + 1; + if (filelength > pathlength) + { + pathlength = filelength * 2; + path = xrealloc (path, pathlength); + } + strcpy (path + dirlength, namep); + errors |= change_file_context (path, sid); + } + free (path); + free (name_space); + return errors; +} + +static void +usage (int status) +{ + if (status != 0) + fprintf (stderr, _("Try `%s --help' for more information.\n"), + program_name); + else + { + printf (_("\ +Usage: %s [OPTION]... CONTEXT FILE...\n\ + or: %s [OPTION]... --reference=RFILE FILE...\n\ + or: %s [OPTION]... --sid=SID FILE...\n\ +"), + program_name, program_name, program_name); + printf (_("\ +Change the security context of each FILE to CONTEXT.\n\ +\n\ + -c, --changes like verbose but report only when a change is made\n\ + -h, --no-dereference affect symbolic links instead of any referenced file\n\ + (available only on systems with lchown system call)\n\ + -f, --silent, --quiet suppress most error messages\n\ + --reference=RFILE use RFILE's group instead of using a CONTEXT value\n\ + --sid=SID use context corresponding to SID for CONTEXT value\n\ + -R, --recursive change files and directories recursively\n\ + -v, --verbose output a diagnostic for every file processed\n\ + --help display this help and exit\n\ + --version output version information and exit\n\ +")); + close_stdout (); + } + exit (status); +} + +int +main (int argc, char **argv) +{ + int sid = -1; + int errors = 0; + int optc; + + program_name = argv[0]; + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + recurse = force_silent = 0; + + while ((optc = getopt_long (argc, argv, "Rcfhv", long_options, NULL)) != -1) + { + switch (optc) + { + case 0: + break; + case CHAR_MAX + 1: + reference_file = optarg; + break; + case CHAR_MAX +2: + sid = (int)strtol( optarg, (char **)NULL, 10); + /* We use an int to represent sids so we can use -1 for * + * an error condition. All valid sids are positive. * + * Check for an invalid sid. */ + if( ( errno == ERANGE ) || ( sid <= 0 ) ) { + error( 1, 0, _("invalid sid")); + } + break; + case 'R': + recurse = 1; + break; + case 'c': + verbosity = V_changes_only; + break; + case 'f': + force_silent = 1; + break; + case 'h': + change_symlinks = 1; + break; + case 'v': + verbosity = V_high; + break; + default: + usage (1); + } + } + + if (show_version) + { + printf ("chcon (%s) %s\n", GNU_PACKAGE, VERSION); + close_stdout (); + exit (0); + } + + if (show_help) + usage (0); + + if (argc - optind + ( (reference_file || ( sid > 0 ) ) ? 1 : 0) <= 1) + { + error (0, 0, _("too few arguments")); + usage (1); + } + + if (reference_file) + { + struct stat ref_stats; + security_id_t ref_sid; + if (stat_secure (reference_file, &ref_stats, &ref_sid)) + error (1, errno, "%s", reference_file); + + sid = ref_sid; + } + else if( sid <= 0 ) /* sid > 0 means sid already set by --sid above */ + { + contextname = argv[optind++]; + + if (*contextname == '\0') + error (1, 0, _("can not change to null context")); + + if (security_context_to_sid (contextname, strlen (contextname) + 1, &sid)) + error (1, errno, "%s", contextname); + } + + for (; optind < argc; ++optind) + errors |= change_file_context (argv[optind], sid); + + if (verbosity != V_off) + close_stdout (); + exit (errors); +} diff -Nur coreutils-5.0/src/copy.c coreutils-5.0.new/src/copy.c --- coreutils-5.0/src/copy.c 2003-06-06 02:58:57.000000000 +0200 +++ coreutils-5.0.new/src/copy.c 2003-06-06 03:01:11.000000000 +0200 @@ -46,6 +46,11 @@ #include "same.h" #include "xreadlink.h" +#ifdef FLASK_LINUX +#include +security_id_t Sid = -1; +#endif + #define DO_CHOWN(Chown, File, New_uid, New_gid) \ (Chown (File, New_uid, New_gid) \ /* If non-root uses -p, it's ok if we can't preserve ownership. \ @@ -199,6 +204,9 @@ off_t n_read_total = 0; int last_write_made_hole = 0; int make_holes = (x->sparse_mode == SPARSE_ALWAYS); +#ifdef FLASK_LINUX + security_id_t lsid; +#endif source_desc = open (src_path, O_RDONLY); if (source_desc < 0) @@ -780,12 +788,20 @@ int copied_as_regular = 0; int dst_mode_valid = 0; int preserve_metadata; +#ifdef FLASK_LINUX + security_id_t lsid; + struct stat tst_sb; +#endif if (x->move_mode && rename_succeeded) *rename_succeeded = 0; *copy_into_self = 0; +#ifdef FLASK_LINUX + if ((*(x->xstat)) (src_path, &src_sb, &lsid)) +#else if ((*(x->xstat)) (src_path, &src_sb)) +#endif { error (0, errno, _("cannot stat %s"), quote (src_path)); return 1; @@ -819,7 +835,11 @@ if (!new_dst) { +#ifdef FLASK_LINUX + if ((*(x->xstat)) (dst_path, &dst_sb, &lsid)) +#else if ((*(x->xstat)) (dst_path, &dst_sb)) +#endif { if (errno != ENOENT) { @@ -1463,6 +1483,25 @@ preserving owner/group is a potential security problem. */ # endif } +#ifdef FLASK_LINUX + /* Trying to preserve a security context can fail for any UID, and user + * should probably always know about it. + */ + if ( x->preserve_security_context ) { + if ( (int) Sid > 0 ) { + error (0, 0, _("cannot set context to SID==%d and preserve it"), (int)Sid); + return 1; + } + if ( stat_secure(src_path, &tst_sb, &lsid) < 0 ) { + error (0, errno, _("getting security context for %s"), src_path); + return 1; + } + if ( chsid(dst_path, lsid) < 0 ) { + error (0, errno, _("preserving security context for %s (sid==%d)"), dst_path, (int)lsid); + return 1; + } + } +#endif } else #endif @@ -1596,6 +1635,15 @@ quote_n (0, dst_backup), quote_n (1, dst_path)); } } + +#ifdef FLASK_LINUX + /* if rename() just failed, so will this */ + if ( (int) Sid > 0 && x->preserve_security_context == 0 ) { + if ( chsid(dst_path, Sid) < 0 ) + error (0, errno, _("setting scontext (%d) for %s"), (int)Sid, dst_path); + } +#endif + return 1; } @@ -1627,6 +1675,17 @@ same as) DST_PATH; otherwise, set it to zero. Return 0 if successful, 1 if an error occurs. */ +#ifdef FLASK_LINUX +int +copy_s (const char *src_path, const char *dst_path, + int nonexistent_dst, const struct cp_options *options, + int *copy_into_self, int *rename_succeeded, security_id_t sid) +{ + Sid = sid; + return( copy( src_path, dst_path, nonexistent_dst, options, copy_into_self, rename_succeeded) ); +} +#endif + int copy (const char *src_path, const char *dst_path, int nonexistent_dst, const struct cp_options *options, diff -Nur coreutils-5.0/src/copy.h coreutils-5.0.new/src/copy.h --- coreutils-5.0/src/copy.h 2003-06-06 02:58:57.000000000 +0200 +++ coreutils-5.0.new/src/copy.h 2003-06-06 03:01:12.000000000 +0200 @@ -105,6 +105,9 @@ int preserve_ownership; int preserve_mode; int preserve_timestamps; +#ifdef FLASK_LINUX + int preserve_security_context; +#endif /* Enabled for mv, and for cp by the --preserve=links option. If nonzero, attempt to preserve in the destination files any diff -Nur coreutils-5.0/src/copy.h.orig coreutils-5.0.new/src/copy.h.orig --- coreutils-5.0/src/copy.h.orig 2003-03-26 19:46:56.000000000 +0100 +++ coreutils-5.0.new/src/copy.h.orig 1970-01-01 01:00:00.000000000 +0100 @@ -1,211 +0,0 @@ -#ifndef COPY_H -# define COPY_H - -# include "hash.h" - -/* Control creation of sparse files (files with holes). */ -enum Sparse_type -{ - SPARSE_UNUSED, - - /* Never create holes in DEST. */ - SPARSE_NEVER, - - /* This is the default. Use a crude (and sometimes inaccurate) - heuristic to determine if SOURCE has holes. If so, try to create - holes in DEST. */ - SPARSE_AUTO, - - /* For every sufficiently long sequence of bytes in SOURCE, try to - create a corresponding hole in DEST. There is a performance penalty - here because CP has to search for holes in SRC. But if the holes are - big enough, that penalty can be offset by the decrease in the amount - of data written to disk. */ - SPARSE_ALWAYS -}; - -/* This type is used to help mv (via copy.c) distinguish these cases. */ -enum Interactive -{ - I_ALWAYS_YES = 1, - I_ALWAYS_NO, - I_ASK_USER, - I_UNSPECIFIED -}; - -/* How to handle symbolic links. */ -enum Dereference_symlink -{ - DEREF_UNDEFINED = 1, - - /* Copy the symbolic link itself. -P */ - DEREF_NEVER, - - /* If the symbolic is a command line argument, then copy - its referent. Otherwise, copy the symbolic link itself. -H */ - DEREF_COMMAND_LINE_ARGUMENTS, - - /* Copy the referent of the symbolic link. -L */ - DEREF_ALWAYS -}; - -# define VALID_SPARSE_MODE(Mode) \ - ((Mode) == SPARSE_NEVER \ - || (Mode) == SPARSE_AUTO \ - || (Mode) == SPARSE_ALWAYS) - -/* These options control how files are copied by at least the - following programs: mv (when rename doesn't work), cp, install. - So, if you add a new member, be sure to initialize it in - mv.c, cp.c, and install.c. */ -struct cp_options -{ - enum backup_type backup_type; - - /* If nonzero, copy all files except (directories and, if not dereferencing - them, symbolic links,) as if they were regular files. */ - int copy_as_regular; - - /* How to handle symlinks. */ - enum Dereference_symlink dereference; - - /* If nonzero, remove each existing destination nondirectory before - trying to open it. */ - int unlink_dest_before_opening; - - /* If nonzero, first try to open each existing destination nondirectory, - then, if the open fails, unlink and try again. - This option must be set for `cp -f', in case the destination file - exists when the open is attempted. It is irrelevant to `mv' since - any destination is sure to be removed before the open. */ - int unlink_dest_after_failed_open; - - /* If nonzero, create hard links instead of copying files. - Create destination directories as usual. */ - int hard_link; - - /* This value is used to determine whether to prompt before removing - each existing destination file. It works differently depending on - whether move_mode is set. See code/comments in copy.c. */ - enum Interactive interactive; - - /* If nonzero, rather than copying, first attempt to use rename. - If that fails, then resort to copying. */ - int move_mode; - - /* This process's effective user ID. */ - uid_t myeuid; - - /* If nonzero, when copying recursively, skip any subdirectories that are - on different filesystems from the one we started on. */ - int one_file_system; - - /* If nonzero, attempt to give the copies the original files' permissions, - owner, group, and timestamps. */ - int preserve_ownership; - int preserve_mode; - int preserve_timestamps; - - /* Enabled for mv, and for cp by the --preserve=links option. - If nonzero, attempt to preserve in the destination files any - logical hard links between the source files. If used with cp's - --no-dereference option, and copying two hard-linked files, - the two corresponding destination files will also be hard linked. - - If used with cp's --dereference (-L) option, then, as that option implies, - hard links are *not* preserved. However, when copying a file F and - a symlink S to F, the resulting S and F in the destination directory - will be hard links to the same file (a copy of F). */ - int preserve_links; - - /* If nonzero and any of the above (for preserve) file attributes cannot - be applied to a destination file, treat it as a failure and return - nonzero immediately. E.g. cp -p requires this be nonzero, mv requires - it be zero. */ - int require_preserve; - - /* If nonzero, copy directories recursively and copy special files - as themselves rather than copying their contents. */ - int recursive; - - /* If nonzero, set file mode to value of MODE. Otherwise, - set it based on current umask modified by UMASK_KILL. */ - int set_mode; - - /* Set the mode of the destination file to exactly this value - if USE_MODE is nonzero. */ - mode_t mode; - - /* Control creation of sparse files. */ - enum Sparse_type sparse_mode; - - /* If nonzero, create symbolic links instead of copying files. - Create destination directories as usual. */ - int symbolic_link; - - /* The bits to preserve in created files' modes. */ - mode_t umask_kill; - - /* If nonzero, do not copy a nondirectory that has an existing destination - with the same or newer modification time. */ - int update; - - /* If nonzero, display the names of the files before copying them. */ - int verbose; - - /* A pointer to either lstat or stat, depending on - whether the copy should dereference symlinks. */ - int (*xstat) (); - - /* If nonzero, stdin is a tty. */ - int stdin_tty; - - /* This is a set of destination name/inode/dev triples. Each such triple - represents a file we have created corresponding to a source file name - that was specified on the command line. Use it to avoid clobbering - source files in commands like this: - rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c - For now, it protects only regular files when copying (i.e. not renaming). - When renaming, it protects all non-directories. - Use dest_info_init to initialize it, or set it to NULL to disable - this feature. */ - Hash_table *dest_info; - - /* FIXME */ - Hash_table *src_info; -}; - -int stat (); -int lstat (); - -/* Arrange to make lstat calls go through the wrapper function - on systems with an lstat function that does not dereference symlinks - that are specified with a trailing slash. */ -# if ! LSTAT_FOLLOWS_SLASHED_SYMLINK -int rpl_lstat (const char *, struct stat *); -# undef lstat -# define lstat rpl_lstat -# endif - -int rename (); - -/* Arrange to make rename calls go through the wrapper function - on systems with a rename function that fails for a source path - specified with a trailing slash. */ -# if RENAME_TRAILING_SLASH_BUG -int rpl_rename (const char *, const char *); -# undef rename -# define rename rpl_rename -# endif - -int -copy (const char *src_path, const char *dst_path, - int nonexistent_dst, const struct cp_options *options, - int *copy_into_self, int *rename_succeeded); - -void -dest_info_init (struct cp_options *); -void -src_info_init (struct cp_options *); - -#endif diff -Nur coreutils-5.0/src/cp.c coreutils-5.0.new/src/cp.c --- coreutils-5.0/src/cp.c 2003-06-06 02:58:57.000000000 +0200 +++ coreutils-5.0.new/src/cp.c 2003-06-06 03:01:12.000000000 +0200 @@ -52,6 +52,16 @@ #define AUTHORS N_ ("Torbjorn Granlund, David MacKenzie, and Jim Meyering") +#ifdef FLASK_LINUX +#include +#include /* for is_flask_enabled() */ +#define CTXTLEN 256 +char *scontext = NULL; +security_id_t sid = -1; +int ctxtlen = CTXTLEN; +char *calloc(); +#endif + #ifndef _POSIX_VERSION uid_t geteuid (); #endif @@ -149,6 +159,10 @@ {"update", no_argument, NULL, 'u'}, {"verbose", no_argument, NULL, 'v'}, {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */ +#ifdef FLASK_LINUX + {"sid", required_argument, NULL, 'Z'}, + {"context", required_argument, NULL, 'X'}, +#endif {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, {NULL, 0, NULL, 0} @@ -198,6 +212,9 @@ additional attributes: links, all\n\ "), stdout); fputs (_("\ + -c same as --preserve=context\n\ +"), stdout); + fputs (_("\ --no-preserve=ATTR_LIST don't preserve the specified attributes\n\ --parents append source path to DIRECTORY\n\ -P same as `--no-dereference'\n\ @@ -225,6 +242,8 @@ destination file is missing\n\ -v, --verbose explain what is being done\n\ -x, --one-file-system stay on this file system\n\ + -X, --context=CONTEXT set security context of copy to CONTEXT\n\ + -Z, --sid=SID set Security ID of copy to SID\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); @@ -288,6 +307,9 @@ char *dst_path; /* A copy of CONST_DST_PATH we can change. */ char *src_path; /* The source name in `dst_path'. */ uid_t myeuid = geteuid (); +#ifdef FLASK_LINUX + security_id_t lsid; +#endif dst_path = (char *) alloca (strlen (const_dst_path) + 1); strcpy (dst_path, const_dst_path); @@ -299,7 +321,11 @@ dst_path[p->slash_offset] = '\0'; +#ifdef FLASK_LINUX + if ((*(x->xstat)) (src_path, &src_sb, &lsid)) +#else if ((*(x->xstat)) (src_path, &src_sb)) +#endif { error (0, errno, _("failed to get attributes of %s"), quote (src_path)); @@ -358,6 +384,28 @@ } } +#ifdef FLASK_LINUX + /* Trying to preserve a security context can fail for any UID, and user + * should probably always know about it. + */ + + if ( x->preserve_security_context ) { + int rv; + struct stat st; + security_id_t lsid; + + if ( (rv = stat_secure(src_path, &st, &lsid)) < 0 ) { + error (0, errno, _("getting security context for %s"), src_path); + return 1; + } + + if ( (rv = chsid(dst_path, lsid)) < 0 ) { + error (0, errno, _("preserving security context for %s (sid==%d)"), dst_path, (int)lsid); + return 1; + } + } +#endif + dst_path[p->slash_offset] = '/'; } return 0; @@ -678,6 +726,11 @@ else { int copy_into_self; +#ifdef FLASK_LINUX + if ( (int) sid > 0 ) + ret |= copy_s (arg, dst_path, new_dst, x, ©_into_self, NULL, sid); + else +#endif ret |= copy (arg, dst_path, new_dst, x, ©_into_self, NULL); if (flag_path) @@ -756,8 +809,12 @@ { new_dest = (char *) dest; } - - return copy (source, new_dest, new_dst, x, &unused, NULL); +#ifdef FLASK_LINUX + if ( (int) sid > 0 ) + return copy_s (source, new_dest, new_dst, x, &unused, NULL, sid); + else +#endif + return copy (source, new_dest, new_dst, x, &unused, NULL); } /* unreachable */ @@ -781,6 +838,10 @@ x->preserve_mode = 0; x->preserve_timestamps = 0; +#ifdef FLASK_LINUX + x->preserve_security_context = 0; +#endif + x->require_preserve = 0; x->recursive = 0; x->sparse_mode = SPARSE_AUTO; @@ -808,19 +869,20 @@ PRESERVE_TIMESTAMPS, PRESERVE_OWNERSHIP, PRESERVE_LINK, + PRESERVE_CONTEXT, PRESERVE_ALL }; static enum File_attribute const preserve_vals[] = { PRESERVE_MODE, PRESERVE_TIMESTAMPS, - PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL + PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_CONTEXT, PRESERVE_ALL }; /* Valid arguments to the `--preserve' option. */ static char const* const preserve_args[] = { "mode", "timestamps", - "ownership", "links", "all", 0 + "ownership", "links", "context", "all", 0 }; char *arg_writable = xstrdup (arg); @@ -855,11 +917,16 @@ x->preserve_links = on_off; break; + case PRESERVE_CONTEXT: + x->preserve_security_context = on_off; + break; + case PRESERVE_ALL: x->preserve_mode = on_off; x->preserve_timestamps = on_off; x->preserve_ownership = on_off; x->preserve_links = on_off; + x->preserve_security_context = on_off; break; default: @@ -882,6 +949,11 @@ struct cp_options x; int copy_contents = 0; char *target_directory = NULL; +#ifdef FLASK_LINUX + int is_flask_enabled_flag; + + is_flask_enabled_flag = is_flask_enabled(); +#endif program_name = argv[0]; setlocale (LC_ALL, ""); @@ -896,7 +968,11 @@ we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); +#ifdef FLASK_LINUX + while ((c = getopt_long (argc, argv, "abcdfHilLprsuvxPRS:V:X:Z:", long_opts, NULL)) +#else while ((c = getopt_long (argc, argv, "abdfHilLprsuvxPRS:V:", long_opts, NULL)) +#endif != -1) { switch (c) @@ -987,6 +1063,85 @@ x.preserve_timestamps = 1; x.require_preserve = 1; break; +#ifdef FLASK_LINUX + case 'c': + if ( (int) sid > 0 ) { /* scontext could be NULL because of calloc() failure */ + if ( scontext ) + (void) fprintf(stderr, "%s: cannot force target context to '%s' and preserve it\n", argv[0], scontext); + else + (void) fprintf(stderr, "%s: cannot force target context <-- %d and preserve it\n", argv[0], (int) sid); + exit( 1 ); + } + else if (is_flask_enabled_flag) + x.preserve_security_context = 1; + break; + case 'Z': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Warning: ignoring --sid (-Z) " + "because the kernel is not flask-enabled.\n" ); + break; + } + if ( x.preserve_security_context ) { + (void) fprintf(stderr, "%s: can't force target context to '%s' and preserve it\n", argv[0], optarg); + exit( 1 ); + } + if ( (int) sid > 0 || scontext != NULL ) { + (void) fprintf(stderr, "%s: --sid (-Z) and --context (-X) are mutually exclusive\n", argv[0]); + exit( 1 ); + } + /* check for typos */ + { + char *ep; + sid = (security_id_t) strtol(optarg, &ep, 10); + if ( *ep ) { + (void) fprintf(stderr, "%s: non-numeric SID '%s'\n", argv[0], optarg); + exit( 1 ); + } + } + /* do a sanity check and save result if SID is OK */ + scontext = calloc(1, ctxtlen+1); + if ( scontext != NULL ) { + if ( security_sid_to_context(sid, scontext, &ctxtlen) ) { + if ( errno != ENOSPC ) { + (void) fprintf(stderr, "%s: security_sid_to_context(%d): '%s'\n", argv[0], (int) sid, strerror(errno)); + exit( 1 ); + } + free(scontext); + scontext = calloc(1, ctxtlen+1); + /* nonfatal */ + if ( scontext != NULL ) + if ( security_sid_to_context(sid, scontext, &ctxtlen) ) { + (void) fprintf(stderr, "%s: security_sid_to_context(%d): %s\n", argv[0], (int) sid, strerror(errno)); + exit( 1 ); + } + } + } + break; + case 'X': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Warning: ignoring --context (-X) " + "because the kernel is not flask-enabled.\n" ); + break; + } + if ( x.preserve_security_context ) { + (void) fprintf(stderr, "%s: cannot force target context to '%s' and preserve it\n", argv[0], optarg); + exit( 1 ); + } + if ( (int) sid > 0 ) { + (void) fprintf(stderr, "%s: --context (-X) and --sid (-Z) are mutually exclusive\n", argv[0]); + exit( 1 ); + } + scontext = optarg; + /* sanity check -- also sets sid val */ + if ( security_context_to_sid(scontext, strlen(scontext)+1, &sid) ) { + (void) fprintf(stderr, "%s: security_context_to_sid(%s): %s\n", + argv[0], scontext, strerror(errno)); + exit( 1 ); + } + break; +#endif case PARENTS_OPTION: flag_path = 1; @@ -1076,13 +1231,21 @@ of `stat' to call. */ if (x.dereference == DEREF_NEVER) +#ifdef FLASK_LINUX + x.xstat = lstat_secure; +#else x.xstat = lstat; +#endif else { /* For DEREF_COMMAND_LINE_ARGUMENTS, x.xstat must be stat for each command line argument, but must later be `lstat' for any symlinks that are found via recursive traversal. */ +#ifdef FLASK_LINUX + x.xstat = stat_secure; +#else x.xstat = stat; +#endif } if (x.recursive) diff -Nur coreutils-5.0/src/id.c coreutils-5.0.new/src/id.c --- coreutils-5.0/src/id.c 2003-03-27 23:39:46.000000000 +0100 +++ coreutils-5.0.new/src/id.c 2003-06-06 03:01:12.000000000 +0200 @@ -25,7 +25,8 @@ #include #include #include - +#include +#include #include "system.h" #include "error.h" #include "closeout.h" @@ -46,6 +47,8 @@ int getugroups (); +static void print_context PARAMS ((char* context)); +static void print_sid PARAMS ((security_id_t sid)); static void print_user (uid_t uid); static void print_group (gid_t gid); static void print_group_list (const char *username); @@ -54,6 +57,12 @@ /* The name this program was run with. */ char *program_name; +/* If nonzero, output only the TOS context. -c */ +static int just_context = 0; + +/* If nonzero, output only the security ID (sid). -s */ +static int just_sid = 0; + /* If nonzero, output user/group name instead of ID number. -n */ static int use_name = 0; @@ -64,12 +73,21 @@ /* The number of errors encountered so far. */ static int problems = 0; +/* The TOS context */ +static char context[1024]; + +/* The security ID ("sid") */ +security_id_t mysid = 0; + + static struct option const longopts[] = { + {"context", no_argument, NULL, 'c'}, {"group", no_argument, NULL, 'g'}, {"groups", no_argument, NULL, 'G'}, {"name", no_argument, NULL, 'n'}, {"real", no_argument, NULL, 'r'}, + {"sid", no_argument, NULL, 's'}, {"user", no_argument, NULL, 'u'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, @@ -89,10 +107,12 @@ Print information for USERNAME, or the current user.\n\ \n\ -a ignore, for compatibility with other versions\n\ + -c, --context print only the context\n\ -g, --group print only the effective group ID\n\ -G, --groups print all group IDs\n\ -n, --name print a name instead of a number, for -ugG\n\ -r, --real print the real ID instead of the effective ID, with -ugG\n\ + -s, --sid print only the security ID\n\ -u, --user print only the effective user ID\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); @@ -110,6 +130,8 @@ main (int argc, char **argv) { int optc; + int len = sizeof (context); + int is_flask_enabled_flag; /* If nonzero, output the list of all group IDs. -G */ int just_group_list = 0; @@ -125,9 +147,15 @@ bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); + /* Set `context' to a known invalid value so print_full_info() will * + * know when `context' has not been set to a meaningful value. */ + context[ 0 ] = '\0'; + + is_flask_enabled_flag = is_flask_enabled(); + atexit (close_stdout); - while ((optc = getopt_long (argc, argv, "agnruG", longopts, NULL)) != -1) + while ((optc = getopt_long (argc, argv, "acgnrsuG", longopts, NULL)) != -1) { switch (optc) { @@ -136,6 +164,15 @@ case 'a': /* Ignore -a, for compatibility with SVR4. */ break; + case 'c': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Sorry, --context (-c) can be used only on " + "a flask-enabled kernel.\n" ); + exit( 1 ); + } + just_context = 1; + break; case 'g': just_group = 1; break; @@ -145,6 +182,15 @@ case 'r': use_real = 1; break; + case 's': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Sorry, --sid (-s) can be used only on " + "a flask-enabled kernel.\n" ); + exit( 1 ); + } + just_sid = 1; + break; case 'u': just_user = 1; break; @@ -158,13 +204,32 @@ } } - if (just_user + just_group + just_group_list > 1) - error (EXIT_FAILURE, 0, _("cannot print only user and only group")); + if (argc - optind == 1) + is_flask_enabled_flag = 0; + + if (just_user + just_group + just_group_list + just_context + just_sid > 1) + error (EXIT_FAILURE, 0, _("cannot print \"only\" of more than one choice")); if (just_user + just_group + just_group_list == 0 && (use_real || use_name)) error (EXIT_FAILURE, 0, _("cannot print only names or real IDs in default format")); + if( (just_context | just_sid) && !is_flask_enabled_flag) + error (1, 0, _("\ +cannot display context/sid when flask not enabled or when displaying the id\n\ +of a different user")); + + /* If we are on a flask-enabled kernel, get our sid and context. * + * Otherwise, leave the sid and context variables alone - they have * + * been initialized known invalid values; if we see these invalid * + * values later, we will know we are on a non-flask kernel. */ + if( is_flask_enabled_flag ) + { + mysid = getsecsid (); + if( security_sid_to_context(mysid, context, &len) ) + error (1, 0, "can't get process context"); + } + if (argc - optind > 1) usage (EXIT_FAILURE); @@ -190,6 +255,10 @@ print_group (use_real ? rgid : egid); else if (just_group_list) print_group_list (argv[optind]); + else if (just_context) + print_context (context); + else if (just_sid) + print_sid (mysid); else print_full_info (argv[optind]); putchar ('\n'); @@ -197,6 +266,20 @@ exit (problems != 0); } +/* Print the TOS context */ +static void +print_context(char *context) +{ + printf ("%s", context); +} + +/* Print the security ID (sid) */ +static void +print_sid( security_id_t sid ) +{ + printf ("%u", sid ); +} + /* Print the name or value of user ID UID. */ static void @@ -397,4 +480,10 @@ free (groups); } #endif /* HAVE_GETGROUPS */ + if ( context[0] ) { + printf(" context=%s",context); + } + if ( mysid != 0 ) { + printf(" sid=%u",mysid); + } } diff -Nur coreutils-5.0/src/install.c coreutils-5.0.new/src/install.c --- coreutils-5.0/src/install.c 2003-06-06 02:58:57.000000000 +0200 +++ coreutils-5.0.new/src/install.c 2003-06-06 03:01:12.000000000 +0200 @@ -50,6 +50,15 @@ # include #endif +#ifdef FLASK_LINUX +#include +#include /* for is_flask_enabled() */ +#define CTXTLEN 256 +char *scontext = NULL; +int ctxtlen = CTXTLEN; +char *calloc(); +#endif + struct passwd *getpwnam (); struct group *getgrnam (); @@ -126,11 +135,18 @@ static struct option const long_options[] = { {"backup", optional_argument, NULL, 'b'}, +#ifdef FLASK_LINUX + {"context", required_argument, NULL, 'X'}, +#endif {"directory", no_argument, NULL, 'd'}, {"group", required_argument, NULL, 'g'}, {"mode", required_argument, NULL, 'm'}, {"owner", required_argument, NULL, 'o'}, {"preserve-timestamps", no_argument, NULL, 'p'}, +#ifdef FLASK_LINUX + {"preserve_context", no_argument, NULL, 'P'}, + {"sid", required_argument, NULL, 'Z'}, +#endif {"strip", no_argument, NULL, 's'}, {"suffix", required_argument, NULL, 'S'}, {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */ @@ -247,11 +263,20 @@ x->update = 0; x->verbose = 0; +#ifdef FLASK_LINUX + x->xstat = stat_secure; + x->preserve_security_context = 0; +#else x->xstat = stat; +#endif x->dest_info = NULL; x->src_info = NULL; } +#ifdef FLASK_LINUX +security_id_t sid = -1; +#endif + int main (int argc, char **argv) { @@ -265,6 +290,13 @@ struct cp_options x; int n_files; char **file; +#ifdef FLASK_LINUX + int rv; + int is_flask_enabled_flag; /* set iff kernel has extra flask system calls */ + + /* Set `is_flask_enabled_flag' iff the kernel has the extra flask syscalls */ + is_flask_enabled_flag = is_flask_enabled(); +#endif program_name = argv[0]; setlocale (LC_ALL, ""); @@ -338,6 +370,90 @@ make_backups = 1; backup_suffix_string = optarg; break; +#ifdef FLASK_LINUX + case 'P': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Warning: ignoring --preserve_context (-P) " + "because the kernel is not flask-enabled.\n" ); + break; + } + if ( (int) sid >= 0 ) { /* scontext could be NULL because of calloc() failure */ + if ( scontext ) + (void) fprintf(stderr, "%s: cannot force target context to '%s' and preserve it\n", argv[0], scontext); + else + (void) fprintf(stderr, "%s: cannot force target context <-- %d and preserve it\n", argv[0], (int) sid); + exit( 1 ); + } + x.preserve_security_context = 1; + break ; + case 'Z': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Warning: ignoring --sid (-Z) " + "because the kernel is not flask-enabled.\n" ); + break; + } + if ( x.preserve_security_context ) { + (void) fprintf(stderr, "%s: can't force target context to '%s' and preserve it\n", argv[0], optarg); + exit( 1 ); + } + if ( scontext != NULL ) { + (void) fprintf(stderr, "%s: --sid (-Z) and --context (-X) are mutually exclusive\n", argv[0]); + exit( 1 ); + } + /* check for typos */ + { + char *ep; + sid = (security_id_t) strtol(optarg, &ep, 10); + if ( *ep ) { + (void) fprintf(stderr, "%s: non-numeric SID '%s'\n", argv[0], optarg); + exit( 1 ); + } + } + /* do a sanity check and save result if SID is OK */ + scontext = calloc(1, ctxtlen+1); + if ( scontext != NULL ) { + if ( security_sid_to_context(sid, scontext, &ctxtlen) ) { + if ( errno != ENOSPC ) { + (void) fprintf(stderr, "%s: security_sid_to_context(%d): '%s'\n", argv[0], (int) sid, strerror(errno)); + exit( 1 ); + } + free(scontext); + scontext = calloc(1, ctxtlen+1); + if ( scontext != NULL ) + if ( security_sid_to_context(sid, scontext, &ctxtlen) ) { + (void) fprintf(stderr, "%s: security_sid_to_context(%d): %s\n", argv[0], (int) sid, strerror(errno)); + exit( 1 ); + } + } + } + break; + case 'X': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Warning: ignoring --context (-X) " + "because the kernel is not flask-enabled.\n" ); + break; + } + if ( x.preserve_security_context ) { + (void) fprintf(stderr, "%s: cannot force target context == '%s' and preserve it\n", argv[0], optarg); + exit( 1 ); + } + if ( (int) sid >= 0 ) { + (void) fprintf(stderr, "%s: --context (-X) and --sid (-Z) are mutually exclusive\n", argv[0]); + exit(1); + } + scontext = optarg; + /* sanity check */ + rv = security_context_to_sid(scontext, strlen(scontext)+1, &sid); + if ( rv ) { + (void) fprintf(stderr, "%s: security_context_to_sid(%s): %s\n", argv[0], scontext, + strerror(errno)); + exit(1); + } + break; +#endif case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: @@ -385,8 +501,13 @@ for (i = 0; i < n_files; i++) { errors |= +#ifdef FLASK_LINUX + make_path_s (file[i], mode, mode, owner_id, group_id, 0, + (x.verbose ? _("creating directory %s") : NULL), sid); +#else make_path (file[i], mode, mode, owner_id, group_id, 0, (x.verbose ? _("creating directory %s") : NULL)); +#endif } } else @@ -449,8 +570,13 @@ that this option is intended mainly to help installers when the distribution doesn't provide proper install rules. */ #define DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) +#ifdef FLASK_LINUX + fail = make_path_s (dest_dir, DIR_MODE, DIR_MODE, owner_id, group_id, 0, + (x->verbose ? _("creating directory %s") : NULL), sid); +#else fail = make_path (dest_dir, DIR_MODE, DIR_MODE, owner_id, group_id, 0, (x->verbose ? _("creating directory %s") : NULL)); +#endif } if (fail == 0) @@ -501,7 +627,6 @@ /* Copy file FROM onto file TO, creating TO if necessary. Return 0 if the copy is successful, 1 if not. */ - static int copy_file (const char *from, const char *to, const struct cp_options *x) { @@ -721,6 +846,12 @@ -S, --suffix=SUFFIX override the usual backup suffix\n\ -v, --verbose print the name of each directory as it is created\n\ "), stdout); + fputs (_("\ + -P, --preserve_context (Flask) Preserve security context\n\ + -Z, --sid=SID (Flask) Set SID of files and directories\n\ + -X, --context=CONTEXT (Flask) Set security context of files and directories\n\ +"), stdout); + fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); fputs (_("\ diff -Nur coreutils-5.0/src/ls.c coreutils-5.0.new/src/ls.c --- coreutils-5.0/src/ls.c 2003-06-06 02:58:57.000000000 +0200 +++ coreutils-5.0.new/src/ls.c 2003-06-06 03:01:12.000000000 +0200 @@ -130,6 +130,18 @@ #define AUTHORS N_ ("Richard Stallman and David MacKenzie") +#ifdef FLASK_LINUX +#include +#include /* for is_flask_enabled() */ + +#define CTXTLEN 256 +#define SID_DIGITS 5 + +static int print_sid = 0; +static int print_scontext = 0; + +#endif + #define obstack_chunk_alloc malloc #define obstack_chunk_free free @@ -227,6 +239,10 @@ /* For long listings, true if the file has an access control list. */ bool have_acl; #endif + +#ifdef FLASK_LINUX + security_id_t sid; +#endif }; #if HAVE_ACL || USE_ACL @@ -290,6 +306,9 @@ static void sort_files (void); static void parse_ls_color (void); void usage (int status); +#ifdef FLASK_LINUX +static void print_scontext_format PARAMS ((const struct fileinfo *f)); +#endif /* The name the program was run with, stripped of any leading path. */ char *program_name; @@ -379,7 +398,12 @@ one_per_line, /* -1 */ many_per_line, /* -C */ horizontal, /* -x */ - with_commas /* -m */ +#ifdef FLASK_LINUX + with_commas, /* -m */ + security_format +#else + with_commas /* -m */ +#endif }; static enum format format; @@ -700,6 +724,13 @@ SHOW_CONTROL_CHARS_OPTION, SI_OPTION, SORT_OPTION, +#ifdef FLASK_LINUX + CONTEXT_OPTION, + LCONTEXT_OPTION, + SCONTEXT_OPTION, + SID_OPTION, + LSID_OPTION, +#endif TIME_OPTION, TIME_STYLE_OPTION }; @@ -743,6 +774,13 @@ {"time-style", required_argument, 0, TIME_STYLE_OPTION}, {"color", optional_argument, 0, COLOR_OPTION}, {"block-size", required_argument, 0, BLOCK_SIZE_OPTION}, +#ifdef FLASK_LINUX + {"context", no_argument, 0, CONTEXT_OPTION}, + {"lcontext", no_argument, 0, LCONTEXT_OPTION}, + {"scontext", no_argument, 0, SCONTEXT_OPTION}, + {"sid", no_argument, 0, SID_OPTION}, + {"lsid", no_argument, 0, LSID_OPTION}, +#endif {"author", no_argument, 0, AUTHOR_OPTION}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, @@ -752,13 +790,21 @@ static char const *const format_args[] = { "verbose", "long", "commas", "horizontal", "across", +#ifdef FLASK_LINUX + "vertical", "single-column", "context", 0 +#else "vertical", "single-column", 0 +#endif }; static enum format const format_types[] = { long_format, long_format, with_commas, horizontal, horizontal, +#ifdef FLASK_LINUX + many_per_line, one_per_line, security_format +#else many_per_line, one_per_line +#endif }; static char const *const sort_args[] = @@ -1121,6 +1167,9 @@ format_needs_stat = sort_type == sort_time || sort_type == sort_size || format == long_format +#ifdef FLASK_LINUX + || format == security_format || print_sid || print_scontext +#endif || dereference == DEREF_ALWAYS || print_block_size || print_inode; format_needs_type = (format_needs_stat == 0 @@ -1243,6 +1292,13 @@ /* Record whether there is an option specifying sort type. */ int sort_type_specified = 0; +#ifdef FLASK_LINUX + int is_flask_enabled_flag; /* 1 iff kernel has new flask system calls */ + + /* Set `is_flask_enabled_flag iff the kernel has new flask system calls. */ + is_flask_enabled_flag = is_flask_enabled(); +#endif + qmark_funny_chars = 0; /* initialize all switches to default settings */ @@ -1293,6 +1349,10 @@ all_files = 0; really_all_files = 0; ignore_patterns = 0; +#ifdef FLASK_LINUX + print_sid = 0; + print_scontext = 0; +#endif /* FIXME: put this in a function. */ { @@ -1656,6 +1716,40 @@ case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); +#ifdef FLASK_LINUX + +#define check_selinux() if (!is_flask_enabled_flag) { \ + fprintf( stderr, "Sorry, this option can only be used " \ + "on a SELinux kernel.\n" ); \ + exit( EXIT_FAILURE ); \ +} + + case CONTEXT_OPTION: /* new security format */ + check_selinux(); + print_scontext = 1; + format = security_format; + break; + case LCONTEXT_OPTION: /* long format plus security context */ + check_selinux(); + print_scontext = 1; + format = long_format; + break; + case SCONTEXT_OPTION: /* short form of new security format */ + check_selinux(); + print_scontext = 0; + format = security_format; + break; + case SID_OPTION: /* SID, format unspecified */ + check_selinux(); + print_sid = 1; + break; + case LSID_OPTION: /* long format plus SID */ + check_selinux(); + print_sid = 1; + format = long_format; + break; +#endif + default: usage (EXIT_FAILURE); } @@ -2371,7 +2465,11 @@ if (explicit_arg) { int need_lstat; +#ifdef FLASK_LINUX + err = stat_secure(path, &files[files_index].stat, &files[files_index].sid); +#else err = stat (path, &files[files_index].stat); +#endif if (dereference == DEREF_COMMAND_LINE_ARGUMENTS) break; @@ -2389,7 +2487,11 @@ } default: /* DEREF_NEVER */ +#ifdef FLASK_LINUX + err = lstat_secure(path, &files[files_index].stat, &files[files_index].sid); +#else err = lstat (path, &files[files_index].stat); +#endif break; } @@ -2819,6 +2921,16 @@ DIRED_PUTCHAR ('\n'); } break; + +#ifdef FLASK_LINUX + case security_format: + for (i = 0; i < files_index; i++) + { + print_scontext_format (files + i); + DIRED_PUTCHAR ('\n'); + } + break; +#endif } } @@ -2936,6 +3048,10 @@ time_t when; int when_ns IF_LINT (= 0); struct tm *when_local; +#ifdef FLASK_LINUX + char *scontext; + int ctxtlen; +#endif /* Compute mode string. On most systems, it's based on st_mode. On systems with migration (via the stat.st_dm_mode field), use @@ -3082,6 +3198,34 @@ p += strlen (p); } +#ifdef FLASK_LINUX + + if ( print_sid ) { + sprintf (p, " %3u ", (unsigned int) f->sid); + p += strlen(p); + } + + if ( print_scontext ) { + ctxtlen = CTXTLEN; + scontext = xmalloc(ctxtlen); + if (security_sid_to_context(f->sid, scontext, &ctxtlen) < 0) { + if (errno == ENOSPC) { + scontext = xrealloc(scontext, ctxtlen); + if (security_sid_to_context(f->sid, scontext, &ctxtlen) < 0) { + (void) fprintf(stderr, "security_sid_to_context(%d): %s\n", f->sid, strerror(errno)); + exit( 1 ); + } + } else { + (void) fprintf(stderr, "security_sid_to_context(%d): %s\n", f->sid, strerror(errno)); + exit( 1 ); + } + } + sprintf (p, "%-32s ", scontext); + p += strlen (p); + free(scontext); + } +#endif + DIRED_INDENT (); DIRED_FPUTS (buf, stdout, p - buf); print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok, @@ -3317,6 +3461,12 @@ if (print_inode) printf ("%*s ", INODE_DIGITS, umaxtostr (f->stat.st_ino, buf)); +#ifdef FLASK_LINUX + if (print_sid) + printf ("%*s ", SID_DIGITS, + human_readable ((uintmax_t) f->sid, buf, human_group_digits, 1, 1)); +#endif + if (print_block_size) printf ("%*s ", block_size_size, human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts, @@ -3454,6 +3604,11 @@ if (print_inode) len += INODE_DIGITS + 1; +#ifdef FLASK_LINUX + if (print_sid) + len += SID_DIGITS + 1; +#endif + if (print_block_size) len += 1 + block_size_size; @@ -3874,6 +4029,18 @@ -X sort alphabetically by entry extension\n\ -1 list one file per line\n\ "), stdout); +#ifdef FLASK_LINUX +printf(_("FLASK options:\n\n\ + --lsid Display Security ID (SID). Enable -l\n\ + --sid Display SID.\n\ + --lcontext Display security context. Enable -l. Lines\n\ + will probably be too wide for most displays.\n\ + --context Display security context so it fits on most\n\ + displays. Displays only mode, user, group,\n\ + security context and file name.\n\ + --scontext Display only security context and file name.\n\ +")); +#endif fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); fputs (_("\n\ @@ -3892,3 +4059,102 @@ } exit (status); } + +#ifdef FLASK_LINUX + +static void +print_scontext_format (const struct fileinfo *f) +{ + char modebuf[12]; + + /* 7 fields that may require LONGEST_HUMAN_READABLE bytes, + 1 10-byte mode string, + 9 spaces, one following each of these fields, and + 1 trailing NUL byte. */ + + char init_bigbuf[7 * LONGEST_HUMAN_READABLE + 10 + 9 + 1]; + char *buf = init_bigbuf; + size_t bufsize = sizeof (init_bigbuf); + size_t s; + char *p; + const char *fmt; + char *user_name; + char *group_name; + int rv; + char *scontext; + int ctxtlen; + + p = buf; + + if ( print_scontext ) { /* zero means terse listing */ + mode_string (f->stat.st_mode, modebuf); + modebuf[10] = (FILE_HAS_ACL (f) ? '+' : ' '); + modebuf[11] = '\0'; + + /* print mode */ + + (void) sprintf (p, "%s ", modebuf); + p += strlen (p); + + /* print standard user and group */ + + user_name = (numeric_ids ? NULL : getuser (f->stat.st_uid)); + if (user_name) + (void) sprintf (p, "%-8.8s ", user_name); + else + (void) sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid); + p += strlen (p); + + if ( print_group ) { + group_name = (numeric_ids ? NULL : getgroup (f->stat.st_gid)); + if (group_name) + (void) sprintf (p, "%-8.8s ", group_name); + else + (void) sprintf (p, "%-8u ", (unsigned int) f->stat.st_gid); + p += strlen (p); + } + } + + if ( print_sid ) { + sprintf (p, " %3u ", (unsigned int) f->sid); + p += strlen(p); + } + + /* print security context */ + ctxtlen = CTXTLEN; + scontext = xmalloc(ctxtlen); + if ( security_sid_to_context(f->sid, scontext, &ctxtlen) ) { + if ( errno == ENOSPC ) { + scontext = xrealloc(scontext, ctxtlen); + if ( security_sid_to_context(f->sid, scontext, &ctxtlen) ) { + (void) fprintf(stderr, "security_sid_to_context(%d): %s\n", f->sid, strerror(errno)); + exit( 1 ); + } + } else { + (void) fprintf(stderr, "security_sid_to_context(%d): %s\n", f->sid, strerror(errno)); + exit( 1 ); + } + } + + (void) sprintf (p, "%-32s ", scontext); + p += strlen (p); + free(scontext); + + DIRED_INDENT (); + DIRED_FPUTS (buf, stdout, p - buf); + print_name_with_quoting (f->name, f->stat.st_mode, f->linkok, &dired_obstack); + + if (f->filetype == symbolic_link) { + if (f->linkname) { + DIRED_FPUTS_LITERAL (" -> ", stdout); + print_name_with_quoting (f->linkname, f->linkmode, f->linkok - 1, NULL); + if (indicator_style != none) + print_type_indicator (f->linkmode); + } + } + else { + if (indicator_style != none) + print_type_indicator (f->stat.st_mode); + } +} +#endif diff -Nur coreutils-5.0/src/Makefile.am coreutils-5.0.new/src/Makefile.am --- coreutils-5.0/src/Makefile.am 2003-06-06 02:58:53.000000000 +0200 +++ coreutils-5.0.new/src/Makefile.am 2003-06-06 03:06:13.000000000 +0200 @@ -4,13 +4,13 @@ EXTRA_SCRIPTS = nohup bin_SCRIPTS = groups @OPTIONAL_BIN_ZCRIPTS@ -bin_PROGRAMS = chgrp chown chmod cp dd dircolors du \ +bin_PROGRAMS = chgrp chown chmod chcon cp dd dircolors du \ ginstall link ln dir vdir ls mkdir \ mkfifo mknod mv readlink rm rmdir shred stat sync touch unlink \ cat cksum comm csplit cut expand fmt fold head join md5sum \ nl od paste pr ptx sha1sum sort split sum tac tail tr tsort unexpand uniq wc \ basename date dirname echo env expr factor false getgid \ - hostname id kill logname pathchk printenv printf pwd seq sleep tee \ + hostname id kill logname pathchk printenv printf pwd runas seq sleep tee \ test true tty whoami yes \ @OPTIONAL_BIN_PROGS@ @DF_PROG@ @@ -24,15 +24,15 @@ groups.sh nohup.sh wheel-gen.pl CLEANFILES = $(SCRIPTS) su -INCLUDES = -I.. -I$(srcdir) -I$(top_srcdir)/lib -I../lib -DEFS = -DLOCALEDIR=\"$(localedir)\" -DSHAREDIR=\"$(datadir)\" @DEFS@ +INCLUDES = -I.. -I$(srcdir) -I$(top_srcdir)/lib -I../lib -I/usr/include/selinux +DEFS = -DLOCALEDIR=\"$(localedir)\" -DSHAREDIR=\"$(datadir)\" -DFLASK_LINUX @DEFS@ # Sometimes, the expansion of @LIBINTL@ includes -lc which may # include modules defining variables like `optind', so libfetish.a # must precede @LIBINTL@ in order to ensure we use GNU getopt. # But libfetish.a must also follow @LIBINTL@, since libintl uses # replacement functions defined in libfetish.a. -LDADD = ../lib/libfetish.a @LIBINTL@ ../lib/libfetish.a +LDADD = ../lib/libfetish.a @LIBINTL@ ../lib/libfetish.a /usr/lib/libsecure.a dir_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@ ls_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@ diff -Nur coreutils-5.0/src/Makefile.am.orig coreutils-5.0.new/src/Makefile.am.orig --- coreutils-5.0/src/Makefile.am.orig 2003-06-06 02:58:53.000000000 +0200 +++ coreutils-5.0.new/src/Makefile.am.orig 1970-01-01 01:00:00.000000000 +0100 @@ -1,242 +0,0 @@ -## Process this file with automake to produce Makefile.in -*-Makefile-*- - -EXTRA_PROGRAMS = chroot df hostid nice pinky stty su uname uptime users who -EXTRA_SCRIPTS = nohup - -bin_SCRIPTS = groups @OPTIONAL_BIN_ZCRIPTS@ -bin_PROGRAMS = chgrp chown chmod cp dd dircolors du \ - ginstall link ln dir vdir ls mkdir \ - mkfifo mknod mv readlink rm rmdir shred stat sync touch unlink \ - cat cksum comm csplit cut expand fmt fold head join md5sum \ - nl od paste pr ptx sha1sum sort split sum tac tail tr tsort unexpand uniq wc \ - basename date dirname echo env expr factor false \ - hostname id kill logname pathchk printenv printf pwd seq sleep tee \ - test true tty whoami yes \ - @OPTIONAL_BIN_PROGS@ @DF_PROG@ - -localedir = $(datadir)/locale - -noinst_HEADERS = \ - system.h sys2.h checksum.h copy.h cp-hash.h ls.h dircolors.h remove.h \ - chown-core.h fs.h \ - wheel.h wheel-size.h -EXTRA_DIST = dcgen dircolors.hin tac-pipe.c \ - groups.sh nohup.sh wheel-gen.pl -CLEANFILES = $(SCRIPTS) su - -INCLUDES = -I.. -I$(srcdir) -I$(top_srcdir)/lib -I../lib -DEFS = -DLOCALEDIR=\"$(localedir)\" -DSHAREDIR=\"$(datadir)\" @DEFS@ - -# Sometimes, the expansion of @LIBINTL@ includes -lc which may -# include modules defining variables like `optind', so libfetish.a -# must precede @LIBINTL@ in order to ensure we use GNU getopt. -# But libfetish.a must also follow @LIBINTL@, since libintl uses -# replacement functions defined in libfetish.a. -LDADD = ../lib/libfetish.a @LIBINTL@ ../lib/libfetish.a - -dir_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@ -ls_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@ -shred_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@ -vdir_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@ - -## If necessary, add -lm to resolve use of pow in lib/strtod.c. -sort_LDADD = $(LDADD) @POW_LIB@ - -# for clock_gettime -date_LDADD = $(LDADD) @LIB_CLOCK_GETTIME@ - -# For sqrt -factor_LDADD = $(LDADD) @SQRT_LIBM@ - -# If necessary, add -lm to resolve use of pow in lib/strtod.c. -# If necessary, add -liconv to resolve use of iconv in lib/unicodeio.c. -printf_LDADD = $(LDADD) @POW_LIB@ @LIBICONV@ - -# If necessary, add -lm to resolve use of floor, rint, modf. -seq_LDADD = $(LDADD) @SEQ_LIBM@ - -# If necessary, add -lm to resolve the `pow' reference in lib/strtod.c -# or for the fesetround reference in programs using nanosec.c. -nanosec_libs = \ - $(LDADD) @FESETROUND_LIBM@ @POW_LIB@ @LIB_CLOCK_GETTIME@ @LIB_NANOSLEEP@ - -sleep_LDADD = $(nanosec_libs) -tail_LDADD = $(nanosec_libs) - -uptime_LDADD = $(LDADD) @GETLOADAVG_LIBS@ - -su_LDADD = $(LDADD) @LIB_CRYPT@ @LIB_PAM@ - -$(PROGRAMS): ../lib/libfetish.a - -$(SCRIPTS): Makefile - -SUFFIXES = .sh - -.sh: - rm -f $@ $@-t - sed \ - -e 's!@''bindir''@!$(bindir)!' \ - -e 's/@''GNU_PACKAGE''@/@GNU_PACKAGE@/' \ - -e 's/@''PACKAGE_BUGREPORT''@/@PACKAGE_BUGREPORT@/' \ - -e 's/@''VERSION''@/@VERSION@/' $< > $@-t - chmod +x $@-t - mv $@-t $@ - -all-local: su$(EXEEXT) - -installed_su = $(DESTDIR)$(bindir)/`echo su|sed '$(transform)'` - -setuid_root_mode = a=rx,u+s - -INSTALL_SU = \ - p=su; \ - echo " $(INSTALL_PROGRAM) $$p $(installed_su)"; \ - $(INSTALL_PROGRAM) $$p $(installed_su); \ - echo " chown root $(installed_su)"; \ - chown root $(installed_su); \ - echo " chmod $(setuid_root_mode) $(installed_su)"; \ - chmod $(setuid_root_mode) $(installed_su) - -install-root: su$(EXEEXT) - @$(INSTALL_SU) - -install-exec-local: su$(EXEEXT) - @TMPFILE=$(DESTDIR)$(bindir)/.su-$$$$; \ - rm -f $$TMPFILE; \ - echo > $$TMPFILE; \ -## See if we can create a setuid root executable in $(bindir). -## If not, then don't even try to install su. - can_create_suid_root_executable=no; \ - chown root $$TMPFILE > /dev/null 2>&1 \ - && chmod $(setuid_root_mode) $$TMPFILE > /dev/null 2>&1 \ - && can_create_suid_root_executable=yes; \ - rm -f $$TMPFILE; \ - if test $$can_create_suid_root_executable = yes; then \ - $(INSTALL_SU); \ - else \ - echo "WARNING: insufficient access; not installing su"; \ - echo "NOTE: to install su, run 'make install-root' as root"; \ - fi - -uninstall-local: -# Remove su only if it's one we installed. - @if grep '@GNU_PACKAGE@' $(installed_su) > /dev/null 2>&1; then \ - echo " rm -f $(installed_su)"; \ - rm -f $(installed_su); \ - else :; fi - -# Use `ginstall' in the definition of PROGRAMS and in dependencies to avoid -# confusion with the `install' target. The install rule transforms `ginstall' -# to install before applying any user-specified name transformations. - -transform = s/ginstall/install/; @program_transform_name@ -ginstall_SOURCES = install.c copy.c cp-hash.c - -cp_SOURCES = cp.c copy.c cp-hash.c -dir_SOURCES = ls.c ls-dir.c -vdir_SOURCES = ls.c ls-vdir.c -ls_SOURCES = ls.c ls-ls.c -chown_SOURCES = chown.c chown-core.c -chgrp_SOURCES = chgrp.c chown-core.c - -mv_SOURCES = mv.c copy.c cp-hash.c remove.c -rm_SOURCES = rm.c remove.c - -md5sum_SOURCES = md5sum.c md5.c -sha1sum_SOURCES = md5sum.c sha1sum.c - -PERL = @PERL@ -editpl = sed -e 's,@''PERL''@,$(PERL),g' - -MAINTAINERCLEANFILES = dircolors.h \ - wheel.h wheel-size.h - -dircolors.h: dcgen dircolors.hin - $(PERL) -w -- $(srcdir)/dcgen $(srcdir)/dircolors.hin > $@-t - mv $@-t $@ - -wheel_size = 5 - -wheel-size.h: Makefile.am - echo '#define WHEEL_SIZE $(wheel_size)' > $@-t - mv $@-t $@ - -wheel.h: wheel-gen.pl Makefile.am - $(srcdir)/wheel-gen.pl $(wheel_size) \ - > $@-t - mv $@-t $@ - -BUILT_SOURCES = dircolors.h false.c wheel.h wheel-size.h - -# false exits nonzero even with --help or --version. -# Tell automake to exempt it from that installcheck test. -AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = false - -false.c: true.c - rm -f $@ - sed \ - -e s/true/false/g \ - -e s/success/failure/g \ - -e 's/(EXIT_SUCCESS)/(EXIT_FAILURE)/g' \ - $(srcdir)/true.c > $@-t - chmod a-w $@-t - mv $@-t $@ - -all_programs = \ - $(bin_PROGRAMS) \ - $(bin_SCRIPTS) \ - $(EXTRA_PROGRAMS) \ - $(EXTRA_SCRIPTS) - -pm = progs-makefile -pr = progs-readme -# Ensure that the list of programs in README matches the list -# of programs we can build. -check: check-README check-misc -.PHONY: check-README -check-README: - rm -rf $(pr) $(pm) - echo $(all_programs) \ - | tr -s ' ' '\n' | sort -u > $(pm) - sed -n '/^The programs .* are:/,/^[a-zA-Z]/p' $(top_srcdir)/README \ - | sed -n '/^ */s///p' | tr -s ' ' '\n' > $(pr) - diff $(pm) $(pr) && rm -rf $(pr) $(pm) - -# Make sure we don't define any S_IS* macros in src/*.c files. -# Not a big deal, but they're already defined via system.h. -# -# Also make sure we don't use st_blocks. Use ST_NBLOCKS instead. -# This is a bit of a kludge, since it prevents use of the string -# even in comments, but for now it does the job with no false positives. -.PHONY: check-misc -check-misc: - cd $(srcdir); grep '^# *define *S_IS' $(SOURCES) && exit 1 || : - cd $(srcdir); grep st_blocks $(SOURCES) && exit 1 || : - cd $(srcdir); grep '^# *define .*defined' $(SOURCES) && exit 1 || : - -# Extract the list of authors from each file. -sed_filter = s/^ *//;s/N_ (//;s/^"//;s/")*$$// -# Sometimes the string is on the same line as the #define... -s1 = '/^\#define AUTHORS \([^\\]\)/{;s//\1/;$(sed_filter);p;q;}' -# Sometimes the string is on the backslash-continued line after the #define. -s2 = '/^\#define AUTHORS \\\\/{;n;$(sed_filter);p;q;}' -# FIXME: handle *.sh; and use $(all_programs), not $(SOURCES) -../AUTHORS: $(SOURCES) - rm -f $@-t - ( \ - set -e; \ - echo "Here are the names of the programs in this package,"; \ - echo "each followed by the name(s) of its author(s)."; \ - echo; \ - for i in $(SOURCES); do \ - a=`sed -n $(s1) $$i`; \ - test "$$a" && : \ - || a=`sed -n $(s2) $$i`; \ - if test "$$a"; then \ - prog=`echo $$i|sed 's/\.c$$//'`; \ - echo "$$prog: $$a"; \ - fi; \ - done | sort -u ) > $@-t - chmod a-w $@-t - mv $@-t $@ diff -Nur coreutils-5.0/src/mkdir.c coreutils-5.0.new/src/mkdir.c --- coreutils-5.0/src/mkdir.c 2002-09-23 09:35:27.000000000 +0200 +++ coreutils-5.0.new/src/mkdir.c 2003-06-06 03:01:12.000000000 +0200 @@ -34,6 +34,15 @@ #define AUTHORS "David MacKenzie" +#ifdef FLASK_LINUX +#include +#include /* for is_flask_enabled() */ +#define CTXTLEN 256 +char *scontext = NULL; +int ctxtlen = CTXTLEN; +char *calloc(); +#endif + /* The name this program was run with. */ char *program_name; @@ -42,6 +51,10 @@ static struct option const longopts[] = { +#ifdef FLASK_LINUX + {"sid", required_argument, NULL, 's'}, + {"context", required_argument, NULL, 'c'}, +#endif {"mode", required_argument, NULL, 'm'}, {"parents", no_argument, NULL, 'p'}, {"verbose", no_argument, NULL, 'v'}, @@ -63,6 +76,12 @@ Create the DIRECTORY(ies), if they do not already exist.\n\ \n\ "), stdout); +#ifdef FLASK_LINUX + printf (_("\ + -s, --sid=SID (Flask) set security ID to SID\n\ + -c, --context=CONTEXT (Flask) set security context to CONTEXT\n\ +")); +#endif fputs (_("\ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); @@ -87,6 +106,13 @@ const char *verbose_fmt_string = NULL; int errors = 0; int optc; +#ifdef FLASK_LINUX + security_id_t sid = -1; + char *scontext = NULL; + int rv; + int is_flask_enabled_flag; /* set iff kernel has extra flask system calls */ + is_flask_enabled_flag = is_flask_enabled(); +#endif program_name = argv[0]; setlocale (LC_ALL, ""); @@ -97,7 +123,11 @@ create_parents = 0; +#ifdef FLASK_LINUX + while ((optc = getopt_long (argc, argv, "pm:s:c:v", longopts, NULL)) != -1) +#else while ((optc = getopt_long (argc, argv, "pm:v", longopts, NULL)) != -1) +#endif { switch (optc) { @@ -112,6 +142,66 @@ case 'v': /* --verbose */ verbose_fmt_string = _("created directory %s"); break; +#ifdef FLASK_LINUX + case 's': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Sorry, --sid (-s) can be used only on " + "a flask-enabled kernel.\n" ); + exit( 1 ); + } + if ( ((int) sid > 0) || (scontext != NULL) ) { + (void) fprintf(stderr, "%s: --sid (-s) and --context (-c) are mutually exclusive\n", argv[0]); + exit( 1 ); + } + { + /* check for typos */ + char *ep; + sid = (security_id_t) strtol(optarg, &ep, 10); + if ( *ep ) { + (void) fprintf(stderr, "%s: non-numeric SID '%s'\n", argv[0], optarg); + exit( 1 ); + } + } + /* do sanity check, save result on success */ + scontext = calloc(1, ctxtlen+1); + if ( scontext != NULL ) { + if ( security_sid_to_context(sid, scontext, &ctxtlen) ) { + if ( errno != ENOSPC ) { + (void) fprintf(stderr, "%s: security_sid_to_context(%d): '%s'\n", argv[0], (int) sid, strerror(errno)); + exit( 1 ); + } + free(scontext); + scontext = calloc(1, ctxtlen+1); + /* nonfatal, so if there's an error we punt */ + if ( scontext != NULL ) + if ( security_sid_to_context(sid, scontext, &ctxtlen) ) { + (void) fprintf(stderr, "%s: security_sid_to_context(%d): %s\n", argv[0], (int) sid, strerror(errno)); + exit( 1 ); + } + } + } + break; + case 'c': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Sorry, --context (-c) can be used only on " + "a flask-enabled kernel.\n" ); + exit( 1 ); + } + if ( ((int) sid >= 0) || (scontext != NULL) ) { + (void) fprintf(stderr, "%s: --context (-c) and --sid (-s) are mutually exclusive\n", argv[0]); + exit( 1 ); + } + scontext = optarg; + /* sanity check */ + rv = security_context_to_sid(scontext, strlen(scontext)+1, &sid); + if ( rv ) { + (void) fprintf(stderr, "%s: security_context_to_sid(%s): %s\n", argv[0], scontext, strerror(errno)); + exit( 1 ); + } + break; +#endif case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: @@ -150,14 +240,23 @@ if (create_parents) { char *dir = argv[optind]; +#ifdef FLASK_LINUX + fail = make_path_s (dir, newmode, parent_mode, + -1, -1, 1, verbose_fmt_string, sid); +#else fail = make_path (dir, newmode, parent_mode, -1, -1, 1, verbose_fmt_string); +#endif } else { const char *dir = argv[optind]; int dir_created; +#ifdef FLASK_LINUX + fail = make_dir_s (dir, dir, newmode, &dir_created, sid); +#else fail = make_dir (dir, dir, newmode, &dir_created); +#endif if (fail) { /* make_dir already gave a diagnostic. */ diff -Nur coreutils-5.0/src/mkfifo.c coreutils-5.0.new/src/mkfifo.c --- coreutils-5.0/src/mkfifo.c 2002-08-31 09:29:21.000000000 +0200 +++ coreutils-5.0.new/src/mkfifo.c 2003-06-06 03:01:12.000000000 +0200 @@ -32,11 +32,20 @@ #define AUTHORS "David MacKenzie" +#ifdef FLASK_LINUX +#include +#include /* for is_flask_enabled() */ +#endif + /* The name this program was run with. */ char *program_name; static struct option const longopts[] = { +#ifdef FLASK_LINUX + {"sid", required_argument, NULL, 's'}, + {"context", required_argument, NULL, 'c'}, +#endif {"mode", required_argument, NULL, 'm'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, @@ -57,6 +66,12 @@ Create named pipes (FIFOs) with the given NAMEs.\n\ \n\ "), stdout); +#ifdef FLASK_LINUX + printf (_("\ + -s, --sid=SID set SID\n\ + -c, --context=CONTEXT set security context (quoted string)\n\ +"), stdout); +#endif fputs (_("\ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); @@ -79,6 +94,15 @@ const char *specified_mode; int errors = 0; int optc; +#ifdef FLASK_LINUX + security_id_t sid = -1; + char *scontext = NULL; + int rv; + int is_flask_enabled_flag; /* set iff kernel has extra flask system calls */ + + /* Set `is_flask_enabled_flag' iff the kernel has the extra flask syscalls */ + is_flask_enabled_flag = is_flask_enabled(); +#endif program_name = argv[0]; setlocale (LC_ALL, ""); @@ -92,7 +116,11 @@ #ifndef S_ISFIFO error (4, 0, _("fifo files not supported")); #else +#ifdef FLASK_LINUX + while ((optc = getopt_long (argc, argv, "m:s:c:", longopts, NULL)) != -1) +#else while ((optc = getopt_long (argc, argv, "m:", longopts, NULL)) != -1) +#endif { switch (optc) { diff -Nur coreutils-5.0/src/mknod.c coreutils-5.0.new/src/mknod.c --- coreutils-5.0/src/mknod.c 2002-12-14 15:14:59.000000000 +0100 +++ coreutils-5.0.new/src/mknod.c 2003-06-06 03:01:12.000000000 +0200 @@ -36,8 +36,17 @@ /* The name this program was run with. */ char *program_name; +#ifdef FLASK_LINUX +#include +#include /* for is_flask_enabled() */ +#endif + static struct option const longopts[] = { +#ifdef FLASK_LINUX + {"sid", required_argument, NULL, 's'}, + {"context", required_argument, NULL, 'c'}, +#endif {"mode", required_argument, NULL, 'm'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, @@ -58,6 +67,12 @@ Create the special file NAME of the given TYPE.\n\ \n\ "), stdout); +#ifdef FLASK_LINUX + fputs(_("\ + -s, --sid=SID set SID\n\ + -c, --context=CONTEXT set security context (quoted string)\n\ +"), stdout); +#endif fputs (_("\ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); @@ -92,6 +107,15 @@ const char *specified_mode; int optc; mode_t node_type; +#ifdef FLASK_LINUX + security_id_t sid = -1; + char *scontext = NULL; + int rv; + int is_flask_enabled_flag; /* set iff kernel has extra flask system calls */ + + /* Set `is_flask_enabled_flag' iff the kernel has the extra flask syscalls */ + is_flask_enabled_flag = is_flask_enabled(); +#endif program_name = argv[0]; setlocale (LC_ALL, ""); @@ -102,7 +126,11 @@ specified_mode = NULL; +#ifdef FLASK_LINUX + while ((optc = getopt_long (argc, argv, "m:s:c:", longopts, NULL)) != -1) +#else while ((optc = getopt_long (argc, argv, "m:", longopts, NULL)) != -1) +#endif { switch (optc) { @@ -111,6 +139,46 @@ case 'm': specified_mode = optarg; break; +#ifdef FLASK_LINUX + case 's': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Sorry, --sid (-s) can be used only on " + "a flask-enabled kernel.\n" ); + exit( 1 ); + } + if ( scontext != NULL ) { + (void) printf("%s: --sid (-s) and --context (-c) are mutually exclusive\n", argv[0]); + (void) fflush(stdout); + close_stdout(); + exit(1); + } + sid = atoi(optarg); + break; + case 'c': + /* politely decline if we're not on a flask-enabled kernel. */ + if( !is_flask_enabled_flag ) { + fprintf( stderr, "Sorry, --context (-c) can be used only on " + "a flask-enabled kernel.\n" ); + exit( 1 ); + } + if ( (int) sid >= 0 ) { + (void) printf("%s: --context (-c) and --sid (-s) are mutually exclusive\n", argv[0]); + (void) fflush(stdout); + close_stdout(); + exit(1); + } + scontext = optarg; + rv = security_context_to_sid(scontext, strlen(scontext)+1, &sid); + if ( rv ) { + (void) printf("%s: security_context_to_sid(%s): %s\n", argv[0], scontext, + strerror(errno)); + (void) fflush(stdout); + close_stdout(); + exit(1); + } + break; +#endif case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: @@ -196,6 +264,18 @@ error (EXIT_FAILURE, 0, _("invalid device %s %s"), s_major, s_minor); #endif +#ifdef FLASK_LINUX + /* `sid' will be > 0 iff the --sid (-s) option was specified on the * + * command line. The --sid argument processing code exits politely * + * if the kernel doesn't support the new flask system calls. So, * + * if sid > 0 at this point, we know we're on a flask-enabled kernel * + * and can call the "_secure" version of mknod. */ + if ( (int) sid > 0 ) { + if ( mknod_secure (argv[optind], newmode | S_IFBLK, makedev (i_major, i_minor), sid) ) + error (1, errno, "mknod_secure(%s)", argv[optind]); + } + else +#endif if (mknod (argv[optind], newmode | node_type, device) != 0) error (EXIT_FAILURE, errno, "%s", quote (argv[optind])); } @@ -211,6 +291,18 @@ major and minor device numbers may not be specified for fifo files")); usage (EXIT_FAILURE); } +#ifdef FLASK_LINUX + /* `sid' will be > 0 iff the --sid (-s) option was specified on the * + * command line. The --sid argument processing code exits politely * + * if the kernel doesn't support the new flask system calls. So, * + * if sid > 0 at this point, we know we're on a flask-enabled kernel * + * and can call the "_secure" version of mknod. */ + if( (int) sid > 0 ) + { + if ( mkfifo_secure (argv[optind], newmode, sid) ) + error (1, errno, "%s", quote (argv[optind])); + } else +#endif if (mkfifo (argv[optind], newmode)) error (EXIT_FAILURE, errno, "%s", quote (argv[optind])); #endif diff -Nur coreutils-5.0/src/mv.c coreutils-5.0.new/src/mv.c --- coreutils-5.0/src/mv.c 2003-06-06 02:58:57.000000000 +0200 +++ coreutils-5.0.new/src/mv.c 2003-06-06 03:01:12.000000000 +0200 @@ -37,6 +37,10 @@ #include "path-concat.h" #include "quote.h" #include "remove.h" +#ifdef FLASK_LINUX +#include +#include /* for is_flask_enabled() */ +#endif /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "mv" @@ -139,7 +143,12 @@ x->update = 0; x->verbose = 0; +#ifdef FLASK_LINUX + x->preserve_security_context = 0; + x->xstat = lstat_secure; +#else x->xstat = lstat; +#endif x->dest_info = NULL; x->src_info = NULL; } @@ -324,6 +333,10 @@ equivalent to --reply=query\n\ "), stdout); fputs (_("\ + -c preserve security context when source and\n\ + destination are on different file systems\n\ +"), stdout); + fputs (_("\ --reply={yes,no,query} specify how to handle the prompt about an\n\ existing destination file\n\ --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\ @@ -371,6 +384,9 @@ int target_directory_specified; unsigned int n_files; char **file; +#ifdef FLASK_LINUX + int is_flask_enabled_flag = is_flask_enabled(); +#endif; program_name = argv[0]; setlocale (LC_ALL, ""); @@ -387,7 +403,11 @@ errors = 0; +#ifdef FLASK_LINUX + while ((c = getopt_long (argc, argv, "bcfiuvS:V:", long_options, NULL)) != -1) +#else while ((c = getopt_long (argc, argv, "bfiuvS:V:", long_options, NULL)) != -1) +#endif { switch (c) { @@ -406,6 +426,12 @@ if (optarg) version_control_string = optarg; break; +#ifdef FLASK_LINUX + case 'c': + if (is_flask_enabled_flag) + x.preserve_security_context = 1; + break; +#endif case 'f': x.interactive = I_ALWAYS_YES; break; diff -Nur coreutils-5.0/src/mv.c.orig coreutils-5.0.new/src/mv.c.orig --- coreutils-5.0/src/mv.c.orig 1970-01-01 01:00:00.000000000 +0100 +++ coreutils-5.0.new/src/mv.c.orig 2003-06-06 03:00:43.000000000 +0200 @@ -0,0 +1,499 @@ +/* mv -- move or rename files + Copyright (C) 86, 89, 90, 91, 1995-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Mike Parker, David MacKenzie, and Jim Meyering */ + +#ifdef _AIX + #pragma alloca +#endif + +#include +#include +#include +#include +#include + +#include "system.h" +#include "argmatch.h" +#include "backupfile.h" +#include "copy.h" +#include "cp-hash.h" +#include "dirname.h" +#include "error.h" +#include "path-concat.h" +#include "quote.h" +#include "remove.h" + +/* The official name of this program (e.g., no `g' prefix). */ +#define PROGRAM_NAME "mv" + +#define AUTHORS N_ ("Mike Parker, David MacKenzie, and Jim Meyering") + +/* Initial number of entries in each hash table entry's table of inodes. */ +#define INITIAL_HASH_MODULE 100 + +/* Initial number of entries in the inode hash table. */ +#define INITIAL_ENTRY_TAB_SIZE 70 + +/* For long options that have no equivalent short option, use a + non-character as a pseudo short option, starting with CHAR_MAX + 1. */ +enum +{ + TARGET_DIRECTORY_OPTION = CHAR_MAX + 1, + STRIP_TRAILING_SLASHES_OPTION, + REPLY_OPTION +}; + +int isdir (); +int lstat (); + +/* The name this program was run with. */ +char *program_name; + +/* Remove any trailing slashes from each SOURCE argument. */ +static int remove_trailing_slashes; + +/* Valid arguments to the `--reply' option. */ +static char const* const reply_args[] = +{ + "yes", "no", "query", 0 +}; + +/* The values that correspond to the above strings. */ +static int const reply_vals[] = +{ + I_ALWAYS_YES, I_ALWAYS_NO, I_ASK_USER +}; + +static struct option const long_options[] = +{ + {"backup", optional_argument, NULL, 'b'}, + {"force", no_argument, NULL, 'f'}, + {"interactive", no_argument, NULL, 'i'}, + {"reply", required_argument, NULL, REPLY_OPTION}, + {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION}, + {"suffix", required_argument, NULL, 'S'}, + {"target-directory", required_argument, NULL, TARGET_DIRECTORY_OPTION}, + {"update", no_argument, NULL, 'u'}, + {"verbose", no_argument, NULL, 'v'}, + {"version-control", required_argument, NULL, 'V'}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, + {NULL, 0, NULL, 0} +}; + +static void +rm_option_init (struct rm_options *x) +{ + x->unlink_dirs = 0; + + x->ignore_missing_files = 0; + + x->recursive = 1; + + /* Should we prompt for removal, too? No. Prompting for the `move' + part is enough. It implies removal. */ + x->interactive = 0; + x->stdin_tty = 0; + + x->verbose = 0; +} + +static void +cp_option_init (struct cp_options *x) +{ + x->copy_as_regular = 0; /* FIXME: maybe make this an option */ + x->dereference = DEREF_NEVER; + x->unlink_dest_before_opening = 0; + x->unlink_dest_after_failed_open = 0; + x->hard_link = 0; + x->interactive = I_UNSPECIFIED; + x->move_mode = 1; + x->myeuid = geteuid (); + x->one_file_system = 0; + x->preserve_ownership = 1; + x->preserve_links = 1; + x->preserve_mode = 1; + x->preserve_timestamps = 1; + x->require_preserve = 0; /* FIXME: maybe make this an option */ + x->recursive = 1; + x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */ + x->symbolic_link = 0; + x->set_mode = 0; + x->mode = 0; + x->stdin_tty = isatty (STDIN_FILENO); + + x->update = 0; + x->verbose = 0; + x->xstat = lstat; + x->dest_info = NULL; + x->src_info = NULL; +} + +/* If PATH is an existing directory, return nonzero, else 0. */ + +static int +is_real_dir (const char *path) +{ + struct stat stats; + + return lstat (path, &stats) == 0 && S_ISDIR (stats.st_mode); +} + +/* Move SOURCE onto DEST. Handles cross-filesystem moves. + If SOURCE is a directory, DEST must not exist. + Return 0 if successful, non-zero if an error occurred. */ + +static int +do_move (const char *source, const char *dest, const struct cp_options *x) +{ + static int first = 1; + int copy_into_self; + int rename_succeeded; + int fail; + + if (first) + { + first = 0; + + /* Allocate space for remembering copied and created files. */ + hash_init (); + } + + fail = copy (source, dest, 0, x, ©_into_self, &rename_succeeded); + + if (!fail) + { + char const *dir_to_remove; + if (copy_into_self) + { + /* In general, when copy returns with copy_into_self set, SOURCE is + the same as, or a parent of DEST. In this case we know it's a + parent. It doesn't make sense to move a directory into itself, and + besides in some situations doing so would give highly nonintuitive + results. Run this `mkdir b; touch a c; mv * b' in an empty + directory. Here's the result of running echo `find b -print`: + b b/a b/b b/b/a b/c. Notice that only file `a' was copied + into b/b. Handle this by giving a diagnostic, removing the + copied-into-self directory, DEST (`b/b' in the example), + and failing. */ + + dir_to_remove = NULL; + fail = 1; + } + else if (rename_succeeded) + { + /* No need to remove anything. SOURCE was successfully + renamed to DEST. Or the user declined to rename a file. */ + dir_to_remove = NULL; + } + else + { + /* This may mean SOURCE and DEST referred to different devices. + It may also conceivably mean that even though they referred + to the same device, rename wasn't implemented for that device. + + E.g., (from Joel N. Weber), + [...] there might someday be cases where you can't rename + but you can copy where the device name is the same, especially + on Hurd. Consider an ftpfs with a primitive ftp server that + supports uploading, downloading and deleting, but not renaming. + + Also, note that comparing device numbers is not a reliable + check for `can-rename'. Some systems can be set up so that + files from many different physical devices all have the same + st_dev field. This is a feature of some NFS mounting + configurations. + + We reach this point if SOURCE has been successfully copied + to DEST. Now we have to remove SOURCE. + + This function used to resort to copying only when rename + failed and set errno to EXDEV. */ + + dir_to_remove = source; + } + + if (dir_to_remove != NULL) + { + struct rm_options rm_options; + enum RM_status status; + + rm_option_init (&rm_options); + rm_options.verbose = x->verbose; + + status = rm (1, &dir_to_remove, &rm_options); + assert (VALID_STATUS (status)); + if (status == RM_ERROR) + fail = 1; + } + } + + return fail; +} + +/* Move file SOURCE onto DEST. Handles the case when DEST is a directory. + DEST_IS_DIR must be nonzero when DEST is a directory or a symlink to a + directory and zero otherwise. + Return 0 if successful, non-zero if an error occurred. */ + +static int +movefile (char *source, char *dest, int dest_is_dir, + const struct cp_options *x) +{ + int dest_had_trailing_slash = strip_trailing_slashes (dest); + int fail; + + /* This code was introduced to handle the ambiguity in the semantics + of mv that is induced by the varying semantics of the rename function. + Some systems (e.g., Linux) have a rename function that honors a + trailing slash, while others (like Solaris 5,6,7) have a rename + function that ignores a trailing slash. I believe the Linux + rename semantics are POSIX and susv2 compliant. */ + + if (remove_trailing_slashes) + strip_trailing_slashes (source); + + /* In addition to when DEST is a directory, if DEST has a trailing + slash and neither SOURCE nor DEST is a directory, presume the target + is DEST/`basename source`. This converts `mv x y/' to `mv x y/x'. + This change means that the command `mv any file/' will now fail + rather than performing the move. The case when SOURCE is a + directory and DEST is not is properly diagnosed by do_move. */ + + if (dest_is_dir || (dest_had_trailing_slash && !is_real_dir (source))) + { + /* DEST is a directory; build full target filename. */ + char const *src_basename = base_name (source); + char *new_dest = path_concat (dest, src_basename, NULL); + if (new_dest == NULL) + xalloc_die (); + strip_trailing_slashes (new_dest); + fail = do_move (source, new_dest, x); + free (new_dest); + } + else + { + fail = do_move (source, dest, x); + } + + return fail; +} + +void +usage (int status) +{ + if (status != 0) + fprintf (stderr, _("Try `%s --help' for more information.\n"), + program_name); + else + { + printf (_("\ +Usage: %s [OPTION]... SOURCE DEST\n\ + or: %s [OPTION]... SOURCE... DIRECTORY\n\ + or: %s [OPTION]... --target-directory=DIRECTORY SOURCE...\n\ +"), + program_name, program_name, program_name); + fputs (_("\ +Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\ +\n\ +"), stdout); + fputs (_("\ +Mandatory arguments to long options are mandatory for short options too.\n\ +"), stdout); + fputs (_("\ + --backup[=CONTROL] make a backup of each existing destination file\n\ + -b like --backup but does not accept an argument\n\ + -f, --force do not prompt before overwriting\n\ + equivalent to --reply=yes\n\ + -i, --interactive prompt before overwrite\n\ + equivalent to --reply=query\n\ +"), stdout); + fputs (_("\ + --reply={yes,no,query} specify how to handle the prompt about an\n\ + existing destination file\n\ + --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\ + argument\n\ + -S, --suffix=SUFFIX override the usual backup suffix\n\ +"), stdout); + fputs (_("\ + --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY\n\ + -u, --update move only when the SOURCE file is newer\n\ + than the destination file or when the\n\ + destination file is missing\n\ + -v, --verbose explain what is being done\n\ +"), stdout); + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); + fputs (_("\ +\n\ +The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\ +The version control method may be selected via the --backup option or through\n\ +the VERSION_CONTROL environment variable. Here are the values:\n\ +\n\ +"), stdout); + fputs (_("\ + none, off never make backups (even if --backup is given)\n\ + numbered, t make numbered backups\n\ + existing, nil numbered if numbered backups exist, simple otherwise\n\ + simple, never always make simple backups\n\ +"), stdout); + printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); + } + exit (status); +} + +int +main (int argc, char **argv) +{ + int c; + int errors; + int make_backups = 0; + int dest_is_dir; + char *backup_suffix_string; + char *version_control_string = NULL; + struct cp_options x; + char *target_directory = NULL; + int target_directory_specified; + unsigned int n_files; + char **file; + + program_name = argv[0]; + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + atexit (close_stdout); + + cp_option_init (&x); + + /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless + we'll actually use backup_suffix_string. */ + backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); + + errors = 0; + + while ((c = getopt_long (argc, argv, "bfiuvS:V:", long_options, NULL)) != -1) + { + switch (c) + { + case 0: + break; + + case 'V': /* FIXME: this is deprecated. Remove it in 2001. */ + error (0, 0, + _("warning: --version-control (-V) is obsolete; support for\ + it\nwill be removed in some future release. Use --backup=%s instead." + ), optarg); + /* Fall through. */ + + case 'b': + make_backups = 1; + if (optarg) + version_control_string = optarg; + break; + case 'f': + x.interactive = I_ALWAYS_YES; + break; + case 'i': + x.interactive = I_ASK_USER; + break; + case REPLY_OPTION: + x.interactive = XARGMATCH ("--reply", optarg, + reply_args, reply_vals); + break; + case STRIP_TRAILING_SLASHES_OPTION: + remove_trailing_slashes = 1; + break; + case TARGET_DIRECTORY_OPTION: + target_directory = optarg; + break; + case 'u': + x.update = 1; + break; + case 'v': + x.verbose = 1; + break; + case 'S': + make_backups = 1; + backup_suffix_string = optarg; + break; + case_GETOPT_HELP_CHAR; + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + default: + usage (EXIT_FAILURE); + } + } + + n_files = argc - optind; + file = argv + optind; + + target_directory_specified = (target_directory != NULL); + if (target_directory == NULL && n_files != 0) + target_directory = file[n_files - 1]; + + dest_is_dir = (n_files > 0 && isdir (target_directory)); + + if (n_files == 0 || (n_files == 1 && !target_directory_specified)) + { + error (0, 0, _("missing file argument")); + usage (EXIT_FAILURE); + } + + if (target_directory_specified) + { + if (!dest_is_dir) + { + error (0, 0, _("specified target, %s is not a directory"), + quote (target_directory)); + usage (EXIT_FAILURE); + } + } + else if (n_files > 2 && !dest_is_dir) + { + error (0, 0, + _("when moving multiple files, last argument must be a directory")); + usage (EXIT_FAILURE); + } + + if (backup_suffix_string) + simple_backup_suffix = xstrdup (backup_suffix_string); + + x.backup_type = (make_backups + ? xget_version (_("backup type"), + version_control_string) + : none); + + /* Move each arg but the last into the target_directory. */ + { + unsigned int last_file_idx = (target_directory_specified + ? n_files - 1 + : n_files - 2); + unsigned int i; + + /* Initialize the hash table only if we'll need it. + The problem it is used to detect can arise only if there are + two or more files to move. */ + if (last_file_idx) + dest_info_init (&x); + + for (i = 0; i <= last_file_idx; ++i) + errors |= movefile (file[i], target_directory, dest_is_dir, &x); + } + + exit (errors); +} diff -Nur coreutils-5.0/src/runas.c coreutils-5.0.new/src/runas.c --- coreutils-5.0/src/runas.c 1970-01-01 01:00:00.000000000 +0100 +++ coreutils-5.0.new/src/runas.c 2003-06-06 03:01:12.000000000 +0200 @@ -0,0 +1,215 @@ +/* + * runas [ context | [ -s sid ] | + * ( [ -r role ] [-t type] [ -u user ] [ -l levelrange ] ) + * command [arg1 [arg2 ...] ] + * + * attempt to run the specified command with the specified context. + * + * -s sid : use the context corresponding to the specified sid + * -r role : use the current context with the specified role + * -t type : use the current context with the specified type + * -u user : use the current context with the specified user + * -l level : use the current context with the specified level range + * + * Contexts are interpreted as follows: + * + * Number of MLS + * components system? + * + * 1 - type + * 2 - role:type + * 3 Y role:type:range + * 3 N user:role:type + * 4 Y user:role:type:range + * 4 N error + */ + +#include +#include +#include +#include +#include +#include +extern int errno; + +char *role = 0; +char *range = 0; +char *user = 0; +char *type = 0; +char *context = 0; + +/* The name the program was run with. */ +char *program_name; + +void +usage(char *str) +{ + printf("Usage: %s [OPTION]... command [args]\n" + "Run a program in a different security context.\n\n" + " context Complete security context\n" + " -s sid Security ID number\n" + " -t type (for same role as parent)\n" + " -u user identity\n" + " -r role\n" + " -l levelrange\n" + " --help display this help and exit\n", + program_name); + exit(1); +} + +int +main(int argc,char **argv,char **envp ) +{ + context_t con; + security_id_t sid = 0; /* 0 is not a vaild sid */ + + program_name = argv[0]; + + while (1) { + int c; + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + { "sid", 1, 0, 's' }, + { "role", 1, 0, 'r' }, + { "type", 1, 0, 't' }, + { "user", 1, 0, 'u' }, + { "range", 1, 0, 'l' }, + { "help", 0, 0, '?' }, + { 0, 0, 0, 0 } + }; + c = getopt_long(argc, argv, "s:r:t:u:l:?", long_options, &option_index); + if ( c == -1 ) { + break; + } + switch ( c ) { + case 's': + if ( !( sid == 0 ) ) { + fprintf(stderr,"multiple sids\n"); + exit(1); + } + sid = (int)strtoul( optarg, (char **)NULL, 10); + + /* Check for an invalid sid. */ + if( ( errno == ERANGE ) || ( sid == 0 ) ) { + fprintf( stderr, "invalid sid\n" ); + exit( 1 ); + } + break; + case 'r': + if ( role ) { + fprintf(stderr,"multiple roles\n"); + exit(1); + } + role = optarg; + break; + case 't': + if ( type ) { + fprintf(stderr,"multiple types\n"); + exit(1); + } + type = optarg; + break; + case 'u': + if ( user ) { + fprintf(stderr,"multiple users\n"); + exit(1); + } + user = optarg; + break; + case 'l': + if ( range ) { + fprintf(stderr,"multiple levelranges\n"); + exit(1); + } + range = optarg; + break; + default: + fprintf(stderr,"unrecognised option %c\n",c); + case '?': + usage(0); + break; + } + } + if ( ( !(user || role || type || range) ) && + ( sid == 0 ) ) { + if ( optind >= argc ) { + usage("must specify -t, -u, -l, -r, -s or context"); + } + context = argv[optind++]; + } + + if ( context ) { + con = context_new(context); + if (!con) { + fprintf(stderr,"%s is not a valid context\n", context); + exit(1); + } + } else if( sid == 0 ) { /* sid != 0 means sid already set by --sid */ + security_id_t mysid; + char buff[1024]; + int len = sizeof(buff); + mysid = getsecsid(); + if ( security_sid_to_context(mysid, + buff, + &len ) ) { + perror("security_sid_to_context"); + exit(1); + } + con = context_new(buff); + if (!con) { + fprintf(stderr,"%s is not a valid context\n", buff); + exit(1); + } + if ( user ) { + context_user_set(con,user); + } + if ( type ) { + context_type_set(con,type); + } + if ( range ) { + context_range_set(con,range); + } + if ( role ) { + context_role_set(con,role); + } + } + if ( optind >= argc ) { + usage("no command found"); + } + +#ifdef DEBUG_BROKEN_NEED_TO_HANDLE_SID_CASE + fprintf(stderr,"Context to use is \"%s\"\n",context_str(con)); + fprintf(stderr,"Command is \""); + { + int tmpoptind = optind; + while ( tmpoptind < argc ) { + fprintf(stderr,"%s",argv[tmpoptind++]); + if ( tmpoptind < argc ) { + printf(" "); + } + } + fprintf(stderr,"\"\n"); + } +#endif + + if( sid == 0 ) { /* sid != 0 means sid already set by --sid */ + if ( security_context_to_sid(context_str(con), + strlen(context_str(con))+1,&sid) ) { + perror("security_context_to_sid"); + exit(1); + } + } + +#ifdef DEBUG + fprintf(stderr,"sid = %d\n",sid); +#endif +#ifdef NOT_NOW + if ( execve_secure(argv[optind],argv+optind,envp,sid) ) { +#endif + if ( execvp_secure(argv[optind],sid,argv+optind) ) { + perror("execvp_secure"); + exit(1); + } + return 1; /* can't reach this statement.... */ +} diff -Nur coreutils-5.0/src/su.c.orig coreutils-5.0.new/src/su.c.orig --- coreutils-5.0/src/su.c.orig 2002-08-31 09:28:18.000000000 +0200 +++ coreutils-5.0.new/src/su.c.orig 1970-01-01 01:00:00.000000000 +0100 @@ -1,583 +0,0 @@ -/* su for GNU. Run a shell with substitute user and group IDs. - Copyright (C) 1992-2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Run a shell with the real and effective UID and GID and groups - of USER, default `root'. - - The shell run is taken from USER's password entry, /bin/sh if - none is specified there. If the account has a password, su - prompts for a password unless run by a user with real UID 0. - - Does not change the current directory. - Sets `HOME' and `SHELL' from the password entry for USER, and if - USER is not root, sets `USER' and `LOGNAME' to USER. - The subshell is not a login shell. - - If one or more ARGs are given, they are passed as additional - arguments to the subshell. - - Does not handle /bin/sh or other shells specially - (setting argv[0] to "-su", passing -c only to certain shells, etc.). - I don't see the point in doing that, and it's ugly. - - This program intentionally does not support a "wheel group" that - restricts who can su to UID 0 accounts. RMS considers that to - be fascist. - - Options: - -, -l, --login Make the subshell a login shell. - Unset all environment variables except - TERM, HOME and SHELL (set as above), and USER - and LOGNAME (set unconditionally as above), and - set PATH to a default value. - Change to USER's home directory. - Prepend "-" to the shell's name. - -c, --commmand=COMMAND - Pass COMMAND to the subshell with a -c option - instead of starting an interactive shell. - -f, --fast Pass the -f option to the subshell. - -m, -p, --preserve-environment - Do not change HOME, USER, LOGNAME, SHELL. - Run $SHELL instead of USER's shell from /etc/passwd - unless not the superuser and USER's shell is - restricted. - Overridden by --login and --shell. - -s, --shell=shell Run SHELL instead of USER's shell from /etc/passwd - unless not the superuser and USER's shell is - restricted. - - Compile-time options: - -DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog. - -DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog. - - -DSYSLOG_NON_ROOT Log all su's, not just those to root (UID 0). - Never logs attempted su's to nonexistent accounts. - - Written by David MacKenzie . */ - -#include -#include -#include -#include -#include -#include - -/* Hide any system prototype for getusershell. - This is necessary because some Cray systems have a conflicting - prototype (returning `int') in . */ -#define getusershell _getusershell_sys_proto_ - -#include "system.h" -#include "closeout.h" -#include "dirname.h" - -#undef getusershell - -#if HAVE_SYSLOG_H && HAVE_SYSLOG -# include -#else -# undef SYSLOG_SUCCESS -# undef SYSLOG_FAILURE -# undef SYSLOG_NON_ROOT -#endif - -#if HAVE_SYS_PARAM_H -# include -#endif - -#ifndef HAVE_ENDGRENT -# define endgrent() ((void) 0) -#endif - -#ifndef HAVE_ENDPWENT -# define endpwent() ((void) 0) -#endif - -#if HAVE_SHADOW_H -# include -#endif - -#include "error.h" - -/* The official name of this program (e.g., no `g' prefix). */ -#define PROGRAM_NAME "su" - -#define AUTHORS "David MacKenzie" - -#if HAVE_PATHS_H -# include -#endif - -/* The default PATH for simulated logins to non-superuser accounts. */ -#ifdef _PATH_DEFPATH -# define DEFAULT_LOGIN_PATH _PATH_DEFPATH -#else -# define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin" -#endif - -/* The default PATH for simulated logins to superuser accounts. */ -#ifdef _PATH_DEFPATH_ROOT -# define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT -#else -# define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc" -#endif - -/* The shell to run if none is given in the user's passwd entry. */ -#define DEFAULT_SHELL "/bin/sh" - -/* The user to become if none is specified. */ -#define DEFAULT_USER "root" - -char *crypt (); -char *getpass (); -char *getusershell (); -void endusershell (); -void setusershell (); - -extern char **environ; - -static void run_shell (const char *, const char *, char **) - ATTRIBUTE_NORETURN; - -/* The name this program was run with. */ -char *program_name; - -/* If nonzero, pass the `-f' option to the subshell. */ -static int fast_startup; - -/* If nonzero, simulate a login instead of just starting a shell. */ -static int simulate_login; - -/* If nonzero, change some environment vars to indicate the user su'd to. */ -static int change_environment; - -static struct option const longopts[] = -{ - {"command", required_argument, 0, 'c'}, - {"fast", no_argument, NULL, 'f'}, - {"login", no_argument, NULL, 'l'}, - {"preserve-environment", no_argument, &change_environment, 0}, - {"shell", required_argument, 0, 's'}, - {GETOPT_HELP_OPTION_DECL}, - {GETOPT_VERSION_OPTION_DECL}, - {0, 0, 0, 0} -}; - -/* Add VAL to the environment, checking for out of memory errors. */ - -static void -xputenv (char *val) -{ - if (putenv (val)) - xalloc_die (); -} - -/* Return a newly-allocated string whose contents concatenate - those of S1, S2, S3. */ - -static char * -concat (const char *s1, const char *s2, const char *s3) -{ - int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); - char *result = (char *) xmalloc (len1 + len2 + len3 + 1); - - strcpy (result, s1); - strcpy (result + len1, s2); - strcpy (result + len1 + len2, s3); - result[len1 + len2 + len3] = 0; - - return result; -} - -/* Return the number of elements in ARR, a null-terminated array. */ - -static int -elements (char **arr) -{ - int n = 0; - - for (n = 0; *arr; ++arr) - ++n; - return n; -} - -#if defined (SYSLOG_SUCCESS) || defined (SYSLOG_FAILURE) -/* Log the fact that someone has run su to the user given by PW; - if SUCCESSFUL is nonzero, they gave the correct password, etc. */ - -static void -log_su (const struct passwd *pw, int successful) -{ - const char *new_user, *old_user, *tty; - -# ifndef SYSLOG_NON_ROOT - if (pw->pw_uid) - return; -# endif - new_user = pw->pw_name; - /* The utmp entry (via getlogin) is probably the best way to identify - the user, especially if someone su's from a su-shell. */ - old_user = getlogin (); - if (old_user == NULL) - { - /* getlogin can fail -- usually due to lack of utmp entry. - Resort to getpwuid. */ - struct passwd *pwd = getpwuid (getuid ()); - old_user = (pwd ? pwd->pw_name : ""); - } - tty = ttyname (2); - if (tty == NULL) - tty = "none"; - /* 4.2BSD openlog doesn't have the third parameter. */ - openlog (base_name (program_name), 0 -# ifdef LOG_AUTH - , LOG_AUTH -# endif - ); - syslog (LOG_NOTICE, -# ifdef SYSLOG_NON_ROOT - "%s(to %s) %s on %s", -# else - "%s%s on %s", -# endif - successful ? "" : "FAILED SU ", -# ifdef SYSLOG_NON_ROOT - new_user, -# endif - old_user, tty); - closelog (); -} -#endif - -/* Ask the user for a password. - Return 1 if the user gives the correct password for entry PW, - 0 if not. Return 1 without asking for a password if run by UID 0 - or if PW has an empty password. */ - -static int -correct_password (const struct passwd *pw) -{ - char *unencrypted, *encrypted, *correct; -#if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP - /* Shadow passwd stuff for SVR3 and maybe other systems. */ - struct spwd *sp = getspnam (pw->pw_name); - - endspent (); - if (sp) - correct = sp->sp_pwdp; - else -#endif - correct = pw->pw_passwd; - - if (getuid () == 0 || correct == 0 || correct[0] == '\0') - return 1; - - unencrypted = getpass (_("Password:")); - if (unencrypted == NULL) - { - error (0, 0, _("getpass: cannot open /dev/tty")); - return 0; - } - encrypted = crypt (unencrypted, correct); - memset (unencrypted, 0, strlen (unencrypted)); - return strcmp (encrypted, correct) == 0; -} - -/* Update `environ' for the new shell based on PW, with SHELL being - the value for the SHELL environment variable. */ - -static void -modify_environment (const struct passwd *pw, const char *shell) -{ - char *term; - - if (simulate_login) - { - /* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH. - Unset all other environment variables. */ - term = getenv ("TERM"); - environ = (char **) xmalloc (2 * sizeof (char *)); - environ[0] = 0; - if (term) - xputenv (concat ("TERM", "=", term)); - xputenv (concat ("HOME", "=", pw->pw_dir)); - xputenv (concat ("SHELL", "=", shell)); - xputenv (concat ("USER", "=", pw->pw_name)); - xputenv (concat ("LOGNAME", "=", pw->pw_name)); - xputenv (concat ("PATH", "=", (pw->pw_uid - ? DEFAULT_LOGIN_PATH - : DEFAULT_ROOT_LOGIN_PATH))); - } - else - { - /* Set HOME, SHELL, and if not becoming a super-user, - USER and LOGNAME. */ - if (change_environment) - { - xputenv (concat ("HOME", "=", pw->pw_dir)); - xputenv (concat ("SHELL", "=", shell)); - if (pw->pw_uid) - { - xputenv (concat ("USER", "=", pw->pw_name)); - xputenv (concat ("LOGNAME", "=", pw->pw_name)); - } - } - } -} - -/* Become the user and group(s) specified by PW. */ - -static void -change_identity (const struct passwd *pw) -{ -#ifdef HAVE_INITGROUPS - errno = 0; - if (initgroups (pw->pw_name, pw->pw_gid) == -1) - error (EXIT_FAILURE, errno, _("cannot set groups")); - endgrent (); -#endif - if (setgid (pw->pw_gid)) - error (EXIT_FAILURE, errno, _("cannot set group id")); - if (setuid (pw->pw_uid)) - error (EXIT_FAILURE, errno, _("cannot set user id")); -} - -/* Run SHELL, or DEFAULT_SHELL if SHELL is empty. - If COMMAND is nonzero, pass it to the shell with the -c option. - If ADDITIONAL_ARGS is nonzero, pass it to the shell as more - arguments. */ - -static void -run_shell (const char *shell, const char *command, char **additional_args) -{ - const char **args; - int argno = 1; - - if (additional_args) - args = (const char **) xmalloc (sizeof (char *) - * (10 + elements (additional_args))); - else - args = (const char **) xmalloc (sizeof (char *) * 10); - if (simulate_login) - { - char *arg0; - char *shell_basename; - - shell_basename = base_name (shell); - arg0 = xmalloc (strlen (shell_basename) + 2); - arg0[0] = '-'; - strcpy (arg0 + 1, shell_basename); - args[0] = arg0; - } - else - args[0] = base_name (shell); - if (fast_startup) - args[argno++] = "-f"; - if (command) - { - args[argno++] = "-c"; - args[argno++] = command; - } - if (additional_args) - for (; *additional_args; ++additional_args) - args[argno++] = *additional_args; - args[argno] = NULL; - execv (shell, (char **) args); - - { - int exit_status = (errno == ENOENT ? 127 : 126); - error (0, errno, "%s", shell); - exit (exit_status); - } -} - -/* Return 1 if SHELL is a restricted shell (one not returned by - getusershell), else 0, meaning it is a standard shell. */ - -static int -restricted_shell (const char *shell) -{ - char *line; - - setusershell (); - while ((line = getusershell ()) != NULL) - { - if (*line != '#' && strcmp (line, shell) == 0) - { - endusershell (); - return 0; - } - } - endusershell (); - return 1; -} - -void -usage (int status) -{ - if (status != 0) - fprintf (stderr, _("Try `%s --help' for more information.\n"), - program_name); - else - { - printf (_("Usage: %s [OPTION]... [-] [USER [ARG]...]\n"), program_name); - fputs (_("\ -Change the effective user id and group id to that of USER.\n\ -\n\ - -, -l, --login make the shell a login shell\n\ - -c, --commmand=COMMAND pass a single COMMAND to the shell with -c\n\ - -f, --fast pass -f to the shell (for csh or tcsh)\n\ - -m, --preserve-environment do not reset environment variables\n\ - -p same as -m\n\ - -s, --shell=SHELL run SHELL if /etc/shells allows it\n\ -"), stdout); - fputs (HELP_OPTION_DESCRIPTION, stdout); - fputs (VERSION_OPTION_DESCRIPTION, stdout); - fputs (_("\ -\n\ -A mere - implies -l. If USER not given, assume root.\n\ -"), stdout); - printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); - close_stdout (); - } - exit (status); -} - -int -main (int argc, char **argv) -{ - int optc; - const char *new_user = DEFAULT_USER; - char *command = 0; - char **additional_args = 0; - char *shell = 0; - struct passwd *pw; - struct passwd pw_copy; - - program_name = argv[0]; - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); - - fast_startup = 0; - simulate_login = 0; - change_environment = 1; - - while ((optc = getopt_long (argc, argv, "c:flmps:", longopts, NULL)) != -1) - { - switch (optc) - { - case 0: - break; - - case 'c': - command = optarg; - break; - - case 'f': - fast_startup = 1; - break; - - case 'l': - simulate_login = 1; - break; - - case 'm': - case 'p': - change_environment = 0; - break; - - case 's': - shell = optarg; - break; - - case_GETOPT_HELP_CHAR; - - case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); - - default: - usage (EXIT_FAILURE); - } - } - - if (optind < argc && !strcmp (argv[optind], "-")) - { - simulate_login = 1; - ++optind; - } - if (optind < argc) - new_user = argv[optind++]; - if (optind < argc) - additional_args = argv + optind; - - pw = getpwnam (new_user); - if (pw == 0) - error (EXIT_FAILURE, 0, _("user %s does not exist"), new_user); - endpwent (); - - /* Make sure pw->pw_shell is non-NULL. It may be NULL when NEW_USER - is a username that is retrieved via NIS (YP), but that doesn't have - a default shell listed. */ - if (pw->pw_shell == NULL || pw->pw_shell[0] == '\0') - pw->pw_shell = (char *) DEFAULT_SHELL; - - /* Make a copy of the password information and point pw at the local - copy instead. Otherwise, some systems (e.g. Linux) would clobber - the static data through the getlogin call from log_su. */ - pw_copy = *pw; - pw = &pw_copy; - pw->pw_name = xstrdup (pw->pw_name); - pw->pw_dir = xstrdup (pw->pw_dir); - pw->pw_shell = xstrdup (pw->pw_shell); - - if (!correct_password (pw)) - { -#ifdef SYSLOG_FAILURE - log_su (pw, 0); -#endif - error (EXIT_FAILURE, 0, _("incorrect password")); - } -#ifdef SYSLOG_SUCCESS - else - { - log_su (pw, 1); - } -#endif - - if (shell == 0 && change_environment == 0) - shell = getenv ("SHELL"); - if (shell != 0 && getuid () && restricted_shell (pw->pw_shell)) - { - /* The user being su'd to has a nonstandard shell, and so is - probably a uucp account or has restricted access. Don't - compromise the account by allowing access with a standard - shell. */ - error (0, 0, _("using restricted shell %s"), pw->pw_shell); - shell = 0; - } - if (shell == 0) - { - shell = xstrdup (pw->pw_shell); - } - modify_environment (pw, shell); - - change_identity (pw); - if (simulate_login && chdir (pw->pw_dir)) - error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir); - - run_shell (shell, command, additional_args); -} diff -Nur coreutils-5.0/src/system.h coreutils-5.0.new/src/system.h --- coreutils-5.0/src/system.h 2003-04-02 12:13:50.000000000 +0200 +++ coreutils-5.0.new/src/system.h 2003-06-06 03:01:12.000000000 +0200 @@ -29,6 +29,10 @@ # define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0)) #endif +#ifdef FLASK_LINUX +#define mkfifo_secure(path, mode, sid) (mknod_secure ((path), (mode) | S_IFIFO, 0, (sid))) +#endif + #if HAVE_SYS_PARAM_H # include #endif diff -Nur coreutils-5.0/tests/cp/Makefile.am coreutils-5.0.new/tests/cp/Makefile.am --- coreutils-5.0/tests/cp/Makefile.am 2003-02-02 21:08:59.000000000 +0100 +++ coreutils-5.0.new/tests/cp/Makefile.am 2003-06-06 03:01:13.000000000 +0200 @@ -3,8 +3,8 @@ TESTS = \ preserve-2 r-vs-symlink link-preserve \ - backup-1 no-deref-link1 no-deref-link2 no-deref-link3 backup-is-src \ - same-file cp-mv-backup symlink-slash slink-2-slink fail-perm dir-slash \ + backup-1 backup-is-src \ + cp-mv-backup symlink-slash slink-2-slink fail-perm dir-slash \ perm cp-HL special-bits link dir-rm-dest cp-parents deref-slink \ dir-vs-file into-self EXTRA_DIST = $(TESTS) diff -Nur coreutils-5.0/tests/Makefile.am coreutils-5.0.new/tests/Makefile.am --- coreutils-5.0/tests/Makefile.am 2003-03-31 09:07:35.000000000 +0200 +++ coreutils-5.0.new/tests/Makefile.am 2003-06-06 03:01:12.000000000 +0200 @@ -11,7 +11,7 @@ SUBDIRS = \ basename chgrp chmod chown cp cut date dd dircolors du expr factor \ - fmt head install join ln ls ls-2 md5sum misc mkdir mv od pr rm rmdir \ + fmt head install join ln ls md5sum misc mkdir mv od pr rm rmdir \ seq sha1sum shred sort stty sum tac tail tail-2 test touch tr tsort \ unexpand uniq wc diff -Nur coreutils-5.0/tests/mv/Makefile.am coreutils-5.0.new/tests/mv/Makefile.am --- coreutils-5.0/tests/mv/Makefile.am 2003-03-01 00:30:44.000000000 +0100 +++ coreutils-5.0.new/tests/mv/Makefile.am 2003-06-06 03:01:13.000000000 +0200 @@ -8,10 +8,10 @@ i-link-no \ part-fail \ dup-source childproof i-4 update i-2 mv-special-1 \ - into-self into-self-2 into-self-3 into-self-4 \ + into-self into-self-3 \ backup-is-src \ i-1 hard-link-1 force partition-perm to-symlink dir-file diag \ - part-symlink part-rename trailing-slash + part-rename trailing-slash EXTRA_DIST = $(TESTS) setup TESTS_ENVIRONMENT = \