acl-util: systematically fall back to fchmod() if acl is not available
Same as 2a64b56da4, but for
fd_acl_make_writable().
While at it, un-export fd_acl_make_{read_only,writable}_fallback(),
instead apply ifdeffery in .c
This commit is contained in:
+53
-45
@@ -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;
|
||||
}
|
||||
|
||||
maybe_fallback:
|
||||
if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return r;
|
||||
#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;
|
||||
|
||||
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) {
|
||||
|
||||
+3
-14
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user