[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1109830: unblock: libarchive/3.7.4-4



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


Reply to: