diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2015-01-18 18:22:27 -0500 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2015-01-22 01:14:53 -0500 |
commit | dd4105b0a90c3c146a01e5a7734ee76c3a9aa1cd (patch) | |
tree | 8495e75a56e34df54a13fcca25a5a2e2ec0248c2 /src/shared/acl-util.c | |
parent | a48a62a1af02aec4473c9deed98dd5b89d210f93 (diff) |
shared/acl-util: add mask only when needed, always add base ACLs
For ACLs to be valid, a set of entries for user, group, and other
must be always present. Always add those entries.
While at it, only add the mask ACL if it is actually required, i.e.
when at least on ACL for non-owner group or user exists.
Diffstat (limited to 'src/shared/acl-util.c')
-rw-r--r-- | src/shared/acl-util.c | 102 |
1 files changed, 82 insertions, 20 deletions
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index 950f472ddd..a4ff1ab878 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -29,14 +29,14 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) { acl_entry_t i; - int found; + int r; assert(acl); assert(entry); - for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); - found > 0; - found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { + for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { acl_tag_t tag; uid_t *u; @@ -60,8 +60,7 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) { return 1; } } - - if (found < 0) + if (r < 0) return -errno; return 0; @@ -69,14 +68,13 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) { int calc_acl_mask_if_needed(acl_t *acl_p) { acl_entry_t i; - int found; + int r; assert(acl_p); - for (found = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); - found > 0; - found = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { - + for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { acl_tag_t tag; if (acl_get_tag_type(i, &tag) < 0) @@ -84,14 +82,80 @@ int calc_acl_mask_if_needed(acl_t *acl_p) { if (tag == ACL_MASK) return 0; + if (IN_SET(tag, ACL_USER, ACL_GROUP)) + goto calc; } - - if (found < 0) + if (r < 0) return -errno; + return 0; +calc: if (acl_calc_mask(acl_p) < 0) return -errno; + return 1; +} + +int add_base_acls_if_needed(acl_t *acl_p, const char *path) { + acl_entry_t i; + int r; + bool have_user_obj = false, have_group_obj = false, have_other = false; + struct stat st; + _cleanup_(acl_freep) acl_t basic = NULL; + + assert(acl_p); + + for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { + acl_tag_t tag; + + if (acl_get_tag_type(i, &tag) < 0) + return -errno; + + if (tag == ACL_USER_OBJ) + have_user_obj = true; + else if (tag == ACL_GROUP_OBJ) + have_group_obj = true; + else if (tag == ACL_OTHER) + have_other = true; + if (have_user_obj && have_group_obj && have_other) + return 0; + } + if (r < 0) + return -errno; + r = stat(path, &st); + if (r < 0) + return -errno; + + basic = acl_from_mode(st.st_mode); + if (!basic) + return -errno; + + for (r = acl_get_entry(basic, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) { + acl_tag_t tag; + acl_entry_t dst; + + if (acl_get_tag_type(i, &tag) < 0) + return -errno; + + if ((tag == ACL_USER_OBJ && have_user_obj) || + (tag == ACL_GROUP_OBJ && have_group_obj) || + (tag == ACL_OTHER && have_other)) + continue; + + r = acl_create_entry(acl_p, &dst); + if (r < 0) + return -errno; + + r = acl_copy_entry(dst, i); + if (r < 0) + return -errno; + } + if (r < 0) + return -errno; return 0; } @@ -221,15 +285,15 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) { _cleanup_(acl_freep) acl_t old; acl_entry_t i; - int found, r; + int r; old = acl_get_file(path, type); if (!old) return -errno; - for (found = acl_get_entry(new, ACL_FIRST_ENTRY, &i); - found > 0; - found = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) { + for (r = acl_get_entry(new, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) { acl_entry_t j; @@ -239,10 +303,8 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) { if (acl_copy_entry(j, i) < 0) return -errno; } - - r = calc_acl_mask_if_needed(&old); if (r < 0) - return r; + return -errno; *acl = old; old = NULL; |