]> Savannah Git Hosting - gnulib.git/commitdiff
file-has-acl: handle NFSv4 ACLs with listxattr returning EACCES
authorPádraig Brady <P@draigBrady.com>
Sat, 11 Jan 2025 16:40:33 +0000 (16:40 +0000)
committerBruno Haible <bruno@clisp.org>
Sat, 18 Jan 2025 08:13:26 +0000 (09:13 +0100)
* 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 <https://bugs.gnu.org/74692>

ChangeLog
lib/file-has-acl.c

index 5a26693602b9ecc058caafe0a06c73025dac40d2..c27a4c8e12d42fab94fa632ef03593497bd3aa06 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2025-01-11  Pádraig Brady  <P@draigBrady.com>
+
+       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 <https://bugs.gnu.org/74692>
+
 2025-01-11  Bruno Haible  <bruno@clisp.org>
 
        eealloc, malloca: Fix module dependencies.
index 5ec6b256ef762d7e0d867323dc34dc23f1c7865f..e8413f8f85f928cff19f757c64e0592d67e25c9a 100644 (file)
@@ -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,