Compare commits

...

No commits in common. "c8" and "c9" have entirely different histories.
c8 ... c9

18 changed files with 137 additions and 1773 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/libarchive-3.3.3.tar.gz SOURCES/libarchive-3.5.3.tar.gz

View File

@ -1 +1 @@
499a8f48a895faff4151d7398b24070d578f0b2e SOURCES/libarchive-3.3.3.tar.gz 361b38405f4d6d01b22e4534aa7c217f5fa2db56 SOURCES/libarchive-3.5.3.tar.gz

View File

@ -1,146 +0,0 @@
From 9d178fe573818764a2d15e0a39691f5eb4e300f6 Mon Sep 17 00:00:00 2001
From: Ondrej Dubaj <odubaj@redhat.com>
Date: Mon, 27 May 2019 10:52:51 +0200
Subject: [PATCH] Fix a few obvious resource leaks and strcpy() misuses
Per Coverity report.
---
cpio/cpio.c | 4 +++-
libarchive/archive_acl.c | 8 ++++++--
libarchive/archive_write_set_format_iso9660.c | 4 ++--
libarchive/archive_write_set_format_mtree.c | 4 ++--
libarchive/archive_write_set_format_pax.c | 6 ++++--
libarchive/archive_write_set_format_xar.c | 10 ++++++----
6 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/cpio/cpio.c b/cpio/cpio.c
index 5beedd0..6696bb5 100644
--- a/cpio/cpio.c
+++ b/cpio/cpio.c
@@ -744,8 +744,10 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
}
if (cpio->option_rename)
destpath = cpio_rename(destpath);
- if (destpath == NULL)
+ if (destpath == NULL) {
+ archive_entry_free(entry);
return (0);
+ }
archive_entry_copy_pathname(entry, destpath);
/*
diff --git a/libarchive/archive_acl.c b/libarchive/archive_acl.c
index b8b6b63..503f379 100644
--- a/libarchive/archive_acl.c
+++ b/libarchive/archive_acl.c
@@ -753,8 +753,10 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
append_entry_w(&wp, prefix, ap->type, ap->tag, flags,
wname, ap->permset, id);
count++;
- } else if (r < 0 && errno == ENOMEM)
+ } else if (r < 0 && errno == ENOMEM) {
+ free(ws);
return (NULL);
+ }
}
/* Add terminating character */
@@ -975,8 +977,10 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
prefix = NULL;
r = archive_mstring_get_mbs_l(
&ap->name, &name, &len, sc);
- if (r != 0)
+ if (r != 0) {
+ free(s);
return (NULL);
+ }
if (count > 0)
*p++ = separator;
if (name == NULL ||
diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c
index c0ca435..badc88b 100644
--- a/libarchive/archive_write_set_format_iso9660.c
+++ b/libarchive/archive_write_set_format_iso9660.c
@@ -4899,10 +4899,10 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
if (p[0] == '/') {
if (p[1] == '/')
/* Convert '//' --> '/' */
- strcpy(p, p+1);
+ memmove(p, p+1, strlen(p+1) + 1);
else if (p[1] == '.' && p[2] == '/')
/* Convert '/./' --> '/' */
- strcpy(p, p+2);
+ memmove(p, p+2, strlen(p+2) + 1);
else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
/* Convert 'dir/dir1/../dir2/'
* --> 'dir/dir2/'
diff --git a/libarchive/archive_write_set_format_mtree.c b/libarchive/archive_write_set_format_mtree.c
index 493d473..0f2431e 100644
--- a/libarchive/archive_write_set_format_mtree.c
+++ b/libarchive/archive_write_set_format_mtree.c
@@ -1810,10 +1810,10 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
if (p[0] == '/') {
if (p[1] == '/')
/* Convert '//' --> '/' */
- strcpy(p, p+1);
+ memmove(p, p+1, strlen(p+1) + 1);
else if (p[1] == '.' && p[2] == '/')
/* Convert '/./' --> '/' */
- strcpy(p, p+2);
+ memmove(p, p+2, strlen(p+2) + 1);
else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
/* Convert 'dir/dir1/../dir2/'
* --> 'dir/dir2/'
diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c
index 0eaf733..4863e46 100644
--- a/libarchive/archive_write_set_format_pax.c
+++ b/libarchive/archive_write_set_format_pax.c
@@ -522,11 +522,13 @@ add_pax_acl(struct archive_write *a,
ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s",
"Can't translate ", attr, " to UTF-8");
return(ARCHIVE_WARN);
- } else if (*p != '\0') {
+ }
+
+ if (*p != '\0') {
add_pax_attr(&(pax->pax_header),
attr, p);
- free(p);
}
+ free(p);
return(ARCHIVE_OK);
}
diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c
index 495f0d4..56cd33c 100644
--- a/libarchive/archive_write_set_format_xar.c
+++ b/libarchive/archive_write_set_format_xar.c
@@ -2120,10 +2120,10 @@ file_gen_utility_names(struct archive_write *a, struct file *file)
if (p[0] == '/') {
if (p[1] == '/')
/* Convert '//' --> '/' */
- strcpy(p, p+1);
+ memmove(p, p+1, strlen(p+1) + 1);
else if (p[1] == '.' && p[2] == '/')
/* Convert '/./' --> '/' */
- strcpy(p, p+2);
+ memmove(p, p+2, strlen(p+2) + 1);
else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
/* Convert 'dir/dir1/../dir2/'
* --> 'dir/dir2/'
@@ -3169,8 +3169,10 @@ save_xattrs(struct archive_write *a, struct file *file)
checksum_update(&(xar->a_sumwrk),
xar->wbuff, size);
if (write_to_temp(a, xar->wbuff, size)
- != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ != ARCHIVE_OK) {
+ free(heap);
+ return (ARCHIVE_FATAL);
+ }
if (r == ARCHIVE_OK) {
xar->stream.next_out = xar->wbuff;
xar->stream.avail_out = sizeof(xar->wbuff);
--
2.17.1

View File

@ -1,78 +0,0 @@
From 6a71cce7ed735f83f9a6a6bad8beaa47f8d14734 Mon Sep 17 00:00:00 2001
From: Ondrej Dubaj <odubaj@redhat.com>
Date: Mon, 27 May 2019 10:06:14 +0200
Subject: [PATCH 1/2] Fix use-after-free in delayed link processing (newc
format)
During archiving, if some of the "delayed" hard link entries
happened to disappear on filesystem (or become unreadable) for
some reason (most probably race), the old code free()d the 'entry'
and continued with the loop; the next loop though dereferenced
'entry' and crashed the archiver.
Per report from Coverity.
---
tar/write.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/tar/write.c b/tar/write.c
index 9c24566..3970de2 100644
--- a/tar/write.c
+++ b/tar/write.c
@@ -540,8 +540,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
lafe_warnc(archive_errno(disk),
"%s", archive_error_string(disk));
bsdtar->return_value = 1;
- archive_entry_free(entry);
- continue;
+ goto next_entry;
}
/*
@@ -559,13 +558,13 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
bsdtar->return_value = 1;
else
archive_read_close(disk);
- archive_entry_free(entry);
- continue;
+ goto next_entry;
}
write_file(bsdtar, a, entry);
- archive_entry_free(entry);
archive_read_close(disk);
+next_entry:
+ archive_entry_free(entry);
entry = NULL;
archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
}
--
2.17.1
From a999ca882aeb8fce4f4f2ee1317f528984b47e8e Mon Sep 17 00:00:00 2001
From: Ondrej Dubaj <odubaj@redhat.com>
Date: Mon, 27 May 2019 10:34:48 +0200
Subject: [PATCH 2/2] call missing archive_read_close() in write_archive()
---
tar/write.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tar/write.c b/tar/write.c
index 3970de2..63c619c 100644
--- a/tar/write.c
+++ b/tar/write.c
@@ -556,8 +556,7 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
"%s", archive_error_string(disk));
if (r == ARCHIVE_FATAL)
bsdtar->return_value = 1;
- else
- archive_read_close(disk);
+ archive_read_close(disk);
goto next_entry;
}
--
2.17.1

View File

@ -1,58 +0,0 @@
From 65a23f5dbee4497064e9bb467f81138a62b0dae1 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Tue, 1 Jan 2019 16:01:40 +1100
Subject: [PATCH 2/2] 7zip: fix crash when parsing certain archives
Fuzzing with CRCs disabled revealed that a call to get_uncompressed_data()
would sometimes fail to return at least 'minimum' bytes. This can cause
the crc32() invocation in header_bytes to read off into invalid memory.
A specially crafted archive can use this to cause a crash.
An ASAN trace is below, but ASAN is not required - an uninstrumented
binary will also crash.
==7719==ERROR: AddressSanitizer: SEGV on unknown address 0x631000040000 (pc 0x7fbdb3b3ec1d bp 0x7ffe77a51310 sp 0x7ffe77a51150 T0)
==7719==The signal is caused by a READ memory access.
#0 0x7fbdb3b3ec1c in crc32_z (/lib/x86_64-linux-gnu/libz.so.1+0x2c1c)
#1 0x84f5eb in header_bytes (/tmp/libarchive/bsdtar+0x84f5eb)
#2 0x856156 in read_Header (/tmp/libarchive/bsdtar+0x856156)
#3 0x84e134 in slurp_central_directory (/tmp/libarchive/bsdtar+0x84e134)
#4 0x849690 in archive_read_format_7zip_read_header (/tmp/libarchive/bsdtar+0x849690)
#5 0x5713b7 in _archive_read_next_header2 (/tmp/libarchive/bsdtar+0x5713b7)
#6 0x570e63 in _archive_read_next_header (/tmp/libarchive/bsdtar+0x570e63)
#7 0x6f08bd in archive_read_next_header (/tmp/libarchive/bsdtar+0x6f08bd)
#8 0x52373f in read_archive (/tmp/libarchive/bsdtar+0x52373f)
#9 0x5257be in tar_mode_x (/tmp/libarchive/bsdtar+0x5257be)
#10 0x51daeb in main (/tmp/libarchive/bsdtar+0x51daeb)
#11 0x7fbdb27cab96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#12 0x41dd09 in _start (/tmp/libarchive/bsdtar+0x41dd09)
This was primarly done with afl and FairFuzz. Some early corpus entries
may have been generated by qsym.
---
libarchive/archive_read_support_format_7zip.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c
index bccbf896..b6d1505d 100644
--- a/libarchive/archive_read_support_format_7zip.c
+++ b/libarchive/archive_read_support_format_7zip.c
@@ -2964,13 +2964,7 @@ get_uncompressed_data(struct archive_read *a, const void **buff, size_t size,
if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) {
/* Copy mode. */
- /*
- * Note: '1' here is a performance optimization.
- * Recall that the decompression layer returns a count of
- * available bytes; asking for more than that forces the
- * decompressor to combine reads by copying data.
- */
- *buff = __archive_read_ahead(a, 1, &bytes_avail);
+ *buff = __archive_read_ahead(a, minimum, &bytes_avail);
if (bytes_avail <= 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
--
2.20.1

View File

@ -1,59 +0,0 @@
From 8312eaa576014cd9b965012af51bc1f967b12423 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Tue, 1 Jan 2019 17:10:49 +1100
Subject: [PATCH 1/2] iso9660: Fail when expected Rockridge extensions is
missing
A corrupted or malicious ISO9660 image can cause read_CE() to loop
forever.
read_CE() calls parse_rockridge(), expecting a Rockridge extension
to be read. However, parse_rockridge() is structured as a while
loop starting with a sanity check, and if the sanity check fails
before the loop has run, the function returns ARCHIVE_OK without
advancing the position in the file. This causes read_CE() to retry
indefinitely.
Make parse_rockridge() return ARCHIVE_WARN if it didn't read an
extension. As someone with no real knowledge of the format, this
seems more apt than ARCHIVE_FATAL, but both the call-sites escalate
it to a fatal error immediately anyway.
Found with a combination of AFL, afl-rb (FairFuzz) and qsym.
---
libarchive/archive_read_support_format_iso9660.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c
index 28acfefb..bad8f1df 100644
--- a/libarchive/archive_read_support_format_iso9660.c
+++ b/libarchive/archive_read_support_format_iso9660.c
@@ -2102,6 +2102,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
const unsigned char *p, const unsigned char *end)
{
struct iso9660 *iso9660;
+ int entry_seen = 0;
iso9660 = (struct iso9660 *)(a->format->data);
@@ -2257,8 +2258,16 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
}
p += p[2];
+ entry_seen = 1;
+ }
+
+ if (entry_seen)
+ return (ARCHIVE_OK);
+ else {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Tried to parse Rockridge extensions, but none found");
+ return (ARCHIVE_WARN);
}
- return (ARCHIVE_OK);
}
static int
--
2.20.1

