selinux: adjust utils to run restorecon with -Z

cp, mv, install, mkdir, mkfifo, mknod are adjusted so that:
 -Z no longer accepts an argument.
 -Z or --context without an argument do not warn without SELinux.
 --context with an argument will warn without SELinux.

* src/local.mk: Reference the new selinux module where required.
* src/system.h: Make the argument to --context optional.
* src/mkdir.c: Likewise.  Also handle the SMACK case for --context.
Note we currently silently ignore -Z with SMACK.
* src/mkfifo.c: Likewise.
* src/mknod.c: Likewise.
* src/install.c: Likewise.  Note install(1) by default already
set the context for target files to their system default,
albeit with an older method.  Use the -Z option to select between
the old and new context restoration behavior, and document
the differences and details for how context restoration
is done in new and old methods, with a view disabling the
old method entirely in future.
* src/cp.c: Make the argument to --context optional.
Note -Z implies --no-preserve=context.  I.E. -Z overrides
that aspect of -a no matter what order specified.
(struct cp_options): Document the context handling options.
(main): Check/adjust option combinations after all
options are processed, to both simplify processing
and to make handling independent of order of options
on the command line.  Also improve the diagnostics
from a failed call to setfscreatecon().
(set_process_security_ctx): A new function,
refactored to set the default context from the source file,
or with the type adjusted as per the system default for
the destination path.
(set_file_security_ctx): A new function refactored to
set the security context of an existing file, either based on
the process context or the default system context for a path.
(copy_internal): Use the refactored functions to simplify
error handling and consistently fail or warn as needed.
(copy_reg): Likewise.
(copy_internal): With --preserve=context, also copy
context from non regular files.  Note for directories this may
impact the copying of subsequent files to that directory?
(copy_attr): If we're handling SELinux explicitly,
then exclude to avoid the redudant copy with --preserve=context,
and the problematic copy with -Z.  Note SELinux attribute exclusion
also now honors cp -a --no-preserve=context.  Note there was a
very small window over 10 years ago, where attr_copy_file was
available, while attr_copy_check_permissions was not, so we
don't bother adding an explicit m4 check for the latter function.
* src/mv.c: Support --context, but don't allow specifying an argument.
* src/chcon.c: Adjust a comment to be specific to SELinux.
* src/runcon.c: Likewise.
* src/copy.c: Honor the context settings to "restorecon" as appropriate.
* src/copy.h: Add a new setting to select "restorecon" functionality.
* tests/mkdir/selinux.sh: s/-Z/--context=/
* tests/cp/cp-a-selinux.sh: Augment this test with cases
testing basic -Z functionality, and also test the various
invalid option combinations and option precedence.
* tests/mkdir/restorecon.sh: Add a new test for the
more involved mkdir -Z handling, since the directory changing
and non existent directories need to be specially handled.
Also check the similar but simpler handling of -Z by mk{nod,fifo}.
* tests/local.mk: Reference the new test.
* doc/coreutils.texi (cp invocation): Update as per interface changes.
(mv invocation): Likewise.
(install invocation): Likewise.
(mkfifo invocation): Likewise.
(mknod invocation): Likewise.
(mkdir invocation): Likewise.
* NEWS: Mention the new feature and change in behavior.
This commit is contained in:
Pádraig Brady 2013-11-27 12:26:51 +00:00
parent d8e27ab0be
commit 7958a4a4fe
19 changed files with 612 additions and 177 deletions

13
NEWS
View File

@ -52,6 +52,13 @@ GNU coreutils NEWS -*- outline -*-
** New features
cp, install, mkdir, mknod, mkfifo and mv now support "restorecon"
functionality through the -Z option, to set the SELinux context
appropriate for the new item location in the file system.
csplit accepts a new option: --suppressed-matched, to elide the lines
used to identify the split points.
df --output now accepts a 'file' field, to propagate a specified
command line argument through to the output.
@ -73,9 +80,6 @@ GNU coreutils NEWS -*- outline -*-
uniq accepts a new option: --group to print all items, while separating
unique groups with empty lines.
csplit accepts a new option: --suppressed-matched, to elide the lines
used to identify the split points.
shred accepts new parameters to the --remove option to give greater
control over that operation, which can greatly reduce sync overhead.
@ -89,6 +93,9 @@ GNU coreutils NEWS -*- outline -*-
Previously, it would create a hard link of the symbolic link, even when
the dereferencing options -L or -H were specified.
cp, install, mkdir, mknod and mkfifo no longer accept an argument to the
short -Z option. The --context equivalent still takes an optional argument.
dd status=none now suppresses all non fatal diagnostic messages,
not just the transfer counts.

View File

