mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-08-05 16:19:23 +02:00
maint: port from matchpathcon to selabel_lookup
Ubuntu 20.10 is using a newer version of libselinux that complains that matchpathcon is obsolete. Rewrite the code that it uses the recommended selabel_lookup instead. * m4/jm-macros.m4 (coreutils_MACROS): Do not check for matchpathcon_init_prefix, as it is no longer used. * src/copy.c (set_file_security_ctx): Omit process_local arg, as it is equivalent to !x->set_security_context. All callers changed. * src/copy.h (struct cp_options): set_security_context is now of type struct selabel_handle *, not bool. All uses changed. * src/cp.c, src/install.c, src/mkdir.c, src/mkfifo.c, src/mknod.c: * src/mv.c: Include selinux/label.h. (main): Use selabel_open for set_security context. * src/install.c (matchpathcon_init_prefix): Remove; now unused. (get_labeling_handle): New static function. (setdefaultfilecon, main): Use it. (setdefaultfilecon): Do something regardless of ENABLE_MATCHPATHCON, which seems to be a revenant macro. (setdefaultfilecon): Use selabel_lookup instead of the obsolescent matchpathcon. Report an error unless it fails due to ENOENT. * src/local.mk (src_ginstall_CPPFLAGS): Remove. * src/selinux.c: Include selinux/label.h Do not include die.h, error.h, canonicalize.h. (defaultcon, restorecon_private, restorecon): New arg HANDLE. All callers changed. Use selabel_lookup rather than matchpathcon. (restorecon_private, restorecon): Don’t lose track of errno. * src/selinux.c, src/selinux.h: (restorecon): Don’t call ‘error’; that’s the caller’s job. Use HAVE_SELINUX_LABEL_H, not HAVE_SELINUX_SELINUX_H, in case there is some weird system with the former but not the latter. * src/selinux.h (struct selinux_handle): Add forward decl.
This commit is contained in:
+1
-16
@@ -1,4 +1,4 @@
|
||||
#serial 111 -*- autoconf -*-
|
||||
#serial 112 -*- autoconf -*-
|
||||
|
||||
dnl Misc type-related macros for coreutils.
|
||||
|
||||
@@ -52,21 +52,6 @@ AC_DEFUN([coreutils_MACROS],
|
||||
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.
|
||||
|
||||
+10
-13
@@ -1141,7 +1141,7 @@ set_process_security_ctx (char const *src_name, char const *dst_name,
|
||||
{
|
||||
/* 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,
|
||||
@@ -1154,21 +1154,21 @@ set_process_security_ctx (char const *src_name, char const *dst_name,
|
||||
}
|
||||
|
||||
/* 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"),
|
||||
@@ -1330,8 +1330,7 @@ copy_reg (char const *src_name, char const *dst_name,
|
||||
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)
|
||||
{
|
||||
@@ -2609,7 +2608,7 @@ copy_internal (char const *src_name, char const *dst_name,
|
||||
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)
|
||||
@@ -2819,8 +2818,7 @@ copy_internal (char const *src_name, char const *dst_name,
|
||||
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;
|
||||
@@ -3020,8 +3018,7 @@ copy_internal (char const *src_name, char const *dst_name,
|
||||
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;
|
||||
|
||||
+5
-3
@@ -22,6 +22,8 @@
|
||||
# include <stdbool.h>
|
||||
# include "hash.h"
|
||||
|
||||
struct selabel_handle;
|
||||
|
||||
/* Control creation of sparse files (files with holes). */
|
||||
enum Sparse_type
|
||||
{
|
||||
@@ -162,8 +164,8 @@ struct cp_options
|
||||
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
|
||||
@@ -294,7 +296,7 @@ extern bool set_process_security_ctx (char const *src_name,
|
||||
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 *);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <getopt.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/label.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "argmatch.h"
|
||||
@@ -531,10 +531,9 @@ make_dir_parents_private (char const *const_dir, size_t src_offset,
|
||||
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++ = '/';
|
||||
@@ -802,7 +801,7 @@ cp_option_init (struct cp_options *x)
|
||||
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;
|
||||
@@ -1116,7 +1115,12 @@ main (int argc, char **argv)
|
||||
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)
|
||||
{
|
||||
@@ -1197,8 +1201,8 @@ main (int argc, char **argv)
|
||||
/* 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,
|
||||
|
||||
+30
-65
@@ -23,7 +23,7 @@
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/label.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "system.h"
|
||||
@@ -65,10 +65,6 @@ static bool use_default_selinux_context = true;
|
||||
# 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;
|
||||
@@ -298,24 +294,37 @@ cp_option_init (struct cp_options *x)
|
||||
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)
|
||||
{
|
||||
@@ -325,51 +334,14 @@ setdefaultfilecon (char const *file)
|
||||
if (lstat (file, &st) != 0)
|
||||
return;
|
||||
|
||||
if (first_call && IS_ABSOLUTE_FILE_NAME (file))
|
||||
struct selabel_handle *hnd = get_labeling_handle ();
|
||||
if (!hnd)
|
||||
return;
|
||||
if (selabel_lookup (hnd, &scontext, file, st.st_mode) != 0)
|
||||
{
|
||||
/* 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>>"))
|
||||
{
|
||||
if (scontext != NULL)
|
||||
freecon (scontext);
|
||||
if (errno != ENOENT)
|
||||
error (0, errno, _("warning: %s: context lookup failed"),
|
||||
quotef (file));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -379,15 +351,7 @@ setdefaultfilecon (char const *file)
|
||||
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,
|
||||
@@ -427,7 +391,8 @@ static int
|
||||
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));
|
||||
@@ -457,7 +422,7 @@ process_dir (char *dir, struct savewd *wd, void *options)
|
||||
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));
|
||||
@@ -902,7 +867,7 @@ main (int argc, char **argv)
|
||||
/* 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;
|
||||
@@ -910,7 +875,7 @@ main (int argc, char **argv)
|
||||
if (optarg)
|
||||
scontext = optarg;
|
||||
else
|
||||
x.set_security_context = true;
|
||||
x.set_security_context = get_labeling_handle ();
|
||||
}
|
||||
else if (optarg)
|
||||
{
|
||||
|
||||
@@ -416,8 +416,6 @@ src_base32_CPPFLAGS = -DBASE_TYPE=32 $(AM_CPPFLAGS)
|
||||
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
|
||||
|
||||
|
||||
+15
-8
@@ -20,7 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/label.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "die.h"
|
||||
@@ -98,7 +98,7 @@ struct mkdir_options
|
||||
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;
|
||||
@@ -123,7 +123,8 @@ make_ancestor (char const *dir, char const *component, void *options)
|
||||
{
|
||||
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));
|
||||
@@ -156,7 +157,8 @@ process_dir (char *dir, struct savewd *wd, void *options)
|
||||
/* 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));
|
||||
@@ -176,7 +178,7 @@ process_dir (char *dir, struct savewd *wd, void *options)
|
||||
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));
|
||||
@@ -197,7 +199,7 @@ main (int argc, char **argv)
|
||||
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]);
|
||||
@@ -231,7 +233,12 @@ main (int argc, char **argv)
|
||||
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)
|
||||
{
|
||||
@@ -255,7 +262,7 @@ main (int argc, char **argv)
|
||||
|
||||
/* 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;
|
||||
|
||||
+9
-4
@@ -20,7 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/label.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "die.h"
|
||||
@@ -81,7 +81,7 @@ main (int argc, char **argv)
|
||||
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]);
|
||||
@@ -109,7 +109,12 @@ main (int argc, char **argv)
|
||||
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)
|
||||
{
|
||||
@@ -164,7 +169,7 @@ main (int argc, char **argv)
|
||||
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]));
|
||||
|
||||
+10
-5
@@ -20,7 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/label.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "die.h"
|
||||
@@ -98,7 +98,7 @@ main (int argc, char **argv)
|
||||
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]);
|
||||
@@ -126,7 +126,12 @@ main (int argc, char **argv)
|
||||
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)
|
||||
{
|
||||
@@ -248,7 +253,7 @@ main (int argc, char **argv)
|
||||
#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]));
|
||||
@@ -257,7 +262,7 @@ main (int argc, char **argv)
|
||||
|
||||
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;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <assert.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/label.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "backupfile.h"
|
||||
@@ -125,7 +125,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->set_security_context = NULL;
|
||||
x->reduce_diagnostics = false;
|
||||
x->data_copy_required = true;
|
||||
x->require_preserve = false; /* FIXME: maybe make this an option */
|
||||
@@ -417,7 +417,10 @@ main (int argc, char **argv)
|
||||
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;
|
||||
|
||||
+35
-84
@@ -17,18 +17,15 @@
|
||||
/* 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
|
||||
/*
|
||||
@@ -98,16 +95,17 @@ quit:
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
@@ -115,20 +113,8 @@ defaultcon (char const *path, mode_t mode)
|
||||
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
|
||||
@@ -160,25 +146,20 @@ quit:
|
||||
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;
|
||||
@@ -189,7 +170,7 @@ restorecon_private (char const *path, bool local)
|
||||
char *constr;
|
||||
int fd;
|
||||
|
||||
if (local)
|
||||
if (!selabel_handle)
|
||||
{
|
||||
if (getfscreatecon (&tcon) < 0)
|
||||
return rc;
|
||||
@@ -199,7 +180,9 @@ restorecon_private (char const *path, bool local)
|
||||
return rc;
|
||||
}
|
||||
rc = lsetfilecon (path, tcon);
|
||||
int err = errno;
|
||||
freecon (tcon);
|
||||
errno = err;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -218,13 +201,13 @@ restorecon_private (char const *path, bool local)
|
||||
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;
|
||||
@@ -258,83 +241,51 @@ restorecon_private (char const *path, bool local)
|
||||
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
|
||||
|
||||
+11
-5
@@ -19,6 +19,8 @@
|
||||
#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
|
||||
@@ -27,21 +29,25 @@ ignorable_ctx_err (int err)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user