Package: release.debian.org Severity: normal X-Debbugs-Cc: libarchive@packages.debian.org, roam@debian.org Control: affects -1 + src:libarchive User: release.debian.org@packages.debian.org Usertags: unblock Please unblock package libarchive; this is a pre-approval request before I upload the package to unstable. [ Reason ] Apply four patches taken from later upstream releases for security issues tracked by the security team as CVE-2025-5914, CVE-2025-5915, CVE-2025-5916, and CVE-2025-5917. [ Impact ] Programs using libarchive may be tricked into mishandling specific types of archives, with effects ranging from undefined behavior to data disclosure. [ Tests ] Some of the patches also add tests to libarchive's unit test suite. [ Risks ] IMHO low; the fixes have been approved by the upstream authors and included in later libarchive releases. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing unblock libarchive/3.7.4-4
diff -Nru libarchive-3.7.4/debian/changelog libarchive-3.7.4/debian/changelog
--- libarchive-3.7.4/debian/changelog 2025-04-27 23:19:29.000000000 +0300
+++ libarchive-3.7.4/debian/changelog 2025-07-24 17:40:32.000000000 +0300
@@ -1,3 +1,11 @@
+libarchive (3.7.4-4) unstable; urgency=medium
+
+ * Add the CVE-2025-5914, CVE-2025-5915, CVE-2025-5916, and
+ CVE-2025-5917 patches.
+ Closes: #1107621, #1107622, #1107623, #1107626
+
+ -- Peter Pentchev <roam@debian.org> Thu, 24 Jul 2025 17:40:32 +0300
+
libarchive (3.7.4-3) unstable; urgency=medium
* Rename the CVE-2025-1632 patch to CVE-2025-1632-25724, use the exact
diff -Nru libarchive-3.7.4/debian/patches/CVE-2025-5914.patch libarchive-3.7.4/debian/patches/CVE-2025-5914.patch
--- libarchive-3.7.4/debian/patches/CVE-2025-5914.patch 1970-01-01 02:00:00.000000000 +0200
+++ libarchive-3.7.4/debian/patches/CVE-2025-5914.patch 2025-07-24 16:53:30.000000000 +0300
@@ -0,0 +1,32 @@
+Description: rar: Fix double free with over 4 billion nodes (#2598)
+ If a system is capable of handling 4 billion nodes in memory, a double
+ free could occur because of an unsigned integer overflow leading to a
+ realloc call with size argument of 0. Eventually, the client will
+ release that memory again, triggering a double free.
+Bug-Debian: https://bugs.debian.org/1107621
+Author: Tobias Stoeckmann <tobias@stoeckmann.org>
+Origin: upstream, https://github.com/libarchive/libarchive/commit/09685126fcec664e2b8ca595e1fc371bd494d209
+Last-Update: 2025-07-24
+
+--- a/libarchive/archive_read_support_format_rar.c
++++ b/libarchive/archive_read_support_format_rar.c
+@@ -335,8 +335,8 @@
+ int found_first_header;
+ char has_endarc_header;
+ struct data_block_offsets *dbo;
+- unsigned int cursor;
+- unsigned int nodes;
++ size_t cursor;
++ size_t nodes;
+ char filename_must_match;
+
+ /* LZSS members */
+@@ -1186,7 +1186,7 @@
+ int whence)
+ {
+ int64_t client_offset, ret;
+- unsigned int i;
++ size_t i;
+ struct rar *rar = (struct rar *)(a->format->data);
+
+ if (rar->compression_method == COMPRESS_METHOD_STORE)
diff -Nru libarchive-3.7.4/debian/patches/CVE-2025-5915.patch libarchive-3.7.4/debian/patches/CVE-2025-5915.patch
--- libarchive-3.7.4/debian/patches/CVE-2025-5915.patch 1970-01-01 02:00:00.000000000 +0200
+++ libarchive-3.7.4/debian/patches/CVE-2025-5915.patch 2025-07-24 16:54:40.000000000 +0300
@@ -0,0 +1,182 @@
+Description: rar: Fix heap-buffer-overflow (#2599)
+ A filter block size must not be larger than the lzss window, which is
+ defined
+ by dictionary size, which in turn can be derived from unpacked file
+ size.
+ .
+ While at it, improve error messages and fix lzss window wrap around
+ logic.
+ .
+ Fixes https://github.com/libarchive/libarchive/issues/2565
+Bug-Debian: https://bugs.debian.org/1107622
+Author: Tobias Stoeckmann <tobias@stoeckmann.org>
+Origin: upstream, https://github.com/libarchive/libarchive/commit/a612bf62f86a6faa47bd57c52b94849f0a404d8c
+Last-Update: 2025-07-24
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -511,6 +511,7 @@
+ libarchive/test/test_read_format_rar_encryption_header.c \
+ libarchive/test/test_read_format_rar_filter.c \
+ libarchive/test/test_read_format_rar_invalid1.c \
++ libarchive/test/test_read_format_rar_overflow.c \
+ libarchive/test/test_read_format_rar5.c \
+ libarchive/test/test_read_format_raw.c \
+ libarchive/test/test_read_format_tar.c \
+@@ -870,6 +871,7 @@
+ libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu \
+ libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu \
+ libarchive/test/test_read_format_rar_noeof.rar.uu \
++ libarchive/test/test_read_format_rar_overflow.rar.uu \
+ libarchive/test/test_read_format_rar_ppmd_lzss_conversion.rar.uu \
+ libarchive/test/test_read_format_rar_ppmd_use_after_free.rar.uu \
+ libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu \
+--- a/libarchive/archive_read_support_format_rar.c
++++ b/libarchive/archive_read_support_format_rar.c
+@@ -451,7 +451,7 @@
+ static int rar_decode_byte(struct archive_read*, uint8_t *);
+ static int execute_filter(struct archive_read*, struct rar_filter *,
+ struct rar_virtual_machine *, size_t);
+-static int copy_from_lzss_window(struct archive_read *, void *, int64_t, int);
++static int copy_from_lzss_window(struct archive_read *, uint8_t *, int64_t, int);
+ static inline void vm_write_32(struct rar_virtual_machine*, size_t, uint32_t);
+ static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
+
+@@ -2903,7 +2903,7 @@
+ }
+
+ if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
+- return (ARCHIVE_FATAL);
++ goto bad_data;
+
+ if (symbol < 256)
+ {
+@@ -2930,14 +2930,14 @@
+ else
+ {
+ if (parse_codes(a) != ARCHIVE_OK)
+- return (ARCHIVE_FATAL);
++ goto bad_data;
+ continue;
+ }
+ }
+ else if(symbol==257)
+ {
+ if (!read_filter(a, end))
+- return (ARCHIVE_FATAL);
++ goto bad_data;
+ continue;
+ }
+ else if(symbol==258)
+@@ -3022,7 +3022,7 @@
+ {
+ if ((lowoffsetsymbol =
+ read_next_symbol(a, &rar->lowoffsetcode)) < 0)
+- return (ARCHIVE_FATAL);
++ goto bad_data;
+ if(lowoffsetsymbol == 16)
+ {
+ rar->numlowoffsetrepeats = 15;
+@@ -3070,7 +3070,7 @@
+ }
+
+ static int
+-copy_from_lzss_window(struct archive_read *a, void *buffer,
++copy_from_lzss_window(struct archive_read *a, uint8_t *buffer,
+ int64_t startpos, int length)
+ {
+ int windowoffs, firstpart;
+@@ -3085,7 +3085,7 @@
+ }
+ if (firstpart < length) {
+ memcpy(buffer, &rar->lzss.window[windowoffs], firstpart);
+- memcpy(buffer, &rar->lzss.window[0], length - firstpart);
++ memcpy(buffer + firstpart, &rar->lzss.window[0], length - firstpart);
+ } else {
+ memcpy(buffer, &rar->lzss.window[windowoffs], length);
+ }
+@@ -3240,6 +3240,9 @@
+ else
+ blocklength = prog ? prog->oldfilterlength : 0;
+
++ if (blocklength > rar->dictionary_size)
++ return 0;
++
+ registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
+ registers[4] = blocklength;
+ registers[5] = prog ? prog->usagecount : 0;
+--- a/libarchive/test/CMakeLists.txt
++++ b/libarchive/test/CMakeLists.txt
+@@ -155,6 +155,7 @@
+ test_read_format_rar_encryption_partially.c
+ test_read_format_rar_invalid1.c
+ test_read_format_rar_filter.c
++ test_read_format_rar_overflow.c
+ test_read_format_rar5.c
+ test_read_format_raw.c
+ test_read_format_tar.c
+--- /dev/null
++++ b/libarchive/test/test_read_format_rar_overflow.c
+@@ -0,0 +1,48 @@
++/*-
++ * Copyright (c) 2003-2025 Tim Kientzle
++ * 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"
++
++DEFINE_TEST(test_read_format_rar_overflow)
++{
++ struct archive *a;
++ struct archive_entry *ae;
++ const char reffile[] = "test_read_format_rar_overflow.rar";
++ const void *buff;
++ size_t size;
++ int64_t offset;
++
++ extract_reference_file(reffile);
++ assert((a = archive_read_new()) != NULL);
++ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
++ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
++ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, reffile, 1024));
++ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
++ assertEqualInt(48, archive_entry_size(ae));
++ /* The next call should reproduce Issue #2565 */
++ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data_block(a, &buff, &size, &offset));
++
++ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
++ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
++}
+--- /dev/null
++++ b/libarchive/test/test_read_format_rar_overflow.rar.uu
+@@ -0,0 +1,11 @@
++begin 644 test_read_format_rar_overflow.rar
++M4F%R(1H'`,($=```(0`@`0``,`````(````````````S`0``````,`"_B%_:
++MZ?^[:7``?S!!,`@P,KB@,T@RN33)MTEB@5Z3<`DP`K35`.0P63@P<,Q&0?#,
++MA##,,",S,(@P,#,@##`&,#":(3`!,#"(`9HPS,,S13`P,#`P,*`PHPS,,S1A
++M,!,!,#","9H@S12D#$PP!C`P`*'F03":,,T8H`@\,/DPJS!/,"30,#`3N%LP
++MCQ6:S3"!,#LP22<-,$5%B"5B$S!)(&*>G#+@!`E`%0ODC])62=DO,)BYJX'P
++M=/LPZ3!!008?%S`P,#`P,#`P,#`P,#`P,#`P,#`P2$PP,#`P03!(,#`P,#`&
++M,`7),#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P
++-,#`P,#`P,#`P,#`P,```
++`
++end
diff -Nru libarchive-3.7.4/debian/patches/CVE-2025-5916.patch libarchive-3.7.4/debian/patches/CVE-2025-5916.patch
--- libarchive-3.7.4/debian/patches/CVE-2025-5916.patch 1970-01-01 02:00:00.000000000 +0200
+++ libarchive-3.7.4/debian/patches/CVE-2025-5916.patch 2025-07-24 16:54:45.000000000 +0300
@@ -0,0 +1,92 @@
+commit ef093729521fcf73fa4007d5ae77adfe4df42403
+Date: Mon Apr 7 00:24:13 2025 +0200
+
+Description: warc: Prevent signed integer overflow (#2568)
+ If a warc archive claims to have more than INT64_MAX - 4 content bytes,
+ the inevitable failure to skip all these bytes could lead to parsing
+ data which should be ignored instead.
+ .
+ The test case contains a conversation entry with that many bytes and if
+ the entry is not properly skipped, the warc implementation would read
+ the conversation data as a new file entry.
+Bug-Debian: https://bugs.debian.org/1107623
+Origin: upstream, https://github.com/libarchive/libarchive/commit/ef093729521fcf73fa4007d5ae77adfe4df42403
+Author: Tobias Stoeckmann <tobias@stoeckmann.org>
+Last-Update: 2025-07-24
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -935,6 +935,7 @@
+ libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \
+ libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \
+ libarchive/test/test_read_format_warc.warc.uu \
++ libarchive/test/test_read_format_warc_incomplete.warc.uu \
+ libarchive/test/test_read_format_xar_doublelink.xar.uu \
+ libarchive/test/test_read_format_zip.zip.uu \
+ libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu \
+--- a/libarchive/archive_read_support_format_warc.c
++++ b/libarchive/archive_read_support_format_warc.c
+@@ -386,7 +386,8 @@
+ case LAST_WT:
+ default:
+ /* consume the content and start over */
+- _warc_skip(a);
++ if (_warc_skip(a) < 0)
++ return (ARCHIVE_FATAL);
+ goto start_over;
+ }
+ return (ARCHIVE_OK);
+@@ -439,7 +440,9 @@
+ {
+ struct warc_s *w = a->format->data;
+
+- __archive_read_consume(a, w->cntlen + 4U/*\r\n\r\n separator*/);
++ if (__archive_read_consume(a, w->cntlen) < 0 ||
++ __archive_read_consume(a, 4U/*\r\n\r\n separator*/) < 0)
++ return (ARCHIVE_FATAL);
+ w->cntlen = 0U;
+ w->cntoff = 0U;
+ return (ARCHIVE_OK);
+--- a/libarchive/test/test_read_format_warc.c
++++ b/libarchive/test/test_read_format_warc.c
+@@ -78,3 +78,27 @@
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+ }
++
++DEFINE_TEST(test_read_format_warc_incomplete)
++{
++ const char reffile[] = "test_read_format_warc_incomplete.warc";
++ struct archive_entry *ae;
++ struct archive *a;
++
++ extract_reference_file(reffile);
++ assert((a = archive_read_new()) != NULL);
++ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
++ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
++ assertEqualIntA(a, ARCHIVE_OK,
++ archive_read_open_filename(a, reffile, 10240));
++
++ /* Entry cannot be parsed */
++ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
++
++ /* Verify archive format. */
++ assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
++
++ /* Verify closing and resource freeing */
++ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
++ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
++}
+--- /dev/null
++++ b/libarchive/test/test_read_format_warc_incomplete.warc.uu
+@@ -0,0 +1,10 @@
++begin 644 test_read_format_warc_incomplete.warc
++M5T%20R\Q+C`-"E=!4D,M5'EP93H@8V]N=F5R<VEO;@T*5T%20RU$871E.B`R
++M,#(U+3`S+3,P5#$U.C`P.C0P6@T*0V]N=&5N="U,96YG=&@Z(#DR,C,S-S(P
++M,S8X-30W-S4X,#<-"@T*5T%20R\Q+C`-"E=!4D,M5'EP93H@<F5S;W5R8V4-
++M"E=!4D,M5&%R9V5T+55223H@9FEL93HO+W)E861M92YT>'0-"E=!4D,M1&%T
++M93H@,C`R-2TP,RTS,%0Q-3HP,#HT,%H-"D-O;G1E;G0M5'EP93H@=&5X="]P
++M;&%I;@T*0V]N=&5N="U,96YG=&@Z(#,X#0H-"E1H92!R96%D;64N='AT('-H
++4;W5L9"!N;W0@8F4@=FES:6)L90H`
++`
++end
diff -Nru libarchive-3.7.4/debian/patches/CVE-2025-5917.patch libarchive-3.7.4/debian/patches/CVE-2025-5917.patch
--- libarchive-3.7.4/debian/patches/CVE-2025-5917.patch 1970-01-01 02:00:00.000000000 +0200
+++ libarchive-3.7.4/debian/patches/CVE-2025-5917.patch 2025-07-24 16:45:18.000000000 +0300
@@ -0,0 +1,40 @@
+Description: Fix overflow in build_ustar_entry (#2588)
+ The calculations for the suffix and prefix can increment the endpoint
+ for a trailing slash. Hence the limits used should be one lower than the
+ maximum number of bytes.
+ .
+ Without this patch, when this happens for both the prefix and the
+ suffix, we end up with 156 + 100 bytes, and the write of the null at the
+ end will overflow the 256 byte buffer. This can be reproduced by running
+ ```
+ mkdir -p foo/bar
+ bsdtar cvf test.tar foo////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////bar
+ ```
+ when bsdtar is compiled with Address Sanitiser, although I originally
+ noticed this by accident with a genuine filename on a CHERI capability
+ system, which faults immediately on the buffer overflow.
+Bug-Debian: https://bugs.debian.org/1107626
+Author: Brian Campbell <Brian.Campbell@ed.ac.uk>
+Origin: upstream, https://github.com/libarchive/libarchive/commit/7c02cde37a63580cd1859183fbbd2cf04a89be85
+Last-Update: 2025-07-24
+
+--- a/libarchive/archive_write_set_format_pax.c
++++ b/libarchive/archive_write_set_format_pax.c
+@@ -1555,7 +1555,7 @@
+ const char *filename, *filename_end;
+ char *p;
+ int need_slash = 0; /* Was there a trailing slash? */
+- size_t suffix_length = 99;
++ size_t suffix_length = 98; /* 99 - 1 for trailing slash */
+ size_t insert_length;
+
+ /* Length of additional dir element to be added. */
+@@ -1607,7 +1607,7 @@
+ /* Step 2: Locate the "prefix" section of the dirname, including
+ * trailing '/'. */
+ prefix = src;
+- prefix_end = prefix + 155;
++ prefix_end = prefix + 154 /* 155 - 1 for trailing / */;
+ if (prefix_end > filename)
+ prefix_end = filename;
+ while (prefix_end > prefix && *prefix_end != '/')
diff -Nru libarchive-3.7.4/debian/patches/series libarchive-3.7.4/debian/patches/series
--- libarchive-3.7.4/debian/patches/series 2025-04-27 23:12:26.000000000 +0300
+++ libarchive-3.7.4/debian/patches/series 2025-07-24 16:55:24.000000000 +0300
@@ -3,3 +3,7 @@
fix-OOB-in-rar-audio-filter-2149.patch
rar4-reader-protect-copy_from_lzss_window_to_unp-217.patch
CVE-2025-1632-25724.patch
+CVE-2025-5914.patch
+CVE-2025-5915.patch
+CVE-2025-5916.patch
+CVE-2025-5917.patch
Attachment:
signature.asc
Description: PGP signature