On 2025-01-08 06:24, Pádraig Brady wrote:
The EACCES is returned from both llistxattr and listxattr.

Is flistxattr the same?


You need read permission to get xattrs on local or nfs.

Isn't it more complicated than that, for local file systems? Here's what I observe on Fedora 41 with a local ext4 file system. Sometimes I need read permission, sometimes I don't. (Is any of this stuff documented?)

  $ touch ghijkl
  $ setfattr -n user.foo -v bar ghijkl
  $ chmod 0 ghijkl
  $ strace -o tr ls -l ghijkl
----------. 1 eggert eggert 0 Jan  8 11:27 ghijkl
  $ grep xattr tr
  llistxattr("ghijkl", "security.selinux\0user.foo\0", 152) = 26
lgetxattr("ghijkl", "security.selinux", "unconfined_u:object_r:user_home_"..., 255) = 37
  $ strace -o tr2 getfattr -n security.selinux ghijkl
  # file: ghijkl
  security.selinux="unconfined_u:object_r:user_home_t:s0"

  $ grep xattr tr2
  getxattr("ghijkl", "security.selinux", NULL, 0) = 37
getxattr("ghijkl", "security.selinux", "unconfined_u:object_r:user_home_"..., 256) = 37


So this looks like an inconsistency in nfs,
but also a common scenario I expect.

Yes, unfortunately.


So I would think we should ignore the EACCES from listxattr()
For ls at least, any real permission issues would be diagnosed with stat() etc.

Ignoring EACCES doesn't sound right. This situation differs from the other ones noted in lib/acl-errno-valid.c. In those situations, a file system or kernel issues a weird errno value when ACLs aren't supported, and so it's appropriate to treat those errno values as if they were ENOTSUP.

Here, if I understand things correctly, the file system supports ACLs but it doesn't want to give you the information. That's something I'd want to know about if I am the 'ls' user.

How about something like the attached patch instead? It's incomplete (needs doc) and untested but I hope it gives you the basic idea, which is to put '?' in the ACL column when you lack permissions to find out whether ACLs are present.
diff --git a/src/ls.c b/src/ls.c
index a42c7707a..605f13e8c 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -199,6 +199,7 @@ static char const d_type_filetype[UCHAR_MAX + 1] =
 enum acl_type
   {
     ACL_T_NONE,
+    ACL_T_UNKNOWN,
     ACL_T_LSM_CONTEXT_ONLY,
     ACL_T_YES
   };
@@ -3518,14 +3519,20 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
       int n = file_has_aclinfo_cache (full_name, f, &ai, aclinfo_flags);
       bool have_acl = 0 < n;
       bool have_scontext = !ai.scontext_err;
+
+      /* Let the user know via '?' if errno is EACCES, which can
+         happen with Linux kernel 6.12 on an NFS file system.
+         That's better than a longwinded diagnostic.  */
+      bool cannot_access_acl = n < 0 && errno == EACCES;
+
       f->acl_type = (!have_scontext && !have_acl
-                     ? ACL_T_NONE
+                     ? (cannot_access_acl ? ACL_T_UNKNOWN : ACL_T_NONE)
                      : (have_scontext && !have_acl
                         ? ACL_T_LSM_CONTEXT_ONLY
                         : ACL_T_YES));
       any_has_acl |= f->acl_type != ACL_T_NONE;
 
-      if (format == long_format && n < 0)
+      if (format == long_format && n < 0 && !cannot_access_acl)
         error (0, ai.u.err, "%s", quotef (full_name));
       else
         {

Reply via email to