#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;
}
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;
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;
if (r < 0)
return -errno;
-finish:
if (!append) { /* want_mask = true */
r = calc_acl_mask_if_needed(&parsed);
if (r < 0)
}
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)
&mode,
&user,
&group,
- &age,
- NULL);
+ &age);
if (r < 0) {
if (IN_SET(r, -EINVAL, -EBADSLT))
/* invalid quoting and such or an unknown specifier */
DISSECT_IMAGE_VALIDATE_OS |
DISSECT_IMAGE_RELAX_VAR_CHECK |
DISSECT_IMAGE_FSCK |
- DISSECT_IMAGE_GROWFS,
+ DISSECT_IMAGE_GROWFS |
+ DISSECT_IMAGE_ALLOW_USERSPACE_VERITY,
&mounted_dir,
/* ret_dir_fd= */ NULL,
&loop_device);