From: Mike Yuan Date: Tue, 16 Dec 2025 01:18:25 +0000 (+0100) Subject: acl-util: systematically fall back to fchmod() if acl is not available X-Git-Tag: v259~10^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5188da568ccd4f987f7762dc1d06a62064f97591;p=thirdparty%2Fsystemd.git acl-util: systematically fall back to fchmod() if acl is not available 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 --- diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index 21bbb01278b..24384e64add 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -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) { diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h index 33a19f30b41..0e0423ad251 100644 --- a/src/shared/acl-util.h +++ b/src/shared/acl-util.h @@ -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 /* IWYU pragma: export */ #include /* 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);