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
}
}
- /* 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 ())
{
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;
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,