diff options
Diffstat (limited to 'src/tmpfiles/tmpfiles.c')
-rw-r--r-- | src/tmpfiles/tmpfiles.c | 97 |
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) |