bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] file-has-acl: scontext even if --disable-acl


From: Paul Eggert
Subject: [PATCH] file-has-acl: scontext even if --disable-acl
Date: Mon, 11 Nov 2024 07:54:07 -0800

Be able to get the security context even if configured with
--disable-acl, as security contexts are not ACLs, and the
main reason for --disable-acl was for efficiency with GNU ls -l,
a concern that does not apply to security contexts (which are
needed only with ls -Z).  Problem reported by Pádraig Brady
<https://bugs.gnu.org/73418#52>.
* lib/acl.h (ACL_GET_SCONTEXT): New constant.
(aclinfo_free, aclinfo_scontext_free): Declare even if !USE_ACL.
* lib/file-has-acl.c (USE_LINUX_XATTR): No longer false merely
because !USE_ACL, because we need xattr to get scontext.
(get_aclinfo): Support new ACL_GET_SCONTEXT flag.
---
 ChangeLog          | 15 ++++++++
 lib/acl.h          | 17 ++++++---
 lib/file-has-acl.c | 93 +++++++++++++++++++++++++---------------------
 3 files changed, 77 insertions(+), 48 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index afce32cf8b..3ae5107c7a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2024-11-11  Paul Eggert  <eggert@cs.ucla.edu>
+
+       file-has-acl: scontext even if --disable-acl
+       Be able to get the security context even if configured with
+       --disable-acl, as security contexts are not ACLs, and the
+       main reason for --disable-acl was for efficiency with GNU ls -l,
+       a concern that does not apply to security contexts (which are
+       needed only with ls -Z).  Problem reported by Pádraig Brady
+       <https://bugs.gnu.org/73418#52>.
+       * lib/acl.h (ACL_GET_SCONTEXT): New constant.
+       (aclinfo_free, aclinfo_scontext_free): Declare even if !USE_ACL.
+       * lib/file-has-acl.c (USE_LINUX_XATTR): No longer false merely
+       because !USE_ACL, because we need xattr to get scontext.
+       (get_aclinfo): Support new ACL_GET_SCONTEXT flag.
+
 2024-11-11  Bruno Haible  <bruno@clisp.org>
 
        nproc: Use affinity mask even in out-of-memory situations.
diff --git a/lib/acl.h b/lib/acl.h
index ca74fe6de8..1d52345c66 100644
--- a/lib/acl.h
+++ b/lib/acl.h
@@ -32,9 +32,16 @@
 extern "C" {
 #endif
 
-/* Follow symlinks when getting an ACL.  This is a bitmask that is guaranteed
-   not to collide with any <dirent.h> DT_* or _GL_DT_* value.  */
-enum { ACL_SYMLINK_FOLLOW = 0x10000 };
+/* file_has_acl flags guaranteed to not collide with any <dirent.h>
+   DT_* or _GL_DT_* value.  */
+enum
+  {
+    /* Get scontext information as well.  */
+    ACL_GET_SCONTEXT = 0x10000,
+
+    /* Follow symlinks.  */
+    ACL_SYMLINK_FOLLOW = 0x20000,
+  };
 
 /* Information about an ACL.  */
 struct aclinfo
@@ -73,7 +80,7 @@ bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST;
 int file_has_acl (char const *, struct stat const *);
 int file_has_aclinfo (char const *restrict, struct aclinfo *restrict, int);
 
-#if USE_ACL && HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
+#if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
 bool aclinfo_has_xattr (struct aclinfo const *, char const *)
   _GL_ATTRIBUTE_PURE;
 void aclinfo_free (struct aclinfo *);
@@ -81,7 +88,7 @@ void aclinfo_free (struct aclinfo *);
 # define aclinfo_has_xattr(ai, xattr) false
 # define aclinfo_free(ai) ((void) 0)
 #endif
-#if (USE_ACL && HAVE_LINUX_XATTR_H && HAVE_LISTXATTR \
+#if (HAVE_LINUX_XATTR_H && HAVE_LISTXATTR \
      && (HAVE_SMACK || USE_SELINUX_SELINUX_H))
 void aclinfo_scontext_free (char *);
 #else
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index 7e05d39131..2cbc20b38d 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -39,7 +39,7 @@ static_assert (ACL_SYMLINK_FOLLOW & ~ (unsigned char) -1);
 
 static char const UNKNOWN_SECURITY_CONTEXT[] = "?";
 
-#if USE_ACL && HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
+#if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
 # define USE_LINUX_XATTR true
 #else
 # define USE_LINUX_XATTR false
@@ -109,7 +109,8 @@ aclinfo_has_xattr (struct aclinfo const *ai, char const 
*xattr)
   return false;
 }
 
