200 lines
6.8 KiB
Diff
200 lines
6.8 KiB
Diff
|
From fba4f123cc456d2b2538f811bb831483bf336bad Mon Sep 17 00:00:00 2001
|
||
|
From: Martin Matuska <martin@matuska.org>
|
||
|
Date: Sat, 21 Aug 2021 20:51:07 +0200
|
||
|
Subject: [PATCH 1/2] Fix handling of symbolic link ACLs
|
||
|
|
||
|
On Linux ACLs on symbolic links are not supported.
|
||
|
We must avoid calling acl_set_file() on symbolic links as their
|
||
|
targets are modified instead.
|
||
|
|
||
|
While here, do not try to set default ACLs on non-directories.
|
||
|
|
||
|
Fixes #1565
|
||
|
---
|
||
|
libarchive/archive_disk_acl_freebsd.c | 20 +++++++++++++++-----
|
||
|
libarchive/archive_disk_acl_linux.c | 23 ++++++++++++++++++++---
|
||
|
libarchive/archive_disk_acl_sunos.c | 13 +++++++++----
|
||
|
3 files changed, 44 insertions(+), 12 deletions(-)
|
||
|
|
||
|
diff --git a/libarchive/archive_disk_acl_freebsd.c b/libarchive/archive_disk_acl_freebsd.c
|
||
|
index aba41e5d..ed4e7a78 100644
|
||
|
--- a/libarchive/archive_disk_acl_freebsd.c
|
||
|
+++ b/libarchive/archive_disk_acl_freebsd.c
|
||
|
@@ -319,7 +319,7 @@ translate_acl(struct archive_read_disk *a,
|
||
|
|
||
|
static int
|
||
|
set_acl(struct archive *a, int fd, const char *name,
|
||
|
- struct archive_acl *abstract_acl,
|
||
|
+ struct archive_acl *abstract_acl, __LA_MODE_T mode,
|
||
|
int ae_requested_type, const char *tname)
|
||
|
{
|
||
|
int acl_type = 0;
|
||
|
@@ -364,6 +364,13 @@ set_acl(struct archive *a, int fd, const char *name,
|
||
|
return (ARCHIVE_FAILED);
|
||
|
}
|
||
|
|
||
|
+ if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
|
||
|
+ errno = EINVAL;
|
||
|
+ archive_set_error(a, errno,
|
||
|
+ "Cannot set default ACL on non-directory");
|
||
|
+ return (ARCHIVE_WARN);
|
||
|
+ }
|
||
|
+
|
||
|
acl = acl_init(entries);
|
||
|
if (acl == (acl_t)NULL) {
|
||
|
archive_set_error(a, errno,
|
||
|
@@ -542,7 +549,10 @@ set_acl(struct archive *a, int fd, const char *name,
|
||
|
else if (acl_set_link_np(name, acl_type, acl) != 0)
|
||
|
#else
|
||
|
/* FreeBSD older than 8.0 */
|
||
|
- else if (acl_set_file(name, acl_type, acl) != 0)
|
||
|
+ else if (S_ISLNK(mode)) {
|
||
|
+ /* acl_set_file() follows symbolic links, skip */
|
||
|
+ ret = ARCHIVE_OK;
|
||
|
+ } else if (acl_set_file(name, acl_type, acl) != 0)
|
||
|
#endif
|
||
|
{
|
||
|
if (errno == EOPNOTSUPP) {
|
||
|
@@ -677,14 +687,14 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||
|
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||
|
if ((archive_acl_types(abstract_acl)
|
||
|
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
||
|
- ret = set_acl(a, fd, name, abstract_acl,
|
||
|
+ ret = set_acl(a, fd, name, abstract_acl, mode,
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
||
|
if (ret != ARCHIVE_OK)
|
||
|
return (ret);
|
||
|
}
|
||
|
if ((archive_acl_types(abstract_acl)
|
||
|
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
||
|
- ret = set_acl(a, fd, name, abstract_acl,
|
||
|
+ ret = set_acl(a, fd, name, abstract_acl, mode,
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
||
|
|
||
|
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
||
|
@@ -693,7 +703,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||
|
#if ARCHIVE_ACL_FREEBSD_NFS4
|
||
|
else if ((archive_acl_types(abstract_acl) &
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
||
|
- ret = set_acl(a, fd, name, abstract_acl,
|
||
|
+ ret = set_acl(a, fd, name, abstract_acl, mode,
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
||
|
}
|
||
|
#endif
|
||
|
diff --git a/libarchive/archive_disk_acl_linux.c b/libarchive/archive_disk_acl_linux.c
|
||
|
index 3928f3d6..31d27053 100644
|
||
|
--- a/libarchive/archive_disk_acl_linux.c
|
||
|
+++ b/libarchive/archive_disk_acl_linux.c
|
||
|
@@ -343,6 +343,11 @@ set_richacl(struct archive *a, int fd, const char *name,
|
||
|
return (ARCHIVE_FAILED);
|
||
|
}
|
||
|
|
||
|
+ if (S_ISLNK(mode)) {
|
||
|
+ /* Linux does not support RichACLs on symbolic links */
|
||
|
+ return (ARCHIVE_OK);
|
||
|
+ }
|
||
|
+
|
||
|
richacl = richacl_alloc(entries);
|
||
|
if (richacl == NULL) {
|
||
|
archive_set_error(a, errno,
|
||
|
@@ -455,7 +460,7 @@ exit_free:
|
||
|
#if ARCHIVE_ACL_LIBACL
|
||
|
static int
|
||
|
set_acl(struct archive *a, int fd, const char *name,
|
||
|
- struct archive_acl *abstract_acl,
|
||
|
+ struct archive_acl *abstract_acl, __LA_MODE_T mode,
|
||
|
int ae_requested_type, const char *tname)
|
||
|
{
|
||
|
int acl_type = 0;
|
||
|
@@ -488,6 +493,18 @@ set_acl(struct archive *a, int fd, const char *name,
|
||
|
return (ARCHIVE_FAILED);
|
||
|
}
|
||
|
|
||
|
+ if (S_ISLNK(mode)) {
|
||
|
+ /* Linux does not support ACLs on symbolic links */
|
||
|
+ return (ARCHIVE_OK);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
|
||
|
+ errno = EINVAL;
|
||
|
+ archive_set_error(a, errno,
|
||
|
+ "Cannot set default ACL on non-directory");
|
||
|
+ return (ARCHIVE_WARN);
|
||
|
+ }
|
||
|
+
|
||
|
acl = acl_init(entries);
|
||
|
if (acl == (acl_t)NULL) {
|
||
|
archive_set_error(a, errno,
|
||
|
@@ -727,14 +744,14 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||
|
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||
|
if ((archive_acl_types(abstract_acl)
|
||
|
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
||
|
- ret = set_acl(a, fd, name, abstract_acl,
|
||
|
+ ret = set_acl(a, fd, name, abstract_acl, mode,
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
||
|
if (ret != ARCHIVE_OK)
|
||
|
return (ret);
|
||
|
}
|
||
|
if ((archive_acl_types(abstract_acl)
|
||
|
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
||
|
- ret = set_acl(a, fd, name, abstract_acl,
|
||
|
+ ret = set_acl(a, fd, name, abstract_acl, mode,
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
||
|
}
|
||
|
#endif /* ARCHIVE_ACL_LIBACL */
|
||
|
diff --git a/libarchive/archive_disk_acl_sunos.c b/libarchive/archive_disk_acl_sunos.c
|
||
|
index b0f5dfad..0ef3ad52 100644
|
||
|
--- a/libarchive/archive_disk_acl_sunos.c
|
||
|
+++ b/libarchive/archive_disk_acl_sunos.c
|
||
|
@@ -443,7 +443,7 @@ translate_acl(struct archive_read_disk *a,
|
||
|
|
||
|
static int
|
||
|
set_acl(struct archive *a, int fd, const char *name,
|
||
|
- struct archive_acl *abstract_acl,
|
||
|
+ struct archive_acl *abstract_acl, __LA_MODE_T mode,
|
||
|
int ae_requested_type, const char *tname)
|
||
|
{
|
||
|
aclent_t *aclent;
|
||
|
@@ -467,7 +467,6 @@ set_acl(struct archive *a, int fd, const char *name,
|
||
|
if (entries == 0)
|
||
|
return (ARCHIVE_OK);
|
||
|
|
||
|
-
|
||
|
switch (ae_requested_type) {
|
||
|
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
|
||
|
cmd = SETACL;
|
||
|
@@ -492,6 +491,12 @@ set_acl(struct archive *a, int fd, const char *name,
|
||
|
return (ARCHIVE_FAILED);
|
||
|
}
|
||
|
|
||
|
+ if (S_ISLNK(mode)) {
|
||
|
+ /* Skip ACLs on symbolic links */
|
||
|
+ ret = ARCHIVE_OK;
|
||
|
+ goto exit_free;
|
||
|
+ }
|
||
|
+
|
||
|
e = 0;
|
||
|
|
||
|
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
|
||
|
@@ -801,7 +806,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||
|
if ((archive_acl_types(abstract_acl)
|
||
|
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||
|
/* Solaris writes POSIX.1e access and default ACLs together */
|
||
|
- ret = set_acl(a, fd, name, abstract_acl,
|
||
|
+ ret = set_acl(a, fd, name, abstract_acl, mode,
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
|
||
|
|
||
|
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
||
|
@@ -810,7 +815,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||
|
#if ARCHIVE_ACL_SUNOS_NFS4
|
||
|
else if ((archive_acl_types(abstract_acl) &
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
||
|
- ret = set_acl(a, fd, name, abstract_acl,
|
||
|
+ ret = set_acl(a, fd, name, abstract_acl, mode,
|
||
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
||
|
}
|
||
|
#endif
|
||
|
--
|
||
|
2.31.1
|
||
|
|