Package: release.debian.org Severity: normal Tags: bullseye User: release.debian....@packages.debian.org Usertags: pu X-Debbugs-Cc: r...@ringlet.net
[ Reason ] This is a future unblock request before I upload libarchive-3.4.3-2+deb11u1 to fix a couple of bugs that were fixed in later upstream versions and in unstable. They are all related to setting permissions and ACLs when extracting archive members that represent symbolic and hard links. [ Impact ] Extracting some (rarely seen) archives may result in files having the wrong access permissions. [ Tests ] All the added patches are taken from upstream commits that include both the bugfixes and the testsuite additions to check for regressions. [ Risks ] The code is mostly easy to follow, the fixes are straightforward. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in stable [x] the issue is verified as fixed in unstable [ Changes ] - correctly extract a hardlink to a symlink using the linkat(2) system call - do not change the ACLs on symlinks, since that would affect the symlink target instead - do not accidentally change the access mode of a symlink target when a change to the symlink's mode was intended [ Other info ] Thanks in advance for looking at this, and keep up the great work!
diff -Nru libarchive-3.4.3/debian/changelog libarchive-3.4.3/debian/changelog --- libarchive-3.4.3/debian/changelog 2020-08-01 21:46:12.000000000 +0300 +++ libarchive-3.4.3/debian/changelog 2021-12-27 18:45:51.000000000 +0200 @@ -1,3 +1,12 @@ +libarchive (3.4.3-2+deb11u1) bullseye; urgency=medium + + * Add four upstream fixes for various problems: + - fix extracting hardlinks to symlinks + - fix handling of symlink ACLs; Closes: 1001986 + - never follow symlinks when setting file flags; Closes: 1001990 + + -- Peter Pentchev <r...@debian.org> Mon, 27 Dec 2021 18:45:51 +0200 + libarchive (3.4.3-2) unstable; urgency=medium * Add some more upstream patches: diff -Nru libarchive-3.4.3/debian/patches/series libarchive-3.4.3/debian/patches/series --- libarchive-3.4.3/debian/patches/series 2020-08-01 21:46:12.000000000 +0300 +++ libarchive-3.4.3/debian/patches/series 2021-12-27 18:27:13.000000000 +0200 @@ -8,3 +8,7 @@ upstream-rar-read-format.patch upstream-memory-stdlib.patch upstream-max-comp-level.patch +upstream-hardlinks-to-symlinks.patch +upstream-symlink-acls.patch +upstream-set-flags-nofollow.patch +upstream-fixup-nofollow.patch diff -Nru libarchive-3.4.3/debian/patches/upstream-fixup-nofollow.patch libarchive-3.4.3/debian/patches/upstream-fixup-nofollow.patch --- libarchive-3.4.3/debian/patches/upstream-fixup-nofollow.patch 1970-01-01 02:00:00.000000000 +0200 +++ libarchive-3.4.3/debian/patches/upstream-fixup-nofollow.patch 2021-12-27 18:26:12.000000000 +0200 @@ -0,0 +1,168 @@ +Description: Do not follow symlinks when processing the fixup list + Published as CVE-2021-31566 +Origin: upstream, https://github.com/libarchive/libarchive/commit/b41daecb5ccb4c8e3b2c53fd6147109fc12c3043 +Bug-Debian: https://bugs.debian.org/1001990 +Author: Martin Matuska <mar...@matuska.org> +Last-Update: 2021-12-20 + +--- a/Makefile.am ++++ b/Makefile.am +@@ -556,6 +556,7 @@ + libarchive/test/test_write_disk.c \ + libarchive/test/test_write_disk_appledouble.c \ + libarchive/test/test_write_disk_failures.c \ ++ libarchive/test/test_write_disk_fixup.c \ + libarchive/test/test_write_disk_hardlink.c \ + libarchive/test/test_write_disk_hfs_compression.c \ + libarchive/test/test_write_disk_lookup.c \ +--- a/libarchive/archive_write_disk_posix.c ++++ b/libarchive/archive_write_disk_posix.c +@@ -2461,6 +2461,7 @@ + { + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *next, *p; ++ struct stat st; + int fd, ret; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, +@@ -2478,6 +2479,20 @@ + (TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) { + fd = open(p->name, + O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC); ++ if (fd == -1) { ++ /* If we cannot lstat, skip entry */ ++ if (lstat(p->name, &st) != 0) ++ goto skip_fixup_entry; ++ /* ++ * If we deal with a symbolic link, mark ++ * it in the fixup mode to ensure no ++ * modifications are made to its target. ++ */ ++ if (S_ISLNK(st.st_mode)) { ++ p->mode &= ~S_IFMT; ++ p->mode |= S_IFLNK; ++ } ++ } + } + if (p->fixup & TODO_TIMES) { + set_times(a, fd, p->mode, p->name, +@@ -2492,7 +2507,12 @@ + fchmod(fd, p->mode); + else + #endif +- chmod(p->name, p->mode); ++#ifdef HAVE_LCHMOD ++ lchmod(p->name, p->mode); ++#else ++ if (!S_ISLNK(p->mode)) ++ chmod(p->name, p->mode); ++#endif + } + if (p->fixup & TODO_ACLS) + archive_write_disk_set_acls(&a->archive, fd, +@@ -2503,6 +2523,7 @@ + if (p->fixup & TODO_MAC_METADATA) + set_mac_metadata(a, p->name, p->mac_metadata, + p->mac_metadata_size); ++skip_fixup_entry: + next = p->next; + archive_acl_clear(&p->acl); + free(p->mac_metadata); +@@ -2643,6 +2664,7 @@ + fe->next = a->fixup_list; + a->fixup_list = fe; + fe->fixup = 0; ++ fe->mode = 0; + fe->name = strdup(pathname); + return (fe); + } +--- a/libarchive/test/CMakeLists.txt ++++ b/libarchive/test/CMakeLists.txt +@@ -208,6 +208,7 @@ + test_write_disk.c + test_write_disk_appledouble.c + test_write_disk_failures.c ++ test_write_disk_fixup.c + test_write_disk_hardlink.c + test_write_disk_hfs_compression.c + test_write_disk_lookup.c +--- /dev/null ++++ b/libarchive/test/test_write_disk_fixup.c +@@ -0,0 +1,77 @@ ++/*- ++ * Copyright (c) 2021 Martin Matuska ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include "test.h" ++ ++/* ++ * Test fixup entries don't follow symlinks ++ */ ++DEFINE_TEST(test_write_disk_fixup) ++{ ++ struct archive *ad; ++ struct archive_entry *ae; ++ int r; ++ ++ if (!canSymlink()) { ++ skipping("Symlinks not supported"); ++ return; ++ } ++ ++ /* Write entries to disk. */ ++ assert((ad = archive_write_disk_new()) != NULL); ++ ++ /* ++ * Create a file ++ */ ++ assertMakeFile("victim", 0600, "a"); ++ ++ /* ++ * Create a directory and a symlink with the same name ++ */ ++ ++ /* Directory: dir */ ++ assert((ae = archive_entry_new()) != NULL); ++ archive_entry_copy_pathname(ae, "dir"); ++ archive_entry_set_mode(ae, AE_IFDIR | 0606); ++ assertEqualIntA(ad, 0, archive_write_header(ad, ae)); ++ assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); ++ archive_entry_free(ae); ++ ++ /* Symbolic Link: dir -> foo */ ++ assert((ae = archive_entry_new()) != NULL); ++ archive_entry_copy_pathname(ae, "dir"); ++ archive_entry_set_mode(ae, AE_IFLNK | 0777); ++ archive_entry_set_size(ae, 0); ++ archive_entry_copy_symlink(ae, "victim"); ++ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); ++ if (r >= ARCHIVE_WARN) ++ assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); ++ archive_entry_free(ae); ++ ++ assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); ++ ++ /* Test the entries on disk. */ ++ assertIsSymlink("dir", "victim", 0); ++ assertFileMode("victim", 0600); ++} diff -Nru libarchive-3.4.3/debian/patches/upstream-hardlinks-to-symlinks.patch libarchive-3.4.3/debian/patches/upstream-hardlinks-to-symlinks.patch --- libarchive-3.4.3/debian/patches/upstream-hardlinks-to-symlinks.patch 1970-01-01 02:00:00.000000000 +0200 +++ libarchive-3.4.3/debian/patches/upstream-hardlinks-to-symlinks.patch 2021-12-27 18:26:12.000000000 +0200 @@ -0,0 +1,214 @@ +Description: Fix extracting hardlinks to symlinks +Origin: upstream, https://github.com/libarchive/libarchive/commit/5e646b890fb3c59ef6f94221ef8ef9ae62a8a9d6 +Author: Martin Matuska <mar...@matuska.org> +Last-Updated: 2021-12-20 + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1352,6 +1352,7 @@ + CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD) + CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN) + CHECK_FUNCTION_EXISTS_GLIBC(link HAVE_LINK) ++CHECK_FUNCTION_EXISTS_GLIBC(linkat HAVE_LINKAT) + CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R) + CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT) + CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES) +--- a/build/cmake/config.h.in ++++ b/build/cmake/config.h.in +@@ -743,6 +743,9 @@ + /* Define to 1 if you have the `link' function. */ + #cmakedefine HAVE_LINK 1 + ++/* Define to 1 if you have the `linkat' function. */ ++#cmakedefine HAVE_LINKAT 1 ++ + /* Define to 1 if you have the <linux/fiemap.h> header file. */ + #cmakedefine HAVE_LINUX_FIEMAP_H 1 + +--- a/configure.ac ++++ b/configure.ac +@@ -631,7 +631,7 @@ + AC_CHECK_FUNCS([futimens futimes futimesat]) + AC_CHECK_FUNCS([geteuid getpid getgrgid_r getgrnam_r]) + AC_CHECK_FUNCS([getpwnam_r getpwuid_r getvfsbyname gmtime_r]) +-AC_CHECK_FUNCS([lchflags lchmod lchown link localtime_r lstat lutimes]) ++AC_CHECK_FUNCS([lchflags lchmod lchown link linkat localtime_r lstat lutimes]) + AC_CHECK_FUNCS([mbrtowc memmove memset]) + AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp]) + AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawnp readlink readlinkat]) +--- a/libarchive/archive_write_disk_posix.c ++++ b/libarchive/archive_write_disk_posix.c +@@ -360,7 +360,7 @@ + static void fsobj_error(int *, struct archive_string *, int, const char *, + const char *); + static int check_symlinks_fsobj(char *, int *, struct archive_string *, +- int); ++ int, int); + static int check_symlinks(struct archive_write_disk *); + static int create_filesystem_object(struct archive_write_disk *); + static struct fixup_entry *current_fixup(struct archive_write_disk *, +@@ -2263,7 +2263,7 @@ + return (EPERM); + } + r = check_symlinks_fsobj(linkname_copy, &error_number, +- &error_string, a->flags); ++ &error_string, a->flags, 1); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); +@@ -2284,7 +2284,12 @@ + */ + if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) + unlink(a->name); ++#ifdef HAVE_LINKAT ++ r = linkat(AT_FDCWD, linkname, AT_FDCWD, a->name, ++ 0) ? errno : 0; ++#else + r = link(linkname, a->name) ? errno : 0; ++#endif + /* + * New cpio and pax formats allow hardlink entries + * to carry data, so we may have to open the file +@@ -2675,7 +2680,7 @@ + */ + static int + check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, +- int flags) ++ int flags, int checking_linkname) + { + #if !defined(HAVE_LSTAT) && \ + !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)) +@@ -2684,6 +2689,7 @@ + (void)error_number; /* UNUSED */ + (void)error_string; /* UNUSED */ + (void)flags; /* UNUSED */ ++ (void)checking_linkname; /* UNUSED */ + return (ARCHIVE_OK); + #else + int res = ARCHIVE_OK; +@@ -2805,6 +2811,28 @@ + head = tail + 1; + } + } else if (S_ISLNK(st.st_mode)) { ++ if (last && checking_linkname) { ++#ifdef HAVE_LINKAT ++ /* ++ * Hardlinks to symlinks are safe to write ++ * if linkat() is supported as it does not ++ * follow symlinks. ++ */ ++ res = ARCHIVE_OK; ++#else ++ /* ++ * We return ARCHIVE_FAILED here as we are ++ * not able to safely write hardlinks ++ * to symlinks. ++ */ ++ tail[0] = c; ++ fsobj_error(a_eno, a_estr, errno, ++ "Cannot write hardlink to symlink ", ++ path); ++ res = ARCHIVE_FAILED; ++#endif ++ break; ++ } else + if (last) { + /* + * Last element is symlink; remove it +@@ -2971,7 +2999,7 @@ + int rc; + archive_string_init(&error_string); + rc = check_symlinks_fsobj(a->name, &error_number, &error_string, +- a->flags); ++ a->flags, 0); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); +--- a/libarchive/config_freebsd.h ++++ b/libarchive/config_freebsd.h +@@ -137,6 +137,7 @@ + #define HAVE_LIBZ 1 + #define HAVE_LIMITS_H 1 + #define HAVE_LINK 1 ++#define HAVE_LINKAT 1 + #define HAVE_LOCALE_H 1 + #define HAVE_LOCALTIME_R 1 + #define HAVE_LONG_LONG_INT 1 +--- a/libarchive/test/test_write_disk_hardlink.c ++++ b/libarchive/test/test_write_disk_hardlink.c +@@ -49,6 +49,9 @@ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct archive *ad; + struct archive_entry *ae; ++#ifdef HAVE_LINKAT ++ int can_symlink; ++#endif + int r; + + /* Force the umask to something predictable. */ +@@ -147,7 +150,7 @@ + archive_entry_free(ae); + + /* +- * Finally, try a new-cpio-like approach, where the initial ++ * Third, try a new-cpio-like approach, where the initial + * regular file is empty and the hardlink has the data. + */ + +@@ -174,6 +177,41 @@ + assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); + } + archive_entry_free(ae); ++ ++#ifdef HAVE_LINKAT ++ /* Finally, try creating a hard link to a dangling symlink */ ++ can_symlink = canSymlink(); ++ if (can_symlink) { ++ /* Symbolic link: link5a -> foo */ ++ assert((ae = archive_entry_new()) != NULL); ++ archive_entry_copy_pathname(ae, "link5a"); ++ archive_entry_set_mode(ae, AE_IFLNK | 0642); ++ archive_entry_unset_size(ae); ++ archive_entry_copy_symlink(ae, "foo"); ++ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); ++ if (r >= ARCHIVE_WARN) { ++ assertEqualInt(ARCHIVE_WARN, ++ archive_write_data(ad, data, sizeof(data))); ++ assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); ++ } ++ archive_entry_free(ae); ++ ++ ++ /* Link. Size of zero means this doesn't carry data. */ ++ assert((ae = archive_entry_new()) != NULL); ++ archive_entry_copy_pathname(ae, "link5b"); ++ archive_entry_set_mode(ae, S_IFREG | 0642); ++ archive_entry_set_size(ae, 0); ++ archive_entry_copy_hardlink(ae, "link5a"); ++ assertEqualIntA(ad, 0, r = archive_write_header(ad, ae)); ++ if (r >= ARCHIVE_WARN) { ++ assertEqualInt(ARCHIVE_WARN, ++ archive_write_data(ad, data, sizeof(data))); ++ assertEqualIntA(ad, 0, archive_write_finish_entry(ad)); ++ } ++ archive_entry_free(ae); ++ } ++#endif + assertEqualInt(0, archive_write_free(ad)); + + /* Test the entries on disk. */ +@@ -211,5 +249,14 @@ + assertFileNLinks("link4a", 2); + assertFileSize("link4a", sizeof(data)); + assertIsHardlink("link4a", "link4b"); ++ ++#ifdef HAVE_LINKAT ++ if (can_symlink) { ++ /* Test #5 */ ++ assertIsSymlink("link5a", "foo", 0); ++ assertFileNLinks("link5a", 2); ++ assertIsHardlink("link5a", "link5b"); ++ } ++#endif + #endif + } diff -Nru libarchive-3.4.3/debian/patches/upstream-set-flags-nofollow.patch libarchive-3.4.3/debian/patches/upstream-set-flags-nofollow.patch --- libarchive-3.4.3/debian/patches/upstream-set-flags-nofollow.patch 1970-01-01 02:00:00.000000000 +0200 +++ libarchive-3.4.3/debian/patches/upstream-set-flags-nofollow.patch 2021-12-27 18:26:12.000000000 +0200 @@ -0,0 +1,19 @@ +Description: Never follow symlinks when setting file flags on Linux + Published as CVE-2021-31566 +Origin: upstream, https://github.com/libarchive/libarchive/commit/e2ad1a2c3064fa9eba6274b3641c4c1beed25c0b +Bug-Debian: https://bugs.debian.org/1001990 +Author: Martin Matuska <mar...@matuska.org> +Last-Update: 2021-12-20 + +--- a/libarchive/archive_write_disk_posix.c ++++ b/libarchive/archive_write_disk_posix.c +@@ -3927,7 +3927,8 @@ + + /* If we weren't given an fd, open it ourselves. */ + if (myfd < 0) { +- myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC); ++ myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | ++ O_CLOEXEC | O_NOFOLLOW); + __archive_ensure_cloexec_flag(myfd); + } + if (myfd < 0) diff -Nru libarchive-3.4.3/debian/patches/upstream-symlink-acls.patch libarchive-3.4.3/debian/patches/upstream-symlink-acls.patch --- libarchive-3.4.3/debian/patches/upstream-symlink-acls.patch 1970-01-01 02:00:00.000000000 +0200 +++ libarchive-3.4.3/debian/patches/upstream-symlink-acls.patch 2021-12-27 18:26:12.000000000 +0200 @@ -0,0 +1,179 @@ +Description: Fix handling of symbolic link ACLs + Published as CVE-2021-23177 +Origin: upstream, https://github.com/libarchive/libarchive/commit/fba4f123cc456d2b2538f811bb831483bf336bad +Bug-Debian: https://bugs.debian.org/1001986 +Author: Martin Matuska <mar...@matuska.org> +Last-Updated: 2021-12-20 + +--- a/libarchive/archive_disk_acl_freebsd.c ++++ b/libarchive/archive_disk_acl_freebsd.c +@@ -319,7 +319,7 @@ + + 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 @@ + 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 @@ + 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_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 @@ + #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 +--- a/libarchive/archive_disk_acl_linux.c ++++ b/libarchive/archive_disk_acl_linux.c +@@ -343,6 +343,11 @@ + 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 @@ + #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 @@ + 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_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 */ +--- a/libarchive/archive_disk_acl_sunos.c ++++ b/libarchive/archive_disk_acl_sunos.c +@@ -443,7 +443,7 @@ + + 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 @@ + if (entries == 0) + return (ARCHIVE_OK); + +- + switch (ae_requested_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + cmd = SETACL; +@@ -492,6 +491,12 @@ + 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 @@ + 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 @@ + #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
signature.asc
Description: PGP signature