diff -up coreutils-8.19/doc/coreutils.texi.restorecon coreutils-8.19/doc/coreutils.texi --- coreutils-8.19/doc/coreutils.texi.restorecon 2012-10-19 17:41:30.073219080 -0400 +++ coreutils-8.19/doc/coreutils.texi 2012-10-19 17:41:31.151219479 -0400 @@ -8629,13 +8629,13 @@ Program used to strip binaries. @opindex --verbose Print the name of each file before copying it. -@item -Z @var{context} -@itemx --context=@var{context} +@item -Z [@var{context}] +@itemx --context[=@var{context}] @opindex -Z @opindex --context @cindex SELinux @cindex security context -Set the default SELinux security context to be used for any +Use the default SELinux security context or use specified context to be used for any created files and directories. If SELinux is disabled then print a warning and ignore the option. @@ -8652,7 +8652,7 @@ print a warning and ignore the option. @command{mv} moves or renames files (or directories). Synopses: @example -mv [@var{option}]@dots{} [-T] @var{source} @var{dest} +mv [@var{option}]@dots{} [-Z] [-T] @var{source} @var{dest} mv [@var{option}]@dots{} @var{source}@dots{} @var{directory} mv [@var{option}]@dots{} -t @var{directory} @var{source}@dots{} @end example @@ -8762,6 +8762,15 @@ same source and destination. @opindex --verbose Print the name of each file before moving it. +@item -Z [@var{context}] +@itemx --context[=@var{context}] +@opindex -Z +@opindex --context +@cindex SELinux +@cindex security context +Set the default SELinux security context on the destination. If SELinux is disabled then +print a warning and ignore the option. + @optStripTrailingSlashes @optBackupSuffix @@ -9557,13 +9566,13 @@ newly-created parent directories are inh Print a message for each created directory. This is most useful with @option{--parents}. -@item -Z @var{context} -@itemx --context=@var{context} +@item -Z [@var{context}] +@itemx --context[=@var{context}] @opindex -Z @opindex --context @cindex SELinux @cindex security context -Set the default SELinux security context to be used for created directories. +Set the default SELinux security context or use specified context for created directories. @end table @@ -9604,13 +9613,13 @@ Set the mode of created FIFOs to @var{mo for the point of departure. @var{mode} should specify only file permission bits. @xref{File permissions}. -@item -Z @var{context} -@itemx --context=@var{context} +@item -Z [@var{context}] +@itemx --context[=@var{context}] @opindex -Z @opindex --context @cindex SELinux @cindex security context -Set the default SELinux security context to be used for created FIFOs. +Set the default SELinux security context or use specified context for created FIFOs. @end table @@ -9687,13 +9696,13 @@ Set the mode of created files to @var{mo @var{mode} should specify only file permission bits. @xref{File permissions}. -@item -Z @var{context} -@itemx --context=@var{context} +@item -Z [@var{context}] +@itemx --context[=@var{context}] @opindex -Z @opindex --context @cindex SELinux @cindex security context -Set the default SELinux security context to be used for created files. +Set the default SELinux security context or use specified context for created files. @end table diff -up coreutils-8.19/lib/selinux.c.restorecon coreutils-8.19/lib/selinux.c --- coreutils-8.19/lib/selinux.c.restorecon 2012-10-19 15:37:13.460218486 -0400 +++ coreutils-8.19/lib/selinux.c 2012-10-19 15:37:13.461218487 -0400 @@ -0,0 +1,181 @@ +#include +#include +#include +#include "fts.h" +security_class_t mode_to_security_class(mode_t m) { + + if (S_ISREG(m)) + return string_to_security_class("file"); + if (S_ISDIR(m)) + return string_to_security_class("dir"); + if (S_ISCHR(m)) + return string_to_security_class("chr_file"); + if (S_ISBLK(m)) + return string_to_security_class("blk_file"); + if (S_ISFIFO(m)) + return string_to_security_class("fifo_file"); + if (S_ISLNK(m)) + return string_to_security_class("lnk_file"); + if (S_ISSOCK(m)) + return string_to_security_class("sock_file"); + + errno=EINVAL; + return 0; +} + +static int computecon(char const *path, mode_t mode, security_context_t *con) { + security_context_t scon = NULL; + security_context_t tcon = NULL; + security_class_t tclass; + int rc = -1; + + char *dir = strdup(path); + if (!dir) + goto quit; + if (getcon(&scon) < 0) + goto quit; + if (getfilecon(dirname((char *) dir), &tcon) < 0) + goto quit; + tclass = mode_to_security_class(mode); + if (!tclass) + goto quit; + rc = security_compute_create(scon, tcon, tclass, con); + +quit: + free(dir); + freecon(scon); + freecon(tcon); + return rc; +} + +int defaultcon (char const *path, mode_t mode) { + int rc = -1; + struct stat sb; + security_context_t scon = NULL, tcon = NULL; + context_t scontext = NULL, tcontext = NULL; + int fd; + + rc = matchpathcon(path, mode, &scon); + if (rc < 0) + goto quit; + rc = computecon(path, mode, &tcon); + if (rc < 0) + goto quit; + scontext = context_new(scon); + rc = -1; + if (!scontext) + goto quit; + tcontext = context_new(tcon); + if (!tcontext) + goto quit; + + context_type_set(tcontext, context_type_get(scontext)); + rc = setfscreatecon (context_str(tcontext)); +// printf("defaultcon %s %s\n", path, context_str(tcontext)); +quit: + close(fd); + if (scontext) + context_free(scontext); + if (scontext) + context_free(tcontext); + freecon(scon); + freecon(tcon); + return rc; +} + +static int restorecon_private (char const *path) { + int rc = -1; + int link_file = false; + struct stat sb; + security_context_t scon = NULL, tcon = NULL; + context_t scontext = NULL, tcontext = NULL; + int fd; + fd = open (path, O_RDONLY | O_NOFOLLOW); + if (!fd && (errno != ELOOP)) + goto quit; + + if (fd) { + rc = fstat (fd, &sb); + if (rc < 0) + goto quit; + } else { + rc = lstat (path, &sb); + if (rc < 0) + goto quit; + } + + rc = matchpathcon(path, sb.st_mode, &scon); + if (rc < 0) + goto quit; + scontext = context_new(scon); + rc = -1; + if (!scontext) + goto quit; + + if (fd) { + rc = fgetfilecon (fd, &tcon); + if (!rc) + goto quit; + } else { + rc = lgetfilecon (path, &tcon); + if (!rc) + goto quit; + } + tcontext = context_new(tcon); + if (!tcontext) + goto quit; + + context_type_set(tcontext, context_type_get(scontext)); + + if (fd) + rc = fsetfilecon (fd, context_str(tcontext)); + else + rc = lsetfilecon (path, context_str(tcontext)); + +// printf("restorcon %s %s\n", path, context_str(tcontext)); +quit: + close(fd); + if (scontext) + context_free(scontext); + if (scontext) + context_free(tcontext); + freecon(scon); + freecon(tcon); + return rc; +} + +int restorecon (char const *path, int recurse) { + if (!recurse) + return restorecon_private(path); + const char *mypath[2] = { path, NULL }; + + FTS *fts = fts_open ((char *const *)mypath, FTS_PHYSICAL, NULL); + bool ok = true; + + while (1) + { + FTSENT *ent; + + ent = fts_read (fts); + if (ent == NULL) + { + if (errno != 0) + { + /* FIXME: try to give a better message */ + error (0, errno, _("fts_read failed")); + ok = false; + } + break; + } + + ok &= restorecon_private(fts->fts_path); + } + + if (fts_close (fts) != 0) + { + error (0, errno, _("fts_close failed")); + ok = false; + } + + return ok; +} diff -up coreutils-8.19/lib/selinux.h.restorecon coreutils-8.19/lib/selinux.h --- coreutils-8.19/lib/selinux.h.restorecon 2012-10-19 15:37:13.461218487 -0400 +++ coreutils-8.19/lib/selinux.h 2012-10-19 15:37:13.462218488 -0400 @@ -0,0 +1,28 @@ +/* Handle SELinux Labeling + + Copyright (C) 2012 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 3 of the License, 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, see . */ + +/* Written by Daniel Walsh . */ + +#ifndef _GL_SELINUX_H +#define _GL_SELINUX_H + +#include +int restorecon (char const *path, int recurse); +int defaultcon (char const *path, mode_t mode); +#include "selinux.c" +#endif diff -up coreutils-8.19/man/cp.1.restorecon coreutils-8.19/man/cp.1 --- coreutils-8.19/man/cp.1.restorecon 2012-08-20 02:14:14.000000000 -0400 +++ coreutils-8.19/man/cp.1 2012-10-19 17:14:38.831525002 -0400 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.35. -.TH CP "1" "August 2012" "GNU coreutils 8.19" "User Commands" +.TH CP "1" "October 2012" "GNU coreutils 8.19" "User Commands" .SH NAME cp \- copy files and directories .SH SYNOPSIS @@ -70,6 +70,9 @@ mode,ownership,timestamps), if possible additional attributes: context, links, xattr, all .TP +\fB\-c\fR +same as \fB\-\-preserve\fR=\fIcontext\fR +.TP \fB\-\-no\-preserve\fR=\fIATTR_LIST\fR don't preserve the specified attributes .TP @@ -116,6 +119,9 @@ explain what is being done \fB\-x\fR, \fB\-\-one\-file\-system\fR stay on this file system .TP +\fB\-Z\fR, \fB\-\-context[\fR=\fICONTEXT\fR] +set default SELinux security context or specified CONTEXT on DEST +.TP \fB\-\-help\fR display this help and exit .TP diff -up coreutils-8.19/man/mkdir.1.restorecon coreutils-8.19/man/mkdir.1 --- coreutils-8.19/man/mkdir.1.restorecon 2012-08-20 02:14:14.000000000 -0400 +++ coreutils-8.19/man/mkdir.1 2012-10-19 17:16:15.433585135 -0400 @@ -21,9 +21,9 @@ no error if existing, make parent direct \fB\-v\fR, \fB\-\-verbose\fR print a message for each created directory .TP -\fB\-Z\fR, \fB\-\-context\fR=\fICTX\fR -set the SELinux security context of each created -directory to CTX +\fB\-Z\fR, \fB\-\-context\fR[=\fICTX\fR] +set default SELinux security context or specified CTX on each created +directory .TP \fB\-\-help\fR display this help and exit diff -up coreutils-8.19/man/mkfifo.1.restorecon coreutils-8.19/man/mkfifo.1 --- coreutils-8.19/man/mkfifo.1.restorecon 2012-08-20 02:14:14.000000000 -0400 +++ coreutils-8.19/man/mkfifo.1 2012-10-19 17:16:39.195594030 -0400 @@ -15,8 +15,9 @@ Mandatory arguments to long options are \fB\-m\fR, \fB\-\-mode\fR=\fIMODE\fR set file permission bits to MODE, not a=rw \- umask .TP -\fB\-Z\fR, \fB\-\-context\fR=\fICTX\fR -set the SELinux security context of each NAME to CTX +\fB\-Z\fR, \fB\-\-context\fR[=\fICTX\fR] +set default SELinux security context or specified CTX on each created +fifo .TP \fB\-\-help\fR display this help and exit diff -up coreutils-8.19/man/mknod.1.restorecon coreutils-8.19/man/mknod.1 --- coreutils-8.19/man/mknod.1.restorecon 2012-08-20 02:14:14.000000000 -0400 +++ coreutils-8.19/man/mknod.1 2012-10-19 17:17:51.271623069 -0400 @@ -15,8 +15,9 @@ Mandatory arguments to long options are \fB\-m\fR, \fB\-\-mode\fR=\fIMODE\fR set file permission bits to MODE, not a=rw \- umask .TP -\fB\-Z\fR, \fB\-\-context\fR=\fICTX\fR -set the SELinux security context of NAME to CTX +\fB\-Z\fR, \fB\-\-context\fR[=\fICTX\fR] +set default SELinux security context or specified CTX on each created +special file .TP \fB\-\-help\fR display this help and exit diff -up coreutils-8.19/man/mv.1.restorecon coreutils-8.19/man/mv.1 --- coreutils-8.19/man/mv.1.restorecon 2012-10-19 17:08:27.601158408 -0400 +++ coreutils-8.19/man/mv.1 2012-10-19 17:11:47.591357536 -0400 @@ -56,6 +56,9 @@ destination file is missing \fB\-v\fR, \fB\-\-verbose\fR explain what is being done .TP +\fB\-Z\fR, \fB\-\-context +set default SELinux security context on DEST +.TP \fB\-\-help\fR display this help and exit .TP diff -up coreutils-8.19/src/copy.c.restorecon coreutils-8.19/src/copy.c --- coreutils-8.19/src/copy.c.restorecon 2012-10-19 15:37:13.452218478 -0400 +++ coreutils-8.19/src/copy.c 2012-10-19 15:37:13.466218492 -0400 @@ -22,6 +22,7 @@ #include #include #include +#include #if HAVE_HURD_H # include @@ -60,6 +61,7 @@ #include "write-any-file.h" #include "areadlink.h" #include "yesno.h" +#include "selinux.h" #if USE_XATTR # include @@ -844,34 +846,37 @@ copy_reg (char const *src_name, char con bool some_errors = !all_errors && !x->reduce_diagnostics; security_context_t con = NULL; - if (getfscreatecon (&con) < 0) - { - if (all_errors || (some_errors && !errno_unsupported (errno))) - error (0, errno, _("failed to get file system create context")); - if (x->require_preserve_context) - { - return_val = false; - goto close_src_and_dst_desc; - } - } + if (x->preserve_security_context) { + if (getfscreatecon (&con) < 0) + { + if (all_errors || (some_errors && !errno_unsupported (errno))) + error (0, errno, _("failed to get file system create context")); + return_val = false; + goto close_src_and_dst_desc; + } + } else { + if (matchpathcon(dst_name, dst_mode, &con) < 0) { + if (all_errors || (some_errors && !errno_unsupported (errno))) + error (0, errno, _("failed to get file system create context")); + return_val = false; + goto close_src_and_dst_desc; + } + } - if (con) - { - if (fsetfilecon (dest_desc, con) < 0) - { + if (fsetfilecon (dest_desc, con) < 0) + { if (all_errors || (some_errors && !errno_unsupported (errno))) - error (0, errno, - _("failed to set the security context of %s to %s"), - quote_n (0, dst_name), quote_n (1, con)); + error (0, errno, + _("failed to set the security context of %s to %s"), + quote_n (0, dst_name), quote_n (1, con)); if (x->require_preserve_context) - { - return_val = false; - freecon (con); - goto close_src_and_dst_desc; - } - } - freecon (con); - } + { + return_val = false; + freecon (con); + goto close_src_and_dst_desc; + } + } + freecon (con); } if (dest_desc < 0 && x->unlink_dest_after_failed_open) @@ -892,6 +897,9 @@ copy_reg (char const *src_name, char con if (*new_dst) { + if (x->set_security_context && (! x->require_preserve_context)) + defaultcon(dst_name, dst_mode); + open_with_O_CREAT:; int open_flags = O_WRONLY | O_CREAT | O_BINARY; @@ -936,6 +944,7 @@ copy_reg (char const *src_name, char con if (dest_desc < 0 && dest_errno == EISDIR && *dst_name && dst_name[strlen (dst_name) - 1] == '/') dest_errno = ENOTDIR; + } else { @@ -974,6 +983,9 @@ copy_reg (char const *src_name, char con goto close_src_and_dst_desc; } + if (x->set_security_context && ! x->preserve_security_context) + restorecon(dst_name, 1); + /* --attributes-only overrides --reflink. */ if (data_copy_required && x->reflink_mode) { @@ -2087,6 +2099,9 @@ copy_internal (char const *src_name, cha emit_verbose (src_name, dst_name, backup_succeeded ? dst_backup : NULL); + if (x->set_security_context) + restorecon(dst_name, 1); + if (rename_succeeded) *rename_succeeded = true; @@ -2226,6 +2241,11 @@ copy_internal (char const *src_name, cha return false; } } + else + { + if (x->set_security_context) + restorecon(dst_name, 1); + } if (S_ISDIR (src_mode)) { diff -up coreutils-8.19/src/cp.c.restorecon coreutils-8.19/src/cp.c --- coreutils-8.19/src/cp.c.restorecon 2012-10-19 15:37:13.453218479 -0400 +++ coreutils-8.19/src/cp.c 2012-10-19 15:37:13.467218493 -0400 @@ -141,7 +141,7 @@ static struct option const long_opts[] = {"target-directory", required_argument, NULL, 't'}, {"update", no_argument, NULL, 'u'}, {"verbose", no_argument, NULL, 'v'}, - {"context", required_argument, NULL, 'Z'}, + {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, {NULL, 0, NULL, 0} @@ -233,7 +233,7 @@ Mandatory arguments to long options are destination file is missing\n\ -v, --verbose explain what is being done\n\ -x, --one-file-system stay on this file system\n\ - -Z, --context=CONTEXT set security context of copy to CONTEXT\n\ + -Z, --context[=CONTEXT] set security context of destination file to default type or to CONTEXT if specified\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); @@ -881,8 +881,10 @@ decode_preserve_arg (char const *arg, st break; case PRESERVE_CONTEXT: - x->preserve_security_context = on_off; - x->require_preserve_context = on_off; + if (! x->set_security_context) { + x->preserve_security_context = on_off; + x->require_preserve_context = on_off; + } break; case PRESERVE_XATTR: @@ -895,7 +897,7 @@ decode_preserve_arg (char const *arg, st x->preserve_timestamps = on_off; x->preserve_ownership = on_off; x->preserve_links = on_off; - if (selinux_enabled) + if (selinux_enabled && (! x->set_security_context)) x->preserve_security_context = on_off; x->preserve_xattr = on_off; break; @@ -938,7 +940,7 @@ main (int argc, char **argv) we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); - while ((c = getopt_long (argc, argv, "abcdfHilLnprst:uvxPRS:TZ:", + while ((c = getopt_long (argc, argv, "abcdfHilLnprst:uvxPRS:TZ::", long_opts, NULL)) != -1) { @@ -965,7 +967,7 @@ main (int argc, char **argv) x.preserve_mode = true; x.preserve_timestamps = true; x.require_preserve = true; - if (selinux_enabled) + if (selinux_enabled && (! x.set_security_context)) x.preserve_security_context = true; x.preserve_xattr = true; x.reduce_diagnostics = true; @@ -1113,18 +1115,16 @@ main (int argc, char **argv) "It requires a SELinux enabled kernel.\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 (optarg) { + /* if there's a security_context given set new path + components to that context, too */ + if ( setfscreatecon(optarg) < 0 ) { + (void) fprintf(stderr, _("cannot set default security context %s\n"), optarg); + exit( 1 ); + } + } x.set_security_context = true; - (void) fprintf(stderr, _("Warning, -Z/--context option is deprecated and will be removed soon!\nPlease use 'install' utility instead of cp for this functionality.\n")); - /* if there's a security_context given set new path - components to that context, too */ - if ( setfscreatecon(optarg) < 0 ) { - (void) fprintf(stderr, _("cannot set default security context %s\n"), optarg); - exit( 1 ); - } + x.preserve_security_context = false; break; case 'S': diff -up coreutils-8.19/src/install.c.restorecon coreutils-8.19/src/install.c --- coreutils-8.19/src/install.c.restorecon 2012-10-19 15:37:13.415218441 -0400 +++ coreutils-8.19/src/install.c 2012-10-19 15:37:13.468218494 -0400 @@ -641,7 +641,7 @@ Mandatory arguments to long options are "), stdout); fputs (_("\ -P, --preserve-context preserve SELinux security context\n\ - -Z, --context=CONTEXT set SELinux security context of files and directories\ + -Z, --context[=CONTEXT] set SELinux security context of files and directories\ \n\ "), stdout); @@ -783,7 +783,7 @@ main (int argc, char **argv) we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); - while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pPt:TvS:Z:", long_options, + while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pPt:TvS:Z::", long_options, NULL)) != -1) { switch (optc) @@ -861,12 +861,11 @@ main (int argc, char **argv) "this kernel is not SELinux-enabled")); break; } - if ( x.set_security_context ) { + if ( x.set_security_context || scontext ) { (void) fprintf(stderr, "%s: cannot force target context and preserve it\n", argv[0]); exit( 1 ); } x.preserve_security_context = true; - use_default_selinux_context = false; break; case 'Z': if ( ! selinux_enabled) @@ -875,9 +874,10 @@ main (int argc, char **argv) "this kernel is not SELinux-enabled")); break; } - scontext = optarg; - x.set_security_context = true; - use_default_selinux_context = false; + if (optarg) + scontext = optarg; + else + x.set_security_context = true; break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); diff -up coreutils-8.19/src/mkdir.c.restorecon coreutils-8.19/src/mkdir.c --- coreutils-8.19/src/mkdir.c.restorecon 2012-10-19 15:37:13.420218446 -0400 +++ coreutils-8.19/src/mkdir.c 2012-10-19 15:37:13.469218495 -0400 @@ -29,6 +29,7 @@ #include "prog-fprintf.h" #include "quote.h" #include "savewd.h" +#include "selinux.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "mkdir" @@ -38,7 +39,6 @@ static struct option const longopts[] = { {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, - {"context", required_argument, NULL, 'Z'}, {"mode", required_argument, NULL, 'm'}, {"parents", no_argument, NULL, 'p'}, {"verbose", no_argument, NULL, 'v'}, @@ -66,8 +66,8 @@ Mandatory arguments to long options are -m, --mode=MODE set file mode (as in chmod), not a=rwx - umask\n\ -p, --parents no error if existing, make parent directories as needed\n\ -v, --verbose print a message for each created directory\n\ - -Z, --context=CTX set the SELinux security context of each created\n\ - directory to CTX\n\ + -Z, --context[=CTX] set the SELinux security context of each created\n\ + directory to default type or to CTX if specified\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); @@ -92,6 +92,9 @@ struct mkdir_options /* File mode bits affected by MODE. */ mode_t mode_bits; + /* Set the SELinux File Context. */ + int set_security_context; + /* If not null, format to use when reporting newly made directories. */ char const *created_directory_format; }; @@ -114,6 +117,9 @@ static int make_ancestor (char const *dir, char const *component, void *options) { struct mkdir_options const *o = options; + + if (o->set_security_context) + defaultcon(dir, S_IFDIR); int r = mkdir (component, o->ancestor_mode); if (r == 0) { @@ -147,6 +153,7 @@ main (int argc, char **argv) options.mode = S_IRWXUGO; options.mode_bits = 0; options.created_directory_format = NULL; + options.set_security_context = false; initialize_main (&argc, &argv); set_program_name (argv[0]); @@ -156,7 +163,7 @@ main (int argc, char **argv) atexit (close_stdout); - while ((optc = getopt_long (argc, argv, "pm:vZ:", longopts, NULL)) != -1) + while ((optc = getopt_long (argc, argv, "pm:vZ::", longopts, NULL)) != -1) { switch (optc) { @@ -170,7 +177,10 @@ main (int argc, char **argv) options.created_directory_format = _("created directory %s"); break; case 'Z': - scontext = optarg; + if (optarg) + scontext = optarg; + else + options.set_security_context = true; break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); diff -up coreutils-8.19/src/mkfifo.c.restorecon coreutils-8.19/src/mkfifo.c --- coreutils-8.19/src/mkfifo.c.restorecon 2012-07-21 10:54:31.000000000 -0400 +++ coreutils-8.19/src/mkfifo.c 2012-10-19 15:37:13.470218496 -0400 @@ -26,6 +26,7 @@ #include "error.h" #include "modechange.h" #include "quote.h" +#include "selinux.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "mkfifo" @@ -60,7 +61,7 @@ Mandatory arguments to long options are -m, --mode=MODE set file permission bits to MODE, not a=rw - umask\n\ "), stdout); fputs (_("\ - -Z, --context=CTX set the SELinux security context of each NAME to CTX\n\ + -Z, --context[=CTX] set the SELinux security context of each NAME to default type or CTX if specified\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); @@ -74,6 +75,7 @@ main (int argc, char **argv) { mode_t newmode; char const *specified_mode = NULL; + int set_security_context = false; int exit_status = EXIT_SUCCESS; int optc; security_context_t scontext = NULL; @@ -86,7 +88,7 @@ main (int argc, char **argv) atexit (close_stdout); - while ((optc = getopt_long (argc, argv, "m:Z:", longopts, NULL)) != -1) + while ((optc = getopt_long (argc, argv, "m:Z::", longopts, NULL)) != -1) { switch (optc) { @@ -94,7 +96,10 @@ main (int argc, char **argv) specified_mode = optarg; break; case 'Z': - scontext = optarg; + if (optarg) + scontext = optarg; + else + set_security_context = true; break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); @@ -128,6 +133,8 @@ main (int argc, char **argv) } for (; optind < argc; ++optind) + if (set_security_context) + defaultcon(argv[optind], S_IFIFO); if (mkfifo (argv[optind], newmode) != 0) { error (0, errno, _("cannot create fifo %s"), quote (argv[optind])); diff -up coreutils-8.19/src/mknod.c.restorecon coreutils-8.19/src/mknod.c --- coreutils-8.19/src/mknod.c.restorecon 2012-10-19 15:37:13.420218446 -0400 +++ coreutils-8.19/src/mknod.c 2012-10-19 15:37:13.471218497 -0400 @@ -27,6 +27,7 @@ #include "modechange.h" #include "quote.h" #include "xstrtol.h" +#include "selinux.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "mknod" @@ -62,7 +63,7 @@ Mandatory arguments to long options are -m, --mode=MODE set file permission bits to MODE, not a=rw - umask\n\ "), stdout); fputs (_("\ - -Z, --context=CTX set the SELinux security context of NAME to CTX\n\ + -Z, --context[=CTX] set the SELinux security context of NAME to default type or to CTX if specified\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); @@ -94,6 +95,7 @@ main (int argc, char **argv) int expected_operands; mode_t node_type; security_context_t scontext = NULL; + int set_security_context = false; initialize_main (&argc, &argv); set_program_name (argv[0]); @@ -103,7 +105,7 @@ main (int argc, char **argv) atexit (close_stdout); - while ((optc = getopt_long (argc, argv, "m:Z:", longopts, NULL)) != -1) + while ((optc = getopt_long (argc, argv, "m:Z::", longopts, NULL)) != -1) { switch (optc) { @@ -111,7 +113,10 @@ main (int argc, char **argv) specified_mode = optarg; break; case 'Z': - scontext = optarg; + if (optarg) + scontext = optarg; + else + set_security_context = true; break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); @@ -212,6 +217,9 @@ main (int argc, char **argv) error (EXIT_FAILURE, 0, _("invalid device %s %s"), s_major, s_minor); #endif + if (set_security_context) + defaultcon(argv[optind], node_type); + if (mknod (argv[optind], newmode | node_type, device) != 0) error (EXIT_FAILURE, errno, "%s", quote (argv[optind])); } diff -up coreutils-8.19/src/mv.c.restorecon coreutils-8.19/src/mv.c --- coreutils-8.19/src/mv.c.restorecon 2012-10-19 15:37:13.421218447 -0400 +++ coreutils-8.19/src/mv.c 2012-10-19 15:37:13.472218498 -0400 @@ -55,6 +55,7 @@ static bool remove_trailing_slashes; static struct option const long_options[] = { {"backup", optional_argument, NULL, 'b'}, + {"context", no_argument, NULL, 'Z'}, {"force", no_argument, NULL, 'f'}, {"interactive", no_argument, NULL, 'i'}, {"no-clobber", no_argument, NULL, 'n'}, @@ -351,6 +352,7 @@ main (int argc, char **argv) bool no_target_directory = false; int n_files; char **file; + bool selinux_enabled = (0 < is_selinux_enabled ()); initialize_main (&argc, &argv); set_program_name (argv[0]); @@ -369,7 +371,7 @@ main (int argc, char **argv) we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); - while ((c = getopt_long (argc, argv, "bfint:uvS:T", long_options, NULL)) + while ((c = getopt_long (argc, argv, "bfint:uvS:TZ", long_options, NULL)) != -1) { switch (c) @@ -418,6 +420,16 @@ main (int argc, char **argv) make_backups = true; backup_suffix_string = optarg; break; + case 'Z': + /* politely decline if we're not on a selinux-enabled kernel. */ + if( !selinux_enabled ) { + fprintf( stderr, "Warning: ignoring --context (-Z). " + "It requires a SELinux enabled kernel.\n" ); + break; + } + x.preserve_security_context = false; + x.set_security_context = true; + break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: diff -up coreutils-8.19/src/system.h.restorecon coreutils-8.19/src/system.h --- coreutils-8.19/src/system.h.restorecon 2012-07-23 06:05:16.000000000 -0400 +++ coreutils-8.19/src/system.h 2012-10-19 15:37:13.473218499 -0400 @@ -330,7 +330,7 @@ enum #define GETOPT_VERSION_OPTION_DECL \ "version", no_argument, NULL, GETOPT_VERSION_CHAR #define GETOPT_SELINUX_CONTEXT_OPTION_DECL \ - "context", required_argument, NULL, 'Z' + "context", optional_argument, NULL, 'Z' #define case_GETOPT_HELP_CHAR \ case GETOPT_HELP_CHAR: \