f4af7d
From e3a7b9c8f26ca3b5a9aedd4c1d596a4a8504c812 Mon Sep 17 00:00:00 2001
f4af7d
From: Pavel Raiskup <praiskup@redhat.com>
f4af7d
Date: Thu, 4 Jun 2015 09:30:38 +0200
f4af7d
Subject: [PATCH] acls: don't mistakenly set default ACLs
f4af7d
f4af7d
Upstream commits
f4af7d
efbf4cce0b93e8c5a5fc93335b917bbeae2f67cb
f4af7d
9df17e6005e7a333399e3dc21a7afec75565c767
f4af7d
7fe7adcbb985e78aaf9f78051fa26167779be1f6
f4af7d
---
f4af7d
 configure.ac       |   2 +
f4af7d
 src/xattrs.c       |  37 ++++++++++++---
f4af7d
 tests/Makefile.am  |   1 +
f4af7d
 tests/acls03.at    | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++
f4af7d
 tests/testsuite.at |   1 +
f4af7d
 5 files changed, 165 insertions(+), 7 deletions(-)
f4af7d
 create mode 100644 tests/acls03.at
f4af7d
f4af7d
diff --git a/configure.ac b/configure.ac
f4af7d
index 9b3e0c8..7ccb579 100644
f4af7d
--- a/configure.ac
f4af7d
+++ b/configure.ac
f4af7d
@@ -85,6 +85,8 @@ if test "x$with_posix_acls" != "xno"; then
f4af7d
   AC_SEARCH_LIBS([acl_set_fd],    [acl pacl],, [with_posix_acl=no])
f4af7d
   AC_SEARCH_LIBS([acl_to_text],   [acl pacl],, [with_posix_acl=no])
f4af7d
   AC_SEARCH_LIBS([acl_from_text], [acl pacl],, [with_posix_acl=no])
f4af7d
+  AC_SEARCH_LIBS([acl_delete_def_file], [acl pacl],, [with_posix_acl=no])
f4af7d
+  AC_SEARCH_LIBS([acl_free], [acl pacl],, [with_posix_acl=no])
f4af7d
   if test "x$with_posix_acls" != xno; then
f4af7d
     AC_DEFINE(HAVE_POSIX_ACLS,,[Define when we have working POSIX acls])
f4af7d
   fi
f4af7d
diff --git a/src/xattrs.c b/src/xattrs.c
f4af7d
index bdf6ba0..5bd4b02 100644
f4af7d
--- a/src/xattrs.c
f4af7d
+++ b/src/xattrs.c
f4af7d
@@ -61,6 +61,7 @@ static struct
f4af7d
 acl_t acl_get_file_at (int dirfd, const char *file, acl_type_t type);
f4af7d
 int acl_set_file_at (int dirfd, const char *file, acl_type_t type, acl_t acl);
f4af7d
 int file_has_acl_at (int dirfd, char const *, struct stat const *);
f4af7d
+int acl_delete_def_file_at (int, char const *);
f4af7d
 
f4af7d
 /* acl_get_file_at */
f4af7d
 #define AT_FUNC_NAME acl_get_file_at
f4af7d
@@ -88,6 +89,17 @@ int file_has_acl_at (int dirfd, char const *, struct stat const *);
f4af7d
 #undef AT_FUNC_POST_FILE_PARAM_DECLS
f4af7d
 #undef AT_FUNC_POST_FILE_ARGS
f4af7d
 
f4af7d
+/* acl_delete_def_file_at */
f4af7d
+#define AT_FUNC_NAME acl_delete_def_file_at
f4af7d
+#define AT_FUNC_F1 acl_delete_def_file
f4af7d
+#define AT_FUNC_POST_FILE_PARAM_DECLS
f4af7d
+#define AT_FUNC_POST_FILE_ARGS
f4af7d
+#include "at-func.c"
f4af7d
+#undef AT_FUNC_NAME
f4af7d
+#undef AT_FUNC_F1
f4af7d
+#undef AT_FUNC_POST_FILE_PARAM_DECLS
f4af7d
+#undef AT_FUNC_POST_FILE_ARGS
f4af7d
+
f4af7d
 /* gnulib file_has_acl_at */