@ -8467,6 +8467,24 @@ Skip subdirectories that are on different file systems from the one that
the copy started on.
However, mount point directories @emph{are} copied.
@macro optContext
@item -Z
@itemx --context[=@var{context}]
@opindex -Z
@opindex --context
@cindex SELinux, setting/restoring security context
@cindex security context
Without a specified @var{context}, adjust the SELinux security context according
to the system default type for destination files, similarly to the
@command{restorecon} command.
The long form of this option with a specific context specified,
will set the context for newly created files only.
With a specified context, if SELinux is disabled, a warning is issued.
@end macro
@optContext
This option is mutually exclusive with the @option{--preserve=context}
option, and overrides the @option{--preserve=all} and @option{-a} options.
@end table
@exitstatus
@ -9110,15 +9128,9 @@ Program used to strip binaries.
@opindex --verbose
Print the name of each file before copying it.
@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
created files and directories. If SELinux is disabled then
print a warning and ignore the option.
@optContext
This option is mutually exclusive with the @option{--preserve-context} option.
@end table
@ -9251,6 +9263,16 @@ Print the name of each file before moving it.
@optNoTargetDirectory
@item -Z
@itemx --context
@opindex -Z
@opindex --context
@cindex SELinux, restoring security context
@cindex security context
This option functions similarly to the @command{restorecon} command,
by adjusting the SELinux security context according
to the system default type for destination files.
@end table
@exitstatus
@ -10066,13 +10088,7 @@ newly-created parent directories are inherited.
Print a message for each created directory. This is most useful with
@option{--parents}.
@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.
@optContext
@end table
@ -10113,13 +10129,7 @@ Set the mode of created FIFOs to @var{mode}, which is symbolic as in
for the point of departure. @var{mode} should specify only file
permission bits. @xref{File permissions}.
@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.
@optContext
@end table
@ -10196,13 +10206,7 @@ Set the mode of created files to @var{mode}, which is symbolic as in
@var{mode} should specify only file permission bits.
@xref{File permissions}.
@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.
@optContext
@end table

View File

@ -355,7 +355,7 @@ Usage: %s [OPTION]... CONTEXT FILE...\n\
"),
program_name, program_name, program_name);
fputs (_("\
Change the security context of each FILE to CONTEXT.\n\
Change the SELinux security context of each FILE to CONTEXT.\n\
With --reference, change the security context of each FILE to that of RFILE.\n\
"), stdout);

View File

