| |
@@ -0,0 +1,217 @@
|
| |
+ commit ccda8a2aedad84d9b730fdd6b36baa9582f54bfd
|
| |
+ Author: rpm-build <rpm-build>
|
| |
+ Date: Mon Sep 11 14:28:05 2023 +0200
|
| |
+
|
| |
+ coreutils-9.3-cp--p-should-copy-NFSv4-acls.patch
|
| |
+
|
| |
+ Cherry picked from the following gnulib upstream commits:
|
| |
+ * b851a965da62cd858d71b2e5a7261a211f00b297 ("file-has-acl: port to Fedora 39")
|
| |
+ * f01d8792778b637f7464533ac019e42f58adb310 ("file-has-acl: don’t access freed storage")
|
| |
+ * 735716931755c74f3788ac83fead717c0bb22dfe ("file-has-acl: improve port to Fedora 39")
|
| |
+
|
| |
+ diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
|
| |
+ index b31a2ea..4cddc80 100644
|
| |
+ --- a/lib/file-has-acl.c
|
| |
+ +++ b/lib/file-has-acl.c
|
| |
+ @@ -29,7 +29,10 @@
|
| |
+
|
| |
+ #include "acl-internal.h"
|
| |
+
|
| |
+ -#if USE_ACL && GETXATTR_WITH_POSIX_ACLS
|
| |
+ +#include "minmax.h"
|
| |
+ +
|
| |
+ +#if USE_ACL && HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
|
| |
+ +# include <stdckdint.h>
|
| |
+ # include <string.h>
|
| |
+ # include <arpa/inet.h>
|
| |
+ # include <sys/xattr.h>
|
| |
+ @@ -44,6 +47,20 @@ enum {
|
| |
+ ACE4_IDENTIFIER_GROUP = 0x00000040
|
| |
+ };
|
| |
+
|
| |
+ +/* Return true if ATTR is in the set represented by the NUL-terminated
|
| |
+ + strings in LISTBUF, which is of size LISTSIZE. */
|
| |
+ +
|
| |
+ +static bool
|
| |
+ +have_xattr (char const *attr, char const *listbuf, ssize_t listsize)
|
| |
+ +{
|
| |
+ + char const *blim = listbuf + listsize;
|
| |
+ + for (char const *b = listbuf; b < blim; b += strlen (b) + 1)
|
| |
+ + for (char const *a = attr; *a == *b; a++, b++)
|
| |
+ + if (!*a)
|
| |
+ + return true;
|
| |
+ + return false;
|
| |
+ +}
|
| |
+ +
|
| |
+ /* Return 1 if given ACL in XDR format is non-trivial, 0 if it is trivial.
|
| |
+ -1 upon failure to determine it. Possibly change errno. Assume that
|
| |
+ the ACL is valid, except avoid undefined behavior even if invalid.
|
| |
+ @@ -137,37 +154,77 @@ file_has_acl (char const *name, struct stat const *sb)
|
| |
+ if (! S_ISLNK (sb->st_mode))
|
| |
+ {
|
| |
+
|
| |
+ -# if GETXATTR_WITH_POSIX_ACLS
|
| |
+ -
|
| |
+ - ssize_t ret;
|
| |
+ +# if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
|
| |
+ int initial_errno = errno;
|
| |
+
|
| |
+ - ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0);
|
| |
+ - if (ret < 0 && errno == ENODATA)
|
| |
+ - ret = 0;
|
| |
+ - else if (ret > 0)
|
| |
+ - return 1;
|
| |
+ -
|
| |
+ - if (ret == 0 && S_ISDIR (sb->st_mode))
|
| |
+ + /* The max length of a trivial NFSv4 ACL is 6 words for owner,
|
| |
+ + 6 for group, 7 for everyone, all times 2 because there are
|
| |
+ + both allow and deny ACEs. There are 6 words for owner
|
| |
+ + because of type, flag, mask, wholen, "OWNER@"+pad and
|
| |
+ + similarly for group; everyone is another word to hold
|
| |
+ + "EVERYONE@". */
|
| |
+ + typedef uint32_t trivial_NFSv4_xattr_buf[2 * (6 + 6 + 7)];
|
| |
+ +
|
| |
+ + /* A buffer large enough to hold any trivial NFSv4 ACL,
|
| |
+ + and also useful as a small array of char. */
|
| |
+ + union {
|
| |
+ + trivial_NFSv4_xattr_buf xattr;
|
| |
+ + char ch[sizeof (trivial_NFSv4_xattr_buf)];
|
| |
+ + } stackbuf;
|
| |
+ +
|
| |
+ + char *listbuf = stackbuf.ch;
|
| |
+ + ssize_t listbufsize = sizeof stackbuf.ch;
|
| |
+ + char *heapbuf = NULL;
|
| |
+ + ssize_t listsize;
|
| |
+ +
|
| |
+ + /* Use listxattr first, as this means just one syscall in the
|
| |
+ + typical case where the file lacks an ACL. Try stackbuf
|
| |
+ + first, falling back on malloc if stackbuf is too small. */
|
| |
+ + while ((listsize = listxattr (name, listbuf, listbufsize)) < 0
|
| |
+ + && errno == ERANGE)
|
| |
+ {
|
| |
+ - ret = getxattr (name, XATTR_NAME_POSIX_ACL_DEFAULT, NULL, 0);
|
| |
+ - if (ret < 0 && errno == ENODATA)
|
| |
+ - ret = 0;
|
| |
+ - else if (ret > 0)
|
| |
+ - return 1;
|
| |
+ + free (heapbuf);
|
| |
+ + ssize_t newsize = listxattr (name, NULL, 0);
|
| |
+ + if (newsize <= 0)
|
| |
+ + return newsize;
|
| |
+ +
|
| |
+ + /* Grow LISTBUFSIZE to at least NEWSIZE. Grow it by a
|
| |
+ + nontrivial amount too, to defend against denial of
|
| |
+ + service by an adversary that fiddles with ACLs. */
|
| |
+ + bool overflow = ckd_add (&listbufsize, listbufsize, listbufsize >> 1);
|
| |
+ + listbufsize = MAX (listbufsize, newsize);
|
| |
+ + if (overflow || SIZE_MAX < listbufsize)
|
| |
+ + {
|
| |
+ + errno = ENOMEM;
|
| |
+ + return -1;
|
| |
+ + }
|
| |
+ +
|
| |
+ + listbuf = heapbuf = malloc (listbufsize);
|
| |
+ + if (!listbuf)
|
| |
+ + return -1;
|
| |
+ }
|
| |
+
|
| |
+ - if (ret < 0)
|
| |
+ + /* In Fedora 39, a file can have both NFSv4 and POSIX ACLs,
|
| |
+ + but if it has an NFSv4 ACL that's the one that matters.
|
| |
+ + In earlier Fedora the two types of ACLs were mutually exclusive.
|
| |
+ + Attempt to work correctly on both kinds of systems. */
|
| |
+ + bool nfsv4_acl
|
| |
+ + = 0 < listsize && have_xattr (XATTR_NAME_NFSV4_ACL, listbuf, listsize);
|
| |
+ + int ret
|
| |
+ + = (listsize <= 0 ? listsize
|
| |
+ + : (nfsv4_acl
|
| |
+ + || have_xattr (XATTR_NAME_POSIX_ACL_ACCESS, listbuf, listsize)
|
| |
+ + || (S_ISDIR (sb->st_mode)
|
| |
+ + && have_xattr (XATTR_NAME_POSIX_ACL_DEFAULT,
|
| |
+ + listbuf, listsize))));
|
| |
+ + free (heapbuf);
|
| |
+ +
|
| |
+ + /* If there is an NFSv4 ACL, follow up with a getxattr syscall
|
| |
+ + to see whether the NFSv4 ACL is nontrivial. */
|
| |
+ + if (nfsv4_acl)
|
| |
+ {
|
| |
+ - /* Check for NFSv4 ACLs. The max length of a trivial
|
| |
+ - ACL is 6 words for owner, 6 for group, 7 for everyone,
|
| |
+ - all times 2 because there are both allow and deny ACEs.
|
| |
+ - There are 6 words for owner because of type, flag, mask,
|
| |
+ - wholen, "OWNER@"+pad and similarly for group; everyone is
|
| |
+ - another word to hold "EVERYONE@". */
|
| |
+ - uint32_t xattr[2 * (6 + 6 + 7)];
|
| |
+ -
|
| |
+ - ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, sizeof xattr);
|
| |
+ + ret = getxattr (name, XATTR_NAME_NFSV4_ACL,
|
| |
+ + stackbuf.xattr, sizeof stackbuf.xattr);
|
| |
+ if (ret < 0)
|
| |
+ switch (errno)
|
| |
+ {
|
| |
+ @@ -177,7 +234,7 @@ file_has_acl (char const *name, struct stat const *sb)
|
| |
+ else
|
| |
+ {
|
| |
+ /* It looks like a trivial ACL, but investigate further. */
|
| |
+ - ret = acl_nfs4_nontrivial (xattr, ret);
|
| |
+ + ret = acl_nfs4_nontrivial (stackbuf.xattr, ret);
|
| |
+ if (ret < 0)
|
| |
+ {
|
| |
+ errno = EINVAL;
|
| |
+ diff --git a/m4/acl.m4 b/m4/acl.m4
|
| |
+ index dc9853a..3fa0779 100644
|
| |
+ --- a/m4/acl.m4
|
| |
+ +++ b/m4/acl.m4
|
| |
+ @@ -177,37 +177,23 @@ AC_DEFUN([gl_ACL_GET_FILE],
|
| |
+ AS_IF([test "$gl_cv_func_working_acl_get_file" != no], [$1], [$2])
|
| |
+ ])
|
| |
+
|
| |
+ -# On GNU/Linux, testing if a file has an acl can be done with the getxattr
|
| |
+ -# syscall which doesn't require linking against additional libraries.
|
| |
+ +# On GNU/Linux, testing if a file has an acl can be done with the
|
| |
+ +# listxattr and getxattr syscalls, which don't require linking
|
| |
+ +# against additional libraries. Assume this works if linux/attr.h
|
| |
+ +# and listxattr are present.
|
| |
+ AC_DEFUN([gl_FILE_HAS_ACL],
|
| |
+ [
|
| |
+ AC_REQUIRE([gl_FUNC_ACL_ARG])
|
| |
+ - if test "$enable_acl" != no; then
|
| |
+ - AC_CACHE_CHECK([for getxattr with XATTR_NAME_POSIX_ACL macros],
|
| |
+ - [gl_cv_getxattr_with_posix_acls],
|
| |
+ - [gl_cv_getxattr_with_posix_acls=no
|
| |
+ - AC_LINK_IFELSE(
|
| |
+ - [AC_LANG_PROGRAM(
|
| |
+ - [[#include <sys/types.h>
|
| |
+ - #include <sys/xattr.h>
|
| |
+ - #include <linux/xattr.h>
|
| |
+ - ]],
|
| |
+ - [[ssize_t a = getxattr (".", XATTR_NAME_POSIX_ACL_ACCESS, 0, 0);
|
| |
+ - ssize_t b = getxattr (".", XATTR_NAME_POSIX_ACL_DEFAULT, 0, 0);
|
| |
+ - return a < 0 || b < 0;
|
| |
+ - ]])],
|
| |
+ - [gl_cv_getxattr_with_posix_acls=yes])])
|
| |
+ - fi
|
| |
+ - if test "$gl_cv_getxattr_with_posix_acls" = yes; then
|
| |
+ - FILE_HAS_ACL_LIB=
|
| |
+ - AC_DEFINE([GETXATTR_WITH_POSIX_ACLS], 1,
|
| |
+ - [Define to 1 if getxattr works with XATTR_NAME_POSIX_ACL_ACCESS
|
| |
+ - and XATTR_NAME_POSIX_ACL_DEFAULT.])
|
| |
+ - else
|
| |
+ - dnl Set gl_need_lib_has_acl to a nonempty value, so that any
|
| |
+ - dnl later gl_FUNC_ACL call will set FILE_HAS_ACL_LIB=$LIB_ACL.
|
| |
+ - gl_need_lib_has_acl=1
|
| |
+ - FILE_HAS_ACL_LIB=$LIB_ACL
|
| |
+ - fi
|
| |
+ + AC_CHECK_HEADERS_ONCE([linux/xattr.h])
|
| |
+ + AC_CHECK_FUNCS_ONCE([listxattr])
|
| |
+ + FILE_HAS_ACL_LIB=
|
| |
+ + AS_CASE([$enable_acl,$ac_cv_header_linux_xattr_h,$ac_cv_func_listxattr],
|
| |
+ + [no,*,*], [],
|
| |
+ + [*,yes,yes], [],
|
| |
+ + [*],
|
| |
+ + [dnl Set gl_need_lib_has_acl to a nonempty value, so that any
|
| |
+ + dnl later gl_FUNC_ACL call will set FILE_HAS_ACL_LIB=$LIB_ACL.
|
| |
+ + gl_need_lib_has_acl=1
|
| |
+ + FILE_HAS_ACL_LIB=$LIB_ACL])
|
| |
+ AC_SUBST([FILE_HAS_ACL_LIB])
|
| |
+ ])
|
| |
Resolves: rhbz#2160675