From: Pádraig Brady Date: Sat, 11 Jan 2025 16:40:33 +0000 (+0000) Subject: file-has-acl: handle NFSv4 ACLs with listxattr returning EACCES X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=05c63bc908a67a316fea29ddf4c702d89cf5bdec;p=gnulib.git file-has-acl: handle NFSv4 ACLs with listxattr returning EACCES * lib/file-has-acl.c (has_xattr): A new helper function to lookup aclinfo for the xattr or fallback to getxattr() if appropriate. (get_aclinfo): Use has_xattr() rather than aclinfo_has_xattr(). Discussed at --- diff --git a/ChangeLog b/ChangeLog index 9399bcbb9b..6ccd999e80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2025-01-11 Pádraig Brady + + file-has-acl: handle NFSv4 ACLs with listxattr returning EACCES + * lib/file-has-acl.c (has_xattr): A new helper function to + lookup aclinfo for the xattr or fallback to getxattr() if appropriate. + (get_aclinfo): Use has_xattr() rather than aclinfo_has_xattr(). + Discussed at + 2025-01-11 Bruno Haible sys_un-h: Document the glibc bug. diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index 5ec6b256ef..e8413f8f85 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -99,6 +99,36 @@ enum { ACE4_IDENTIFIER_GROUP = 0x00000040 }; +/* AI indicates XATTR may be present but wasn't accessible. + This is the case when [l]listxattr failed with E2BIG, + or failed with EACCES which in Linux kernel 6.12 NFS can mean merely + that we lack read access. +*/ + +static bool +aclinfo_may_indicate_xattr (struct aclinfo const *ai) +{ + return ai->size < 0 && (ai->u.err == EACCES || ai->u.err == E2BIG); +} + +/* Does NAME have XATTR? */ + +static bool +has_xattr (char const *xattr, struct aclinfo const *ai, + MAYBE_UNUSED char const *restrict name, MAYBE_UNUSED int flags) +{ + if (ai && aclinfo_has_xattr (ai, xattr)) + return true; + else if (!ai || aclinfo_may_indicate_xattr (ai)) + { + int ret = ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr) + (name, xattr, NULL, 0)); + if (0 <= ret || (errno == ERANGE || errno == E2BIG)) + return true; + } + return false; +} + /* Does AI's xattr set contain XATTR? */ bool @@ -176,13 +206,9 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags) } } - /* A security context can exist only if extended attributes do: i.e., - [l]listxattr either returned a positive number, or failed with E2BIG, - or failed with EACCES which in Linux kernel 6.12 NFS can mean merely - that we lack read access. */ + /* A security context can exist only if extended attributes do. */ if (flags & ACL_GET_SCONTEXT - && (0 < ai->size - || (ai->size < 0 && (ai->u.err == E2BIG || ai->u.err == EACCES)))) + && (0 < ai->size || aclinfo_may_indicate_xattr (ai))) { if (is_smack_enabled ()) { @@ -358,7 +384,7 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, int initial_errno = errno; get_aclinfo (name, ai, flags); - if (ai->size <= 0) + if (!aclinfo_may_indicate_xattr (ai) && ai->size <= 0) { errno = ai->size < 0 ? ai->u.err : initial_errno; return ai->size; @@ -369,11 +395,11 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, In earlier Fedora the two types of ACLs were mutually exclusive. Attempt to work correctly on both kinds of systems. */ - if (!aclinfo_has_xattr (ai, XATTR_NAME_NFSV4_ACL)) + if (!has_xattr (XATTR_NAME_NFSV4_ACL, ai, name, flags)) return - (aclinfo_has_xattr (ai, XATTR_NAME_POSIX_ACL_ACCESS) + (has_xattr (XATTR_NAME_POSIX_ACL_ACCESS, ai, name, flags) || ((d_type == DT_DIR || d_type == DT_UNKNOWN) - && aclinfo_has_xattr (ai, XATTR_NAME_POSIX_ACL_DEFAULT))); + && has_xattr (XATTR_NAME_POSIX_ACL_DEFAULT, ai, name, flags))); /* A buffer large enough to hold any trivial NFSv4 ACL. The max length of a trivial NFSv4 ACL is 6 words for owner,