return 1;
}
-
-int fd_acl_make_writable(int fd) {
- _cleanup_(acl_freep) acl_t acl = NULL;
- acl_entry_t i;
- int r;
-
- /* Safely adds the writable bit to the owner's ACL entry of this inode. (And only the owner's! – This
- * not the obvious inverse of fd_acl_make_read_only() hence!) */
-
- r = dlopen_libacl();
- if (r < 0)
- return r;
-
- 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);
- }
-
- for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
- r > 0;
- r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
- acl_permset_t permset;
- acl_tag_t tag;
- int b;
-
- if (sym_acl_get_tag_type(i, &tag) < 0)
- return -errno;
-
- if (tag != ACL_USER_OBJ)
- continue;
-
- if (sym_acl_get_permset(i, &permset) < 0)
- return -errno;
-
- b = sym_acl_get_perm(permset, ACL_WRITE);
- if (b < 0)
- return -errno;
-
- if (b)
- return 0; /* Already set? Then there's nothing to do. */
-
- if (sym_acl_add_perm(permset, ACL_WRITE) < 0)
- return -errno;
-
- break;
- }
- if (r < 0)
- 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);
- }
-
- return 1;
-}
#endif
int fd_acl_make_read_only_fallback(int fd) {
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;
-}
-
int inode_type_can_acl(mode_t mode) {
return IN_SET(mode & S_IFMT, S_IFSOCK, S_IFREG, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO);
}
#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 */
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);
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 inode_type_can_acl(mode_t mode);
cmd = strjoina("stat ", fn);
ASSERT_OK_ZERO_ERRNO(system(cmd));
- log_info("writable");
- ASSERT_OK_POSITIVE(fd_acl_make_writable(fd));
-
- ASSERT_OK_ERRNO(fstat(fd, &st));
- ASSERT_EQ(st.st_mode & 0222, 0200u);
-
- cmd = strjoina("getfacl -p ", fn);
- ASSERT_OK_ZERO_ERRNO(system(cmd));
-
- cmd = strjoina("stat ", fn);
- ASSERT_OK_ZERO_ERRNO(system(cmd));
-
- log_info("read-only");
- ASSERT_OK_POSITIVE(fd_acl_make_read_only(fd));
-
- ASSERT_OK_ERRNO(fstat(fd, &st));
- ASSERT_EQ(st.st_mode & 0222, 0000u);
-
- cmd = strjoina("getfacl -p ", fn);
- ASSERT_OK_ZERO_ERRNO(system(cmd));
-
- cmd = strjoina("stat ", fn);
- ASSERT_OK_ZERO_ERRNO(system(cmd));
-
return 0;
}