View File

@ -1,34 +0,0 @@
From 88311f46cdfc719d26bb99d3b47944eb92ceae02 Mon Sep 17 00:00:00 2001
From: Ondrej Dubaj <odubaj@redhat.com>
Date: Tue, 30 Apr 2019 11:50:33 +0200
Subject: [PATCH] Avoid a double-free when a window size of 0 is specified
new_size can be 0 with a malicious or corrupted RAR archive.
realloc(area, 0) is equivalent to free(area), so the region would
be free()d here and the free()d again in the cleanup function.
Found with a setup running AFL, afl-rb, and qsym.
---
libarchive/archive_read_support_format_rar.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
index c4a8278..3f88eef 100644
--- a/libarchive/archive_read_support_format_rar.c
+++ b/libarchive/archive_read_support_format_rar.c
@@ -2317,6 +2317,11 @@ parse_codes(struct archive_read *a)
new_size = DICTIONARY_MAX_SIZE;
else
new_size = rar_fls((unsigned int)rar->unp_size) << 1;
+ if (new_size == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Zero window size is invalid.");
+ return (ARCHIVE_FATAL);
+ }
new_window = realloc(rar->lzss.window, new_size);
if (new_window == NULL) {
archive_set_error(&a->archive, ENOMEM,
--
2.17.1

View File

@ -1,75 +0,0 @@
From d00ccaf8c20efbd009964e3e2697d26907d14163 Mon Sep 17 00:00:00 2001
From: Ondrej Dubaj <odubaj@redhat.com>
Date: Tue, 30 Apr 2019 11:36:08 +0200
Subject: [PATCH] rar: file split across multi-part archives must match
Fuzzing uncovered some UAF and memory overrun bugs where a file in a
single file archive reported that it was split across multiple
volumes. This was caused by ppmd7 operations calling
rar_br_fillup. This would invoke rar_read_ahead, which would in some
situations invoke archive_read_format_rar_read_header. That would
check the new file name against the old file name, and if they didn't
match up it would free the ppmd7 buffer and allocate a new
one. However, because the ppmd7 decoder wasn't actually done with the
buffer, it would continue to used the freed buffer. Both reads and
writes to the freed region can be observed.
This is quite tricky to solve: once the buffer has been freed it is
too late, as the ppmd7 decoder functions almost universally assume
success - there's no way for ppmd_read to signal error, nor are there
good ways for functions like Range_Normalise to propagate them. So we
can't detect after the fact that we're in an invalid state - e.g. by
checking rar->cursor, we have to prevent ourselves from ever ending up
there. So, when we are in the dangerous part or rar_read_ahead that
assumes a valid split, we set a flag force read_header to either go
down the path for split files or bail. This means that the ppmd7
decoder keeps a valid buffer and just runs out of data.
Found with a combination of AFL, afl-rb and qsym.
---
libarchive/archive_read_support_format_rar.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
index cbb14c3..c4a8278 100644
--- a/libarchive/archive_read_support_format_rar.c
+++ b/libarchive/archive_read_support_format_rar.c
@@ -258,6 +258,7 @@ struct rar
struct data_block_offsets *dbo;
unsigned int cursor;
unsigned int nodes;
+ char filename_must_match;
/* LZSS members */
struct huffman_code maincode;
@@ -1570,6 +1571,12 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
return ret;
}
+ else if (rar->filename_must_match)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Mismatch of file parts split across multi-volume archive");
+ return (ARCHIVE_FATAL);
+ }
rar->filename_save = (char*)realloc(rar->filename_save,
filename_size + 1);
@@ -2938,12 +2945,14 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
rar->file_flags & FHD_SPLIT_AFTER)
{
+ rar->filename_must_match = 1;
ret = archive_read_format_rar_read_header(a, a->entry);
if (ret == (ARCHIVE_EOF))
{
rar->has_endarc_header = 1;
ret = archive_read_format_rar_read_header(a, a->entry);
}
+ rar->filename_must_match = 0;
if (ret != (ARCHIVE_OK))
return NULL;
return rar_read_ahead(a, min, avail);
--
2.17.1

View File

@ -1,31 +0,0 @@
From 1abcbf1af5209631ccf4fca4ddcab3c863294c85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Patrik=20Novotn=C3=BD?= <panovotn@redhat.com>
Date: Wed, 15 Jan 2020 16:10:04 +0100
Subject: [PATCH] RAR reader: fix use after free
If read_data_compressed() returns ARCHIVE_FAILED, the caller is allowed
to continue with next archive headers. We need to set rar->start_new_table
after the ppmd7_context got freed, otherwise it won't be allocated again.
---
libarchive/archive_read_support_format_rar.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
index cbb14c32..9c26ef97 100644
--- a/libarchive/archive_read_support_format_rar.c
+++ b/libarchive/archive_read_support_format_rar.c
@@ -1037,8 +1037,10 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
case COMPRESS_METHOD_GOOD:
case COMPRESS_METHOD_BEST:
ret = read_data_compressed(a, buff, size, offset);
- if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
+ if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) {
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
+ rar->start_new_table = 1;
+ }
break;
default:
--
2.24.1

View File

@ -1,98 +0,0 @@
From 72085b30bf30867360c4aa77bd43de5e1788d875 Mon Sep 17 00:00:00 2001
From: Ondrej Dubaj <odubaj@redhat.com>
Date: Tue, 24 Mar 2020 09:22:47 +0100
Subject: [PATCH] Bugfix and optimize archive_wstring_append_from_mbs()
The cal to mbrtowc() or mbtowc() should read up to mbs_length
bytes and not wcs_length. This avoids out-of-bounds reads.
mbrtowc() and mbtowc() return (size_t)-1 wit errno EILSEQ when
they encounter an invalid multibyte character and (size_t)-2 when
they they encounter an incomplete multibyte character. As we return
failure and all our callers error out it makes no sense to continue
parsing mbs.
As we allocate `len` wchars at the beginning and each wchar has
at least one byte, there will never be need to grow the buffer,
so the code can be left out. On the other hand, we are always
allocatng more memory than we need.
As long as wcs_length == mbs_length == len we can omit wcs_length.
We keep the old code commented if we decide to save memory and
use autoexpanding wcs_length in the future.
---
libarchive/archive_string.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c
index 5ae09b6..d7541dc 100644
--- a/libarchive/archive_string.c
+++ b/libarchive/archive_string.c
@@ -590,7 +590,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
* No single byte will be more than one wide character,
* so this length estimate will always be big enough.
*/
- size_t wcs_length = len;
+ //size_t wcs_length = len;
size_t mbs_length = len;
const char *mbs = p;
wchar_t *wcs;
@@ -599,7 +599,11 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
memset(&shift_state, 0, sizeof(shift_state));
#endif
- if (NULL == archive_wstring_ensure(dest, dest->length + wcs_length + 1))
+ /*
+ * As we decided to have wcs_length == mbs_length == len
+ * we can use len here instead of wcs_length
+ */
+ if (NULL == archive_wstring_ensure(dest, dest->length + len + 1))
return (-1);
wcs = dest->s + dest->length;
/*
@@ -608,6 +612,12 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
* multi bytes.
*/
while (*mbs && mbs_length > 0) {
+ /*
+ * The buffer we allocated is always big enough.
+ * Keep this code path in a comment if we decide to choose
+ * smaller wcs_length in the future
+ */
+/*
if (wcs_length == 0) {
dest->length = wcs - dest->s;
dest->s[dest->length] = L'\0';
@@ -617,24 +627,20 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
return (-1);
wcs = dest->s + dest->length;
}
+*/
#if HAVE_MBRTOWC
- r = mbrtowc(wcs, mbs, wcs_length, &shift_state);
+ r = mbrtowc(wcs, mbs, mbs_length, &shift_state);
#else
- r = mbtowc(wcs, mbs, wcs_length);
+ r = mbtowc(wcs, mbs, mbs_length);
#endif
if (r == (size_t)-1 || r == (size_t)-2) {
ret_val = -1;
- if (errno == EILSEQ) {
- ++mbs;
- --mbs_length;
- continue;
- } else
- break;
+ break;
}
if (r == 0 || r > mbs_length)
break;
wcs++;
- wcs_length--;
+ //wcs_length--;
mbs += r;
mbs_length -= r;
}
--
2.24.1

