diff mbox series

[scarthgap,02/11] libarchive: fix CVE-2025-5915

Message ID 99fdc86ad57db4d8829a33033918cf78419977af.1751641631.git.steve@sakoman.com
State New
Headers show
Series [scarthgap,01/11] libarchive: fix CVE-2025-5914 | expand

Commit Message

Steve Sakoman July 4, 2025, 3:10 p.m. UTC
From: Divya Chellam <divya.chellam@windriver.com>

A vulnerability has been identified in the libarchive library. This flaw can lead to a heap b
uffer over-read due to the size of a filter block potentially exceeding the Lempel-Ziv-Storer
-Schieber (LZSS) window. This means the library may attempt to read beyond the allocated memo
ry buffer, which can result in unpredictable program behavior, crashes (denial of service), o
r the disclosure of sensitive information from adjacent memory regions.

Reference:
https://security-tracker.debian.org/tracker/CVE-2025-5915

Upstream-patches:
https://github.com/libarchive/libarchive/commit/a612bf62f86a6faa47bd57c52b94849f0a404d8c

Signed-off-by: Divya Chellam <divya.chellam@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
---
 .../libarchive/libarchive/CVE-2025-5915.patch | 217 ++++++++++++++++++
 .../libarchive/libarchive_3.7.9.bb            |   1 +
 2 files changed, 218 insertions(+)
 create mode 100644 meta/recipes-extended/libarchive/libarchive/CVE-2025-5915.patch
diff mbox series

Patch

diff --git a/meta/recipes-extended/libarchive/libarchive/CVE-2025-5915.patch b/meta/recipes-extended/libarchive/libarchive/CVE-2025-5915.patch
new file mode 100644
index 0000000000..3c911ce9d9
--- /dev/null
+++ b/meta/recipes-extended/libarchive/libarchive/CVE-2025-5915.patch
@@ -0,0 +1,217 @@ 
+From a612bf62f86a6faa47bd57c52b94849f0a404d8c Mon Sep 17 00:00:00 2001
+From: Tobias Stoeckmann <stoeckmann@users.noreply.github.com>
+Date: Sun, 11 May 2025 19:00:11 +0200
+Subject: [PATCH] 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
+
+---------
+
+Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
+Co-authored-by: Tim Kientzle <kientzle@acm.org>
+
+CVE: CVE-2025-5915
+
+Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/a612bf62f86a6faa47bd57c52b94849f0a404d8c]
+
+Signed-off-by: Divya Chellam <divya.chellam@windriver.com>
+---
+ Makefile.am                                   |  2 +
+ libarchive/archive_read_support_format_rar.c  | 17 ++++---
+ libarchive/test/CMakeLists.txt                |  1 +
+ .../test/test_read_format_rar_overflow.c      | 48 +++++++++++++++++++
+ .../test/test_read_format_rar_overflow.rar.uu | 11 +++++
+ 5 files changed, 72 insertions(+), 7 deletions(-)
+ create mode 100644 libarchive/test/test_read_format_rar_overflow.c
+ create mode 100644 libarchive/test/test_read_format_rar_overflow.rar.uu
+
+diff --git a/Makefile.am b/Makefile.am
+index 4fafc41..9f3a6d1 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -519,6 +519,7 @@ libarchive_test_SOURCES= \
+ 	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 \
+@@ -889,6 +890,7 @@ libarchive_test_EXTRA_DIST=\
+ 	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 \
+diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
+index 9eb3c84..88eab62 100644
+--- a/libarchive/archive_read_support_format_rar.c
++++ b/libarchive/archive_read_support_format_rar.c
+@@ -451,7 +451,7 @@ static int read_filter(struct archive_read *, int64_t *);
+ 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);
+ 
+@@ -2929,7 +2929,7 @@ expand(struct archive_read *a, int64_t *end)
+     }
+ 
+     if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
+-      return (ARCHIVE_FATAL);
++      goto bad_data;
+ 
+     if (symbol < 256)
+     {
+@@ -2956,14 +2956,14 @@ expand(struct archive_read *a, int64_t *end)
+       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)
+@@ -3048,7 +3048,7 @@ expand(struct archive_read *a, int64_t *end)
+           {
+             if ((lowoffsetsymbol =
+               read_next_symbol(a, &rar->lowoffsetcode)) < 0)
+-              return (ARCHIVE_FATAL);
++              goto bad_data;
+             if(lowoffsetsymbol == 16)
+             {
+               rar->numlowoffsetrepeats = 15;
+@@ -3096,7 +3096,7 @@ bad_data:
+ }
+ 
+ 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;
+@@ -3111,7 +3111,7 @@ copy_from_lzss_window(struct archive_read *a, void *buffer,
+   }
+   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);
+   }
+@@ -3266,6 +3266,9 @@ parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint
+   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;
+diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt
+index 5d7a5d2..59c5f5d 100644
+--- a/libarchive/test/CMakeLists.txt
++++ b/libarchive/test/CMakeLists.txt
+@@ -163,6 +163,7 @@ IF(ENABLE_TEST)
+     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
+diff --git a/libarchive/test/test_read_format_rar_overflow.c b/libarchive/test/test_read_format_rar_overflow.c
+new file mode 100644
+index 0000000..b39ed6b
+--- /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));
++}
+diff --git a/libarchive/test/test_read_format_rar_overflow.rar.uu b/libarchive/test/test_read_format_rar_overflow.rar.uu
+new file mode 100644
+index 0000000..48fd3fd
+--- /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
+-- 
+2.40.0
+
diff --git a/meta/recipes-extended/libarchive/libarchive_3.7.9.bb b/meta/recipes-extended/libarchive/libarchive_3.7.9.bb
index c26a14e32e..42c91e641e 100644
--- a/meta/recipes-extended/libarchive/libarchive_3.7.9.bb
+++ b/meta/recipes-extended/libarchive/libarchive_3.7.9.bb
@@ -32,6 +32,7 @@  EXTRA_OECONF += "--enable-largefile --without-iconv"
 SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz \
            file://configurehack.patch \
            file://CVE-2025-5914.patch \
+           file://CVE-2025-5915.patch \
            "
 UPSTREAM_CHECK_URI = "http://libarchive.org/"