36e8a3
From bbe9ac11d8d4a8511214605509a593fb9f04ffaa Mon Sep 17 00:00:00 2001
36e8a3
From: Lennart Poettering <lennart@poettering.net>
36e8a3
Date: Fri, 19 Oct 2018 11:28:40 +0200
36e8a3
Subject: [PATCH] chown-recursive: also drop ACLs when recursively chown()ing
36e8a3
36e8a3
Let's better be safe than sorry and also drop ACLs.
36e8a3
36e8a3
(cherry-picked from commit f89bc84f3242449cbc308892c87573b131f121df)
36e8a3
36e8a3
Related: #1643368
36e8a3
---
36e8a3
 src/core/chown-recursive.c | 16 ++++++++++++----
36e8a3
 1 file changed, 12 insertions(+), 4 deletions(-)
36e8a3
36e8a3
diff --git a/src/core/chown-recursive.c b/src/core/chown-recursive.c
36e8a3
index 27c64489b..447b77126 100644
36e8a3
--- a/src/core/chown-recursive.c
36e8a3
+++ b/src/core/chown-recursive.c
36e8a3
@@ -3,6 +3,7 @@
36e8a3
 #include <fcntl.h>
36e8a3
 #include <sys/stat.h>
36e8a3
 #include <sys/types.h>
36e8a3
+#include <sys/xattr.h>
36e8a3
 
36e8a3
 #include "chown-recursive.h"
36e8a3
 #include "dirent-util.h"
36e8a3
@@ -14,6 +15,7 @@
36e8a3
 
36e8a3
 static int chown_one(int fd, const struct stat *st, uid_t uid, gid_t gid) {
36e8a3
         char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
36e8a3
+        const char *n;
36e8a3
 
36e8a3
         assert(fd >= 0);
36e8a3
         assert(st);
36e8a3
@@ -26,13 +28,19 @@ static int chown_one(int fd, const struct stat *st, uid_t uid, gid_t gid) {
36e8a3
          * O_PATH. (Note: fchown() and fchmod() do not work with O_PATH, the kernel refuses that. */
36e8a3
         xsprintf(procfs_path, "/proc/self/fd/%i", fd);
36e8a3
 
36e8a3
+        /* Drop any ACL if there is one */
36e8a3
+        FOREACH_STRING(n, "system.posix_acl_access", "system.posix_acl_default")
36e8a3
+                if (removexattr(procfs_path, n) < 0)
36e8a3
+                        if (!IN_SET(errno, ENODATA, EOPNOTSUPP, ENOSYS, ENOTTY))
36e8a3
+                                return -errno;
36e8a3
+
36e8a3
         if (chown(procfs_path, uid, gid) < 0)
36e8a3
                 return -errno;
36e8a3
 
36e8a3
-        /* The linux kernel alters the mode in some cases of chown(). Let's undo this. We do this only for non-symlinks
36e8a3
-         * however. That's because for symlinks the access mode is ignored anyway and because on some kernels/file
36e8a3
-         * systems trying to change the access mode will succeed but has no effect while on others it actively
36e8a3
-         * fails. */
36e8a3
+        /* The linux kernel alters the mode in some cases of chown(), as well when we change ACLs. Let's undo this. We
36e8a3
+         * do this only for non-symlinks however. That's because for symlinks the access mode is ignored anyway and
36e8a3
+         * because on some kernels/file systems trying to change the access mode will succeed but has no effect while
36e8a3
+         * on others it actively fails. */
36e8a3
         if (!S_ISLNK(st->st_mode))
36e8a3
                 if (chmod(procfs_path, st->st_mode & 07777) < 0)
36e8a3
                         return -errno;