-/* Get attributes of the file NAME into AI.
+/* Get attributes of the file NAME into AI, if USE_ACL.
+   If FLAGS & ACL_GET_SCONTEXT, also get security context.
    If FLAGS & ACL_SYMLINK_FOLLOW, follow symbolic links.  */
 static void
 get_aclinfo (char const *name, struct aclinfo *ai, int flags)
@@ -118,53 +119,58 @@ get_aclinfo (char const *name, struct aclinfo *ai, int 
flags)
   ai->buf = ai->u.__gl_acl_ch;
   ssize_t acl_alloc = sizeof ai->u.__gl_acl_ch;
 
-  ssize_t (*lsxattr) (char const *, char *, size_t)
-    = (flags & ACL_SYMLINK_FOLLOW ? listxattr : llistxattr);
-  while (true)
+  if (! (USE_ACL || flags & ACL_GET_SCONTEXT))
+    ai->size = 0;
+  else
     {
-      ai->size = lsxattr (name, ai->buf, acl_alloc);
-      if (0 < ai->size)
-        break;
-      ai->u.err = ai->size < 0 ? errno : 0;
-      if (! (ai->size < 0 && ai->u.err == ERANGE && acl_alloc < SSIZE_MAX))
-        break;
-
-      /* The buffer was too small.  Find how large it should have been.  */
-      ssize_t size = lsxattr (name, NULL, 0);
-      if (size <= 0)
+      ssize_t (*lsxattr) (char const *, char *, size_t)
+        = (flags & ACL_SYMLINK_FOLLOW ? listxattr : llistxattr);
+      while (true)
         {
-          ai->size = size;
-          ai->u.err = size < 0 ? errno : 0;
-          break;
-        }
+          ai->size = lsxattr (name, ai->buf, acl_alloc);
+          if (0 < ai->size)
+            break;
+          ai->u.err = ai->size < 0 ? errno : 0;
+          if (! (ai->size < 0 && ai->u.err == ERANGE && acl_alloc < SSIZE_MAX))
+            break;
 
-      /* Grow allocation to at least 'size'.  Grow it by a nontrivial
-         amount, to defend against denial of service by an adversary
-         that fiddles with ACLs.  */
-      if (ai->buf != ai->u.__gl_acl_ch)
-        {
-          free (ai->buf);
-          ai->buf = ai->u.__gl_acl_ch;
-        }
-      if (ckd_add (&acl_alloc, acl_alloc, acl_alloc >> 1))
-        acl_alloc = SSIZE_MAX;
-      if (acl_alloc < size)
-        acl_alloc = size;
-      if (SIZE_MAX < acl_alloc)
-        {
-          ai->u.err = ENOMEM;
-          break;
-        }
-      char *newbuf = malloc (acl_alloc);
-      if (!newbuf)
-        {
-          ai->u.err = errno;
-          break;
+          /* The buffer was too small.  Find how large it should have been.  */
+          ssize_t size = lsxattr (name, NULL, 0);
+          if (size <= 0)
+            {
+              ai->size = size;
+              ai->u.err = size < 0 ? errno : 0;
+              break;
+            }
+
+          /* Grow allocation to at least 'size'.  Grow it by a nontrivial
+             amount, to defend against denial of service by an adversary
+             that fiddles with ACLs.  */
+          if (ai->buf != ai->u.__gl_acl_ch)
+            {
+              free (ai->buf);
+              ai->buf = ai->u.__gl_acl_ch;
+            }
+          if (ckd_add (&acl_alloc, acl_alloc, acl_alloc >> 1))
+            acl_alloc = SSIZE_MAX;
+          if (acl_alloc < size)
+            acl_alloc = size;
+          if (SIZE_MAX < acl_alloc)
+            {
+              ai->u.err = ENOMEM;
+              break;
+            }
+          char *newbuf = malloc (acl_alloc);
+          if (!newbuf)
+            {
+              ai->u.err = errno;
+              break;
+            }
+          ai->buf = newbuf;
         }
-      ai->buf = newbuf;
     }
 
-  if (0 < ai->size)
+  if (0 < ai->size && flags & ACL_GET_SCONTEXT)
     {
       if (is_smack_enabled ())
         {
@@ -325,6 +331,7 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes)
    Set *AI to ACL info regardless of return value.
    FLAGS should be a <dirent.h> d_type value, optionally ORed with
      - _GL_DT_NOTDIR if it is known that NAME is not a directory,
+     - ACL_GET_SCONTEXT to retrieve extended attributes,
      - ACL_SYMLINK_FOLLOW to follow the link if NAME is a symbolic link.
    If the d_type value is not known, use DT_UNKNOWN though this may be less
    efficient.
-- 
2.47.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]