f4af7d
 #define AT_FUNC_NAME file_has_acl_at
f4af7d
 #define AT_FUNC_F1 file_has_acl
f4af7d
@@ -187,7 +199,8 @@ fixup_extra_acl_fields (char *ptr)
f4af7d
   return ptr;
f4af7d
 }
f4af7d
 
f4af7d
-/* "system.posix_acl_access" */
f4af7d
+/* Set the "system.posix_acl_access/system.posix_acl_default" extended
f4af7d
+   attribute.  Called only when acls_option > 0. */
f4af7d
 static void
f4af7d
 xattrs__acls_set (struct tar_stat_info const *st,
f4af7d
                   char const *file_name, int type,
f4af7d
@@ -199,15 +212,25 @@ xattrs__acls_set (struct tar_stat_info const *st,
f4af7d
     {
f4af7d
       /* assert (strlen (ptr) == len); */
f4af7d
       ptr = fixup_extra_acl_fields (ptr);
f4af7d
-
f4af7d
       acl = acl_from_text (ptr);
f4af7d
-      acls_option = 1;
f4af7d
     }
f4af7d
-  else if (acls_option > 0)
f4af7d
+  else if (def)
f4af7d
+    {
f4af7d
+      /* No "default" IEEE 1003.1e ACL set for directory.  At this moment,
f4af7d
+         FILE_NAME may already have inherited default acls from parent
f4af7d
+         directory;  clean them up. */
f4af7d
+      if (acl_delete_def_file_at (chdir_fd, file_name))
f4af7d
+        WARNOPT (WARN_XATTR_WRITE,
f4af7d
+                (0, errno,
f4af7d
+                 _("acl_delete_def_file_at: Cannot drop default POSIX ACLs "
f4af7d
+                   "for file '%s'"),
f4af7d
+                 file_name));
f4af7d
+      return;
f4af7d
+    }
f4af7d
+  else
f4af7d
+    /* There is nothing like "acl_delete_def_file" for non-default acls, we
f4af7d
+       need to re-set ACLs based on permission bits */
f4af7d
     acl = perms2acl (st->stat.st_mode);
f4af7d
-  else
f4af7d
-    return;  /* don't call acl functions unless we first hit an ACL, or
f4af7d
-		--acls was passed explicitly */
f4af7d
 
f4af7d
   if (!acl)
f4af7d
     {
f4af7d
diff --git a/tests/Makefile.am b/tests/Makefile.am
f4af7d
index b0da439..228e936 100644
f4af7d
--- a/tests/Makefile.am
f4af7d
+++ b/tests/Makefile.am
f4af7d
@@ -179,6 +179,7 @@ TESTSUITE_AT = \
f4af7d
  xattr05.at\
f4af7d
  acls01.at\
f4af7d
  acls02.at\
f4af7d
+ acls03.at\
f4af7d
  selnx01.at\
f4af7d
  selacl01.at\
f4af7d
  capabs_raw01.at
f4af7d
diff --git a/tests/acls03.at b/tests/acls03.at
f4af7d
new file mode 100644
f4af7d
index 0000000..83c5bdc
f4af7d
--- /dev/null
f4af7d
+++ b/tests/acls03.at
f4af7d
@@ -0,0 +1,131 @@
f4af7d
+# Process this file with autom4te to create testsuite. -*- Autotest -*-
f4af7d
+#
f4af7d
+# Test suite for GNU tar.
f4af7d
+# Copyright 2013, 2014 Free Software Foundation, Inc.
f4af7d
+
f4af7d
+# This file is part of GNU tar.
f4af7d
+
f4af7d
+# GNU tar is free software; you can redistribute it and/or modify
f4af7d
+# it under the terms of the GNU General Public License as published by
f4af7d
+# the Free Software Foundation; either version 3 of the License, or
f4af7d
+# (at your option) any later version.
f4af7d
+
f4af7d
+# GNU tar is distributed in the hope that it will be useful,
f4af7d
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
f4af7d
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
f4af7d
+# GNU General Public License for more details.
f4af7d
+
f4af7d
+# You should have received a copy of the GNU General Public License
f4af7d
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
f4af7d
+#
f4af7d
+# Test description:
f4af7d
+#
f4af7d
+# Check the storing/restoring with/without default ACLs.  When --acls is passed,
f4af7d
+# restored directory tree should always match archive contents (even when the
f4af7d
+# archive does not contain any ACLs).
f4af7d
+#
f4af7d
+# References:
f4af7d
+# http://www.mail-archive.com/bug-tar@gnu.org/msg04355.html
f4af7d
+
f4af7d
+AT_SETUP([acls: default ACLs])
f4af7d
+AT_KEYWORDS([xattrs acls acls03])
f4af7d
+
f4af7d
+m4_define([ACL_LISTDIR], [
f4af7d
+    cd $1
f4af7d
+    $1="$(find d1 | sort | xargs -n 1 getfacl)"
f4af7d
+    cd ..
f4af7d
+])
f4af7d
+
f4af7d
+m4_define([ACL_ASSERT], [
f4af7d
+    echo "$$1" > $1.log
f4af7d
+    echo "$$2" > $2.log
f4af7d
+    if test ! "$$1" "$3" "$$2"; then
f4af7d
+        echo "bad '$1' against '$2' output"
f4af7d
+    fi
f4af7d
+])
f4af7d
+
f4af7d
+AT_TAR_CHECK([
f4af7d
+AT_XATTRS_UTILS_PREREQ
f4af7d
+AT_ACLS_PREREQ
f4af7d
+AT_SORT_PREREQ
f4af7d
+
f4af7d
+MYNAME=$( id -un )
f4af7d
+MYGROUP=$( id -gn )
f4af7d
+
f4af7d
+# Prepare directory structure with default ACLs
f4af7d
+mkdir -p pure/d1/d2
f4af7d
+genfile --file pure/d1/f2a
f4af7d
+genfile --file pure/d1/f2b
f4af7d
+genfile --file pure/d1/d2/f3a
f4af7d
+genfile --file pure/d1/d2/f3b
f4af7d
+setfacl    -m g:$MYGROUP:r-x pure/d1
f4af7d
+setfacl -d -m g:$MYGROUP:rwx pure/d1
f4af7d
+setfacl -d -m u:$MYNAME:rwx  pure/d1
f4af7d
+# "*a" files have "some" additional ACLs
f4af7d
+setfacl    -m u:$MYNAME:--- pure/d1/d2/f3a
f4af7d
+setfacl    -m u:$MYNAME:--- pure/d1/f2a
f4af7d
+
f4af7d
+# use default format (no acls stored)
f4af7d
+tar -cf noacl.tar -C pure d1
f4af7d
+
f4af7d
+# use posix format, acls stored
f4af7d
+tar --acls -cf acl.tar -C pure d1
f4af7d
+
f4af7d
+# Directory names are chosen based on "how the files were extracted from
f4af7d
+# archive".  Equivalent no* tags are used also:
f4af7d
+#   ^sacl_    — extracted archive has stored ACLs
f4af7d
+#   _def_     — target directory (-C) has default ACLs
f4af7d
+#   _optacl$  — extraction was done with --acls option
f4af7d
+
f4af7d
+mkdir sacl_def_optacl
f4af7d
+mkdir sacl_def_optnoacl
f4af7d
+mkdir sacl_nodef_optacl
f4af7d
+mkdir sacl_nodef_optnoacl
f4af7d
+mkdir nosacl_def_optacl
f4af7d
+mkdir nosacl_def_optnoacl
f4af7d
+mkdir nosacl_nodef_optacl
f4af7d
+mkdir nosacl_nodef_optnoacl
f4af7d
+
f4af7d
+setfacl -d -m u:$MYNAME:---  nosacl_def_optnoacl sacl_def_optnoacl sacl_def_optacl nosacl_def_optacl
f4af7d
+setfacl -d -m g:$MYGROUP:--- nosacl_def_optnoacl sacl_def_optnoacl sacl_def_optacl nosacl_def_optacl
f4af7d
+
f4af7d
+tar -xf acl.tar -C sacl_nodef_optnoacl
f4af7d
+tar --acls -xf acl.tar -C sacl_nodef_optacl
f4af7d
+tar -xf acl.tar -C sacl_def_optnoacl
f4af7d
+tar --acls -xf acl.tar -C sacl_def_optacl
f4af7d
+tar -xf noacl.tar -C nosacl_def_optnoacl
f4af7d
+# _NO_ ACLs in output
f4af7d
+tar -xf noacl.tar -C nosacl_nodef_optnoacl
f4af7d
+tar -xf noacl.tar -C nosacl_nodef_optacl
f4af7d
+tar -cf noacl_repackaged.tar -C nosacl_nodef_optnoacl d1
f4af7d
+# _NO_ ACLs in output (even when default ACLs exist)
f4af7d
+tar --acls -xf noacl_repackaged.tar -C nosacl_def_optacl
f4af7d
+
f4af7d
+ACL_LISTDIR(pure)
f4af7d
+
f4af7d
+ACL_LISTDIR(sacl_def_optacl)
f4af7d
+ACL_LISTDIR(sacl_def_optnoacl)
f4af7d
+ACL_LISTDIR(sacl_nodef_optacl)
f4af7d
+ACL_LISTDIR(sacl_nodef_optnoacl)
f4af7d
+ACL_LISTDIR(nosacl_def_optacl)
f4af7d
+ACL_LISTDIR(nosacl_def_optnoacl)
f4af7d
+ACL_LISTDIR(nosacl_nodef_optacl)
f4af7d
+ACL_LISTDIR(nosacl_nodef_optnoacl)
f4af7d
+
f4af7d
+ACL_ASSERT(pure, sacl_def_optacl, =)
f4af7d
+
f4af7d
+ACL_ASSERT(sacl_def_optacl,     sacl_nodef_optacl,      =)
f4af7d
+ACL_ASSERT(sacl_def_optnoacl,   nosacl_def_optnoacl,    =)
f4af7d
+ACL_ASSERT(sacl_nodef_optnoacl, nosacl_nodef_optnoacl,  =)
f4af7d
+ACL_ASSERT(nosacl_def_optacl,   nosacl_nodef_optacl,    =)
f4af7d
+ACL_ASSERT(nosacl_def_optacl,   nosacl_nodef_optnoacl,  =)
f4af7d
+
f4af7d
+ACL_ASSERT(sacl_def_optacl,     sacl_def_optnoacl,      !=)
f4af7d
+ACL_ASSERT(sacl_def_optacl,     nosacl_def_optnoacl,    !=)
f4af7d
+ACL_ASSERT(nosacl_def_optnoacl, nosacl_nodef_optnoacl,  !=)
f4af7d
+],
f4af7d
+[0],
f4af7d
+[],
f4af7d
+[])
f4af7d
+
f4af7d
+AT_CLEANUP
f4af7d
diff --git a/tests/testsuite.at b/tests/testsuite.at
f4af7d
index d5925b3..10cf26a 100644
f4af7d
--- a/tests/testsuite.at
f4af7d
+++ b/tests/testsuite.at
f4af7d
@@ -341,6 +341,7 @@ m4_include([xattr05.at])
f4af7d
 
f4af7d
 m4_include([acls01.at])
f4af7d
 m4_include([acls02.at])
f4af7d
+m4_include([acls03.at])
f4af7d
 
f4af7d
 m4_include([selnx01.at])
f4af7d
 m4_include([selacl01.at])
f4af7d
-- 
f4af7d
2.1.0
f4af7d