@ -61,6 +61,7 @@
#include "write-any-file.h"
#include "areadlink.h"
#include "yesno.h"
#include "selinux.h"
#if USE_XATTR
# include <attr/error_context.h>
@ -512,6 +513,18 @@ copy_attr_free (struct error_context *ctx _GL_UNUSED,
{
}
/* Exclude SELinux extended attributes that are otherwise handled,
and are problematic to copy again. Also honor attributes
configured for exclusion in /etc/xattr.conf.
FIXME: Should we handle POSIX ACLs similarly?
Return zero to skip. */
static int
check_selinux_attr (const char *name, struct error_context *ctx)
{
return STRNCMP_LIT (name, "security.selinux")
&& attr_copy_check_permissions (name, ctx);
}
/* If positive SRC_FD and DST_FD descriptors are passed,
then copy by fd, otherwise copy by name. */
@ -522,6 +535,7 @@ copy_attr (char const *src_path, int src_fd,
int ret;
bool all_errors = (!x->data_copy_required || x->require_preserve_xattr);
bool some_errors = (!all_errors && !x->reduce_diagnostics);
bool selinux_done = (x->preserve_security_context || x->set_security_context);
struct error_context ctx =
{
.error = all_errors ? copy_attr_allerror : copy_attr_error,
@ -529,10 +543,12 @@ copy_attr (char const *src_path, int src_fd,
.quote_free = copy_attr_free
};
if (0 <= src_fd && 0 <= dst_fd)
ret = attr_copy_fd (src_path, src_fd, dst_path, dst_fd, 0,
ret = attr_copy_fd (src_path, src_fd, dst_path, dst_fd,
selinux_done ? check_selinux_attr : NULL,
(all_errors || some_errors ? &ctx : NULL));
else
ret = attr_copy_file (src_path, dst_path, 0,
ret = attr_copy_file (src_path, dst_path,
selinux_done ? check_selinux_attr : NULL,
(all_errors || some_errors ? &ctx : NULL));
return ret == 0;
@ -737,6 +753,96 @@ set_author (const char *dst_name, int dest_desc, const struct stat *src_sb)
#endif
}
/* Set the default security context for the process. New files will
have this security context set. Also existing files can have their
context adjusted based on this process context, by
set_file_security_ctx() called with PROCESS_LOCAL=true.
This should be called before files are created so there is no race
where a file may be present without an appropriate security context.
Based on CP_OPTIONS, diagnose warnings and fail when appropriate.
Return FALSE on failure, TRUE on success. */
static bool
set_process_security_ctx (char const *src_name, char const *dst_name,
mode_t mode, bool new_dst, const struct cp_options *x)
{
if (x->preserve_security_context)
{
/* Set the default context for the process to match the source. */
bool all_errors = !x->data_copy_required || x->require_preserve_context;
bool some_errors = !all_errors && !x->reduce_diagnostics;
security_context_t con;
if (0 <= lgetfilecon (src_name, &con))
{
if (setfscreatecon (con) < 0)
{
if (all_errors || (some_errors && !errno_unsupported (errno)))
error (0, errno,
_("failed to set default file creation context to %s"),
quote (con));
if (x->require_preserve_context)
{
freecon (con);
return false;
}
}
freecon (con);
}
else
{
if (all_errors || (some_errors && !errno_unsupported (errno)))
{
error (0, errno,
_("failed to get security context of %s"),
quote (src_name));
}
if (x->require_preserve_context)
return false;
}
}
else if (x->set_security_context)
{
/* With -Z, adjust the default context for the process
to have the type component adjusted as per the destination path. */
if (new_dst && defaultcon (dst_name, mode) < 0)
{
if (!errno_unsupported (errno))
error (0, errno,
_("failed to set default file creation context for %s"),
quote (dst_name));
}
}
return true;
}
/* Reset the security context of DST_NAME, to that already set
as the process default if PROCESS_LOCAL is true. Otherwise
adjust the type component of DST_NAME's security context as
per the system default for that path. Issue warnings upon
failure, when allowed by various settings in CP_OPTIONS.
Return FALSE on failure, TRUE on success. */
static bool
set_file_security_ctx (char const *dst_name, bool process_local,
bool recurse, const struct cp_options *x)
{
bool all_errors = (!x->data_copy_required
|| x->require_preserve_context);
bool some_errors = !all_errors && !x->reduce_diagnostics;
if (! restorecon (dst_name, recurse, process_local))
{
if (all_errors || (some_errors && !errno_unsupported (errno)))
error (0, errno, _("failed to set the security context of %s"),
quote_n (0, dst_name));
return false;
}
return true;
}
/* Change the file mode bits of the file identified by DESC or NAME to MODE.
Use DESC if DESC is valid and fchmod is available, NAME otherwise. */
@ -834,45 +940,24 @@ copy_reg (char const *src_name, char const *dst_name,
dest_errno = errno;
/* When using cp --preserve=context to copy to an existing destination,
use the default context rather than that of the source. Why?
1) the src context may prohibit writing, and
2) because it's more consistent to use the same context
that is used when the destination file doesn't already exist. */
if (x->preserve_security_context && 0 <= dest_desc)
reset the context as per the default context, which has already been
set according to the src.
When using the mutually exclusive -Z option, then adjust the type of
the existing context according to the system default for the dest.
Note we set the context here, _after_ the file is opened, lest the
new context disallow that. */
if ((x->set_security_context || x->preserve_security_context)
&& 0 <= dest_desc)
{
bool all_errors = (!x->data_copy_required
|| x->require_preserve_context);
bool some_errors = !all_errors && !x->reduce_diagnostics;
security_context_t con = NULL;
if (getfscreatecon (&con) < 0)
if (! set_file_security_ctx (dst_name, x->preserve_security_context,
false, x))
{
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 (con)
{
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));
if (x->require_preserve_context)
{
return_val = false;
freecon (con);
goto close_src_and_dst_desc;
}
}
freecon (con);
}
}
if (dest_desc < 0 && x->unlink_dest_after_failed_open)
@ -888,6 +973,18 @@ copy_reg (char const *src_name, char const *dst_name,
/* Tell caller that the destination file was unlinked. */
*new_dst = true;
/* Ensure there is no race where a file may be left without
an appropriate security context. */
if (x->set_security_context)
{
if (! set_process_security_ctx (src_name, dst_name, dst_mode,
*new_dst, x))
{
return_val = false;
goto close_src_desc;
}
}
}
}
@ -2113,6 +2210,12 @@ copy_internal (char const *src_name, char const *dst_name,
emit_verbose (src_name, dst_name,
backup_succeeded ? dst_backup : NULL);
if (x->set_security_context)
{
/* -Z failures are only warnings currently. */
(void) set_file_security_ctx (dst_name, false, true, x);
}
if (rename_succeeded)
*rename_succeeded = true;
@ -2222,40 +2325,12 @@ copy_internal (char const *src_name, char const *dst_name,
delayed_ok = true;
if (x->preserve_security_context)
{
bool all_errors = !x->data_copy_required || x->require_preserve_context;
bool some_errors = !all_errors && !x->reduce_diagnostics;
security_context_t con;
if (0 <= lgetfilecon (src_name, &con))
{
if (setfscreatecon (con) < 0)
{
if (all_errors || (some_errors && !errno_unsupported (errno)))
error (0, errno,
_("failed to set default file creation context to %s"),
quote (con));
if (x->require_preserve_context)
{
freecon (con);
return false;
}
}
freecon (con);
}
else
{
if (all_errors || (some_errors && !errno_unsupported (errno)))
{
error (0, errno,
_("failed to get security context of %s"),
quote (src_name));
}
if (x->require_preserve_context)
return false;
}
}
/* If required, set the default security context for new files.
Also for existing files this is used as a reference
when copying the context with --preserve=context.
FIXME: Do we need to consider dst_mode_bits here? */
if (! set_process_security_ctx (src_name, dst_name, src_mode, new_dst, x))
return false;
if (S_ISDIR (src_mode))
{
@ -2521,6 +2596,19 @@ copy_internal (char const *src_name, char const *dst_name,
goto un_backup;
}
/* With -Z or --preserve=context, set the context for existing files.
Note this is done already for copy_reg() for reasons described therein. */
if (!new_dst && !x->copy_as_regular
&& (x->set_security_context || x->preserve_security_context))
{
if (! set_file_security_ctx (dst_name, x->preserve_security_context,
false, x))
{
if (x->require_preserve_context)
goto un_backup;
}
}
if (command_line_arg && x->dest_info)
{
/* Now that the destination file is very likely to exist,

View File

@ -159,6 +159,9 @@ struct cp_options
bool preserve_timestamps;
bool explicit_no_preserve_mode;
/* If true, attempt to set specified security context */
bool set_security_context;
/* Enabled for mv, and for cp by the --preserve=links option.
If true, attempt to preserve in the destination files any
logical hard links between the source files. If used with cp's

View File

@ -141,6 +141,7 @@ static struct option const long_opts[] =
{"target-directory", required_argument, NULL, 't'},
{"update", no_argument, NULL, 'u'},
{"verbose", no_argument, NULL, 'v'},
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@ -227,6 +228,10 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
destination file is missing\n\
-v, --verbose explain what is being done\n\
-x, --one-file-system stay on this file system\n\
"), stdout);
fputs (_("\
-Z, --context[=CTX] set SELinux security context of destination\n\
file to default type, or to CTX if specified\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@ -782,8 +787,9 @@ cp_option_init (struct cp_options *x)
x->preserve_mode = false;
x->preserve_timestamps = false;
x->explicit_no_preserve_mode = false;
x->preserve_security_context = false;
x->require_preserve_context = false;
x->preserve_security_context = false; /* -a or --preserve=context. */
x->require_preserve_context = false; /* --preserve=context. */
x->set_security_context = false; /* -Z, set sys default context. */
x->preserve_xattr = false;
x->reduce_diagnostics = false;
x->require_preserve_xattr = false;
@ -876,8 +882,8 @@ decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off)
break;
case PRESERVE_CONTEXT:
x->preserve_security_context = on_off;
x->require_preserve_context = on_off;
x->preserve_security_context = on_off;
break;
case PRESERVE_XATTR:
@ -918,6 +924,7 @@ main (int argc, char **argv)
bool copy_contents = false;
char *target_directory = NULL;
bool no_target_directory = false;
security_context_t scontext = NULL;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@ -934,7 +941,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, "abdfHilLnprst:uvxPRS:T",
while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:TZ",
long_opts, NULL))
!= -1)
{
@ -1092,6 +1099,24 @@ main (int argc, char **argv)
x.one_file_system = true;
break;
case 'Z':
/* politely decline if we're not on a selinux-enabled kernel. */
if (selinux_enabled)
{
if (optarg)
scontext = optarg;
else
x.set_security_context = true;
}
else if (optarg)
{
error (0, 0,
_("warning: ignoring --context; "
"it requires an SELinux-enabled kernel"));
}
break;
case 'S':
make_backups = true;
backup_suffix_string = optarg;
@ -1150,13 +1175,30 @@ main (int argc, char **argv)
if (x.unlink_dest_after_failed_open && (x.hard_link || x.symbolic_link))
x.unlink_dest_before_opening = true;
if (x.preserve_security_context)
{
if (!selinux_enabled)
error (EXIT_FAILURE, 0,
_("cannot preserve security context "
"without an SELinux-enabled kernel"));
}
/* Ensure -Z overrides -a. */
if ((x.set_security_context || scontext)
&& ! x.require_preserve_context)
x.preserve_security_context = false;
if (x.preserve_security_context && (x.set_security_context || scontext))
error (EXIT_FAILURE, 0,
_("cannot set target context and preserve it"));
if (x.require_preserve_context && ! selinux_enabled)
error (EXIT_FAILURE, 0,
_("cannot preserve security context "
"without an SELinux-enabled kernel"));
/* FIXME: This handles new files. But what about existing files?
I.E. if updating a tree, new files would have the specified context,
but shouldn't existing files be updated for consistency like this?
if (scontext)
restorecon (dst_path, 0, true);
*/
if (scontext && setfscreatecon (optarg) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (optarg));
#if !USE_XATTR
if (x.require_preserve_xattr)

View File

@ -40,8 +40,8 @@
proper_name ("Arnold Robbins"), \
proper_name ("David MacKenzie")
/* If nonzero, output only the SELinux context. -Z */
static int just_context = 0;
/* If nonzero, output only the SELinux context. */
static bool just_context = 0;
static void print_user (uid_t uid);
static void print_full_info (const char *username);
@ -155,7 +155,7 @@ main (int argc, char **argv)
error (EXIT_FAILURE, 0,
_("--context (-Z) works only on an SELinux-enabled kernel"));
#endif
just_context = 1;
just_context = true;
break;
case 'g':

View File

@ -279,7 +279,6 @@ cp_option_init (struct cp_options *x)
x->reduce_diagnostics=false;
x->data_copy_required = true;
x->require_preserve = false;
x->require_preserve_context = false;
x->require_preserve_xattr = false;
x->recursive = false;
x->sparse_mode = SPARSE_AUTO;
@ -295,7 +294,9 @@ cp_option_init (struct cp_options *x)
x->open_dangling_dest_symlink = false;
x->update = false;
x->preserve_security_context = false;
x->require_preserve_context = false; /* Not used by install currently. */
x->preserve_security_context = false; /* Whether to copy context from src. */
x->set_security_context = false; /* Whether to set sys default context. */
x->preserve_xattr = false;
x->verbose = false;
x->dest_info = NULL;
@ -305,7 +306,8 @@ cp_option_init (struct cp_options *x)
#ifdef ENABLE_MATCHPATHCON
/* Modify file context to match the specified policy.
If an error occurs the file will remain with the default directory
context. */
context. Note this sets the context to that returned by matchpathcon,
and thus discards MLS levels and user identity of the FILE. */
static void
setdefaultfilecon (char const *file)
{
@ -359,7 +361,8 @@ setdefaultfilecon (char const *file)
first_call = false;
/* If there's an error determining the context, or it has none,
return to allow default context */
return to allow default context. Note the "<<none>>" check
is only needed for libselinux < 1.20 (2005-01-04). */
if ((matchpathcon (file, st.st_mode, &scontext) != 0)
|| STREQ (scontext, "<<none>>"))
{
@ -644,8 +647,8 @@ In the 4th form, create all components of the given DIRECTORY(ies).\n\
"), stdout);
fputs (_("\
--preserve-context preserve SELinux security context\n\
-Z, --context=CONTEXT set SELinux security context of files and directories\
\n\
-Z, --context[=CTX] set SELinux security context of destination file to\n\
default type, or to CTX if specified\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
@ -791,7 +794,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:pt:TvS:Z:", long_options,
while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z", long_options,
NULL)) != -1)
{
switch (optc)
@ -863,7 +866,7 @@ main (int argc, char **argv)
break;
case PRESERVE_CONTEXT_OPTION:
if ( ! selinux_enabled)
if (! selinux_enabled)
{
error (0, 0, _("WARNING: ignoring --preserve-context; "
"this kernel is not SELinux-enabled"));
@ -873,14 +876,27 @@ main (int argc, char **argv)
use_default_selinux_context = false;
break;
case 'Z':
if ( ! selinux_enabled)
if (selinux_enabled)
{
error (0, 0, _("WARNING: ignoring --context (-Z); "
"this kernel is not SELinux-enabled"));
break;
/* Disable use of the install(1) specific setdefaultfilecon().
Note setdefaultfilecon() is different from the newer and more
generic restorecon() in that the former sets the context of
the dest files to that returned by matchpathcon directly,
thus discarding MLS level and user identity of the file.
TODO: consider removing setdefaultfilecon() in future. */
use_default_selinux_context = false;
if (optarg)
scontext = optarg;
else
x.set_security_context = true;
}
else if (optarg)
{
error (0, 0,
_("warning: ignoring --context; "
"it requires an SELinux-enabled kernel"));
}
scontext = optarg;
use_default_selinux_context = false;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@ -897,11 +913,6 @@ main (int argc, char **argv)
error (EXIT_FAILURE, 0,
_("target directory not allowed when installing a directory"));
if (x.preserve_security_context && scontext != NULL)
error (EXIT_FAILURE, 0,
_("cannot force target context to %s and preserve it"),
quote (scontext));
if (backup_suffix_string)
simple_backup_suffix = xstrdup (backup_suffix_string);
@ -910,6 +921,10 @@ main (int argc, char **argv)
version_control_string)
: no_backups);
if (x.preserve_security_context && (x.set_security_context || scontext))
error (EXIT_FAILURE, 0,
_("cannot set target context and preserve it"));
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),

View File

@ -312,6 +312,10 @@ RELEASE_YEAR = \
`sed -n '/.*COPYRIGHT_YEAR = \([0-9][0-9][0-9][0-9]\) };/s//\1/p' \
$(top_srcdir)/lib/version-etc.c`
selinux_sources = \
src/selinux.c \
src/selinux.h
copy_sources = \
src/copy.c \
src/cp-hash.c \
@ -323,12 +327,13 @@ copy_sources = \
# to install before applying any user-specified name transformations.
transform = s/ginstall/install/; $(program_transform_name)
src_ginstall_SOURCES = src/install.c src/prog-fprintf.c $(copy_sources)
src_ginstall_SOURCES = src/install.c src/prog-fprintf.c $(copy_sources) \
$(selinux_sources)
# This is for the '[' program. Automake transliterates '[' and '/' to '_'.
src___SOURCES = src/lbracket.c
src_cp_SOURCES = src/cp.c $(copy_sources)
src_cp_SOURCES = src/cp.c $(copy_sources) $(selinux_sources)
src_dir_SOURCES = src/ls.c src/ls-dir.c
src_vdir_SOURCES = src/ls.c src/ls-vdir.c
src_id_SOURCES = src/id.c src/group-list.c
@ -341,12 +346,15 @@ src_kill_SOURCES = src/kill.c src/operand2sig.c
src_realpath_SOURCES = src/realpath.c src/relpath.c src/relpath.h
src_timeout_SOURCES = src/timeout.c src/operand2sig.c
src_mv_SOURCES = src/mv.c src/remove.c $(copy_sources)
src_mv_SOURCES = src/mv.c src/remove.c $(copy_sources) $(selinux_sources)
src_rm_SOURCES = src/rm.c src/remove.c
src_mkdir_SOURCES = src/mkdir.c src/prog-fprintf.c
src_mkdir_SOURCES = src/mkdir.c src/prog-fprintf.c $(selinux_sources)
src_rmdir_SOURCES = src/rmdir.c src/prog-fprintf.c
src_mkfifo_SOURCES = src/mkfifo.c $(selinux_sources)
src_mknod_SOURCES = src/mknod.c $(selinux_sources)
src_df_SOURCES = src/df.c src/find-mount-point.c
src_stat_SOURCES = src/stat.c src/find-mount-point.c

View File

@ -29,6 +29,7 @@
#include "prog-fprintf.h"
#include "quote.h"
#include "savewd.h"
#include "selinux.h"
#include "smack.h"
/* The official name of this program (e.g., no 'g' prefix). */
@ -65,8 +66,8 @@ Create the DIRECTORY(ies), if they do not already exist.\n\
-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);
@ -91,6 +92,9 @@ struct mkdir_options
/* File mode bits affected by MODE. */
mode_t mode_bits;
/* Set the SELinux File Context. */
bool set_security_context;
/* If not null, format to use when reporting newly made directories. */
char const *created_directory_format;
};
@ -113,12 +117,16 @@ static int
make_ancestor (char const *dir, char const *component, void *options)
{
struct mkdir_options const *o = options;
int r;
if (o->set_security_context && defaultcon (dir, S_IFDIR) < 0)
error (0, errno, _("failed to set default creation context for %s"),
quote (dir));
mode_t user_wx = S_IWUSR | S_IXUSR;
bool self_denying_umask = (o->umask_value & user_wx) != 0;
if (self_denying_umask)
umask (o->umask_value & ~user_wx);
r = mkdir (component, S_IRWXUGO);
int r = mkdir (component, S_IRWXUGO);
if (self_denying_umask)
{
int mkdir_errno = errno;
@ -138,11 +146,46 @@ static int
process_dir (char *dir, struct savewd *wd, void *options)
{
struct mkdir_options const *o = options;
return (make_dir_parents (dir, wd, o->make_ancestor_function, options,
o->mode, announce_mkdir,
o->mode_bits, (uid_t) -1, (gid_t) -1, true)
? EXIT_SUCCESS
: EXIT_FAILURE);
bool set_defaultcon = false;
/* If possible set context before DIR created. */
if (o->set_security_context)
{
if (! o->make_ancestor_function)
set_defaultcon = true;
else
{
char *pdir = dir_name (dir);
struct stat st;
if (STREQ (pdir, ".")
|| (stat (pdir, &st) == 0 && S_ISDIR (st.st_mode)))
set_defaultcon = true;
free (pdir);
}
if (set_defaultcon && defaultcon (dir, S_IFDIR) < 0)
error (0, errno, _("failed to set default creation context for %s"),
quote (dir));
}
int ret = (make_dir_parents (dir, wd, o->make_ancestor_function, options,
o->mode, announce_mkdir,
o->mode_bits, (uid_t) -1, (gid_t) -1, true)
? EXIT_SUCCESS
: EXIT_FAILURE);
/* FIXME: Due to the current structure of make_dir_parents()
we don't have the facility to call defaultcon() before the
final component of DIR is created. So for now, create the
final component with the context from previous component
and here we set the context for the final component. */
if (ret == EXIT_SUCCESS && o->set_security_context && ! set_defaultcon)
{
if (restorecon (last_component (dir), false, false) < 0)
error (0, errno, _("failed to set restore context for %s"),
quote (dir));
}
return ret;
}
int
@ -157,6 +200,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]);
@ -166,7 +210,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)
{
@ -180,7 +224,24 @@ main (int argc, char **argv)
options.created_directory_format = _("created directory %s");
break;
case 'Z':
scontext = optarg;
if (is_smack_enabled ())
{
/* We don't yet support -Z to restore context with SMACK. */
scontext = optarg;
}
else if (is_selinux_enabled () > 0)
{
if (optarg)
scontext = optarg;
else
options.set_security_context = true;
}
else if (optarg)
{
error (0, 0,
_("warning: ignoring --context; "
"it requires an SELinux/SMACK-enabled kernel"));
}
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@ -195,6 +256,9 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
/* FIXME: This assumes mkdir() is done in the same process.
If that's not always the case we would need to call this
like we do when options.set_security_context == true. */
if (scontext)
{
int ret = 0;

View File

@ -26,6 +26,7 @@
#include "error.h"
#include "modechange.h"
#include "quote.h"
#include "selinux.h"
#include "smack.h"
/* The official name of this program (e.g., no 'g' prefix). */
@ -60,7 +61,8 @@ Create named pipes (FIFOs) with the given NAMEs.\n\
-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\n\
default type, or CTX if specified\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@ -77,6 +79,7 @@ main (int argc, char **argv)
int exit_status = EXIT_SUCCESS;
int optc;
security_context_t scontext = NULL;
bool set_security_context = false;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@ -86,7 +89,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 +97,24 @@ main (int argc, char **argv)
specified_mode = optarg;
break;
case 'Z':
scontext = optarg;
if (is_smack_enabled ())
{
/* We don't yet support -Z to restore context with SMACK. */
scontext = optarg;
}
else if (is_selinux_enabled () > 0)
{
if (optarg)
scontext = optarg;
else
set_security_context = true;
}
else if (optarg)
{
error (0, 0,
_("warning: ignoring --context; "
"it requires an SELinux/SMACK-enabled kernel"));
}
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@ -140,17 +160,21 @@ main (int argc, char **argv)
}
for (; optind < argc; ++optind)
if (mkfifo (argv[optind], newmode) != 0)
{
error (0, errno, _("cannot create fifo %s"), quote (argv[optind]));
exit_status = EXIT_FAILURE;
}
else if (specified_mode && lchmod (argv[optind], newmode) != 0)
{
error (0, errno, _("cannot set permissions of `%s'"),
quote (argv[optind]));
exit_status = EXIT_FAILURE;
}
{
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]));
exit_status = EXIT_FAILURE;
}
else if (specified_mode && lchmod (argv[optind], newmode) != 0)
{
error (0, errno, _("cannot set permissions of `%s'"),
quote (argv[optind]));
exit_status = EXIT_FAILURE;
}
}
exit (exit_status);
}

