X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Flibadacl.c;h=0d07f2c6d0126880b59e830011fcbbefc75e797f;hb=6727b9e8ed3807cd565127f87fa6faa33c4b5ee4;hp=35f8de79033f3c694138bc27cbc377acc9320eff;hpb=9cf74aa49835a8309bdc1d9e12afe1925003f141;p=apply-default-acl.git diff --git a/src/libadacl.c b/src/libadacl.c index 35f8de7..0d07f2c 100644 --- a/src/libadacl.c +++ b/src/libadacl.c @@ -256,8 +256,8 @@ int acl_set_entry(acl_t* aclp, acl_entry_t entry) { if (existing_tag == entry_tag) { /* If we update something, we're done and return ACL_SUCCESS */ if (acl_set_permset(existing_entry, entry_permset) == ACL_ERROR) { - perror("acl_set_entry (acl_set_permset)"); - return ACL_ERROR; + perror("acl_set_entry (acl_set_permset)"); + return ACL_ERROR; } return ACL_SUCCESS; @@ -416,23 +416,23 @@ int acl_execute_masked(acl_t acl) { if (tag == ACL_MASK) { /* This is the mask entry, get its permissions, and see if - execute is specified. */ + execute is specified. */ acl_permset_t permset; if (acl_get_permset(entry, &permset) == ACL_ERROR) { - perror("acl_execute_masked (acl_get_permset)"); - return ACL_ERROR; + perror("acl_execute_masked (acl_get_permset)"); + return ACL_ERROR; } int gp_result = acl_get_perm(permset, ACL_EXECUTE); if (gp_result == ACL_ERROR) { - perror("acl_execute_masked (acl_get_perm)"); - return ACL_ERROR; + perror("acl_execute_masked (acl_get_perm)"); + return ACL_ERROR; } if (gp_result == ACL_FAILURE) { - /* No execute bit set in the mask; execute not allowed. */ - return ACL_SUCCESS; + /* No execute bit set in the mask; execute not allowed. */ + return ACL_SUCCESS; } } @@ -530,8 +530,8 @@ int any_can_execute(int fd, const struct stat* sp) { if (gp_result == ACL_SUCCESS) { /* Only return ACL_SUCCESS if this execute bit is not masked. */ if (acl_execute_masked(acl) != ACL_SUCCESS) { - result = ACL_SUCCESS; - goto cleanup; + result = ACL_SUCCESS; + goto cleanup; } } @@ -653,8 +653,8 @@ int acl_copy_xattr(int src_fd, if (src_size_guess == XATTR_ERROR) { if (errno == ENODATA) { /* A missing ACL isn't really an error. ENOATTR and ENODATA are - synonyms, but using ENODATA here lets us avoid another - "include" directive. */ + synonyms, but using ENODATA here lets us avoid another + "include" directive. */ return ACL_FAILURE; } perror("acl_copy_xattr (fgetxattr size guess)"); @@ -681,6 +681,30 @@ int acl_copy_xattr(int src_fd, } +/** + * @brief Determine if a file descriptor has a default ACL. + * + * @param fd + * The file descriptor whose default ACL is in question. + * + * @return + * - @c ACL_SUCCESS - If @c fd has a default ACL. + * - @c ACL_FAILURE - If @c fd does not have a default ACL. + * - @c ACL_ERROR - Unexpected library error. + */ +int has_default_acl_fd(int fd) { + if (fgetxattr(fd, XATTR_NAME_POSIX_ACL_DEFAULT, NULL, 0) == XATTR_ERROR) { + if (errno == ENODATA) { + return ACL_FAILURE; + } + perror("has_default_acl_fd (fgetxattr)"); + return ACL_ERROR; + } + + return ACL_SUCCESS; +} + + /** * @brief Apply parent default ACL to a path. * @@ -702,8 +726,8 @@ int acl_copy_xattr(int src_fd, * - @c ACL_ERROR - Unexpected library error. */ int apply_default_acl_ex(const char* path, - const struct stat* sp, - bool no_exec_mask) { + const struct stat* sp, + bool no_exec_mask) { if (path == NULL) { errno = EINVAL; @@ -743,7 +767,7 @@ int apply_default_acl_ex(const char* path, if (parent_fd == OPEN_ERROR) { if (errno == ELOOP || errno == ENOTDIR) { /* We hit a symlink, either in the last path component (ELOOP) - or higher up (ENOTDIR). */ + or higher up (ENOTDIR). */ result = ACL_FAILURE; goto cleanup; } @@ -754,11 +778,18 @@ int apply_default_acl_ex(const char* path, } } + /* Check to make sure the parent descriptor actually has a default + ACL. If it doesn't, then we can "succeed" immediately. */ + if (has_default_acl_fd(parent_fd) == ACL_FAILURE) { + result = ACL_SUCCESS; + goto cleanup; + } + fd = safe_open(path, O_NOFOLLOW); if (fd == OPEN_ERROR) { if (errno == ELOOP || errno == ENOTDIR) { /* We hit a symlink, either in the last path component (ELOOP) - or higher up (ENOTDIR). */ + or higher up (ENOTDIR). */ result = ACL_FAILURE; goto cleanup; } @@ -898,25 +929,25 @@ int apply_default_acl_ex(const char* path, } if (tag == ACL_MASK || - tag == ACL_USER_OBJ || - tag == ACL_GROUP_OBJ || - tag == ACL_OTHER) { + tag == ACL_USER_OBJ || + tag == ACL_GROUP_OBJ || + tag == ACL_OTHER) { if (!allow_exec) { - /* The mask doesn't affect acl_user_obj, acl_group_obj (in - minimal ACLs) or acl_other entries, so if execute should be - masked, we have to do it manually. */ - if (acl_delete_perm(permset, ACL_EXECUTE) == ACL_ERROR) { - perror("apply_default_acl_ex (acl_delete_perm)"); - result = ACL_ERROR; - goto cleanup; - } - - if (acl_set_permset(entry, permset) == ACL_ERROR) { - perror("apply_default_acl_ex (acl_set_permset)"); - result = ACL_ERROR; - goto cleanup; - } + /* The mask doesn't affect acl_user_obj, acl_group_obj (in + minimal ACLs) or acl_other entries, so if execute should be + masked, we have to do it manually. */ + if (acl_delete_perm(permset, ACL_EXECUTE) == ACL_ERROR) { + perror("apply_default_acl_ex (acl_delete_perm)"); + result = ACL_ERROR; + goto cleanup; + } + + if (acl_set_permset(entry, permset) == ACL_ERROR) { + perror("apply_default_acl_ex (acl_set_permset)"); + result = ACL_ERROR; + goto cleanup; + } } } @@ -968,11 +999,11 @@ int apply_default_acl_ex(const char* path, if (new_acl_unmasked != (acl_t)NULL) { acl_free(new_acl_unmasked); } - if (fd >= 0 && close(fd) == CLOSE_ERROR) { + if (fd > 0 && close(fd) == CLOSE_ERROR) { perror("apply_default_acl_ex (close fd)"); result = ACL_ERROR; } - if (parent_fd >= 0 && close(parent_fd) == CLOSE_ERROR) { + if (parent_fd > 0 && close(parent_fd) == CLOSE_ERROR) { perror("apply_default_acl_ex (close parent_fd)"); result = ACL_ERROR; }