From 1f0bacd901fe2f54ca4d441fad92b51e851ed439 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 16 Mar 2020 16:11:07 -0400 Subject: fsade: Fix default ACL processing. For default ACLs, any entries at all makes them non-trivial. C.f.: https://lists.freebsd.org/pipermail/posix1e/2014-July/000517.html --- fsade.c | 88 +++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 38 deletions(-) (limited to 'fsade.c') diff --git a/fsade.c b/fsade.c index 668f586..a4c50ee 100644 --- a/fsade.c +++ b/fsade.c @@ -126,29 +126,10 @@ static bool is_absence_error(int error) { #if BFS_CAN_CHECK_ACL -/** Check if any ACLs of the given type are non-trivial. */ -static int bfs_check_acl_type(const char *path, acl_type_t type) { - acl_t acl = acl_get_file(path, type); - if (!acl) { - if (is_absence_error(errno)) { - return 0; - } else { - return -1; - } - } - +/** Check if a POSIX.1e ACL is non-trivial. */ +static int bfs_check_posix1e_acl(acl_t acl, bool ignore_required) { int ret = 0; -#if __FreeBSD__ - int trivial; - if (acl_is_trivial_np(acl, &trivial) < 0) { - ret = -1; - } else if (trivial) { - ret = 0; - } else { - ret = 1; - } -#else acl_entry_t entry; for (int status = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); #if __APPLE__ @@ -160,27 +141,46 @@ static int bfs_check_acl_type(const char *path, acl_type_t type) { #endif status = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) { #if defined(ACL_USER_OBJ) && defined(ACL_GROUP_OBJ) && defined(ACL_OTHER) - acl_tag_t tag; - if (acl_get_tag_type(entry, &tag) != 0) { - continue; - } - if (tag != ACL_USER_OBJ && tag != ACL_GROUP_OBJ && tag != ACL_OTHER) { - ret = 1; - break; + if (ignore_required) { + acl_tag_t tag; + if (acl_get_tag_type(entry, &tag) != 0) { + ret = -1; + continue; + } + if (tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER) { + continue; + } } -#else +#endif + ret = 1; break; -#endif } -#endif // !__FreeBSD__ - int error = errno; - acl_free(acl); - errno = error; return ret; } +/** Check if an ACL of the given type is non-trivial. */ +static int bfs_check_acl_type(acl_t acl, acl_type_t type) { + if (type == ACL_TYPE_DEFAULT) { + // For directory default ACLs, any entries make them non-trivial + return bfs_check_posix1e_acl(acl, false); + } + +#if __FreeBSD__ + int trivial; + if (acl_is_trivial_np(acl, &trivial) < 0) { + return -1; + } else if (trivial) { + return 0; + } else { + return 1; + } +#endif + + return bfs_check_posix1e_acl(acl, true); +} + int bfs_check_acl(const struct BFTW *ftwbuf) { static const acl_type_t acl_types[] = { #if __APPLE__ @@ -205,18 +205,30 @@ int bfs_check_acl(const struct BFTW *ftwbuf) { const char *path = fake_at(ftwbuf); - int ret = -1; + int ret = -1, error = 0; for (size_t i = 0; i < n_acl_types && ret <= 0; ++i) { - if (acl_types[i] == ACL_TYPE_DEFAULT && ftwbuf->typeflag != BFTW_DIR) { + acl_type_t type = acl_types[i]; + + if (type == ACL_TYPE_DEFAULT && ftwbuf->typeflag != BFTW_DIR) { // ACL_TYPE_DEFAULT is supported only for directories, // otherwise acl_get_file() gives EACCESS continue; } - ret = bfs_check_acl_type(path, acl_types[i]); + acl_t acl = acl_get_file(path, type); + if (!acl) { + error = errno; + if (is_absence_error(error)) { + ret = 0; + } + continue; + } + + ret = bfs_check_acl_type(acl, type); + error = errno; + acl_free(acl); } - int error = errno; free_fake_at(ftwbuf, path); errno = error; return ret; -- cgit v1.2.3