On Thu, Dec 30, 2021 at 09:10:34PM +0100, Salvatore Bonaccorso wrote: > Hi Peter, > > On Mon, Dec 27, 2021 at 10:10:58PM +0200, Peter Pentchev wrote: > > 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 > > While at it, can you as well add the CVE references to the > debian/changelog?
Right... I'm not very smart these days, am I? Thanks a lot for your patience with me these past few weeks! Attached is an updated debdiff, the only difference being the CVE references added to the changelog entry. G'luck, Peter -- Peter Pentchev r...@ringlet.net r...@debian.org p...@storpool.com PGP key: http://people.FreeBSD.org/~roam/roam.key.asc Key fingerprint 2EE7 A7A5 17FC 124C F115 C354 651E EFB0 2527 DF13
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,13 @@ +libarchive (3.4.3-2+deb11u1) bullseye; urgency=medium + + * Add four upstream fixes for various problems: + - fix extracting hardlinks to symlinks + - CVE-2021-23177: fix handling of symlink ACLs; Closes: 1001986 + - CVE-2021-31566: 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:45:51.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:45:51.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:45:51.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:45:51.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:45:51.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