View File

@ -26,6 +26,7 @@
#include "error.h"
#include "modechange.h"
#include "quote.h"
#include "selinux.h"
#include "smack.h"
#include "xstrtol.h"
@ -62,7 +63,8 @@ Create the special file NAME of the given TYPE.\n\
-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\n\
default type, or to CTX if specified\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@ -94,6 +96,7 @@ main (int argc, char **argv)
int expected_operands;
mode_t node_type;
security_context_t scontext = NULL;
bool set_security_context = false;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@ -103,7 +106,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 +114,24 @@ main (int argc, char **argv)
specified_mode = optarg;
break;
case 'Z':
scontext = optarg;
if (is_smack_enabled ())
{
/* We don't yet support -Z to restore context with SMACK. */
scontext = optarg;
}
else if (is_selinux_enabled () > 0)
{
if (optarg)
scontext = optarg;
else
set_security_context = true;
}
else if (optarg)
{
error (0, 0,
_("warning: ignoring --context; "
"it requires an SELinux/SMACK-enabled kernel"));
}
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@ -224,12 +244,17 @@ 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]));
}
break;
case 'p': /* 'pipe' */
if (set_security_context)
defaultcon (argv[optind], S_IFIFO);
if (mkfifo (argv[optind], newmode) != 0)
error (EXIT_FAILURE, errno, "%s", quote (argv[optind]));
break;

