summaryrefslogtreecommitdiffstats
path: root/src/tmpfiles/tmpfiles.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tmpfiles/tmpfiles.c')
-rw-r--r--src/tmpfiles/tmpfiles.c97
1 files changed, 44 insertions, 53 deletions
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index bc83aab..4919cb7 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -817,7 +817,7 @@ static int dir_cleanup(
cutoff_nsec, sub_path, age_by_file, false))
continue;
- fd = xopenat(dirfd(d),
+ fd = xopenat_full(dirfd(d),
de->d_name,
O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME|O_NONBLOCK,
/* xopen_flags = */ 0,
@@ -1173,60 +1173,47 @@ static int parse_acls_from_arg(Item *item) {
#if HAVE_ACL
static int parse_acl_cond_exec(
const char *path,
- acl_t access, /* could be empty (NULL) */
- acl_t cond_exec,
const struct stat *st,
+ acl_t cond_exec,
+ acl_t access, /* could be empty (NULL) */
bool append,
acl_t *ret) {
- _cleanup_(acl_freep) acl_t parsed = NULL;
acl_entry_t entry;
acl_permset_t permset;
bool has_exec;
int r;
assert(path);
- assert(ret);
assert(st);
+ assert(cond_exec);
+ assert(ret);
- parsed = access ? acl_dup(access) : acl_init(0);
- if (!parsed)
- return -errno;
-
- /* Since we substitute 'X' with 'x' in parse_acl(), we just need to copy the entries over
- * for directories */
- if (S_ISDIR(st->st_mode)) {
- for (r = acl_get_entry(cond_exec, ACL_FIRST_ENTRY, &entry);
- r > 0;
- r = acl_get_entry(cond_exec, ACL_NEXT_ENTRY, &entry)) {
-
- acl_entry_t parsed_entry;
-
- if (acl_create_entry(&parsed, &parsed_entry) < 0)
- return -errno;
-
- if (acl_copy_entry(parsed_entry, entry) < 0)
- return -errno;
- }
- if (r < 0)
- return -errno;
-
- goto finish;
- }
-
- has_exec = st->st_mode & S_IXUSR;
-
- if (!has_exec && append) {
+ if (!S_ISDIR(st->st_mode)) {
_cleanup_(acl_freep) acl_t old = NULL;
old = acl_get_file(path, ACL_TYPE_ACCESS);
if (!old)
return -errno;
+ has_exec = false;
+
for (r = acl_get_entry(old, ACL_FIRST_ENTRY, &entry);
r > 0;
r = acl_get_entry(old, ACL_NEXT_ENTRY, &entry)) {
+ acl_tag_t tag;
+
+ if (acl_get_tag_type(entry, &tag) < 0)
+ return -errno;
+
+ if (tag == ACL_MASK)
+ continue;
+
+ /* If not appending, skip ACL definitions */
+ if (!append && IN_SET(tag, ACL_USER, ACL_GROUP))
+ continue;
+
if (acl_get_permset(entry, &permset) < 0)
return -errno;
@@ -1240,28 +1227,33 @@ static int parse_acl_cond_exec(
}
if (r < 0)
return -errno;
- }
- /* Check if we're about to set the execute bit in acl_access */
- if (!has_exec && access) {
- for (r = acl_get_entry(access, ACL_FIRST_ENTRY, &entry);
- r > 0;
- r = acl_get_entry(access, ACL_NEXT_ENTRY, &entry)) {
+ /* Check if we're about to set the execute bit in acl_access */
+ if (!has_exec && access) {
+ for (r = acl_get_entry(access, ACL_FIRST_ENTRY, &entry);
+ r > 0;
+ r = acl_get_entry(access, ACL_NEXT_ENTRY, &entry)) {
- if (acl_get_permset(entry, &permset) < 0)
- return -errno;
+ if (acl_get_permset(entry, &permset) < 0)
+ return -errno;
- r = acl_get_perm(permset, ACL_EXECUTE);
+ r = acl_get_perm(permset, ACL_EXECUTE);
+ if (r < 0)
+ return -errno;
+ if (r > 0) {
+ has_exec = true;
+ break;
+ }
+ }
if (r < 0)
return -errno;
- if (r > 0) {
- has_exec = true;
- break;
- }
}
- if (r < 0)
- return -errno;
- }
+ } else
+ has_exec = true;
+
+ _cleanup_(acl_freep) acl_t parsed = access ? acl_dup(access) : acl_init(0);
+ if (!parsed)
+ return -errno;
for (r = acl_get_entry(cond_exec, ACL_FIRST_ENTRY, &entry);
r > 0;
@@ -1275,6 +1267,7 @@ static int parse_acl_cond_exec(
if (acl_copy_entry(parsed_entry, entry) < 0)
return -errno;
+ /* We substituted 'X' with 'x' in parse_acl(), so drop execute bit here if not applicable. */
if (!has_exec) {
if (acl_get_permset(parsed_entry, &permset) < 0)
return -errno;
@@ -1286,7 +1279,6 @@ static int parse_acl_cond_exec(
if (r < 0)
return -errno;
-finish:
if (!append) { /* want_mask = true */
r = calc_acl_mask_if_needed(&parsed);
if (r < 0)
@@ -1390,10 +1382,9 @@ static int fd_set_acls(
}
if (item->acl_access_exec) {
- r = parse_acl_cond_exec(FORMAT_PROC_FD_PATH(fd),
- item->acl_access,
+ r = parse_acl_cond_exec(FORMAT_PROC_FD_PATH(fd), st,
item->acl_access_exec,
- st,
+ item->acl_access,
item->append_or_force,
&access_with_exec_parsed);
if (r < 0)