mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-04-12 23:08:17 +02:00
cp: set SELinux context for --parents directories
* src/copy.c (set_process_security_ctx, set_file_security_ctx): Export for use in cp.c. * src/copy.h: Likewise. * src/cp.c (make_dir_parents_private): Call the exported functions to set the security context for new and updated directories. * tests/cp/cp-a-selinux.sh: Add a test case. Fixes http://bugs.gnu.org/25378
This commit is contained in:
4
NEWS
4
NEWS
@@ -10,6 +10,10 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
** Bug fixes
|
||||
|
||||
cp --parents will now set an SELinux context for created directories,
|
||||
as appropriate for the -a, --preseve=context, or -Z options.
|
||||
[bug present since SELinux support added in coreutils-6.10]
|
||||
|
||||
date again converts from a specified time zone. Previously output was
|
||||
not converted to the local time zone, and remained in the specified one.
|
||||
[bug introduced in coreutils-8.26]
|
||||
|
||||
@@ -889,7 +889,7 @@ set_author (const char *dst_name, int dest_desc, const struct stat *src_sb)
|
||||
Based on CP_OPTIONS, diagnose warnings and fail when appropriate.
|
||||
Return FALSE on failure, TRUE on success. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
set_process_security_ctx (char const *src_name, char const *dst_name,
|
||||
mode_t mode, bool new_dst, const struct cp_options *x)
|
||||
{
|
||||
@@ -951,7 +951,7 @@ set_process_security_ctx (char const *src_name, char const *dst_name,
|
||||
failure, when allowed by various settings in CP_OPTIONS.
|
||||
Return FALSE on failure, TRUE on success. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
set_file_security_ctx (char const *dst_name, bool process_local,
|
||||
bool recurse, const struct cp_options *x)
|
||||
{
|
||||
|
||||
@@ -285,6 +285,14 @@ bool copy (char const *src_name, char const *dst_name,
|
||||
bool nonexistent_dst, const struct cp_options *options,
|
||||
bool *copy_into_self, bool *rename_succeeded);
|
||||
|
||||
extern bool set_process_security_ctx (char const *src_name,
|
||||
char const *dst_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,
|
||||
bool recurse, const struct cp_options *x);
|
||||
|
||||
void dest_info_init (struct cp_options *);
|
||||
void src_info_init (struct cp_options *);
|
||||
|
||||
|
||||
20
src/cp.c
20
src/cp.c
@@ -394,6 +394,8 @@ make_dir_parents_private (char const *const_dir, size_t src_offset,
|
||||
|
||||
*attr_list = NULL;
|
||||
|
||||
/* XXX: If all dirs are present at the destination,
|
||||
no permissions or security contexts will be updated. */
|
||||
if (stat (dst_dir, &stats) != 0)
|
||||
{
|
||||
/* A parent of CONST_DIR does not exist.
|
||||
@@ -437,6 +439,12 @@ make_dir_parents_private (char const *const_dir, size_t src_offset,
|
||||
*attr_list = new;
|
||||
}
|
||||
|
||||
/* If required set the default context for created dirs. */
|
||||
if (! set_process_security_ctx (src, dir,
|
||||
missing_dir ? new->st.st_mode : 0,
|
||||
missing_dir, x))
|
||||
return false;
|
||||
|
||||
if (missing_dir)
|
||||
{
|
||||
mode_t src_mode;
|
||||
@@ -524,6 +532,18 @@ make_dir_parents_private (char const *const_dir, size_t src_offset,
|
||||
}
|
||||
else
|
||||
*new_dst = false;
|
||||
|
||||
/* For existing dirs, set the security context as per that already
|
||||
set for the process global context. */
|
||||
if (! *new_dst
|
||||
&& (x->set_security_context || x->preserve_security_context))
|
||||
{
|
||||
if (! set_file_security_ctx (dir, x->preserve_security_context,
|
||||
false, x)
|
||||
&& x->require_preserve_context)
|
||||
return false;
|
||||
}
|
||||
|
||||
*slash++ = '/';
|
||||
|
||||
/* Avoid unnecessary calls to 'stat' when given
|
||||
|
||||
@@ -48,7 +48,6 @@ rm -f f
|
||||
# due to recursion, and was handled incorrectly in coreutils-8.22
|
||||
# Note standard permissions are updated for existing directories
|
||||
# in the destination, so SELinux contexts should be updated too.
|
||||
chmod o+rw restore/existing_dir
|
||||
mkdir -p backup/existing_dir/ || framework_failure_
|
||||
ls -Zd backup/existing_dir > ed_ctx || fail=1
|
||||
grep $ctx ed_ctx && framework_failure_
|
||||
@@ -57,11 +56,31 @@ chcon $ctx backup/existing_dir/file || framework_failure_
|
||||
# Set the dir context to ensure it is reset
|
||||
mkdir -p --context="$ctx" restore/existing_dir || framework_failure_
|
||||
# Copy and ensure existing directories updated
|
||||
cp -a backup/. restore/
|
||||
cp -a backup/. restore/ || fail=1
|
||||
ls -Zd restore/existing_dir > ed_ctx || fail=1
|
||||
grep $ctx ed_ctx &&
|
||||
{ ls -lZd restore/existing_dir; fail=1; }
|
||||
|
||||
# Check context preserved with directories created with --parents,
|
||||
# which was not handled before coreutils-8.27
|
||||
mkdir -p parents/a/b || framework_failure_
|
||||
ls -Zd parents/a/b > ed_ctx || fail=1
|
||||
grep $ctx ed_ctx && framework_failure_
|
||||
touch parents/a/b/file || framework_failure_
|
||||
chcon $ctx parents/a/b || framework_failure_
|
||||
# Set the dir context to ensure it is reset
|
||||
mkdir -p --context="$ctx" parents_dest/parents/a || framework_failure_
|
||||
# Copy and ensure existing directories updated
|
||||
cp -r --parents --preserve=context parents/a/b/file parents_dest || fail=1
|
||||
# Check new context
|
||||
ls -Zd parents_dest/parents/a/b > ed_ctx || fail=1
|
||||
grep $ctx ed_ctx ||
|
||||
{ ls -lZd parents_dest/parents/a/b; fail=1; }
|
||||
# Check updated context
|
||||
ls -Zd parents_dest/parents/a > ed_ctx || fail=1
|
||||
grep $ctx ed_ctx &&
|
||||
{ ls -lZd parents_dest/parents/a; fail=1; }
|
||||
|
||||
# Check restorecon (-Z) functionality for file and directory
|
||||
# Also make a dir with our known context
|
||||
mkdir c_d || framework_failure_
|
||||
|
||||
Reference in New Issue
Block a user