summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorMike Yuan <me@yhndnzj.com>2023-04-27 22:40:09 +0800
committerGitHub <noreply@github.com>2023-04-27 22:40:09 +0800
commit82060b62c98f262558d9b5d0b98f0c96cd675b6a (patch)
tree61693083b7b54d5216e7fd40ffae04b7188902c2 /src/shared
parenta84e741b36ba0ad1e35b90d0f55753e825b848e8 (diff)
parentf582e61bc3a956fb09af66bcd6778b4dd5058e40 (diff)
downloadsystemd-82060b62c98f262558d9b5d0b98f0c96cd675b6a.tar.gz
Merge pull request #25622 from YHNdnzj/tmpfiles-X-bit-support
tmpfiles: add conditionalized execute permission (X) support
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/acl-util.c68
-rw-r--r--src/shared/acl-util.h7
2 files changed, 63 insertions, 12 deletions
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index b734ee1e0c..5c0c4e21aa 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -209,14 +209,20 @@ int acl_search_groups(const char *path, char ***ret_groups) {
return ret;
}
-int parse_acl(const char *text, acl_t *ret_acl_access, acl_t *ret_acl_default, bool want_mask) {
- _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not freed */
- _cleanup_strv_free_ char **split = NULL;
- int r = -EINVAL;
- _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL;
+int parse_acl(
+ const char *text,
+ acl_t *ret_acl_access,
+ acl_t *ret_acl_access_exec, /* extra rules to apply to inodes subject to uppercase X handling */
+ acl_t *ret_acl_default,
+ bool want_mask) {
+
+ _cleanup_strv_free_ char **a = NULL, **e = NULL, **d = NULL, **split = NULL;
+ _cleanup_(acl_freep) acl_t a_acl = NULL, e_acl = NULL, d_acl = NULL;
+ int r;
assert(text);
assert(ret_acl_access);
+ assert(ret_acl_access_exec);
assert(ret_acl_default);
split = strv_split(text, ",");
@@ -224,13 +230,38 @@ int parse_acl(const char *text, acl_t *ret_acl_access, acl_t *ret_acl_default, b
return -ENOMEM;
STRV_FOREACH(entry, split) {
- char *p;
+ _cleanup_strv_free_ char **entry_split = NULL;
+ _cleanup_free_ char *entry_join = NULL;
+ int n;
+
+ n = strv_split_full(&entry_split, *entry, ":", EXTRACT_DONT_COALESCE_SEPARATORS|EXTRACT_RETAIN_ESCAPE);
+ if (n < 0)
+ return n;
+
+ if (n < 3 || n > 4)
+ return -EINVAL;
+
+ string_replace_char(entry_split[n-1], 'X', 'x');
+
+ if (n == 4) {
+ if (!STR_IN_SET(entry_split[0], "default", "d"))
+ return -EINVAL;
- p = STARTSWITH_SET(*entry, "default:", "d:");
- if (p)
- r = strv_push(&d, p);
- else
- r = strv_push(&a, *entry);
+ entry_join = strv_join(entry_split + 1, ":");
+ if (!entry_join)
+ return -ENOMEM;
+
+ r = strv_consume(&d, TAKE_PTR(entry_join));
+ } else { /* n == 3 */
+ entry_join = strv_join(entry_split, ":");
+ if (!entry_join)
+ return -ENOMEM;
+
+ if (!streq(*entry, entry_join))
+ r = strv_consume(&e, TAKE_PTR(entry_join));
+ else
+ r = strv_consume(&a, TAKE_PTR(entry_join));
+ }
if (r < 0)
return r;
}
@@ -253,6 +284,20 @@ int parse_acl(const char *text, acl_t *ret_acl_access, acl_t *ret_acl_default, b
}
}
+ if (!strv_isempty(e)) {
+ _cleanup_free_ char *join = NULL;
+
+ join = strv_join(e, ",");
+ if (!join)
+ return -ENOMEM;
+
+ e_acl = acl_from_text(join);
+ if (!e_acl)
+ return -errno;
+
+ /* The mask must be calculated after deciding whether the execute bit should be set. */
+ }
+
if (!strv_isempty(d)) {
_cleanup_free_ char *join = NULL;
@@ -272,6 +317,7 @@ int parse_acl(const char *text, acl_t *ret_acl_access, acl_t *ret_acl_default, b
}
*ret_acl_access = TAKE_PTR(a_acl);
+ *ret_acl_access_exec = TAKE_PTR(e_acl);
*ret_acl_default = TAKE_PTR(d_acl);
return 0;
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
index d3a341fbe6..978389ed1d 100644
--- a/src/shared/acl-util.h
+++ b/src/shared/acl-util.h
@@ -15,7 +15,12 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
int calc_acl_mask_if_needed(acl_t *acl_p);
int add_base_acls_if_needed(acl_t *acl_p, const char *path);
int acl_search_groups(const char* path, char ***ret_groups);
-int parse_acl(const char *text, acl_t *ret_acl_access, acl_t *ret_acl_default, bool want_mask);
+int parse_acl(
+ const char *text,
+ acl_t *ret_acl_access,
+ acl_t *ret_acl_access_exec,
+ acl_t *ret_acl_default,
+ bool want_mask);
int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *ret);
int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask);