File bsc1192427.patch of Package libarchive.34318

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 +++++++-
 4 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 libarchive/test/test_write_disk_fixup.c

diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index 8474617eb..fcd733aff 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);
 }
openSUSE Build Service is sponsored by