]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
acl-util: systematically fall back to fchmod() if acl is not available
authorMike Yuan <me@yhndnzj.com>
Tue, 16 Dec 2025 01:18:25 +0000 (02:18 +0100)
committerMike Yuan <me@yhndnzj.com>
Tue, 16 Dec 2025 19:16:58 +0000 (20:16 +0100)
Same as 2a64b56da44751a3205c16ed4de6aa52c8e92929, but for
fd_acl_make_writable().

While at it, un-export fd_acl_make_{read_only,writable}_fallback(),
instead apply ifdeffery in .c

src/shared/acl-util.c
src/shared/acl-util.h

index 21bbb01278b47140576904554cd7871f765e4ddf..24384e64add7348faec7f675335060d8d6bc0755 100644 (file)
@@ -668,15 +668,34 @@ int fd_add_uid_acl_permission(
 
         return 0;
 }
+#endif
+
+static int fd_acl_make_read_only_fallback(int fd) {
+        struct stat st;
+
+        assert(fd >= 0);
+
+        if (fstat(fd, &st) < 0)
+                return -errno;
+
+        if ((st.st_mode & 0222) == 0)
+                return 0;
+
+        if (fchmod(fd, st.st_mode & 0555) < 0)
+                return -errno;
+
+        return 1;
+}
 
 int fd_acl_make_read_only(int fd) {
+        assert(fd >= 0);
+
+#if HAVE_ACL
         _cleanup_(acl_freep) acl_t acl = NULL;
         bool changed = false;
         acl_entry_t i;
         int r;
 
-        assert(fd >= 0);
-
         /* Safely drops all W bits from all relevant ACL entries of the file, without changing entries which
          * are masked by the ACL mask */
 
@@ -734,12 +753,33 @@ int fd_acl_make_read_only(int fd) {
 maybe_fallback:
         if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
                 return r;
+#endif
 
         /* No ACLs? Then just update the regular mode_t */
         return fd_acl_make_read_only_fallback(fd);
 }
 
+static int fd_acl_make_writable_fallback(int fd) {
+        struct stat st;
+
+        assert(fd >= 0);
+
+        if (fstat(fd, &st) < 0)
+                return -errno;
+
+        if ((st.st_mode & 0200) != 0) /* already set */
+                return 0;
+
+        if (fchmod(fd, (st.st_mode & 07777) | 0200) < 0)
+                return -errno;
+
+        return 1;
+}
+
 int fd_acl_make_writable(int fd) {
+        assert(fd >= 0);
+
+#if HAVE_ACL
         _cleanup_(acl_freep) acl_t acl = NULL;
         acl_entry_t i;
         int r;
@@ -749,15 +789,12 @@ int fd_acl_make_writable(int fd) {
 
         r = dlopen_libacl();
         if (r < 0)
-                return r;
+                goto maybe_fallback;
 
         acl = sym_acl_get_fd(fd);
         if (!acl) {
-                if (!ERRNO_IS_NOT_SUPPORTED(errno))
-                        return -errno;
-
-                /* No ACLs? Then just update the regular mode_t */
-                return fd_acl_make_writable_fallback(fd);
+                r = -errno;
+                goto maybe_fallback;
         }
 
         for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
@@ -792,48 +829,19 @@ int fd_acl_make_writable(int fd) {
                 return -errno;
 
         if (sym_acl_set_fd(fd, acl) < 0) {
-                if (!ERRNO_IS_NOT_SUPPORTED(errno))
-                        return -errno;
-
-                return fd_acl_make_writable_fallback(fd);
+                r = -errno;
+                goto maybe_fallback;
         }
 
         return 1;
-}
-#endif
-
-int fd_acl_make_read_only_fallback(int fd) {
-        struct stat st;
-
-        assert(fd >= 0);
-
-        if (fstat(fd, &st) < 0)
-                return -errno;
-
-        if ((st.st_mode & 0222) == 0)
-                return 0;
-
-        if (fchmod(fd, st.st_mode & 0555) < 0)
-                return -errno;
-
-        return 1;
-}
-
-int fd_acl_make_writable_fallback(int fd) {
-        struct stat st;
-
-        assert(fd >= 0);
-
-        if (fstat(fd, &st) < 0)
-                return -errno;
 
-        if ((st.st_mode & 0200) != 0) /* already set */
-                return 0;
-
-        if (fchmod(fd, (st.st_mode & 07777) | 0200) < 0)
-                return -errno;
+maybe_fallback:
+        if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
+                return r;
+#endif
 
-        return 1;
+        /* No ACLs? Then just update the regular mode_t */
+        return fd_acl_make_writable_fallback(fd);
 }
 
 int inode_type_can_acl(mode_t mode) {
index 33a19f30b4130dd9bf71c5e9fecd6e383f061170..0e0423ad25130bed2aa1e32a4286d95139cd939f 100644 (file)
@@ -3,9 +3,6 @@
 
 #include "shared-forward.h"
 
-int fd_acl_make_read_only_fallback(int fd);
-int fd_acl_make_writable_fallback(int fd);
-
 #if HAVE_ACL
 #include <acl/libacl.h> /* IWYU pragma: export */
 #include <sys/acl.h>    /* IWYU pragma: export */
@@ -55,9 +52,6 @@ int parse_acl(
 int acls_for_file(const char *path, acl_type_t type, acl_t acl, acl_t *ret);
 int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask);
 
-int fd_acl_make_read_only(int fd);
-int fd_acl_make_writable(int fd);
-
 /* acl_free() takes multiple argument types. Multiple cleanup functions are necessary. */
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(acl_t, sym_acl_free, acl_freep, NULL);
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(char*, sym_acl_free, acl_free_charpp, NULL);
@@ -102,14 +96,9 @@ static inline int devnode_acl(int fd, uid_t uid) {
 static inline int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask) {
         return -EOPNOTSUPP;
 }
-
-static inline int fd_acl_make_read_only(int fd) {
-        return fd_acl_make_read_only_fallback(fd);
-}
-
-static inline int fd_acl_make_writable(int fd) {
-        return fd_acl_make_writable_fallback(fd);
-}
 #endif
 
+int fd_acl_make_read_only(int fd);
+int fd_acl_make_writable(int fd);
+
 int inode_type_can_acl(mode_t mode);