View File

@ -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'},
@ -120,6 +121,7 @@ cp_option_init (struct cp_options *x)
x->preserve_timestamps = true;
x->explicit_no_preserve_mode= false;
x->preserve_security_context = selinux_enabled;
x->set_security_context = false;
x->reduce_diagnostics = false;
x->data_copy_required = true;
x->require_preserve = false; /* FIXME: maybe make this an option */
@ -316,6 +318,8 @@ If you specify more than one of -i, -f, -n, only the final one takes effect.\n\
than the destination file or when the\n\
destination file is missing\n\
-v, --verbose explain what is being done\n\
-Z, --context set SELinux security context of destination\n\
file to default type\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@ -350,6 +354,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]);
@ -368,7 +373,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 +423,14 @@ 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)
{
x.preserve_security_context = false;
x.set_security_context = true;
}
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:

View File

@ -85,7 +85,7 @@ Usage: %s CONTEXT COMMAND [args]\n\
or: %s [ -c ] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n\
"), program_name, program_name);
fputs (_("\
Run a program in a different security context.\n\
Run a program in a different SELinux security context.\n\
With neither CONTEXT nor COMMAND, print the current security context.\n\
"), stdout);
@ -197,8 +197,8 @@ main (int argc, char **argv)
}
if (is_selinux_enabled () != 1)
error (EXIT_FAILURE, 0,
_("%s may be used only on a SELinux kernel"), program_name);
error (EXIT_FAILURE, 0, _("%s may be used only on a SELinux kernel"),
program_name);
if (context)
{
@ -223,8 +223,7 @@ main (int argc, char **argv)
/* compute result of process transition */
if (security_compute_create (cur_context, file_context,
SECCLASS_PROCESS, &new_context) != 0)
error (EXIT_FAILURE, errno,
_("failed to compute a new context"));
error (EXIT_FAILURE, errno, _("failed to compute a new context"));
/* free contexts */
freecon (file_context);
freecon (cur_context);

View File

@ -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: \

View File

@ -1,5 +1,5 @@
#!/bin/sh
# Ensure that cp -a and cp --preserve=context work properly.
# Ensure that cp -Z, -a and cp --preserve=context work properly.
# In particular, test on a writable NFS partition.
# Check also locally if --preserve=context, -a and --preserve=all
# does work
@ -41,6 +41,45 @@ test -s err && fail=1 #there must be no stderr output for -a
ls -Z e | grep $ctx || fail=1
ls -Z f | grep $ctx || fail=1
# Check restorecon (-Z) functionality for file and directory
get_selinux_type() { ls -Zd "$1" | sed -n 's/.*:\(.*_t\):.*/\1/p'; }
# Also make a dir with our known context
mkdir c_d || framework_failure_
chcon $ctx c_d || framework_failure_
# Get the type of this known context for file and dir
old_type_f=$(get_selinux_type c)
old_type_d=$(get_selinux_type c_d)
# Setup copies for manipulation with restorecon
# and get the adjusted type for comparison
cp -a c Z1 || fail=1
cp -a c_d Z1_d || fail=1
if restorecon Z1 Z1_d 2>/dev/null; then
new_type_f=$(get_selinux_type Z1)
new_type_d=$(get_selinux_type Z1_d)
# Ensure -Z sets the type like restorecon does
cp -Z c Z2 || fail=1
cpZ_type_f=$(get_selinux_type Z2)
test "$cpZ_type_f" = "$new_type_f" || fail=1
# Ensuze -Z overrides -a and that dirs are handled too
cp -aZ c Z3 || fail=1
cp -aZ c_d Z3_d || fail=1
cpaZ_type_f=$(get_selinux_type Z3)
cpaZ_type_d=$(get_selinux_type Z3_d)
test "$cpaZ_type_f" = "$new_type_f" || fail=1
test "$cpaZ_type_d" = "$new_type_d" || fail=1
# Ensure -Z sets the type for existing files
mkdir -p existing/c_d || framework_failure_
touch existing/c || framework_failure_
cp -aZ c c_d existing || fail=1
cpaZ_type_f=$(get_selinux_type existing/c)
cpaZ_type_d=$(get_selinux_type existing/c_d)
test "$cpaZ_type_f" = "$new_type_f" || fail=1
test "$cpaZ_type_d" = "$new_type_d" || fail=1
fi
skip=0
# Create a file system, then mount it with the context=... option.
dd if=/dev/zero of=blob bs=8192 count=200 || skip=1
@ -97,7 +136,7 @@ echo > g
cp --preserve=context f g 2> out && fail=1
# Here, we *do* expect the destination to be empty.
test -s g && fail=1
sed "s/ .g' to .*//" out > k
sed "s/ .g'.*//" out > k
mv k out
compare exp out || fail=1
@ -107,8 +146,39 @@ echo > g
cp -a --preserve=context f g 2> out2 && fail=1
# Here, we *do* expect the destination to be empty.
test -s g && fail=1
sed "s/ .g' to .*//" out2 > k
sed "s/ .g'.*//" out2 > k
mv k out2
compare exp out2 || fail=1
for no_g_cmd in '' 'rm -f g'; do
# restorecon equivalent. Note even though the context
# returned from matchpathcon() will not match $ctx
# the resulting ENOTSUP warning will be suppressed.
# With absolute path
$no_g_cmd
cp -Z f $(realpath g) || fail=1
# With relative path
$no_g_cmd
cp -Z f g || fail=1
# -Z overrides -a
$no_g_cmd
cp -Z -a f g || fail=1
# -Z doesn't take an arg
$no_g_cmd
cp -Z "$ctx" f g && fail=1
# Explicit context
$no_g_cmd
# Explicitly defaulting to the global $ctx should work
cp --context="$ctx" f g || fail=1
# --context overrides -a
$no_g_cmd
cp -a --context="$ctx" f g || fail=1
done
# Mutually exlusive options
cp -Z --preserve=context f g && fail=1
cp --preserve=context -Z f g && fail=1
cp --preserve=context --context="$ctx" f g && fail=1
Exit $fail

View File

@ -567,6 +567,7 @@ all_tests = \
tests/mkdir/parents.sh \
tests/mkdir/perm.sh \
tests/mkdir/selinux.sh \
tests/mkdir/restorecon.sh \
tests/mkdir/special-1.sh \
tests/mkdir/t-slash.sh \
tests/mv/acl.sh \

72
tests/mkdir/restorecon.sh Executable file
View File

@ -0,0 +1,72 @@
#!/bin/sh
# test mkdir, mknod, mkfifo -Z
# Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
print_ver_ mkdir
require_selinux_
get_selinux_type() { ls -Zd "$1" | sed -n 's/.*:\(.*_t\):.*/\1/p'; }
mkdir subdir || framework_failure_
chcon 'root:object_r:tmp_t:s0' subdir || framework_failure_
cd subdir
# --- mkdir -Z ---
# Since in a tmp_t dir, dirs can be created as user_tmp_t ...
mkdir standard || framework_failure_
mkdir restored || framework_failure_
if restorecon restored 2>/dev/null; then
# ... but when restored can be set to user_home_t
# So ensure the type for these mkdir -Z cases matches
# the directory type as set by restorecon.
mkdir -Z single || fail=1
# Run these as separate processes in case global context
# set for an arg, impacts on another arg
for dir in single_p single_p/existing multi/ple; do
mkdir -Zp "$dir" || fail=1
done
restored_type=$(get_selinux_type 'restored')
test "$(get_selinux_type 'single')" = "$restored_type" || fail=1
test "$(get_selinux_type 'single_p')" = "$restored_type" || fail=1
test "$(get_selinux_type 'single_p/existing')" = "$restored_type" || fail=1
test "$(get_selinux_type 'multi')" = "$restored_type" || fail=1
test "$(get_selinux_type 'multi/ple')" = "$restored_type" || fail=1
fi
if test "$fail" = '1'; then
ls -UZd standard restored
ls -UZd single single_p single_p/existing multi multi/ple
fi
# --- mknod -Z and mkfifo -Z ---
# Assume if selinux present that we can create fifos
for cmd_w_arg in 'mknod' 'mkfifo'; do
# In OpenBSD's /bin/sh, mknod is a shell built-in.
# Running via "env" ensures we run our program and not the built-in.
basename="$cmd_w_arg"
test "$basename" = 'mknod' && nt='p' || nt=''
env -- $cmd_w_arg $basename $nt || fail=1
env -- $cmd_w_arg ${basename}_restore $nt || fail=1
if restorecon ${basename}_restore 2>/dev/null; then
env -- $cmd_w_arg -Z ${basename}_Z $nt || fail=1
restored_type=$(get_selinux_type "${basename}_restore")
test "$(get_selinux_type ${basename}_Z)" = "$restored_type" || fail=1
fi
done
Exit $fail

View File

@ -32,7 +32,7 @@ msg="failed to set default file creation context to '$c':"
for cmd_w_arg in 'mkdir dir' 'mknod b p' 'mkfifo f'; do
# In OpenBSD's /bin/sh, mknod is a shell built-in.
# Running via "env" ensures we run our program and not the built-in.
env -- $cmd_w_arg -Z $c 2> out && fail=1
env -- $cmd_w_arg --context=$c 2> out && fail=1
set $cmd_w_arg; cmd=$1
echo "$cmd: $msg" > exp || fail=1