View File

@ -1,199 +0,0 @@
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

View File

@ -1,811 +0,0 @@
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

View File

@ -1,114 +0,0 @@
From 1bb2ec24b433bf87fed40e207c61c6aa8790e793 Mon Sep 17 00:00:00 2001
From: Ondrej Dubaj <odubaj@redhat.com>
Date: Mon, 18 Nov 2019 12:41:07 +0100
Subject: [PATCH] test_write_filter_zstd: size @ lvl=20 < default < lvl=1
Raise compression on the second test to level=20, and perform a
third at level=1. Expect the output archive sizes to line up
based on compression level. Reduces test susceptibility to small
output size variations from different libzstd releases.
---
libarchive/test/test_write_filter_zstd.c | 66 +++++++++++++++++--
1 file changed, 60 insertions(+), 6 deletions(-)
diff --git a/libarchive/test/test_write_filter_zstd.c b/libarchive/test/test_write_filter_zstd.c
index da3c806..13de134 100644
--- a/libarchive/test/test_write_filter_zstd.c
+++ b/libarchive/test/test_write_filter_zstd.c
@@ -34,7 +34,7 @@ DEFINE_TEST(test_write_filter_zstd)
char *buff, *data;
size_t buffsize, datasize;
char path[16];
- size_t used1, used2;
+ size_t used1, used2, used3;
int i, r;
buffsize = 2000000;
@@ -125,7 +125,7 @@ DEFINE_TEST(test_write_filter_zstd)
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_filter_option(a, NULL, "compression-level", "9"));
assertEqualIntA(a, ARCHIVE_OK,
- archive_write_set_filter_option(a, NULL, "compression-level", "6"));
+ archive_write_set_filter_option(a, NULL, "compression-level", "20"));
assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
for (i = 0; i < 100; i++) {
sprintf(path, "file%03d", i);
@@ -140,10 +140,6 @@ DEFINE_TEST(test_write_filter_zstd)
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
- failure("compression-level=6 wrote %d bytes, default wrote %d bytes",
- (int)used2, (int)used1);
- assert(used2 < used1);
-
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
r = archive_read_support_filter_zstd(a);
@@ -167,6 +163,64 @@ DEFINE_TEST(test_write_filter_zstd)
}
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+ /*
+ * One more time at level 1
+ */
+ assert((a = archive_write_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_bytes_per_block(a, 10));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "compression-level", "1"));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used3));
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_set_filetype(ae, AE_IFREG);
+ archive_entry_set_size(ae, datasize);
+ for (i = 0; i < 100; i++) {
+ sprintf(path, "file%03d", i);
+ archive_entry_copy_pathname(ae, path);
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ assertA(datasize == (size_t)archive_write_data(a, data, datasize));
+ }
+ archive_entry_free(ae);
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ r = archive_read_support_filter_zstd(a);
+ if (r == ARCHIVE_WARN) {
+ skipping("zstd reading not fully supported on this platform");
+ } else {
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_memory(a, buff, used3));
+ for (i = 0; i < 100; i++) {
+ sprintf(path, "file%03d", i);
+ failure("Trying to read %s", path);
+ if (!assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_next_header(a, &ae)))
+ break;
+ assertEqualString(path, archive_entry_pathname(ae));
+ assertEqualInt((int)datasize, archive_entry_size(ae));
+ }
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ }
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+
+ /*
+ * Check output sizes for various compression levels, expectation
+ * is that archive size for level=20 < default < level=1
+ */
+ failure("compression-level=20 wrote %d bytes, default wrote %d bytes",
+ (int)used2, (int)used1);
+ assert(used2 < used1);
+ failure("compression-level=1 wrote %d bytes, default wrote %d bytes",
+ (int)used3, (int)used1);
+ assert(used1 < used3);
+
/*
* Test various premature shutdown scenarios to make sure we
* don't crash or leak memory.
--
2.19.1

View File

@ -0,0 +1,14 @@
# Patch sources from libarchive upstream
# Source: https://github.com/libarchive/libarchive/commit/cfaa28168a07ea4a53276b63068f94fce37d6aff
--- libarchive-3.5.3/libarchive/archive_read_support_format_zip.c.old 2022-05-18 08:55:50.861574517 +0000
+++ libarchive-3.5.3/libarchive/archive_read_support_format_zip.c 2022-05-18 08:57:03.049574517 +0000
@@ -1657,7 +1657,7 @@ zipx_lzma_alone_init(struct archive_read
*/
/* Read magic1,magic2,lzma_params from the ZIPX stream. */
- if((p = __archive_read_ahead(a, 9, NULL)) == NULL) {
+ if(zip->entry_bytes_remaining < 9 || (p = __archive_read_ahead(a, 9, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated lzma data");
return (ARCHIVE_FATAL);

View File

@ -11,7 +11,7 @@ diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c
index 66592e82..27626b54 100644 index 66592e82..27626b54 100644
--- a/libarchive/archive_write.c --- a/libarchive/archive_write.c
+++ b/libarchive/archive_write.c +++ b/libarchive/archive_write.c
@@ -211,6 +211,10 @@ __archive_write_allocate_filter(struct a @@ -201,6 +201,10 @@ __archive_write_allocate_filter(struct archive *_a)
struct archive_write_filter *f; struct archive_write_filter *f;
f = calloc(1, sizeof(*f)); f = calloc(1, sizeof(*f));
@ -20,8 +20,8 @@ index 66592e82..27626b54 100644
+ return (NULL); + return (NULL);
+ +
f->archive = _a; f->archive = _a;
f->state = ARCHIVE_WRITE_FILTER_STATE_NEW;
if (a->filter_first == NULL) if (a->filter_first == NULL)
a->filter_first = f;
@@ -548,6 +552,10 @@ archive_write_open2(struct archive *_a, void *client_data, @@ -548,6 +552,10 @@ archive_write_open2(struct archive *_a, void *client_data,
a->client_data = client_data; a->client_data = client_data;

View File

@ -0,0 +1,15 @@
--- libarchive-3.5.1/libarchive/archive_digest.c.old 2021-05-27 15:46:54.988302284 +0200
+++ libarchive-3.5.1/libarchive/archive_digest.c 2021-05-27 15:50:03.519746886 +0200
@@ -432,9 +432,11 @@
static int
__archive_ripemd160init(archive_rmd160_ctx *ctx)
{
+ int ret;
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
- EVP_DigestInit(*ctx, EVP_ripemd160());
+ if (!(ret = EVP_DigestInit(*ctx, EVP_ripemd160())))
+ return (ARCHIVE_FAILED);
return (ARCHIVE_OK);
}

View File

@ -1,49 +1,41 @@
%bcond_without check %bcond_without check
Name: libarchive Name: libarchive
Version: 3.3.3 Version: 3.5.3
Release: 5%{?dist} Release: 4%{?dist}
Summary: A library for handling streaming archive formats Summary: A library for handling streaming archive formats
License: BSD License: BSD
URL: http://www.libarchive.org/ URL: https://www.libarchive.org/
Source0: http://www.libarchive.org/downloads/%{name}-%{version}.tar.gz Source0: https://libarchive.org/downloads/%{name}-%{version}.tar.gz
Patch1: libarchive-3.1.2-CVE-2019-1000019.patch Patch1: openssl3-rmd160failure.patch
Patch2: libarchive-3.1.2-CVE-2019-1000020.patch # Source: https://github.com/libarchive/libarchive/commit/cfaa28168a07ea4a53276b63068f94fce37d6aff
Patch3: libarchive-3.3.2-CVE-2018-1000878.patch Patch2: %{name}-3.5.3-Fix-CVE-2022-26280.patch
Patch4: libarchive-3.3.2-CVE-2018-1000877.patch
Patch5: fix-use-after-free-in-delayed-newc.patch
Patch6: fix-few-obvious-resource-leaks-covscan.patch
Patch7: libarchive-3.3.2-CVE-2019-18408.patch
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
# Source: https://github.com/libarchive/libarchive/commit/b1b501161013296d19dfe9acb84a341c8a1755b9 # Source: https://github.com/libarchive/libarchive/commit/b1b501161013296d19dfe9acb84a341c8a1755b9
Patch12: %{name}-3.3.3-Fix-size-filed-in-pax-header.patch Patch3: %{name}-3.5.3-Fix-size-filed-in-pax-header.patch
Patch13: %{name}-3.3.3-Fix-CVE-2022-36227.patch # Source: https://github.com/libarchive/libarchive/commit/fd180c36036df7181a64931264732a10ad8cd024
Patch4: %{name}-3.5.3-Fix-CVE-2022-36227.patch
BuildRequires: automake
BuildRequires: gcc
BuildRequires: bison BuildRequires: bison
BuildRequires: sharutils
BuildRequires: zlib-devel
BuildRequires: bzip2-devel BuildRequires: bzip2-devel
BuildRequires: xz-devel
BuildRequires: lzo-devel
BuildRequires: e2fsprogs-devel BuildRequires: e2fsprogs-devel
BuildRequires: gcc
BuildRequires: libacl-devel BuildRequires: libacl-devel
BuildRequires: libattr-devel BuildRequires: libattr-devel
BuildRequires: openssl-devel
BuildRequires: libxml2-devel BuildRequires: libxml2-devel
BuildRequires: lz4-devel
BuildRequires: automake
BuildRequires: libzstd-devel BuildRequires: libzstd-devel
BuildRequires: libtool BuildRequires: lz4-devel
# According to libarchive maintainer, linking against liblzo violates
# LZO license.
# See https://github.com/libarchive/libarchive/releases/tag/v3.3.0
#BuildRequires: lzo-devel
BuildRequires: openssl-devel
BuildRequires: sharutils
BuildRequires: xz-devel
BuildRequires: zlib-devel
BuildRequires: make
%description %description
Libarchive is a programming library that can create and read several different Libarchive is a programming library that can create and read several different
@ -91,20 +83,15 @@ standard output.
%prep %prep
%autosetup -p1 %autosetup -p1
bash build/autogen.sh
%build %build
%configure --disable-static --disable-rpath %configure --disable-static LT_SYS_LIBRARY_PATH=%_libdir
# remove rpaths %make_build
sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
make %{?_smp_mflags}
%install %install
make install DESTDIR=$RPM_BUILD_ROOT %make_install
find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
# rhbz#1294252 # rhbz#1294252
@ -166,7 +153,7 @@ cat_logs ()
run_testsuite () run_testsuite ()
{ {
rc=0 rc=0
LD_LIBRARY_PATH=`pwd`/.libs make %{?_smp_mflags} check -j1 || { %make_build check -j1 || {
# error happened - try to extract in koji as much info as possible # error happened - try to extract in koji as much info as possible
cat_logs cat_logs
@ -232,42 +219,93 @@ run_testsuite
%changelog %changelog
* Tue Dec 06 2022 Lukas Javorsky <ljavorsk@redhat.com> - 3.3.3-5 * Wed Nov 23 2022 Lukas Javorsky <ljavorsk@redhat.com> - 3.5.3-4
- Fix for CVE-2022-36227 - Resolves: CVE-2022-36227
* Tue Jul 12 2022 Lukas Javorsky <ljavorsk@redhat.com> - 3.3.3-4 * Tue Jul 12 2022 Lukas Javorsky <ljavorsk@redhat.com> - 3.5.3-3
- Resolves: #2037839 - Resolves: #2106651
* Tue Dec 21 2021 Matej Mužila <mmuzila@redhat.com> - 3.3.3-3 * Wed May 18 2022 Lukas Javorsky <ljavorsk@redhat.com> - 3.5.3-2
- Do not follow symlinks when processing the fixup list (CVE-2021-31566) - Resolves: CVE-2022-26280
* Mon Dec 20 2021 Matej Mužila <mmuzila@redhat.com> - 3.3.3-2 * Mon Feb 14 2022 Lukas Javorsky <ljavorsk@redhat.com> - 3.5.3-1
- Fix handling of symbolic link ACLs (CVE-2021-23177) - Rebase to version 3.5.3
* Thu Apr 30 2020 Ondrej Dubaj <odubaj@redhat.com> - 3.3.3-1 * Mon Aug 23 2021 Ondrej Dubaj <odubaj@redhat.com> - 3.5.2-1
- Rebase to version 3.3.3 - Rebased to version 3.5.2 (#1996634)
- Fixed symlink handling
* Tue Mar 24 2020 Ondrej Dubaj <odubaj@redhat.com> - 3.3.2-9 * Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 3.5.1-7
- Fix out-of-bounds read (CVE-2019-19221) (#1803967) - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Wed Jan 15 2020 Patrik Novotný <panovotn@redhat.com> - 3.3.2-8 * Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 3.5.1-6
- Fix CVE-2019-18408: RAR use-after-free - Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Mon May 27 2019 Ondrej Dubaj <odubaj@redhat.com> - 3.3.2-7 * Thu May 27 2021 Petr Kubat <pkubat@redhat.com> - 3.5.1-5
- fix use-after-free in delayed newc link processing (#1602575) - Return error when ripemd160 is used with OpenSSL3 (#1962067)
- fix a few obvious resource leaks and strcpy() misuses (#1602575)
* Tue Apr 30 2019 Ondrej Dubaj <odubaj@redhat.com> - 3.3.2-6 * Mon May 10 2021 Ondrej Dubaj <odubaj@redhat.com> - 3.5.1-4
- fixed use after free in RAR decoder (#1700752) - Fixed covscan issues (#1938755)
- fixed double free in RAR decoder (#1700753)
* Tue Apr 02 2019 Ondrej Dubaj <odubaj@redhat.com> - 3.3.2-5 * Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 3.5.1-3
- release bump due to gating (#1680768) - Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Fri Feb 22 2019 Pavel Raiskup <praiskup@redhat.com> - 3.3.2-4 * Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.5.1-2
- fix out-of-bounds read within lha_read_data_none() (CVE-2017-14503) - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
- fix crash on crafted 7zip archives (CVE-2019-1000019)
- fix infinite loop in ISO9660 (CVE-2019-1000020) * Mon Jan 04 2021 Ondrej Dubaj <odubaj@redhat.com> - 3.5.1-1
- Rebased to version 3.5.1
* Wed Dec 02 2020 Ondrej Dubaj <odubaj@redhat.com> - 3.5.0-1
- Rebased to version 3.5.0
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.4.3-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon Jul 13 2020 Tom Stellard <tstellar@redhat.com> - 3.4.3-2
- Use make macros
- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro
* Fri May 22 2020 Ondrej Dubaj <odubaj@redhat.com> - 3.4.3-1
- Rebased to version 3.4.3
* Wed Feb 12 2020 Ondrej Dubaj <odubaj@redhat.com> - 3.4.2-1
- Rebased to version 3.4.2
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.4.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Fri Aug 30 2019 FeRD (Frank Dana) <ferdnyc@gmail.com> - 3.4.0-1
- New upstream release, adds RAR5 and ZIPX support (readonly)
- Drop upstreamed patches
- Add upstreamed patch to fix test failure with libzstd-1.4.2
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.3.3-8
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Thu Mar 28 2019 Pavel Raiskup <praiskup@redhat.com> - 3.3.3-7
- simplify libtool hacks
* Tue Mar 19 2019 Ondrej Dubaj <odubaj@redhat.com> - 3.3.3-6
- applied various flaws (#1663893)
* Tue Mar 19 2019 Ondrej Dubaj <odubaj@redhat.com> - 3.3.3-5
- applied CVE patches (#1690071)
* Thu Mar 14 2019 Ondrej Dubaj <odubaj@redhat.com> - 3.3.3-4
- applied various flaws (#1672900)
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.3.3-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Mon Nov 26 2018 Pavel Raiskup <praiskup@redhat.com> - 3.3.3-2
- fix some covscan issues (rhbz#1602575)
- build-requires libzstd-devel (rhbz#1653046)
* Tue Oct 23 2018 Pavel Raiskup <praiskup@redhat.com> - 3.3.3-1
- the latest upstream release
* Wed Jul 18 2018 Pavel Raiskup <praiskup@redhat.com> - 3.3.2-3 * Wed Jul 18 2018 Pavel Raiskup <praiskup@redhat.com> - 3.3.2-3
- drop use of %%ldconfig_scriptlets - drop use of %%ldconfig_scriptlets