From 4ce7488e8d96080f18b518bcf6a6356e0c392dda Mon Sep 17 00:00:00 2001 From: =?utf8?q?P=C3=A1draig=20Brady?= Date: Thu, 21 May 2015 11:38:13 +0100 Subject: [PATCH] mkdir: fix -pZ with existing parent directories When the parent directory exists and has a different default context to the final directory, the context was incorrectly left as that of the parent directory. * src/mkdir.c (process_dir): Because defaultcon() is called for existing ancestors (as it must be to avoid races), then we must unconditionally call restorecon() on the last component due to the already documented caveat with make_dir_parents(). Alternatively you could temp disable o->set_security_context around make_dir_parents(), but that would be subject to races. * tests (tests/mkdir/restorecon.sh): Add a TODO for improvement. Reference mknod and mkfifo with print_ver_. * NEWS: Mention the bug fix. Fixes http://bugs.gnu.org/20616 --- NEWS | 4 ++++ src/mkdir.c | 17 +++-------------- tests/mkdir/restorecon.sh | 3 ++- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index 1d4b718b17..c2576c5569 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,10 @@ GNU coreutils NEWS -*- outline -*- head, od, split, tac, tail, and wc no longer mishandle input from files in /proc and /sys file systems that report somewhat-incorrect file sizes. + mkdir --parents -Z now correctly sets the context for the last component, + even if the parent directory exists and has a different default context. + [bug introduced with the -Z restorecon functionality in coreutils-8.22] + paste no longer truncates output for large input files. This would happen for example with files larger than 4GiB on 32 bit systems with a '\n' character at the 4GiB position. diff --git a/src/mkdir.c b/src/mkdir.c index 404a04a71e..ff51ae1e60 100644 --- a/src/mkdir.c +++ b/src/mkdir.c @@ -151,23 +151,11 @@ static int process_dir (char *dir, struct savewd *wd, void *options) { struct mkdir_options const *o = options; - 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 + if (! o->make_ancestor_function && defaultcon (dir, S_IFDIR) < 0 && ! ignorable_ctx_err (errno)) error (0, errno, _("failed to set default creation context for %s"), quote (dir)); @@ -184,7 +172,8 @@ process_dir (char *dir, struct savewd *wd, void *options) 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 (ret == EXIT_SUCCESS && o->set_security_context + && o->make_ancestor_function) { if (! restorecon (last_component (dir), false, false) && ! ignorable_ctx_err (errno)) diff --git a/tests/mkdir/restorecon.sh b/tests/mkdir/restorecon.sh index a31cab9bce..7d6a671b58 100755 --- a/tests/mkdir/restorecon.sh +++ b/tests/mkdir/restorecon.sh @@ -17,7 +17,7 @@ # along with this program. If not, see . . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src -print_ver_ mkdir +print_ver_ mkdir mknod mkfifo require_selinux_ @@ -38,6 +38,7 @@ if restorecon restored 2>/dev/null; then mkdir -Z single || fail=1 # Run these as separate processes in case global context # set for an arg, impacts on another arg + # TODO: Have the defaultcon() vary over these directories for dir in single_p single_p/existing multi/ple; do mkdir -Zp "$dir" || fail=1 done -- 2.47.2