diff --git a/SOURCES/libarchive-3.3.3-CVE-2021-23177.patch b/SOURCES/libarchive-3.3.3-CVE-2021-23177.patch
new file mode 100644
index 0000000..09babb5
--- /dev/null
+++ b/SOURCES/libarchive-3.3.3-CVE-2021-23177.patch
@@ -0,0 +1,199 @@
+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
+
diff --git a/SOURCES/libarchive-3.3.3-CVE-2021-31566.patch b/SOURCES/libarchive-3.3.3-CVE-2021-31566.patch
new file mode 100644
index 0000000..48adb55
--- /dev/null
+++ b/SOURCES/libarchive-3.3.3-CVE-2021-31566.patch
@@ -0,0 +1,811 @@
+From b837c72c423b744a2e6c554742877173406dbfa0 Mon Sep 17 00:00:00 2001
+From: Martin Matuska <martin@matuska.org>
+Date: Sat, 25 May 2019 23:46:59 +0200
+Subject: [PATCH] archive_write_disk_posix: open a fd when processing fixup
+ entries
+
+---
+ libarchive/archive_write_disk_posix.c | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
+index 70b27b50..0583fbd1 100644
+--- a/libarchive/archive_write_disk_posix.c
++++ b/libarchive/archive_write_disk_posix.c
+@@ -182,6 +182,7 @@ struct fixup_entry {
+ 	void			*mac_metadata;
+ 	int			 fixup; /* bitmask of what needs fixing */
+ 	char			*name;
++	int			 fd;
+ };
+ 
+ /*
+@@ -2354,20 +2355,31 @@ _archive_write_disk_close(struct archive *_a)
+ 
+ 	while (p != NULL) {
+ 		a->pst = NULL; /* Mark stat cache as out-of-date. */
++		if (p->fd < 0 && p->fixup &
++		    (TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
++			p->fd = open(p->name,
++			    O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
++		}
+ 		if (p->fixup & TODO_TIMES) {
+-			set_times(a, -1, p->mode, p->name,
++			set_times(a, p->fd, p->mode, p->name,
+ 			    p->atime, p->atime_nanos,
+ 			    p->birthtime, p->birthtime_nanos,
+ 			    p->mtime, p->mtime_nanos,
+ 			    p->ctime, p->ctime_nanos);
+ 		}
+-		if (p->fixup & TODO_MODE_BASE)
++		if (p->fixup & TODO_MODE_BASE) {
++#ifdef HAVE_FCHMOD
++			if (p->fd >= 0)
++				fchmod(p->fd, p->mode);
++			else
++#endif
+ 			chmod(p->name, p->mode);
++		}
+ 		if (p->fixup & TODO_ACLS)
+-			archive_write_disk_set_acls(&a->archive, -1, p->name,
+-			    &p->acl, p->mode);
++			archive_write_disk_set_acls(&a->archive, p->fd,
++			    p->name, &p->acl, p->mode);
+ 		if (p->fixup & TODO_FFLAGS)
+-			set_fflags_platform(a, -1, p->name,
++			set_fflags_platform(a, p->fd, p->name,
+ 			    p->mode, p->fflags_set, 0);
+ 		if (p->fixup & TODO_MAC_METADATA)
+ 			set_mac_metadata(a, p->name, p->mac_metadata,
+@@ -2376,6 +2388,8 @@ _archive_write_disk_close(struct archive *_a)
+ 		archive_acl_clear(&p->acl);
+ 		free(p->mac_metadata);
+ 		free(p->name);
++		if (p->fd >= 0)
++			close(p->fd);	
+ 		free(p);
+ 		p = next;
+ 	}
+@@ -2510,6 +2524,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
+ 	a->fixup_list = fe;
+ 	fe->fixup = 0;
+ 	fe->name = strdup(pathname);
++	fe->fd = -1;
+ 	return (fe);
+ }
+ 
+-- 
+2.31.1
+
+From 6d5204058ed51e11588a438737e9033305cfd248 Mon Sep 17 00:00:00 2001
+From: Martin Matuska <martin@matuska.org>
+Date: Thu, 6 Jun 2019 15:12:11 +0200
+Subject: [PATCH] archive_write_disk_posix changes - private file descriptor in
+ _archive_write_disk_close() - use la_opendirat() in edit_deep_directories()
+
+---
+ libarchive/archive_write_disk_posix.c | 25 ++++++++++++-------------
+ 1 file changed, 12 insertions(+), 13 deletions(-)
+
+diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
+index 89941c64..b1a0bb38 100644
+--- a/libarchive/archive_write_disk_posix.c
++++ b/libarchive/archive_write_disk_posix.c
+@@ -186,7 +186,6 @@ struct fixup_entry {
+ 	void			*mac_metadata;
+ 	int			 fixup; /* bitmask of what needs fixing */
+ 	char			*name;
+-	int			 fd;
+ };
+ 
+ /*
+@@ -1947,7 +1946,7 @@ edit_deep_directories(struct archive_write_disk *a)
+ 		return;
+ 
+ 	/* Try to record our starting dir. */
+-	a->restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
++	a->restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC | O_DIRECTORY);
+ 	__archive_ensure_cloexec_flag(a->restore_pwd);
+ 	if (a->restore_pwd < 0)
+ 		return;
+@@ -2380,7 +2379,7 @@ _archive_write_disk_close(struct archive *_a)
+ {
+ 	struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ 	struct fixup_entry *next, *p;
+-	int ret;
++	int fd, ret;
+ 
+ 	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ 	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+@@ -2391,14 +2390,15 @@ _archive_write_disk_close(struct archive *_a)
+ 	p = sort_dir_list(a->fixup_list);
+ 
+ 	while (p != NULL) {
++		fd = -1;
+ 		a->pst = NULL; /* Mark stat cache as out-of-date. */
+-		if (p->fd < 0 && p->fixup &
++		if (p->fixup &
+ 		    (TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
+-			p->fd = open(p->name,
++			fd = open(p->name,
+ 			    O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
+ 		}
+ 		if (p->fixup & TODO_TIMES) {
+-			set_times(a, p->fd, p->mode, p->name,
++			set_times(a, fd, p->mode, p->name,
+ 			    p->atime, p->atime_nanos,
+ 			    p->birthtime, p->birthtime_nanos,
+ 			    p->mtime, p->mtime_nanos,
+@@ -2406,17 +2406,17 @@ _archive_write_disk_close(struct archive *_a)
+ 		}
+ 		if (p->fixup & TODO_MODE_BASE) {
+ #ifdef HAVE_FCHMOD
+-			if (p->fd >= 0)
+-				fchmod(p->fd, p->mode);
++			if (fd >= 0)
++				fchmod(fd, p->mode);
+ 			else
+ #endif
+ 			chmod(p->name, p->mode);
+ 		}
+ 		if (p->fixup & TODO_ACLS)
+-			archive_write_disk_set_acls(&a->archive, p->fd,
++			archive_write_disk_set_acls(&a->archive, fd,
+ 			    p->name, &p->acl, p->mode);
+ 		if (p->fixup & TODO_FFLAGS)
+-			set_fflags_platform(a, p->fd, p->name,
++			set_fflags_platform(a, fd, p->name,
+ 			    p->mode, p->fflags_set, 0);
+ 		if (p->fixup & TODO_MAC_METADATA)
+ 			set_mac_metadata(a, p->name, p->mac_metadata,
+@@ -2425,8 +2425,8 @@ _archive_write_disk_close(struct archive *_a)
+ 		archive_acl_clear(&p->acl);
+ 		free(p->mac_metadata);
+ 		free(p->name);
+-		if (p->fd >= 0)
+-			close(p->fd);	
++		if (fd >= 0)
++			close(fd);
+ 		free(p);
+ 		p = next;
+ 	}
+@@ -2561,7 +2561,6 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
+ 	a->fixup_list = fe;
+ 	fe->fixup = 0;
+ 	fe->name = strdup(pathname);
+-	fe->fd = -1;
+ 	return (fe);
+ }
+ 
+-- 
+2.31.1
+
+From e2ad1a2c3064fa9eba6274b3641c4c1beed25c0b Mon Sep 17 00:00:00 2001
+From: Martin Matuska <martin@matuska.org>
+Date: Sun, 22 Aug 2021 03:53:28 +0200
+Subject: [PATCH] Never follow symlinks when setting file flags on Linux
+
+When opening a file descriptor to set file flags on linux, ensure
+no symbolic links are followed. This fixes the case when an archive
+contains a directory entry followed by a symlink entry with the same
+path. The fixup code would modify file flags of the symlink target.
+---
+ libarchive/archive_write_disk_posix.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
+index ba4e65df..8474617e 100644
+--- a/libarchive/archive_write_disk_posix.c
++++ b/libarchive/archive_write_disk_posix.c
+@@ -3927,7 +3927,8 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
+ 
+ 	/* 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)
+-- 
+2.31.1
+
+From b41daecb5ccb4c8e3b2c53fd6147109fc12c3043 Mon Sep 17 00:00:00 2001
+From: Martin Matuska <martin@matuska.org>
+Date: Fri, 20 Aug 2021 01:50:27 +0200
+Subject: [PATCH] Do not follow symlinks when processing the fixup list
+
+Use lchmod() instead of chmod() and tell the remaining functions that the
+real file to be modified is a symbolic link.
+
+Fixes #1566
+---
+ Makefile.am                             |  1 +
+ libarchive/archive_write_disk_posix.c   | 24 +++++++-
+ libarchive/test/CMakeLists.txt          |  1 +
+ libarchive/test/test_write_disk_fixup.c | 77 +++++++++++++++++++++++++
+ 4 files changed, 102 insertions(+), 1 deletion(-)
+ create mode 100644 libarchive/test/test_write_disk_fixup.c
+
+diff --git a/Makefile.am b/Makefile.am
+index 58edb74e..c93a82e9 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -560,6 +560,7 @@ libarchive_test_SOURCES= \
+ 	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 \
+diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
+index 8474617e..fcd733af 100644
+--- a/libarchive/archive_write_disk_posix.c
++++ b/libarchive/archive_write_disk_posix.c
+@@ -2461,6 +2461,7 @@ _archive_write_disk_close(struct archive *_a)
+ {
+ 	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 @@ _archive_write_disk_close(struct archive *_a)
+ 		    (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 @@ _archive_write_disk_close(struct archive *_a)
+ 				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 @@ _archive_write_disk_close(struct archive *_a)
+ 		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 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
+ 	fe->next = a->fixup_list;
+ 	a->fixup_list = fe;
+ 	fe->fixup = 0;
++	fe->mode = 0;
+ 	fe->name = strdup(pathname);
+ 	return (fe);
+ }
+diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt
+index b26f679c..53cc3e22 100644
+--- a/libarchive/test/CMakeLists.txt
++++ b/libarchive/test/CMakeLists.txt
+@@ -209,6 +209,7 @@ IF(ENABLE_TEST)
+     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
+diff --git a/libarchive/test/test_write_disk_fixup.c b/libarchive/test/test_write_disk_fixup.c
+new file mode 100644
+index 00000000..153cc3a9
+--- /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");
++	assertFileMode("victim", 0600);
++}
+-- 
+2.31.1
+
+From 8a1bd5c18e896f0411a991240ce0d772bb02c840 Mon Sep 17 00:00:00 2001
+From: Martin Matuska <martin@matuska.org>
+Date: Fri, 27 Aug 2021 10:56:28 +0200
+Subject: [PATCH] Fix following symlinks when processing the fixup list
+
+The previous fix in b41daecb5 was incomplete. Fixup entries are
+given the original path without calling cleanup_pathname().
+To make sure we don't follow a symlink, we must strip trailing
+slashes from the path.
+
+The fixup entries are always directories. Make sure we try to modify
+only directories by providing O_DIRECTORY to open() (if supported)
+and if it fails to check directory via lstat().
+
+Fixes #1566
+---
+ libarchive/archive_write_disk_posix.c   | 62 +++++++++++++++++--------
+ libarchive/test/test_write_disk_fixup.c | 44 ++++++++++++++----
+ 2 files changed, 78 insertions(+), 28 deletions(-)
+
+diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
+index fcd733af..aadc5871 100644
+--- a/libarchive/archive_write_disk_posix.c
++++ b/libarchive/archive_write_disk_posix.c
+@@ -2462,6 +2462,7 @@ _archive_write_disk_close(struct archive *_a)
+ 	struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ 	struct fixup_entry *next, *p;
+ 	struct stat st;
++	char *c;
+ 	int fd, ret;
+ 
+ 	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+@@ -2475,24 +2476,49 @@ _archive_write_disk_close(struct archive *_a)
+ 	while (p != NULL) {
+ 		fd = -1;
+ 		a->pst = NULL; /* Mark stat cache as out-of-date. */
+-		if (p->fixup &
+-		    (TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
+-			fd = open(p->name,
+-			    O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
++
++		/* We must strip trailing slashes from the path to avoid
++		   dereferencing symbolic links to directories */
++		c = p->name;
++		while (*c != '\0')
++			c++;
++		while (c != p->name && *(c - 1) == '/') {
++			c--;
++			*c = '\0';
++		}
++
++		if (p->fixup == 0)
++			goto skip_fixup_entry;
++		else {
++			fd = open(p->name, O_BINARY | O_NOFOLLOW | O_RDONLY
++#if defined(O_DIRECTORY)
++			    | O_DIRECTORY
++#endif
++			    | O_CLOEXEC);
++			/*
++		 `	 * If we don't support O_DIRECTORY,
++			 * or open() has failed, we must stat()
++			 * to verify that we are opening a directory
++			 */
++#if defined(O_DIRECTORY)
+ 			if (fd == -1) {
+-				/* If we cannot lstat, skip entry */
+-				if (lstat(p->name, &st) != 0)
++				if (lstat(p->name, &st) != 0 ||
++				    !S_ISDIR(st.st_mode)) {
+ 					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;
+ 				}
+ 			}
++#else
++#if HAVE_FSTAT
++			if (fd > 0 && (
++			    fstat(fd, &st) != 0 || !S_ISDIR(st.st_mode))) {
++				goto skip_fixup_entry;
++			} else
++#endif
++			if (lstat(p->name, &st) != 0 ||
++			    !S_ISDIR(st.st_mode)) {
++				goto skip_fixup_entry;
++			}
++#endif
+ 		}
+ 		if (p->fixup & TODO_TIMES) {
+ 			set_times(a, fd, p->mode, p->name,
+@@ -2504,14 +2530,13 @@ _archive_write_disk_close(struct archive *_a)
+ 		if (p->fixup & TODO_MODE_BASE) {
+ #ifdef HAVE_FCHMOD
+ 			if (fd >= 0)
+-				fchmod(fd, p->mode);
++				fchmod(fd, p->mode & 07777);
+ 			else
+ #endif
+ #ifdef HAVE_LCHMOD
+-			lchmod(p->name, p->mode);
++			lchmod(p->name, p->mode & 07777);
+ #else
+-			if (!S_ISLNK(p->mode))
+-				chmod(p->name, p->mode);
++			chmod(p->name, p->mode & 07777);
+ #endif
+ 		}
+ 		if (p->fixup & TODO_ACLS)
+@@ -2664,7 +2689,6 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
+ 	fe->next = a->fixup_list;
+ 	a->fixup_list = fe;
+ 	fe->fixup = 0;
+-	fe->mode = 0;
+ 	fe->name = strdup(pathname);
+ 	return (fe);
+ }
+diff --git a/libarchive/test/test_write_disk_fixup.c b/libarchive/test/test_write_disk_fixup.c
+index c399c984..b83b7307 100644
+--- a/libarchive/test/test_write_disk_fixup.c
++++ b/libarchive/test/test_write_disk_fixup.c
+@@ -47,26 +47,50 @@ DEFINE_TEST(test_write_disk_fixup)
+ 	/*
+ 	 * Create a file
+ 	 */
+-	assertMakeFile("victim", 0600, "a");
++	assertMakeFile("file", 0600, "a");
++
++	/*
++	 * Create a directory
++	 */
++	assertMakeDir("dir", 0700);
+ 
+ 	/*
+ 	 * Create a directory and a symlink with the same name
+ 	 */
+ 
+-	/* Directory: dir */
++	/* Directory: dir1 */
++        assert((ae = archive_entry_new()) != NULL);
++        archive_entry_copy_pathname(ae, "dir1/");
++        archive_entry_set_mode(ae, AE_IFDIR | 0555);
++	assertEqualIntA(ad, 0, archive_write_header(ad, ae));
++	assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
++        archive_entry_free(ae);
++
++	/* Directory: dir2 */
+         assert((ae = archive_entry_new()) != NULL);
+-        archive_entry_copy_pathname(ae, "dir");
+-        archive_entry_set_mode(ae, AE_IFDIR | 0606);
++        archive_entry_copy_pathname(ae, "dir2/");
++        archive_entry_set_mode(ae, AE_IFDIR | 0555);
+ 	assertEqualIntA(ad, 0, archive_write_header(ad, ae));
+ 	assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+         archive_entry_free(ae);
+ 
+-	/* Symbolic Link: dir -> foo */
++	/* Symbolic Link: dir1 -> dir */
++	assert((ae = archive_entry_new()) != NULL);
++	archive_entry_copy_pathname(ae, "dir1");
++	archive_entry_set_mode(ae, AE_IFLNK | 0777);
++	archive_entry_set_size(ae, 0);
++	archive_entry_copy_symlink(ae, "dir");
++	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);
++
++	/* Symbolic Link: dir2 -> file */
+ 	assert((ae = archive_entry_new()) != NULL);
+-	archive_entry_copy_pathname(ae, "dir");
++	archive_entry_copy_pathname(ae, "dir2");
+ 	archive_entry_set_mode(ae, AE_IFLNK | 0777);
+ 	archive_entry_set_size(ae, 0);
+-	archive_entry_copy_symlink(ae, "victim");
++	archive_entry_copy_symlink(ae, "file");
+ 	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
+ 	if (r >= ARCHIVE_WARN)
+ 		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
+@@ -75,6 +99,8 @@ DEFINE_TEST(test_write_disk_fixup)
+ 	assertEqualInt(ARCHIVE_OK, archive_write_free(ad));
+ 
+ 	/* Test the entries on disk. */
+-	assertIsSymlink("dir", "victim");
+-	assertFileMode("victim", 0600);
++	assertIsSymlink("dir1", "dir");
++	assertIsSymlink("dir2", "file");
++	assertFileMode("dir", 0700);
++	assertFileMode("file", 0600);
+ }
+-- 
+2.31.1
+
+From ede459d2ebb879f5eedb6f7abea203be0b334230 Mon Sep 17 00:00:00 2001
+From: Martin Matuska <martin@matuska.org>
+Date: Wed, 17 Nov 2021 21:06:00 +0100
+Subject: [PATCH] archive_write_disk_posix: fix writing fflags broken in
+ 8a1bd5c
+
+The fixup list was erroneously assumed to be directories only.
+Only in the case of critical file flags modification (e.g. SF_IMMUTABLE
+on BSD systems), other file types (e.g. regular files or symbolic links)
+may be added to the fixup list. We still need to verify that we are writing
+to the correct file type, so compare the archive entry file type with
+the file type of the file to be modified.
+
+Fixes #1617
+---
+ libarchive/archive_write_disk_posix.c | 87 +++++++++++++++++++++++----
+ 1 file changed, 75 insertions(+), 12 deletions(-)
+
+diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
+index aadc5871..7e57aac2 100644
+--- a/libarchive/archive_write_disk_posix.c
++++ b/libarchive/archive_write_disk_posix.c
+@@ -173,6 +173,7 @@ struct fixup_entry {
+ 	struct fixup_entry	*next;
+ 	struct archive_acl	 acl;
+ 	mode_t			 mode;
++	__LA_MODE_T		 filetype;
+ 	int64_t			 atime;
+ 	int64_t                  birthtime;
+ 	int64_t			 mtime;
+@@ -357,6 +358,7 @@ struct archive_write_disk {
+ 
+ #define HFS_BLOCKS(s)	((s) >> 12)
+ 
++static int	la_verify_filetype(mode_t, __LA_MODE_T);
+ static void	fsobj_error(int *, struct archive_string *, int, const char *,
+ 		    const char *);
+ static int	check_symlinks_fsobj(char *, int *, struct archive_string *,
+@@ -464,6 +466,39 @@ la_opendirat(int fd, const char *path) {
+ static ssize_t	_archive_write_disk_data_block(struct archive *, const void *,
+ 		    size_t, int64_t);
+ 
++static int
++la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
++	int ret = 0;
++
++	switch (filetype) {
++	case AE_IFREG:
++		ret = (S_ISREG(mode));
++		break;
++	case AE_IFDIR:
++		ret = (S_ISDIR(mode));
++		break;
++	case AE_IFLNK:
++		ret = (S_ISLNK(mode));
++		break;
++	case AE_IFSOCK:
++		ret = (S_ISSOCK(mode));
++		break;
++	case AE_IFCHR:
++		ret = (S_ISCHR(mode));
++		break;
++	case AE_IFBLK:
++		ret = (S_ISBLK(mode));
++		break;
++	case AE_IFIFO:
++		ret = (S_ISFIFO(mode));
++		break;
++	default:
++		break;
++	}
++
++	return (ret);
++}
++
+ static int
+ lazy_stat(struct archive_write_disk *a)
+ {
+@@ -822,6 +857,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
+ 		fe = current_fixup(a, archive_entry_pathname(entry));
+ 		if (fe == NULL)
+ 			return (ARCHIVE_FATAL);
++		fe->filetype = archive_entry_filetype(entry);
+ 		fe->fixup |= TODO_MODE_BASE;
+ 		fe->mode = a->mode;
+ 	}
+@@ -832,6 +868,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
+ 		fe = current_fixup(a, archive_entry_pathname(entry));
+ 		if (fe == NULL)
+ 			return (ARCHIVE_FATAL);
++		fe->filetype = archive_entry_filetype(entry);
+ 		fe->mode = a->mode;
+ 		fe->fixup |= TODO_TIMES;
+ 		if (archive_entry_atime_is_set(entry)) {
+@@ -865,6 +902,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
+ 		fe = current_fixup(a, archive_entry_pathname(entry));
+ 		if (fe == NULL)
+ 			return (ARCHIVE_FATAL);
++		fe->filetype = archive_entry_filetype(entry);
+ 		fe->fixup |= TODO_ACLS;
+ 		archive_acl_copy(&fe->acl, archive_entry_acl(entry));
+ 	}
+@@ -877,6 +915,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
+ 			fe = current_fixup(a, archive_entry_pathname(entry));
+ 			if (fe == NULL)
+ 				return (ARCHIVE_FATAL);
++			fe->filetype = archive_entry_filetype(entry);
+ 			fe->mac_metadata = malloc(metadata_size);
+ 			if (fe->mac_metadata != NULL) {
+ 				memcpy(fe->mac_metadata, metadata,
+@@ -891,6 +930,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
+ 		fe = current_fixup(a, archive_entry_pathname(entry));
+ 		if (fe == NULL)
+ 			return (ARCHIVE_FATAL);
++		fe->filetype = archive_entry_filetype(entry);
+ 		fe->fixup |= TODO_FFLAGS;
+ 		/* TODO: Complete this.. defer fflags from below. */
+ 	}
+@@ -2463,7 +2503,7 @@ _archive_write_disk_close(struct archive *_a)
+ 	struct fixup_entry *next, *p;
+ 	struct stat st;
+ 	char *c;
+-	int fd, ret;
++	int fd, ret, openflags;
+ 
+ 	archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ 	    ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+@@ -2490,32 +2530,53 @@ _archive_write_disk_close(struct archive *_a)
+ 		if (p->fixup == 0)
+ 			goto skip_fixup_entry;
+ 		else {
+-			fd = open(p->name, O_BINARY | O_NOFOLLOW | O_RDONLY
++			/*
++			 * We need to verify if the type of the file
++			 * we are going to open matches the file type
++			 * of the fixup entry.
++			 */
++			openflags = O_BINARY | O_NOFOLLOW | O_RDONLY
++			    | O_CLOEXEC;
+ #if defined(O_DIRECTORY)
+-			    | O_DIRECTORY
++			if (p->filetype == AE_IFDIR)
++				openflags |= O_DIRECTORY;
+ #endif
+-			    | O_CLOEXEC);
++			fd = open(p->name, openflags);
++
++#if defined(O_DIRECTORY)
+ 			/*
+-		 `	 * If we don't support O_DIRECTORY,
+-			 * or open() has failed, we must stat()
+-			 * to verify that we are opening a directory
++			 * If we support O_DIRECTORY and open was
++			 * successful we can skip the file type check
++			 * for directories. For other file types
++			 * we need to verify via fstat() or lstat()
+ 			 */
+-#if defined(O_DIRECTORY)
+-			if (fd == -1) {
++			if (fd == -1 || p->filetype != AE_IFDIR) {
++#if HAVE_FSTAT
++				if (fd > 0 && (
++				    fstat(fd, &st) != 0 ||
++				    la_verify_filetype(st.st_mode,
++				    p->filetype) == 0)) {
++					goto skip_fixup_entry;
++				} else
++#endif
+ 				if (lstat(p->name, &st) != 0 ||
+-				    !S_ISDIR(st.st_mode)) {
++				    la_verify_filetype(st.st_mode,
++				    p->filetype) == 0) {
+ 					goto skip_fixup_entry;
+ 				}
+ 			}
+ #else
+ #if HAVE_FSTAT
+ 			if (fd > 0 && (
+-			    fstat(fd, &st) != 0 || !S_ISDIR(st.st_mode))) {
++			    fstat(fd, &st) != 0 ||
++			    la_verify_filetype(st.st_mode,
++			    p->filetype) == 0)) {
+ 				goto skip_fixup_entry;
+ 			} else
+ #endif
+ 			if (lstat(p->name, &st) != 0 ||
+-			    !S_ISDIR(st.st_mode)) {
++			    la_verify_filetype(st.st_mode,
++			    p->filetype) == 0) {
+ 				goto skip_fixup_entry;
+ 			}
+ #endif
+@@ -2689,6 +2750,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
+ 	fe->next = a->fixup_list;
+ 	a->fixup_list = fe;
+ 	fe->fixup = 0;
++	fe->filetype = 0;
+ 	fe->name = strdup(pathname);
+ 	return (fe);
+ }
+@@ -3811,6 +3873,7 @@ set_fflags(struct archive_write_disk *a)
+ 			le = current_fixup(a, a->name);
+ 			if (le == NULL)
+ 				return (ARCHIVE_FATAL);
++			le->filetype = archive_entry_filetype(a->entry);
+ 			le->fixup |= TODO_FFLAGS;
+ 			le->fflags_set = set;
+ 			/* Store the mode if it's not already there. */
+-- 
+2.31.1
+
diff --git a/SPECS/libarchive.spec b/SPECS/libarchive.spec
index bb5334a..0ce2924 100644
--- a/SPECS/libarchive.spec
+++ b/SPECS/libarchive.spec
@@ -2,7 +2,7 @@
 
 Name:           libarchive
 Version:        3.3.3
-Release:        1%{?dist}
+Release:        3%{?dist}
 Summary:        A library for handling streaming archive formats
 
 License:        BSD
@@ -20,6 +20,9 @@ Patch8:        libarchive-3.3.2-CVE-2019-19221.patch
 # upstream reference
 # https://github.com/libarchive/libarchive/commit/aaacc8762fd8ced8823350edd8ce2e46b565582b#diff-bc144884a8e634e16f247e0588a266ee
 Patch9:        libarchive-3.3.3-fixed-zstd_test.patch
+Patch10:       libarchive-3.3.3-CVE-2021-23177.patch
+Patch11:       libarchive-3.3.3-CVE-2021-31566.patch
+
 
 
 BuildRequires:  gcc
@@ -37,6 +40,7 @@ BuildRequires:  libxml2-devel
 BuildRequires:  lz4-devel
 BuildRequires:  automake
 BuildRequires:  libzstd-devel
+BuildRequires:  libtool
 
 
 %description
@@ -85,6 +89,7 @@ standard output.
 
 %prep
 %autosetup -p1
+bash build/autogen.sh
 
 
 %build
@@ -225,6 +230,12 @@ run_testsuite
 
 
 %changelog
+* Tue Dec 21 2021 Matej Mužila <mmuzila@redhat.com> - 3.3.3-3
+- Do not follow symlinks when processing the fixup list (CVE-2021-31566)
+
+* Mon Dec 20 2021 Matej Mužila <mmuzila@redhat.com> - 3.3.3-2
+- Fix handling of symbolic link ACLs (CVE-2021-23177)
+
 * Thu Apr 30 2020 Ondrej Dubaj <odubaj@redhat.com> - 3.3.3-1
 - Rebase to version 3.3.3