Skip to content

Commit

Permalink
Fix handling of symbolic link ACLs
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mmatuska committed Aug 22, 2021
1 parent 1302359 commit fba4f12
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
20 changes: 15 additions & 5 deletions libarchive/archive_disk_acl_freebsd.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 */
Expand All @@ -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
Expand Down
23 changes: 20 additions & 3 deletions libarchive/archive_disk_acl_linux.c
Expand Up @@ -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,
Expand Down Expand Up @@ -455,7 +460,7 @@ set_richacl(struct archive *a, int fd, const char *name,
#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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down
13 changes: 9 additions & 4 deletions libarchive/archive_disk_acl_sunos.c
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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 */
Expand All @@ -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
Expand Down

0 comments on commit fba4f12

Please sign in to comment.