Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3332d143e3 | ||
|
|
e1a1745d0c | ||
|
|
f338c12bfa |
4 changed files with 938 additions and 22 deletions
254
coreutils-9.1-copy-relative-dir.patch
Normal file
254
coreutils-9.1-copy-relative-dir.patch
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
diff -Naur coreutils-9.1.orig/src/copy.c coreutils-9.1/src/copy.c
|
||||||
|
--- coreutils-9.1.orig/src/copy.c 2022-04-15 13:53:28.000000000 +0000
|
||||||
|
+++ coreutils-9.1/src/copy.c 2023-05-04 21:09:46.290253081 +0000
|
||||||
|
@@ -1954,6 +1954,7 @@
|
||||||
|
bool restore_dst_mode = false;
|
||||||
|
char *earlier_file = NULL;
|
||||||
|
char *dst_backup = NULL;
|
||||||
|
+ char const *drelname = *dst_relname ? dst_relname : ".";
|
||||||
|
bool delayed_ok;
|
||||||
|
bool copied_as_regular = false;
|
||||||
|
bool dest_is_symlink = false;
|
||||||
|
@@ -1971,7 +1972,7 @@
|
||||||
|
if (x->move_mode)
|
||||||
|
{
|
||||||
|
if (rename_errno < 0)
|
||||||
|
- rename_errno = (renameatu (AT_FDCWD, src_name, dst_dirfd, dst_relname,
|
||||||
|
+ rename_errno = (renameatu (AT_FDCWD, src_name, dst_dirfd, drelname,
|
||||||
|
RENAME_NOREPLACE)
|
||||||
|
? errno : 0);
|
||||||
|
nonexistent_dst = *rename_succeeded = new_dst = rename_errno == 0;
|
||||||
|
@@ -1983,7 +1984,7 @@
|
||||||
|
{
|
||||||
|
char const *name = rename_errno == 0 ? dst_name : src_name;
|
||||||
|
int dirfd = rename_errno == 0 ? dst_dirfd : AT_FDCWD;
|
||||||
|
- char const *relname = rename_errno == 0 ? dst_relname : src_name;
|
||||||
|
+ char const *relname = rename_errno == 0 ? drelname : src_name;
|
||||||
|
int fstatat_flags
|
||||||
|
= x->dereference == DEREF_NEVER ? AT_SYMLINK_NOFOLLOW : 0;
|
||||||
|
if (follow_fstatat (dirfd, relname, &src_sb, fstatat_flags) != 0)
|
||||||
|
@@ -2051,8 +2052,7 @@
|
||||||
|
int fstatat_flags = use_lstat ? AT_SYMLINK_NOFOLLOW : 0;
|
||||||
|
if (!use_lstat && nonexistent_dst < 0)
|
||||||
|
new_dst = true;
|
||||||
|
- else if (follow_fstatat (dst_dirfd, dst_relname, &dst_sb,
|
||||||
|
- fstatat_flags)
|
||||||
|
+ else if (follow_fstatat (dst_dirfd, drelname, &dst_sb, fstatat_flags)
|
||||||
|
== 0)
|
||||||
|
{
|
||||||
|
have_dst_lstat = use_lstat;
|
||||||
|
@@ -2077,7 +2077,7 @@
|
||||||
|
bool return_now = false;
|
||||||
|
|
||||||
|
if (x->interactive != I_ALWAYS_NO
|
||||||
|
- && ! same_file_ok (src_name, &src_sb, dst_dirfd, dst_relname,
|
||||||
|
+ && ! same_file_ok (src_name, &src_sb, dst_dirfd, drelname,
|
||||||
|
&dst_sb, x, &return_now))
|
||||||
|
{
|
||||||
|
error (0, 0, _("%s and %s are the same file"),
|
||||||
|
@@ -2140,7 +2140,7 @@
|
||||||
|
cp and mv treat -i and -f differently. */
|
||||||
|
if (x->move_mode)
|
||||||
|
{
|
||||||
|
- if (abandon_move (x, dst_name, dst_dirfd, dst_relname, &dst_sb))
|
||||||
|
+ if (abandon_move (x, dst_name, dst_dirfd, drelname, &dst_sb))
|
||||||
|
{
|
||||||
|
/* Pretend the rename succeeded, so the caller (mv)
|
||||||
|
doesn't end up removing the source file. */
|
||||||
|
@@ -2321,14 +2321,11 @@
|
||||||
|
Otherwise, use AT_SYMLINK_NOFOLLOW, in case dst_name is a symlink. */
|
||||||
|
if (have_dst_lstat)
|
||||||
|
dst_lstat_sb = &dst_sb;
|
||||||
|
+ else if (fstatat (dst_dirfd, drelname, &tmp_buf, AT_SYMLINK_NOFOLLOW)
|
||||||
|
+ == 0)
|
||||||
|
+ dst_lstat_sb = &tmp_buf;
|
||||||
|
else
|
||||||
|
- {
|
||||||
|
- if (fstatat (dst_dirfd, dst_relname, &tmp_buf,
|
||||||
|
- AT_SYMLINK_NOFOLLOW) == 0)
|
||||||
|
- dst_lstat_sb = &tmp_buf;
|
||||||
|
- else
|
||||||
|
- lstat_ok = false;
|
||||||
|
- }
|
||||||
|
+ lstat_ok = false;
|
||||||
|
|
||||||
|
/* Never copy through a symlink we've just created. */
|
||||||
|
if (lstat_ok
|
||||||
|
@@ -2475,8 +2472,7 @@
|
||||||
|
if (x->move_mode)
|
||||||
|
{
|
||||||
|
if (rename_errno == EEXIST)
|
||||||
|
- rename_errno = ((renameat (AT_FDCWD, src_name, dst_dirfd, dst_relname)
|
||||||
|
- == 0)
|
||||||
|
+ rename_errno = (renameat (AT_FDCWD, src_name, dst_dirfd, drelname) == 0
|
||||||
|
? 0 : errno);
|
||||||
|
|
||||||
|
if (rename_errno == 0)
|
||||||
|
@@ -2576,7 +2572,7 @@
|
||||||
|
or not, and this is enforced above. Therefore we check the src_mode
|
||||||
|
and operate on dst_name here as a tighter constraint and also because
|
||||||
|
src_mode is readily available here. */
|
||||||
|
- if ((unlinkat (dst_dirfd, dst_relname,
|
||||||
|
+ if ((unlinkat (dst_dirfd, drelname,
|
||||||
|
S_ISDIR (src_mode) ? AT_REMOVEDIR : 0)
|
||||||
|
!= 0)
|
||||||
|
&& errno != ENOENT)
|
||||||
|
@@ -2646,7 +2642,7 @@
|
||||||
|
to ask mkdir to copy all the CHMOD_MODE_BITS, letting mkdir
|
||||||
|
decide what to do with S_ISUID | S_ISGID | S_ISVTX. */
|
||||||
|
mode_t mode = dst_mode_bits & ~omitted_permissions;
|
||||||
|
- if (mkdirat (dst_dirfd, dst_relname, mode) != 0)
|
||||||
|
+ if (mkdirat (dst_dirfd, drelname, mode) != 0)
|
||||||
|
{
|
||||||
|
error (0, errno, _("cannot create directory %s"),
|
||||||
|
quoteaf (dst_name));
|
||||||
|
@@ -2657,8 +2653,7 @@
|
||||||
|
for writing the directory's contents. Check if these
|
||||||
|
permissions are there. */
|
||||||
|
|
||||||
|
- if (fstatat (dst_dirfd, dst_relname, &dst_sb,
|
||||||
|
- AT_SYMLINK_NOFOLLOW) != 0)
|
||||||
|
+ if (fstatat (dst_dirfd, drelname, &dst_sb, AT_SYMLINK_NOFOLLOW) != 0)
|
||||||
|
{
|
||||||
|
error (0, errno, _("cannot stat %s"), quoteaf (dst_name));
|
||||||
|
goto un_backup;
|
||||||
|
@@ -2670,7 +2665,7 @@
|
||||||
|
dst_mode = dst_sb.st_mode;
|
||||||
|
restore_dst_mode = true;
|
||||||
|
|
||||||
|
- if (lchmodat (dst_dirfd, dst_relname, dst_mode | S_IRWXU) != 0)
|
||||||
|
+ if (lchmodat (dst_dirfd, drelname, dst_mode | S_IRWXU) != 0)
|
||||||
|
{
|
||||||
|
error (0, errno, _("setting permissions for %s"),
|
||||||
|
quoteaf (dst_name));
|
||||||
|
@@ -2924,7 +2919,7 @@
|
||||||
|
/* Now that the destination file is very likely to exist,
|
||||||
|
add its info to the set. */
|
||||||
|
struct stat sb;
|
||||||
|
- if (fstatat (dst_dirfd, dst_relname, &sb, AT_SYMLINK_NOFOLLOW) == 0)
|
||||||
|
+ if (fstatat (dst_dirfd, drelname, &sb, AT_SYMLINK_NOFOLLOW) == 0)
|
||||||
|
record_file (x->dest_info, dst_relname, &sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2957,7 +2952,7 @@
|
||||||
|
timespec[1] = get_stat_mtime (&src_sb);
|
||||||
|
|
||||||
|
int utimensat_flags = dest_is_symlink ? AT_SYMLINK_NOFOLLOW : 0;
|
||||||
|
- if (utimensat (dst_dirfd, dst_relname, timespec, utimensat_flags) != 0)
|
||||||
|
+ if (utimensat (dst_dirfd, drelname, timespec, utimensat_flags) != 0)
|
||||||
|
{
|
||||||
|
error (0, errno, _("preserving times for %s"), quoteaf (dst_name));
|
||||||
|
if (x->require_preserve)
|
||||||
|
@@ -2969,7 +2964,7 @@
|
||||||
|
if (!dest_is_symlink && x->preserve_ownership
|
||||||
|
&& (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb)))
|
||||||
|
{
|
||||||
|
- switch (set_owner (x, dst_name, dst_dirfd, dst_relname, -1,
|
||||||
|
+ switch (set_owner (x, dst_name, dst_dirfd, drelname, -1,
|
||||||
|
&src_sb, new_dst, &dst_sb))
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
@@ -3024,8 +3019,9 @@
|
||||||
|
the lstat, but deducing the current destination mode
|
||||||
|
is tricky in the presence of implementation-defined
|
||||||
|
rules for special mode bits. */
|
||||||
|
- if (new_dst && fstatat (dst_dirfd, dst_relname, &dst_sb,
|
||||||
|
- AT_SYMLINK_NOFOLLOW) != 0)
|
||||||
|
+ if (new_dst && (fstatat (dst_dirfd, drelname, &dst_sb,
|
||||||
|
+ AT_SYMLINK_NOFOLLOW)
|
||||||
|
+ != 0))
|
||||||
|
{
|
||||||
|
error (0, errno, _("cannot stat %s"), quoteaf (dst_name));
|
||||||
|
return false;
|
||||||
|
@@ -3038,7 +3034,7 @@
|
||||||
|
|
||||||
|
if (restore_dst_mode)
|
||||||
|
{
|
||||||
|
- if (lchmodat (dst_dirfd, dst_relname, dst_mode | omitted_permissions)
|
||||||
|
+ if (lchmodat (dst_dirfd, drelname, dst_mode | omitted_permissions)
|
||||||
|
!= 0)
|
||||||
|
{
|
||||||
|
error (0, errno, _("preserving permissions for %s"),
|
||||||
|
@@ -3068,7 +3064,7 @@
|
||||||
|
if (dst_backup)
|
||||||
|
{
|
||||||
|
char const *dst_relbackup = &dst_backup[dst_relname - dst_name];
|
||||||
|
- if (renameat (dst_dirfd, dst_relbackup, dst_dirfd, dst_relname) != 0)
|
||||||
|
+ if (renameat (dst_dirfd, dst_relbackup, dst_dirfd, drelname) != 0)
|
||||||
|
error (0, errno, _("cannot un-backup %s"), quoteaf (dst_name));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff -Naur coreutils-9.1.orig/src/cp.c coreutils-9.1/src/cp.c
|
||||||
|
--- coreutils-9.1.orig/src/cp.c 2023-05-04 21:08:46.747627135 +0000
|
||||||
|
+++ coreutils-9.1/src/cp.c 2023-05-04 21:09:50.067286480 +0000
|
||||||
|
@@ -273,15 +273,19 @@
|
||||||
|
when done. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
-re_protect (char const *const_dst_name, int dst_dirfd, char const *dst_relname,
|
||||||
|
+re_protect (char const *const_dst_name, int dst_dirfd, char const *dst_fullname,
|
||||||
|
struct dir_attr *attr_list, const struct cp_options *x)
|
||||||
|
{
|
||||||
|
struct dir_attr *p;
|
||||||
|
char *dst_name; /* A copy of CONST_DST_NAME we can change. */
|
||||||
|
- char *src_name; /* The source name in 'dst_name'. */
|
||||||
|
+ char *src_name; /* The relative source name in 'dst_name'. */
|
||||||
|
+ char *full_src_name; /* The full source name in 'dst_name'. */
|
||||||
|
|
||||||
|
ASSIGN_STRDUPA (dst_name, const_dst_name);
|
||||||
|
- src_name = dst_name + (dst_relname - const_dst_name);
|
||||||
|
+ full_src_name = dst_name + (dst_fullname - const_dst_name);
|
||||||
|
+ src_name = full_src_name;
|
||||||
|
+ while (*src_name == '/')
|
||||||
|
+ src_name++;
|
||||||
|
|
||||||
|
for (p = attr_list; p; p = p->next)
|
||||||
|
{
|
||||||
|
@@ -324,7 +328,7 @@
|
||||||
|
|
||||||
|
if (x->preserve_mode)
|
||||||
|
{
|
||||||
|
- if (copy_acl (src_name, -1, dst_name, -1, p->st.st_mode) != 0)
|
||||||
|
+ if (copy_acl (full_src_name, -1, dst_name, -1, p->st.st_mode) != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (p->restore_mode)
|
||||||
|
@@ -664,6 +668,7 @@
|
||||||
|
bool parent_exists = true; /* True if dir_name (dst_name) exists. */
|
||||||
|
struct dir_attr *attr_list;
|
||||||
|
char *arg_in_concat = NULL;
|
||||||
|
+ char *full_arg_in_concat = NULL;
|
||||||
|
char *arg = file[i];
|
||||||
|
|
||||||
|
/* Trailing slashes are meaningful (i.e., maybe worth preserving)
|
||||||
|
@@ -696,6 +701,7 @@
|
||||||
|
(x->verbose ? "%s -> %s\n" : NULL),
|
||||||
|
&attr_list, &new_dst, x));
|
||||||
|
|
||||||
|
+ full_arg_in_concat = arg_in_concat;
|
||||||
|
while (*arg_in_concat == '/')
|
||||||
|
arg_in_concat++;
|
||||||
|
}
|
||||||
|
@@ -724,7 +730,7 @@
|
||||||
|
new_dst, x, ©_into_self, NULL);
|
||||||
|
|
||||||
|
if (parents_option)
|
||||||
|
- ok &= re_protect (dst_name, target_dirfd, arg_in_concat,
|
||||||
|
+ ok &= re_protect (dst_name, target_dirfd, full_arg_in_concat,
|
||||||
|
attr_list, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff -Naur coreutils-9.1.orig/tests/cp/cp-parents.sh coreutils-9.1/tests/cp/cp-parents.sh
|
||||||
|
--- coreutils-9.1.orig/tests/cp/cp-parents.sh 2022-04-08 11:22:18.000000000 +0000
|
||||||
|
+++ coreutils-9.1/tests/cp/cp-parents.sh 2023-05-04 21:09:50.067286480 +0000
|
||||||
|
@@ -66,4 +66,10 @@
|
||||||
|
cp --parents --no-preserve=mode np/b/file np_dest/ || fail=1
|
||||||
|
p=$(ls -ld np_dest/np|cut -b-10); case $p in drwxr-xr-x);; *) fail=1;; esac
|
||||||
|
|
||||||
|
+# coreutils 9.1-9.3 inclusive would fail to copy acls for absolute dirs
|
||||||
|
+mkdir dest || framework_failure_
|
||||||
|
+if test -f /bin/ls; then
|
||||||
|
+ cp -t dest --parents -p /bin/ls || fail=1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
Exit $fail
|
||||||
625
coreutils-nfsv4-acls.patch
Normal file
625
coreutils-nfsv4-acls.patch
Normal file
|
|
@ -0,0 +1,625 @@
|
||||||
|
From 5a6af47c3db45b6303bac4dcd6da186fd5cd178c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ondrej Valousek <ondrej.valousek.xm@renesas.com>
|
||||||
|
Date: Fri, 2 Dec 2022 13:40:19 +0100
|
||||||
|
Subject: [PATCH 1/3] file-has-acl: Basic support for checking NFSv4 ACLs in
|
||||||
|
Linux.
|
||||||
|
|
||||||
|
* lib/acl-internal.h (acl_nfs4_nontrivial): New declaration.
|
||||||
|
* lib/acl-internal.c (acl_nfs4_nontrivial): New function.
|
||||||
|
* lib/file-has-acl.c: Include <arpa/inet.h>.
|
||||||
|
(XATTR_NAME_NFSV4_ACL, TRIVIAL_NFS4_ACL_MAX_LENGTH): New macros.
|
||||||
|
(file_has_acl): Test for NFSv4 ACLs.
|
||||||
|
* doc/acl-nfsv4.txt: New file.
|
||||||
|
|
||||||
|
Upstream-commit: b0604a8e134dbcc307c0ffdd5ebd3693e9de7081
|
||||||
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
||||||
|
---
|
||||||
|
doc/acl-nfsv4.txt | 17 ++++++++
|
||||||
|
lib/acl-internal.c | 100 +++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
lib/acl-internal.h | 3 ++
|
||||||
|
lib/file-has-acl.c | 21 ++++++++++
|
||||||
|
4 files changed, 141 insertions(+)
|
||||||
|
create mode 100644 doc/acl-nfsv4.txt
|
||||||
|
|
||||||
|
diff --git a/doc/acl-nfsv4.txt b/doc/acl-nfsv4.txt
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..71352f5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/doc/acl-nfsv4.txt
|
||||||
|
@@ -0,0 +1,17 @@
|
||||||
|
+General introduction:
|
||||||
|
+ https://linux.die.net/man/5/nfs4_acl
|
||||||
|
+
|
||||||
|
+The NFSv4 acls are defined in RFC7530 and as such, every NFSv4 server supporting ACLs
|
||||||
|
+will support this kind of ACLs (note the difference from POSIX draft ACLs)
|
||||||
|
+
|
||||||
|
+The ACLs can be obtained via the nfsv4-acl-tools, i.e.
|
||||||
|
+
|
||||||
|
+$ nfs4_getfacl <file>
|
||||||
|
+
|
||||||
|
+# file: <file>
|
||||||
|
+A::OWNER@:rwaDxtTnNcCy
|
||||||
|
+A::GROUP@:rwaDxtTnNcy
|
||||||
|
+A::EVERYONE@:rwaDxtTnNcy
|
||||||
|
+
|
||||||
|
+Gnulib is aiming to only provide a basic support of these, i.e. recognize trivial
|
||||||
|
+and non-trivial ACLs
|
||||||
|
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
|
||||||
|
index be244c6..4c65dff 100644
|
||||||
|
--- a/lib/acl-internal.c
|
||||||
|
+++ b/lib/acl-internal.c
|
||||||
|
@@ -25,6 +25,9 @@
|
||||||
|
|
||||||
|
#if USE_ACL && HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
|
||||||
|
|
||||||
|
+# include <string.h>
|
||||||
|
+# include <arpa/inet.h>
|
||||||
|
+
|
||||||
|
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
|
||||||
|
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
|
||||||
|
@@ -122,6 +125,103 @@ acl_default_nontrivial (acl_t acl)
|
||||||
|
return (acl_entries (acl) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+# define ACE4_WHO_OWNER "OWNER@"
|
||||||
|
+# define ACE4_WHO_GROUP "GROUP@"
|
||||||
|
+# define ACE4_WHO_EVERYONE "EVERYONE@"
|
||||||
|
+
|
||||||
|
+# define ACE4_ACCESS_ALLOWED_ACE_TYPE 0
|
||||||
|
+# define ACE4_ACCESS_DENIED_ACE_TYPE 1
|
||||||
|
+
|
||||||
|
+/* ACE flag values */
|
||||||
|
+# define ACE4_IDENTIFIER_GROUP 0x00000040
|
||||||
|
+# define ROUNDUP(x, y) (((x) + (y) - 1) & - (y))
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+acl_nfs4_nontrivial (char *xattr, int len)
|
||||||
|
+{
|
||||||
|
+ int bufs = len;
|
||||||
|
+ uint32_t num_aces = ntohl (*((uint32_t*)(xattr))), /* Grab the number of aces in the acl */
|
||||||
|
+ num_a_aces = 0,
|
||||||
|
+ num_d_aces = 0;
|
||||||
|
+ char *bufp = xattr;
|
||||||
|
+
|
||||||
|
+ bufp += 4; /* sizeof(uint32_t); */
|
||||||
|
+ bufs -= 4;
|
||||||
|
+
|
||||||
|
+ for (uint32_t ace_n = 0; num_aces > ace_n ; ace_n++)
|
||||||
|
+ {
|
||||||
|
+ int d_ptr;
|
||||||
|
+ uint32_t flag,
|
||||||
|
+ wholen,
|
||||||
|
+ type;
|
||||||
|
+
|
||||||
|
+ /* Get the acl type */
|
||||||
|
+ if (bufs <= 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ type = ntohl (*((uint32_t*)bufp));
|
||||||
|
+
|
||||||
|
+ bufp += 4;
|
||||||
|
+ bufs -= 4;
|
||||||
|
+ if (bufs <= 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ flag = ntohl (*((uint32_t*)bufp));
|
||||||
|
+ /* As per RFC 7530, the flag should be 0, but we are just generous to Netapp
|
||||||
|
+ * and also accept the Group flag
|
||||||
|
+ */
|
||||||
|
+ if (flag & ~ACE4_IDENTIFIER_GROUP)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ /* we skip mask -
|
||||||
|
+ * it's too risky to test it and it does not seem to be actually needed */
|
||||||
|
+ bufp += 2*4;
|
||||||
|
+ bufs -= 2*4;
|
||||||
|
+
|
||||||
|
+ if (bufs <= 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ wholen = ntohl (*((uint32_t*)bufp));
|
||||||
|
+
|
||||||
|
+ bufp += 4;
|
||||||
|
+ bufs -= 4;
|
||||||
|
+
|
||||||
|
+ /* Get the who string */
|
||||||
|
+ if (bufs <= 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ /* for trivial ACL, we expect max 5 (typically 3) ACES, 3 Allow, 2 deny */
|
||||||
|
+ if (((strncmp (bufp, ACE4_WHO_OWNER, wholen) == 0)
|
||||||
|
+ || (strncmp (bufp, ACE4_WHO_GROUP, wholen) == 0))
|
||||||
|
+ && wholen == 6)
|
||||||
|
+ {
|
||||||
|
+ if (type == ACE4_ACCESS_ALLOWED_ACE_TYPE)
|
||||||
|
+ num_a_aces++;
|
||||||
|
+ if (type == ACE4_ACCESS_DENIED_ACE_TYPE)
|
||||||
|
+ num_d_aces++;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ if ((strncmp (bufp, ACE4_WHO_EVERYONE, wholen) == 0)
|
||||||
|
+ && (type == ACE4_ACCESS_ALLOWED_ACE_TYPE)
|
||||||
|
+ && (wholen == 9))
|
||||||
|
+ num_a_aces++;
|
||||||
|
+ else
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ d_ptr = ROUNDUP (wholen, 4);
|
||||||
|
+ bufp += d_ptr;
|
||||||
|
+ bufs -= d_ptr;
|
||||||
|
+
|
||||||
|
+ /* Make sure we aren't outside our domain */
|
||||||
|
+ if (bufs < 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+ return !((num_a_aces <= 3) && (num_d_aces <= 2)
|
||||||
|
+ && (num_a_aces + num_d_aces == num_aces));
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
|
||||||
|
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
|
||||||
|
index 9353376..2a249ff 100644
|
||||||
|
--- a/lib/acl-internal.h
|
||||||
|
+++ b/lib/acl-internal.h
|
||||||
|
@@ -147,6 +147,9 @@ rpl_acl_set_fd (int fd, acl_t acl)
|
||||||
|
# define acl_entries rpl_acl_entries
|
||||||
|
extern int acl_entries (acl_t);
|
||||||
|
# endif
|
||||||
|
+/* Return 1 if given ACL in XDR format is non-trivial
|
||||||
|
+ * Return 0 if it is trivial */
|
||||||
|
+extern int acl_nfs4_nontrivial (char *, int);
|
||||||
|
|
||||||
|
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
|
||||||
|
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
|
||||||
|
index e02f062..1710234 100644
|
||||||
|
--- a/lib/file-has-acl.c
|
||||||
|
+++ b/lib/file-has-acl.c
|
||||||
|
@@ -32,6 +32,11 @@
|
||||||
|
#if GETXATTR_WITH_POSIX_ACLS
|
||||||
|
# include <sys/xattr.h>
|
||||||
|
# include <linux/xattr.h>
|
||||||
|
+# include <arpa/inet.h>
|
||||||
|
+# ifndef XATTR_NAME_NFSV4_ACL
|
||||||
|
+# define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
|
||||||
|
+# endif
|
||||||
|
+# define TRIVIAL_NFS4_ACL_MAX_LENGTH 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Return 1 if NAME has a nontrivial access control list,
|
||||||
|
@@ -67,6 +72,22 @@ file_has_acl (char const *name, struct stat const *sb)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ { /* we might be on NFS, so try to check NFSv4 ACLs too */
|
||||||
|
+ char xattr[TRIVIAL_NFS4_ACL_MAX_LENGTH];
|
||||||
|
+
|
||||||
|
+ errno = 0; /* we need to reset errno set by the previous getxattr() */
|
||||||
|
+ ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, TRIVIAL_NFS4_ACL_MAX_LENGTH);
|
||||||
|
+ if (ret < 0 && errno == ENODATA)
|
||||||
|
+ ret = 0;
|
||||||
|
+ else
|
||||||
|
+ if (ret < 0 && errno == ERANGE)
|
||||||
|
+ return 1; /* we won't fit into the buffer, so non-trivial ACL is presented */
|
||||||
|
+ else
|
||||||
|
+ if (ret > 0)
|
||||||
|
+ /* looks like trivial ACL, but we need to investigate further */
|
||||||
|
+ return acl_nfs4_nontrivial (xattr, ret);
|
||||||
|
+ }
|
||||||
|
if (ret < 0)
|
||||||
|
return - acl_errno_valid (errno);
|
||||||
|
return ret;
|
||||||
|
--
|
||||||
|
2.38.1
|
||||||
|
|
||||||
|
|
||||||
|
From c5266d204a446bea619fa18da8520dceb0a54192 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
Date: Fri, 23 Dec 2022 15:18:29 -0800
|
||||||
|
Subject: [PATCH 2/3] file-has-acl: improve recent NFSv4 support
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
This fixes a link failure with emacsclient on GNU/Linux. This
|
||||||
|
program wants file_has_acl but none of the other ACL primitives,
|
||||||
|
so it doesn’t link acl-internal.o; this way it doesn’t need to
|
||||||
|
link with -lacl. While I was at it I reviewed the recent changes,
|
||||||
|
fixed some unlikely overflow bugs, and adjusted to GNU style.
|
||||||
|
* doc/acl-nfsv4.txt: Remove. Its contents are now in a
|
||||||
|
comment in lib/file-has-acl.c.
|
||||||
|
* lib/acl-internal.c, lib/acl-internal.h: Move recent changes
|
||||||
|
relating to acl_nfs4_nontrivial to lib/file-has-acl.c, so that
|
||||||
|
there is no trouble linking programs that need only file_has_acl.
|
||||||
|
* lib/file-has-acl.c (acl_nfs4_nontrivial): Move here from
|
||||||
|
lib/acl-internal.c, so that we needn't link -lacl in
|
||||||
|
programs that want only file_has_acl, such as emacsclient.
|
||||||
|
Do not assume a char buffer is aligned for uint32_t.
|
||||||
|
Check more carefully for buffer read overrun.
|
||||||
|
Allow up to 6 ACEs, since other code does; but check
|
||||||
|
that they’re distinct. Avoid integer overflow.
|
||||||
|
Use memcmp rather than strncmp to compare memory blocks.
|
||||||
|
(file_has_acl): Preserve initial errno instead of setting to 0.
|
||||||
|
Allocate a bit more room for trivial ACL buffer.
|
||||||
|
Use EINVAL for botchedk NFSv4 ACLs (which shouldn’t happen).
|
||||||
|
|
||||||
|
Upstream-commit: 35bd46f0c816948dc1a0430c8ba8b10a01167320
|
||||||
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
||||||
|
---
|
||||||
|
doc/acl-nfsv4.txt | 17 ------
|
||||||
|
lib/acl-internal.c | 100 -----------------------------------
|
||||||
|
lib/acl-internal.h | 3 --
|
||||||
|
lib/file-has-acl.c | 129 +++++++++++++++++++++++++++++++++++++++------
|
||||||
|
4 files changed, 113 insertions(+), 136 deletions(-)
|
||||||
|
delete mode 100644 doc/acl-nfsv4.txt
|
||||||
|
|
||||||
|
diff --git a/doc/acl-nfsv4.txt b/doc/acl-nfsv4.txt
|
||||||
|
deleted file mode 100644
|
||||||
|
index 71352f5..0000000
|
||||||
|
--- a/doc/acl-nfsv4.txt
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,17 +0,0 @@
|
||||||
|
-General introduction:
|
||||||
|
- https://linux.die.net/man/5/nfs4_acl
|
||||||
|
-
|
||||||
|
-The NFSv4 acls are defined in RFC7530 and as such, every NFSv4 server supporting ACLs
|
||||||
|
-will support this kind of ACLs (note the difference from POSIX draft ACLs)
|
||||||
|
-
|
||||||
|
-The ACLs can be obtained via the nfsv4-acl-tools, i.e.
|
||||||
|
-
|
||||||
|
-$ nfs4_getfacl <file>
|
||||||
|
-
|
||||||
|
-# file: <file>
|
||||||
|
-A::OWNER@:rwaDxtTnNcCy
|
||||||
|
-A::GROUP@:rwaDxtTnNcy
|
||||||
|
-A::EVERYONE@:rwaDxtTnNcy
|
||||||
|
-
|
||||||
|
-Gnulib is aiming to only provide a basic support of these, i.e. recognize trivial
|
||||||
|
-and non-trivial ACLs
|
||||||
|
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
|
||||||
|
index 4c65dff..be244c6 100644
|
||||||
|
--- a/lib/acl-internal.c
|
||||||
|
+++ b/lib/acl-internal.c
|
||||||
|
@@ -25,9 +25,6 @@
|
||||||
|
|
||||||
|
#if USE_ACL && HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
|
||||||
|
|
||||||
|
-# include <string.h>
|
||||||
|
-# include <arpa/inet.h>
|
||||||
|
-
|
||||||
|
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
|
||||||
|
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
|
||||||
|
@@ -125,103 +122,6 @@ acl_default_nontrivial (acl_t acl)
|
||||||
|
return (acl_entries (acl) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
-# define ACE4_WHO_OWNER "OWNER@"
|
||||||
|
-# define ACE4_WHO_GROUP "GROUP@"
|
||||||
|
-# define ACE4_WHO_EVERYONE "EVERYONE@"
|
||||||
|
-
|
||||||
|
-# define ACE4_ACCESS_ALLOWED_ACE_TYPE 0
|
||||||
|
-# define ACE4_ACCESS_DENIED_ACE_TYPE 1
|
||||||
|
-
|
||||||
|
-/* ACE flag values */
|
||||||
|
-# define ACE4_IDENTIFIER_GROUP 0x00000040
|
||||||
|
-# define ROUNDUP(x, y) (((x) + (y) - 1) & - (y))
|
||||||
|
-
|
||||||
|
-int
|
||||||
|
-acl_nfs4_nontrivial (char *xattr, int len)
|
||||||
|
-{
|
||||||
|
- int bufs = len;
|
||||||
|
- uint32_t num_aces = ntohl (*((uint32_t*)(xattr))), /* Grab the number of aces in the acl */
|
||||||
|
- num_a_aces = 0,
|
||||||
|
- num_d_aces = 0;
|
||||||
|
- char *bufp = xattr;
|
||||||
|
-
|
||||||
|
- bufp += 4; /* sizeof(uint32_t); */
|
||||||
|
- bufs -= 4;
|
||||||
|
-
|
||||||
|
- for (uint32_t ace_n = 0; num_aces > ace_n ; ace_n++)
|
||||||
|
- {
|
||||||
|
- int d_ptr;
|
||||||
|
- uint32_t flag,
|
||||||
|
- wholen,
|
||||||
|
- type;
|
||||||
|
-
|
||||||
|
- /* Get the acl type */
|
||||||
|
- if (bufs <= 0)
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- type = ntohl (*((uint32_t*)bufp));
|
||||||
|
-
|
||||||
|
- bufp += 4;
|
||||||
|
- bufs -= 4;
|
||||||
|
- if (bufs <= 0)
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- flag = ntohl (*((uint32_t*)bufp));
|
||||||
|
- /* As per RFC 7530, the flag should be 0, but we are just generous to Netapp
|
||||||
|
- * and also accept the Group flag
|
||||||
|
- */
|
||||||
|
- if (flag & ~ACE4_IDENTIFIER_GROUP)
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
- /* we skip mask -
|
||||||
|
- * it's too risky to test it and it does not seem to be actually needed */
|
||||||
|
- bufp += 2*4;
|
||||||
|
- bufs -= 2*4;
|
||||||
|
-
|
||||||
|
- if (bufs <= 0)
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- wholen = ntohl (*((uint32_t*)bufp));
|
||||||
|
-
|
||||||
|
- bufp += 4;
|
||||||
|
- bufs -= 4;
|
||||||
|
-
|
||||||
|
- /* Get the who string */
|
||||||
|
- if (bufs <= 0)
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- /* for trivial ACL, we expect max 5 (typically 3) ACES, 3 Allow, 2 deny */
|
||||||
|
- if (((strncmp (bufp, ACE4_WHO_OWNER, wholen) == 0)
|
||||||
|
- || (strncmp (bufp, ACE4_WHO_GROUP, wholen) == 0))
|
||||||
|
- && wholen == 6)
|
||||||
|
- {
|
||||||
|
- if (type == ACE4_ACCESS_ALLOWED_ACE_TYPE)
|
||||||
|
- num_a_aces++;
|
||||||
|
- if (type == ACE4_ACCESS_DENIED_ACE_TYPE)
|
||||||
|
- num_d_aces++;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- if ((strncmp (bufp, ACE4_WHO_EVERYONE, wholen) == 0)
|
||||||
|
- && (type == ACE4_ACCESS_ALLOWED_ACE_TYPE)
|
||||||
|
- && (wholen == 9))
|
||||||
|
- num_a_aces++;
|
||||||
|
- else
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
- d_ptr = ROUNDUP (wholen, 4);
|
||||||
|
- bufp += d_ptr;
|
||||||
|
- bufs -= d_ptr;
|
||||||
|
-
|
||||||
|
- /* Make sure we aren't outside our domain */
|
||||||
|
- if (bufs < 0)
|
||||||
|
- return -1;
|
||||||
|
-
|
||||||
|
- }
|
||||||
|
- return !((num_a_aces <= 3) && (num_d_aces <= 2)
|
||||||
|
- && (num_a_aces + num_d_aces == num_aces));
|
||||||
|
-
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
|
||||||
|
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
|
||||||
|
index 2a249ff..9353376 100644
|
||||||
|
--- a/lib/acl-internal.h
|
||||||
|
+++ b/lib/acl-internal.h
|
||||||
|
@@ -147,9 +147,6 @@ rpl_acl_set_fd (int fd, acl_t acl)
|
||||||
|
# define acl_entries rpl_acl_entries
|
||||||
|
extern int acl_entries (acl_t);
|
||||||
|
# endif
|
||||||
|
-/* Return 1 if given ACL in XDR format is non-trivial
|
||||||
|
- * Return 0 if it is trivial */
|
||||||
|
-extern int acl_nfs4_nontrivial (char *, int);
|
||||||
|
|
||||||
|
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
|
||||||
|
/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
|
||||||
|
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
|
||||||
|
index 1710234..676523b 100644
|
||||||
|
--- a/lib/file-has-acl.c
|
||||||
|
+++ b/lib/file-has-acl.c
|
||||||
|
@@ -29,14 +29,97 @@
|
||||||
|
|
||||||
|
#include "acl-internal.h"
|
||||||
|
|
||||||
|
-#if GETXATTR_WITH_POSIX_ACLS
|
||||||
|
+#if USE_ACL && GETXATTR_WITH_POSIX_ACLS
|
||||||
|
+# include <string.h>
|
||||||
|
+# include <arpa/inet.h>
|
||||||
|
# include <sys/xattr.h>
|
||||||
|
# include <linux/xattr.h>
|
||||||
|
-# include <arpa/inet.h>
|
||||||
|
# ifndef XATTR_NAME_NFSV4_ACL
|
||||||
|
# define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
|
||||||
|
# endif
|
||||||
|
-# define TRIVIAL_NFS4_ACL_MAX_LENGTH 128
|
||||||
|
+
|
||||||
|
+enum {
|
||||||
|
+ /* ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000, */
|
||||||
|
+ ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001,
|
||||||
|
+ ACE4_IDENTIFIER_GROUP = 0x00000040
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* 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.
|
||||||
|
+
|
||||||
|
+ See <https://linux.die.net/man/5/nfs4_acl>. The NFSv4 acls are
|
||||||
|
+ defined in Internet RFC 7530 and as such, every NFSv4 server
|
||||||
|
+ supporting ACLs should support NFSv4 ACLs (they differ from from
|
||||||
|
+ POSIX draft ACLs). The ACLs can be obtained via the
|
||||||
|
+ nfsv4-acl-tools, e.g., the nfs4_getfacl command. Gnulib provides
|
||||||
|
+ only basic support of NFSv4 ACLs, i.e., recognize trivial vs
|
||||||
|
+ nontrivial ACLs. */
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes)
|
||||||
|
+{
|
||||||
|
+ enum { BYTES_PER_NETWORK_UINT = 4};
|
||||||
|
+
|
||||||
|
+ /* Grab the number of aces in the acl. */
|
||||||
|
+ nbytes -= BYTES_PER_NETWORK_UINT;
|
||||||
|
+ if (nbytes < 0)
|
||||||
|
+ return -1;
|
||||||
|
+ uint32_t num_aces = ntohl (*xattr++);
|
||||||
|
+ if (6 < num_aces)
|
||||||
|
+ return 1;
|
||||||
|
+ int ace_found = 0;
|
||||||
|
+
|
||||||
|
+ for (int ace_n = 0; ace_n < num_aces; ace_n++)
|
||||||
|
+ {
|
||||||
|
+ /* Get the acl type and flag. Skip the mask; it's too risky to
|
||||||
|
+ test it and it does not seem to be needed. Get the wholen. */
|
||||||
|
+ nbytes -= 4 * BYTES_PER_NETWORK_UINT;
|
||||||
|
+ if (nbytes < 0)
|
||||||
|
+ return -1;
|
||||||
|
+ uint32_t type = ntohl (xattr[0]);
|
||||||
|
+ uint32_t flag = ntohl (xattr[1]);
|
||||||
|
+ uint32_t wholen = ntohl (xattr[3]);
|
||||||
|
+ xattr += 4;
|
||||||
|
+ int64_t wholen4 = wholen;
|
||||||
|
+ wholen4 = ((wholen4 + (BYTES_PER_NETWORK_UINT))
|
||||||
|
+ & ~ (BYTES_PER_NETWORK_UINT - 1));
|
||||||
|
+
|
||||||
|
+ /* Trivial ACLs have only ACE4_ACCESS_ALLOWED_ACE_TYPE or
|
||||||
|
+ ACE4_ACCESS_DENIED_ACE_TYPE. */
|
||||||
|
+ if (ACE4_ACCESS_DENIED_ACE_TYPE < type)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ /* RFC 7530 says FLAG should be 0, but be generous to NetApp and
|
||||||
|
+ also accept the group flag. */
|
||||||
|
+ if (flag & ~ACE4_IDENTIFIER_GROUP)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ /* Get the who string. Check NBYTES - WHOLEN4 before storing
|
||||||
|
+ into NBYTES, to avoid truncation on conversion. */
|
||||||
|
+ if (nbytes - wholen4 < 0)
|
||||||
|
+ return -1;
|
||||||
|
+ nbytes -= wholen4;
|
||||||
|
+
|
||||||
|
+ /* For a trivial ACL, max 6 (typically 3) ACEs, 3 allow, 3 deny.
|
||||||
|
+ Check that there is at most one ACE of each TYPE and WHO. */
|
||||||
|
+ int who2
|
||||||
|
+ = (wholen == 6 && memcmp (xattr, "OWNER@", 6) == 0 ? 0
|
||||||
|
+ : wholen == 6 && memcmp (xattr, "GROUP@", 6) == 0 ? 2
|
||||||
|
+ : wholen == 9 && memcmp (xattr, "EVERYONE@", 9) == 0 ? 4
|
||||||
|
+ : -1);
|
||||||
|
+ if (who2 < 0)
|
||||||
|
+ return 1;
|
||||||
|
+ int ace_found_bit = 1 << (who2 | type);
|
||||||
|
+ if (ace_found & ace_found_bit)
|
||||||
|
+ return 1;
|
||||||
|
+ ace_found |= ace_found_bit;
|
||||||
|
+
|
||||||
|
+ xattr = (uint32_t *) ((char *) xattr + wholen4);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Return 1 if NAME has a nontrivial access control list,
|
||||||
|
@@ -56,6 +139,7 @@ file_has_acl (char const *name, struct stat const *sb)
|
||||||
|
# if GETXATTR_WITH_POSIX_ACLS
|
||||||
|
|
||||||
|
ssize_t ret;
|
||||||
|
+ int initial_errno = errno;
|
||||||
|
|
||||||
|
ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0);
|
||||||
|
if (ret < 0 && errno == ENODATA)
|
||||||
|
@@ -73,20 +157,33 @@ file_has_acl (char const *name, struct stat const *sb)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
- { /* we might be on NFS, so try to check NFSv4 ACLs too */
|
||||||
|
- char xattr[TRIVIAL_NFS4_ACL_MAX_LENGTH];
|
||||||
|
-
|
||||||
|
- errno = 0; /* we need to reset errno set by the previous getxattr() */
|
||||||
|
- ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, TRIVIAL_NFS4_ACL_MAX_LENGTH);
|
||||||
|
- if (ret < 0 && errno == ENODATA)
|
||||||
|
- ret = 0;
|
||||||
|
+ {
|
||||||
|
+ /* 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);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ switch (errno)
|
||||||
|
+ {
|
||||||
|
+ case ENODATA: return 0;
|
||||||
|
+ case ERANGE : return 1; /* ACL must be nontrivial. */
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
- if (ret < 0 && errno == ERANGE)
|
||||||
|
- return 1; /* we won't fit into the buffer, so non-trivial ACL is presented */
|
||||||
|
- else
|
||||||
|
- if (ret > 0)
|
||||||
|
- /* looks like trivial ACL, but we need to investigate further */
|
||||||
|
- return acl_nfs4_nontrivial (xattr, ret);
|
||||||
|
+ {
|
||||||
|
+ /* It looks like a trivial ACL, but investigate further. */
|
||||||
|
+ ret = acl_nfs4_nontrivial (xattr, ret);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ {
|
||||||
|
+ errno = EINVAL;
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ errno = initial_errno;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
return - acl_errno_valid (errno);
|
||||||
|
--
|
||||||
|
2.38.1
|
||||||
|
|
||||||
|
|
||||||
|
From faf965110372c82cd99e9f44f0c64f03cdabb2c1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
Date: Tue, 27 Dec 2022 20:00:58 -0800
|
||||||
|
Subject: [PATCH 3/3] file-has-acl: fix recently-introduced NFSv4 bug
|
||||||
|
|
||||||
|
* lib/file-has-acl.c (acl_nfs4_nontrivial): Fix off-by-one
|
||||||
|
error when rounding WHOLEN up to next multiple of 4.
|
||||||
|
Pacify GCC 12.2.1 -Wcast-align.
|
||||||
|
|
||||||
|
Upstream-commit: d65e5a8ba77595a598c9ddb8dfa09c4aea732659
|
||||||
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
||||||
|
---
|
||||||
|
lib/file-has-acl.c | 9 +++++----
|
||||||
|
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
|
||||||
|
index 676523b..7876edc 100644
|
||||||
|
--- a/lib/file-has-acl.c
|
||||||
|
+++ b/lib/file-has-acl.c
|
||||||
|
@@ -81,9 +81,10 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes)
|
||||||
|
uint32_t flag = ntohl (xattr[1]);
|
||||||
|
uint32_t wholen = ntohl (xattr[3]);
|
||||||
|
xattr += 4;
|
||||||
|
- int64_t wholen4 = wholen;
|
||||||
|
- wholen4 = ((wholen4 + (BYTES_PER_NETWORK_UINT))
|
||||||
|
- & ~ (BYTES_PER_NETWORK_UINT - 1));
|
||||||
|
+ int whowords = (wholen / BYTES_PER_NETWORK_UINT
|
||||||
|
+ + (wholen % BYTES_PER_NETWORK_UINT != 0));
|
||||||
|
+ int64_t wholen4 = whowords;
|
||||||
|
+ wholen4 *= BYTES_PER_NETWORK_UINT;
|
||||||
|
|
||||||
|
/* Trivial ACLs have only ACE4_ACCESS_ALLOWED_ACE_TYPE or
|
||||||
|
ACE4_ACCESS_DENIED_ACE_TYPE. */
|
||||||
|
@@ -115,7 +116,7 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes)
|
||||||
|
return 1;
|
||||||
|
ace_found |= ace_found_bit;
|
||||||
|
|
||||||
|
- xattr = (uint32_t *) ((char *) xattr + wholen4);
|
||||||
|
+ xattr += whowords;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
--
|
||||||
|
2.38.1
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Summary: A set of basic GNU tools commonly used in shell scripts
|
Summary: A set of basic GNU tools commonly used in shell scripts
|
||||||
Name: coreutils
|
Name: coreutils
|
||||||
Version: 9.1
|
Version: 9.1
|
||||||
Release: 6%{?dist}
|
Release: 8%{?dist}
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
Url: https://www.gnu.org/software/coreutils/
|
Url: https://www.gnu.org/software/coreutils/
|
||||||
Source0: https://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz
|
Source0: https://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz
|
||||||
|
|
@ -20,11 +20,17 @@ Source106: coreutils-colorls.csh
|
||||||
# Make simple backups in correct dir; broken in 9.1
|
# Make simple backups in correct dir; broken in 9.1
|
||||||
Patch1: gnulib-simple-backup-fix.patch
|
Patch1: gnulib-simple-backup-fix.patch
|
||||||
|
|
||||||
|
# basic support for checking NFSv4 ACLs (#2137866)
|
||||||
|
Patch2: coreutils-nfsv4-acls.patch
|
||||||
|
|
||||||
|
# Fix directory-relative syscalls in copy code; broken in 9.1
|
||||||
|
Patch3: coreutils-9.1-copy-relative-dir.patch
|
||||||
|
|
||||||
# disable the test-lock gnulib test prone to deadlock
|
# disable the test-lock gnulib test prone to deadlock
|
||||||
Patch100: coreutils-8.26-test-lock.patch
|
Patch100: coreutils-8.26-test-lock.patch
|
||||||
|
|
||||||
# require_selinux_(): use selinuxenabled(8) if available
|
# require_selinux_(): use selinuxenabled(8) if available
|
||||||
Patch105: coreutils-8.26-selinuxenable.patch
|
Patch101: coreutils-8.26-selinuxenable.patch
|
||||||
|
|
||||||
# downstream changes to default DIR_COLORS
|
# downstream changes to default DIR_COLORS
|
||||||
Patch102: coreutils-8.32-DIR_COLORS.patch
|
Patch102: coreutils-8.32-DIR_COLORS.patch
|
||||||
|
|
@ -265,6 +271,13 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir
|
||||||
%license COPYING
|
%license COPYING
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu May 04 2023 Pádraig Brady <P@draigBrady.com> - 9.1-8
|
||||||
|
- further fixes to backups; broken in 9.1
|
||||||
|
- fix some directory-relative syscalls; broken in 9.1
|
||||||
|
|
||||||
|
* Mon Jan 02 2023 Kamil Dudka <kdudka@redhat.com> - 9.1-7
|
||||||
|
- basic support for checking NFSv4 ACLs (#2137866)
|
||||||
|
|
||||||
* Mon Aug 08 2022 Kamil Dudka <kdudka@redhat.com> - 9.1-6
|
* Mon Aug 08 2022 Kamil Dudka <kdudka@redhat.com> - 9.1-6
|
||||||
- improve wording of a comment in /etc/DIR_COLORS (#2112593)
|
- improve wording of a comment in /etc/DIR_COLORS (#2112593)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,60 @@
|
||||||
commit 7347caeb9d902d3fca2c11f69a55a3e578d93bfe
|
diff -Naur coreutils-9.1.orig/lib/backupfile.c coreutils-9.1/lib/backupfile.c
|
||||||
Author: Paul Eggert <eggert@cs.ucla.edu>
|
--- coreutils-9.1.orig/lib/backupfile.c 2022-04-08 11:22:26.000000000 +0000
|
||||||
Date: Wed Apr 20 19:34:57 2022 -0700
|
+++ coreutils-9.1/lib/backupfile.c 2023-05-04 17:07:20.784911071 +0000
|
||||||
|
@@ -332,7 +332,7 @@
|
||||||
backupfile: fix bug when renaming simple backups
|
|
||||||
|
|
||||||
* lib/backupfile.c (backupfile_internal): Fix bug when RENAME
|
|
||||||
and when doing simple backups. Problem reported by Steve Ward in:
|
|
||||||
https://bugs.gnu.org/55029
|
|
||||||
|
|
||||||
diff --git a/lib/backupfile.c b/lib/backupfile.c
|
|
||||||
index 1e9290a187..d9f465a3e0 100644
|
|
||||||
--- a/lib/backupfile.c
|
|
||||||
+++ b/lib/backupfile.c
|
|
||||||
@@ -332,7 +332,7 @@ backupfile_internal (int dir_fd, char const *file,
|
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
DIR *dirp = NULL;
|
DIR *dirp = NULL;
|
||||||
- int sdir = AT_FDCWD;
|
- int sdir = AT_FDCWD;
|
||||||
+ int sdir = dir_fd;
|
+ int sdir = -1;
|
||||||
idx_t base_max = 0;
|
idx_t base_max = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -371,10 +371,9 @@ backupfile_internal (int dir_fd, char const *file,
|
@@ -371,10 +371,10 @@
|
||||||
if (! rename)
|
if (! rename)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
- int olddirfd = sdir < 0 ? dir_fd : sdir;
|
- int olddirfd = sdir < 0 ? dir_fd : sdir;
|
||||||
- idx_t offset = sdir < 0 ? 0 : base_offset;
|
+ dir_fd = sdir < 0 ? dir_fd : sdir;
|
||||||
+ idx_t offset = backup_type == simple_backups ? 0 : base_offset;
|
idx_t offset = sdir < 0 ? 0 : base_offset;
|
||||||
unsigned flags = backup_type == simple_backups ? 0 : RENAME_NOREPLACE;
|
unsigned flags = backup_type == simple_backups ? 0 : RENAME_NOREPLACE;
|
||||||
- if (renameatu (olddirfd, file + offset, sdir, s + offset, flags) == 0)
|
- if (renameatu (olddirfd, file + offset, sdir, s + offset, flags) == 0)
|
||||||
+ if (renameatu (sdir, file + offset, sdir, s + offset, flags) == 0)
|
+ if (renameatu (dir_fd, file + offset, dir_fd, s + offset, flags) == 0)
|
||||||
break;
|
break;
|
||||||
int e = errno;
|
int e = errno;
|
||||||
if (! (e == EEXIST && extended))
|
if (! (e == EEXIST && extended))
|
||||||
|
diff -Naur coreutils-9.1.orig/tests/cp/backup-dir.sh coreutils-9.1/tests/cp/backup-dir.sh
|
||||||
|
--- coreutils-9.1.orig/tests/cp/backup-dir.sh 2022-04-08 11:22:18.000000000 +0000
|
||||||
|
+++ coreutils-9.1/tests/cp/backup-dir.sh 2023-05-04 17:07:24.851960384 +0000
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
-# Ensure that cp -b doesn't back up directories.
|
||||||
|
+# Ensure that cp -b handles directories appropriately
|
||||||
|
|
||||||
|
# Copyright (C) 2006-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
@@ -29,4 +29,10 @@
|
||||||
|
test -d y/x || fail=1
|
||||||
|
test -d y/x~ && fail=1
|
||||||
|
|
||||||
|
+# Bug 62607.
|
||||||
|
+# This would fail to backup using rename, and thus fail to replace the file
|
||||||
|
+mkdir -p src/foo dst/foo || framework_failure_
|
||||||
|
+touch src/foo/bar dst/foo/bar || framework_failure_
|
||||||
|
+cp --recursive --backup src/* dst || fail=1
|
||||||
|
+
|
||||||
|
Exit $fail
|
||||||
|
diff -Naur coreutils-9.1.orig/tests/mv/backup-dir.sh coreutils-9.1/tests/mv/backup-dir.sh
|
||||||
|
--- coreutils-9.1.orig/tests/mv/backup-dir.sh 2022-04-08 11:22:18.000000000 +0000
|
||||||
|
+++ coreutils-9.1/tests/mv/backup-dir.sh 2023-05-04 17:03:29.593098230 +0000
|
||||||
|
@@ -36,4 +36,10 @@
|
||||||
|
mv -T --backup=numbered C E/ || fail=1
|
||||||
|
mv -T --backup=numbered D E/ || fail=1
|
||||||
|
|
||||||
|
+# Bug#55029
|
||||||
|
+mkdir F && echo 1 >1 && echo 2 >2 && cp 1 F/X && cp 2 X || framework_failure_
|
||||||
|
+mv --backup=simple X F/ || fail=1
|
||||||
|
+compare 1 F/X~ || fail=1
|
||||||
|
+compare 2 F/X || fail=1
|
||||||
|
+
|
||||||
|
Exit $fail
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue