-#serial 111 -*- autoconf -*-
+#serial 112 -*- autoconf -*-
dnl Misc type-related macros for coreutils.
LIBS="$LIBS $LIB_SELINUX"
# Used by selinux.c.
AC_CHECK_FUNCS([mode_to_security_class], [], [])
- # Used by install.c.
- AC_CHECK_FUNCS([matchpathcon_init_prefix], [],
- [
- if test "$with_selinux" != no; then
- case "$ac_cv_search_setfilecon:$ac_cv_header_selinux_selinux_h" in
- no:*) # SELinux disabled
- ;;
- *:no) # SELinux disabled
- ;;
- *)
- AC_MSG_WARN([SELinux enabled, but matchpathcon_init_prefix not found])
- AC_MSG_WARN([The install utility may run slowly])
- esac
- fi
- ])
LIBS=$coreutils_saved_libs
# Used by sort.c.
{
/* 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 (new_dst && defaultcon (x->set_security_context, dst_name, mode) < 0
&& ! ignorable_ctx_err (errno))
{
error (0, errno,
}
/* Reset the security context of DST_NAME, to that already set
- as the process default if PROCESS_LOCAL is true. Otherwise
+ as the process default if !X->set_security_context. 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. */
+ failure, when allowed by various settings in X.
+ Return false on failure, true on success. */
bool
-set_file_security_ctx (char const *dst_name, bool process_local,
+set_file_security_ctx (char const *dst_name,
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 (! restorecon (x->set_security_context, dst_name, recurse))
{
if (all_errors || (some_errors && !errno_unsupported (errno)))
error (0, errno, _("failed to set the security context of %s"),
if ((x->set_security_context || x->preserve_security_context)
&& 0 <= dest_desc)
{
- if (! set_file_security_ctx (dst_name, x->preserve_security_context,
- false, x))
+ if (! set_file_security_ctx (dst_name, false, x))
{
if (x->require_preserve_context)
{
if (x->set_security_context)
{
/* -Z failures are only warnings currently. */
- (void) set_file_security_ctx (dst_name, false, true, x);
+ (void) set_file_security_ctx (dst_name, true, x);
}
if (rename_succeeded)
descendents, so use it to set the context for existing dirs here.
This will also give earlier indication of failure to set ctx. */
if (x->set_security_context || x->preserve_security_context)
- if (! set_file_security_ctx (dst_name, x->preserve_security_context,
- false, x))
+ if (! set_file_security_ctx (dst_name, false, x))
{
if (x->require_preserve_context)
goto un_backup;
if (!new_dst && !x->copy_as_regular && !S_ISDIR (src_mode)
&& (x->set_security_context || x->preserve_security_context))
{
- if (! set_file_security_ctx (dst_name, x->preserve_security_context,
- false, x))
+ if (! set_file_security_ctx (dst_name, false, x))
{
if (x->require_preserve_context)
goto un_backup;
# include <stdbool.h>
# include "hash.h"
+struct selabel_handle;
+
/* Control creation of sparse files (files with holes). */
enum Sparse_type
{
bool preserve_timestamps;
bool explicit_no_preserve_mode;
- /* If true, attempt to set specified security context */
- bool set_security_context;
+ /* If non-null, attempt to set specified security context */
+ struct selabel_handle *set_security_context;
/* Enabled for mv, and for cp by the --preserve=links option.
If true, attempt to preserve in the destination files any
mode_t mode, bool new_dst,
const struct cp_options *x);
-extern bool set_file_security_ctx (char const *dst_name, bool process_local,
+extern bool set_file_security_ctx (char const *dst_name,
bool recurse, const struct cp_options *x);
void dest_info_init (struct cp_options *);
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
-#include <selinux/selinux.h>
+#include <selinux/label.h>
#include "system.h"
#include "argmatch.h"
if (! *new_dst
&& (x->set_security_context || x->preserve_security_context))
{
- if (! set_file_security_ctx (dir, x->preserve_security_context,
- false, x)
+ if (! set_file_security_ctx (dir, false, x)
&& x->require_preserve_context)
- return false;
+ return false;
}
*slash++ = '/';
x->explicit_no_preserve_mode = 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->set_security_context = NULL; /* -Z, set sys default context. */
x->preserve_xattr = false;
x->reduce_diagnostics = false;
x->require_preserve_xattr = false;
if (optarg)
scontext = optarg;
else
- x.set_security_context = true;
+ {
+ x.set_security_context = selabel_open (SELABEL_CTX_FILE,
+ NULL, 0);
+ if (! x.set_security_context)
+ error (0, errno, _("warning: ignoring --context"));
+ }
}
else if (optarg)
{
/* 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 && !restorecon (NULL, dst_path, 0))
+ error (...);
*/
if (scontext && setfscreatecon (se_const (scontext)) < 0)
die (EXIT_FAILURE, errno,
#include <signal.h>
#include <pwd.h>
#include <grp.h>
-#include <selinux/selinux.h>
+#include <selinux/label.h>
#include <sys/wait.h>
#include "system.h"
# define lchown(name, uid, gid) chown (name, uid, gid)
#endif
-#if ! HAVE_MATCHPATHCON_INIT_PREFIX
-# define matchpathcon_init_prefix(a, p) /* empty */
-#endif
-
/* The user name that will own the files, or NULL to make the owner
the current user ID. */
static char *owner_name;
x->update = 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->set_security_context = NULL; /* Whether to set sys default context. */
x->preserve_xattr = false;
x->verbose = false;
x->dest_info = NULL;
x->src_info = NULL;
}
-#ifdef ENABLE_MATCHPATHCON
+static struct selabel_handle *
+get_labeling_handle (void)
+{
+ static bool initialized;
+ static struct selabel_handle *hnd;
+ if (!initialized)
+ {
+ initialized = true;
+ hnd = selabel_open (SELABEL_CTX_FILE, NULL, 0);
+ if (!hnd)
+ error (0, errno, _("warning: security labeling handle failed"));
+ }
+ return hnd;
+}
+
/* Modify file context to match the specified policy.
If an error occurs the file will remain with the default directory
- context. Note this sets the context to that returned by matchpathcon,
+ context. Note this sets the context to that returned by selabel_lookup
and thus discards MLS levels and user identity of the FILE. */
static void
setdefaultfilecon (char const *file)
{
struct stat st;
char *scontext = NULL;
- static bool first_call = true;
if (selinux_enabled != 1)
{
if (lstat (file, &st) != 0)
return;
- if (first_call && IS_ABSOLUTE_FILE_NAME (file))
- {
- /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
- is an optimization to minimize the expense of the following
- matchpathcon call. Do it only once, just before the first
- matchpathcon call. We *could* call matchpathcon_fini after
- the final matchpathcon call, but that's not necessary, since
- by then we're about to exit, and besides, the buffers it
- would free are still reachable. */
- char const *p0;
- char const *p = file + 1;
- while (ISSLASH (*p))
- ++p;
-
- /* Record final leading slash, for when FILE starts with two or more. */
- p0 = p - 1;
-
- if (*p)
- {
- char *prefix;
- do
- {
- ++p;
- }
- while (*p && !ISSLASH (*p));
-
- prefix = malloc (p - p0 + 2);
- if (prefix)
- {
- stpcpy (stpncpy (prefix, p0, p - p0), "/");
- matchpathcon_init_prefix (NULL, prefix);
- free (prefix);
- }
- }
- }
- first_call = false;
-
- /* If there's an error determining the context, or it has none,
- 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>>"))
+ struct selabel_handle *hnd = get_labeling_handle ();
+ if (!hnd)
+ return;
+ if (selabel_lookup (hnd, &scontext, file, st.st_mode) != 0)
{
- if (scontext != NULL)
- freecon (scontext);
+ if (errno != ENOENT)
+ error (0, errno, _("warning: %s: context lookup failed"),
+ quotef (file));
return;
}
quotef_n (0, file), quote_n (1, scontext));
freecon (scontext);
- return;
}
-#else
-static void
-setdefaultfilecon (char const *file)
-{
- (void) file;
-}
-#endif
/* FILE is the last operand of this command. Return true if FILE is a
directory. But report an error there is a problem accessing FILE,
make_ancestor (char const *dir, char const *component, void *options)
{
struct cp_options const *x = options;
- if (x->set_security_context && defaultcon (component, S_IFDIR) < 0
+ if (x->set_security_context
+ && defaultcon (x->set_security_context, component, S_IFDIR) < 0
&& ! ignorable_ctx_err (errno))
error (0, errno, _("failed to set default creation context for %s"),
quoteaf (dir));
and here we set the context for the final component. */
if (ret == EXIT_SUCCESS && x->set_security_context)
{
- if (! restorecon (last_component (dir), false, false)
+ if (! restorecon (x->set_security_context, last_component (dir), false)
&& ! ignorable_ctx_err (errno))
error (0, errno, _("failed to restore context for %s"),
quoteaf (dir));
/* 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,
+ the dest files to that returned by selabel_lookup 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;
+ x.set_security_context = get_labeling_handle ();
}
else if (optarg)
{
src_basenc_SOURCES = src/basenc.c
src_basenc_CPPFLAGS = -DBASE_TYPE=42 $(AM_CPPFLAGS)
-src_ginstall_CPPFLAGS = -DENABLE_MATCHPATHCON=1 $(AM_CPPFLAGS)
-
src_expand_SOURCES = src/expand.c src/expand-common.c
src_unexpand_SOURCES = src/unexpand.c src/expand-common.c
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
-#include <selinux/selinux.h>
+#include <selinux/label.h>
#include "system.h"
#include "die.h"
mode_t mode_bits;
/* Set the SELinux File Context. */
- bool set_security_context;
+ struct selabel_handle *set_security_context;
/* If not null, format to use when reporting newly made directories. */
char const *created_directory_format;
{
struct mkdir_options const *o = options;
- if (o->set_security_context && defaultcon (component, S_IFDIR) < 0
+ if (o->set_security_context
+ && defaultcon (o->set_security_context, component, S_IFDIR) < 0
&& ! ignorable_ctx_err (errno))
error (0, errno, _("failed to set default creation context for %s"),
quoteaf (dir));
/* If possible set context before DIR created. */
if (o->set_security_context)
{
- if (! o->make_ancestor_function && defaultcon (dir, S_IFDIR) < 0
+ if (! o->make_ancestor_function
+ && defaultcon (o->set_security_context, dir, S_IFDIR) < 0
&& ! ignorable_ctx_err (errno))
error (0, errno, _("failed to set default creation context for %s"),
quoteaf (dir));
if (ret == EXIT_SUCCESS && o->set_security_context
&& o->make_ancestor_function)
{
- if (! restorecon (last_component (dir), false, false)
+ if (! restorecon (o->set_security_context, last_component (dir), false)
&& ! ignorable_ctx_err (errno))
error (0, errno, _("failed to restore context for %s"),
quoteaf (dir));
options.mode = S_IRWXUGO;
options.mode_bits = 0;
options.created_directory_format = NULL;
- options.set_security_context = false;
+ options.set_security_context = NULL;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
if (optarg)
scontext = optarg;
else
- options.set_security_context = true;
+ {
+ options.set_security_context = selabel_open (SELABEL_CTX_FILE,
+ NULL, 0);
+ if (! options.set_security_context)
+ error (0, errno, _("warning: ignoring --context"));
+ }
}
else if (optarg)
{
/* 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. */
+ like we do when options.set_security_context. */
if (scontext)
{
int ret = 0;
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
-#include <selinux/selinux.h>
+#include <selinux/label.h>
#include "system.h"
#include "die.h"
int exit_status = EXIT_SUCCESS;
int optc;
char const *scontext = NULL;
- bool set_security_context = false;
+ struct selabel_handle *set_security_context = NULL;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
if (optarg)
scontext = optarg;
else
- set_security_context = true;
+ {
+ set_security_context = selabel_open (SELABEL_CTX_FILE,
+ NULL, 0);
+ if (! set_security_context)
+ error (0, errno, _("warning: ignoring --context"));
+ }
}
else if (optarg)
{
for (; optind < argc; ++optind)
{
if (set_security_context)
- defaultcon (argv[optind], S_IFIFO);
+ defaultcon (set_security_context, argv[optind], S_IFIFO);
if (mkfifo (argv[optind], newmode) != 0)
{
error (0, errno, _("cannot create fifo %s"), quoteaf (argv[optind]));
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
-#include <selinux/selinux.h>
+#include <selinux/label.h>
#include "system.h"
#include "die.h"
size_t expected_operands;
mode_t node_type;
char const *scontext = NULL;
- bool set_security_context = false;
+ struct selabel_handle *set_security_context = NULL;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
if (optarg)
scontext = optarg;
else
- set_security_context = true;
+ {
+ set_security_context = selabel_open (SELABEL_CTX_FILE,
+ NULL, 0);
+ if (! set_security_context)
+ error (0, errno, _("warning: ignoring --context"));
+ }
}
else if (optarg)
{
#endif
if (set_security_context)
- defaultcon (argv[optind], node_type);
+ defaultcon (set_security_context, argv[optind], node_type);
if (mknod (argv[optind], newmode | node_type, device) != 0)
die (EXIT_FAILURE, errno, "%s", quotef (argv[optind]));
case 'p': /* 'pipe' */
if (set_security_context)
- defaultcon (argv[optind], S_IFIFO);
+ defaultcon (set_security_context, argv[optind], S_IFIFO);
if (mkfifo (argv[optind], newmode) != 0)
die (EXIT_FAILURE, errno, "%s", quotef (argv[optind]));
break;
#include <getopt.h>
#include <sys/types.h>
#include <assert.h>
-#include <selinux/selinux.h>
+#include <selinux/label.h>
#include "system.h"
#include "backupfile.h"
x->preserve_timestamps = true;
x->explicit_no_preserve_mode= false;
x->preserve_security_context = selinux_enabled;
- x->set_security_context = false;
+ x->set_security_context = NULL;
x->reduce_diagnostics = false;
x->data_copy_required = true;
x->require_preserve = false; /* FIXME: maybe make this an option */
if (selinux_enabled)
{
x.preserve_security_context = false;
- x.set_security_context = true;
+ x.set_security_context = selabel_open (SELABEL_CTX_FILE,
+ NULL, 0);
+ if (! x.set_security_context)
+ error (0, errno, _("warning: ignoring --context"));
}
break;
case_GETOPT_HELP_CHAR;
/* Written by Daniel Walsh <dwalsh@redhat.com> */
#include <config.h>
-#include <selinux/selinux.h>
+#include <selinux/label.h>
#include <selinux/context.h>
#include <sys/types.h>
-#include "die.h"
-#include "error.h"
#include "system.h"
-#include "canonicalize.h"
#include "xfts.h"
#include "selinux.h"
-#if HAVE_SELINUX_SELINUX_H
+#if HAVE_SELINUX_LABEL_H
# if ! HAVE_MODE_TO_SECURITY_CLASS
/*
}
/*
- This function takes a path and a mode, it calls computecon to get the
+ This function takes a handle, path and mode, it calls computecon to get the
label of the path object if the current process created it, then it calls
- matchpathcon to get the default type for the object. It substitutes the
+ selabel_lookup to get the default type for the object. It substitutes the
default type into label. It tells the SELinux Kernel to label all new file
system objects created by the current process with this label.
Returns -1 on failure. errno will be set appropriately.
*/
int
-defaultcon (char const *path, mode_t mode)
+defaultcon (struct selabel_handle *selabel_handle,
+ char const *path, mode_t mode)
{
int rc = -1;
char *scon = NULL;
context_t scontext = 0, tcontext = 0;
const char *contype;
char *constr;
- char *newpath = NULL;
- if (! IS_ABSOLUTE_FILE_NAME (path))
- {
- /* Generate absolute path as required by subsequent matchpathcon(),
- with libselinux < 2.1.5 2011-0826. */
- newpath = canonicalize_filename_mode (path, CAN_MISSING);
- if (! newpath)
- die (EXIT_FAILURE, errno, _("error canonicalizing %s"),
- quoteaf (path));
- path = newpath;
- }
-
- if (matchpathcon (path, mode, &scon) < 0)
+ if (selabel_lookup (selabel_handle, &scon, path, mode) < 0)
{
/* "No such file or directory" is a confusing error,
when processing files, when in fact it was the
context_free (tcontext);
freecon (scon);
freecon (tcon);
- free (newpath);
return rc;
}
/*
- This function takes a PATH of an existing file system object, and a LOCAL
- boolean that indicates whether the function should set the object's label
- to the default for the local process, or one using system wide settings.
- If LOCAL == true, it will ask the SELinux Kernel what the default label
- for all objects created should be and then sets the label on the object.
- Otherwise it calls matchpathcon on the object to ask the system what the
- default label should be, extracts the type field and then modifies the file
+ If SELABEL_HANDLE is null, set PATH's label to the default to the
+ local process. Otherwise use selabel_lookup to determine the
+ default label, extract the type field and then modify the file
system object. Note only the type field is updated, thus preserving MLS
levels and user identity etc. of the PATH.
Returns -1 on failure. errno will be set appropriately.
*/
static int
-restorecon_private (char const *path, bool local)
+restorecon_private (struct selabel_handle *selabel_handle, char const *path)
{
int rc = -1;
struct stat sb;
char *constr;
int fd;
- if (local)
+ if (!selabel_handle)
{
if (getfscreatecon (&tcon) < 0)
return rc;
return rc;
}
rc = lsetfilecon (path, tcon);
+ int err = errno;
freecon (tcon);
+ errno = err;
return rc;
}
goto quit;
}
- if (matchpathcon (path, sb.st_mode, &scon) < 0)
+ if (selabel_lookup (selabel_handle, &scon, path, sb.st_mode) < 0)
{
/* "No such file or directory" is a confusing error,
when processing files, when in fact it was the
associated default context that was not found.
Therefore map the error to something more appropriate
- to the context in which we're using matchpathcon(). */
+ to the context in which we're using selabel_lookup. */
if (errno == ENOENT)
errno = ENODATA;
goto quit;
else
rc = lsetfilecon (path, constr);
-quit:
+ quit:;
+ int err = errno;
if (fd != -1)
close (fd);
context_free (scontext);
context_free (tcontext);
freecon (scon);
freecon (tcon);
+ errno = err;
return rc;
}
/*
This function takes three parameters:
+ SELABEL_HANDLE for selabel_lookup, or null to preserve.
+
PATH of an existing file system object.
A RECURSE boolean which if the file system object is a directory, will
call restorecon_private on every file system object in the directory.
- A LOCAL boolean that indicates whether the function should set object labels
- to the default for the local process, or use system wide settings.
-
- Returns false on failure. errno will be set appropriately.
+ Return false on failure. errno will be set appropriately.
*/
bool
-restorecon (char const *path, bool recurse, bool local)
+restorecon (struct selabel_handle *selabel_handle,
+ char const *path, bool recurse)
{
- char *newpath = NULL;
- FTS *fts;
- bool ok = true;
-
- if (! IS_ABSOLUTE_FILE_NAME (path) && ! local)
- {
- /* Generate absolute path as required by subsequent matchpathcon(),
- with libselinux < 2.1.5 2011-0826. Also generating the absolute
- path before the fts walk, will generate absolute paths in the
- fts entries, which may be quicker to process in any case. */
- newpath = canonicalize_filename_mode (path, CAN_MISSING);
- if (! newpath)
- die (EXIT_FAILURE, errno, _("error canonicalizing %s"),
- quoteaf (path));
- }
-
- const char *ftspath[2] = { newpath ? newpath : path, NULL };
-
if (! recurse)
- {
- ok = restorecon_private (*ftspath, local) != -1;
- free (newpath);
- return ok;
- }
+ return restorecon_private (selabel_handle, path) == 0;
- fts = xfts_open ((char *const *) ftspath, FTS_PHYSICAL, NULL);
- while (1)
- {
- FTSENT *ent;
+ char const *ftspath[2] = { path, NULL };
+ FTS *fts = xfts_open ((char *const *) ftspath, FTS_PHYSICAL, NULL);
- ent = fts_read (fts);
- if (ent == NULL)
- {
- if (errno != 0)
- {
- error (0, errno, _("fts_read failed"));
- ok = false;
- }
- break;
- }
+ int err = 0;
+ for (FTSENT *ent; (ent = fts_read (fts)); )
+ if (restorecon_private (selabel_handle, fts->fts_path) < 0)
+ err = errno;
- ok &= restorecon_private (fts->fts_path, local) != -1;
- }
+ if (errno != 0)
+ err = errno;
if (fts_close (fts) != 0)
- {
- error (0, errno, _("fts_close failed"));
- ok = false;
- }
+ err = errno;
- free (newpath);
- return ok;
+ return !err;
}
#endif
#ifndef COREUTILS_SELINUX_H
# define COREUTILS_SELINUX_H
+struct selabel_handle;
+
/* Return true if ERR corresponds to an unsupported request,
or if there is no context or it's inaccessible. */
static inline bool
return err == ENOTSUP || err == ENODATA;
}
-# if HAVE_SELINUX_SELINUX_H
+# if HAVE_SELINUX_LABEL_H
extern bool
-restorecon (char const *path, bool recurse, bool preserve);
+restorecon (struct selabel_handle *selabel_handle,
+ char const *path, bool recurse);
extern int
-defaultcon (char const *path, mode_t mode);
+defaultcon (struct selabel_handle *selabel_handle,
+ char const *path, mode_t mode);
# else
static inline bool
-restorecon (char const *path, bool recurse, bool preserve)
+restorecon (struct selabel_handle *selabel_handle,
+ char const *path, bool recurse)
{ errno = ENOTSUP; return false; }
static inline int
-defaultcon (char const *path, mode_t mode)
+defaultcon (struct selabel_handle *selabel_handle,
+ char const *path, mode_t mode)
{ errno = ENOTSUP; return -1; }
# endif