Version in base suite: 3.6.2-1+deb12u1 Base version: libarchive_3.6.2-1+deb12u1 Target version: libarchive_3.6.2-1+deb12u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/liba/libarchive/libarchive_3.6.2-1+deb12u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/liba/libarchive/libarchive_3.6.2-1+deb12u2.dsc changelog | 8 patches/rar4-reader-protect-copy_from_lzss_window_to_unp-217.patch | 122 ++++++++++ patches/series | 1 3 files changed, 131 insertions(+) diff -Nru libarchive-3.6.2/debian/changelog libarchive-3.6.2/debian/changelog --- libarchive-3.6.2/debian/changelog 2024-06-02 14:38:00.000000000 +0000 +++ libarchive-3.6.2/debian/changelog 2024-11-03 12:30:44.000000000 +0000 @@ -1,3 +1,11 @@ +libarchive (3.6.2-1+deb12u2) bookworm-security; urgency=high + + * Non-maintainer upload by the Security Team. + * rar4 reader: protect copy_from_lzss_window_to_unp() (CVE-2024-20696) + (Closes: #1086155) + + -- Salvatore Bonaccorso Sun, 03 Nov 2024 13:30:44 +0100 + libarchive (3.6.2-1+deb12u1) bookworm-security; urgency=high [ Peter Pentchev ] diff -Nru libarchive-3.6.2/debian/patches/rar4-reader-protect-copy_from_lzss_window_to_unp-217.patch libarchive-3.6.2/debian/patches/rar4-reader-protect-copy_from_lzss_window_to_unp-217.patch --- libarchive-3.6.2/debian/patches/rar4-reader-protect-copy_from_lzss_window_to_unp-217.patch 1970-01-01 00:00:00.000000000 +0000 +++ libarchive-3.6.2/debian/patches/rar4-reader-protect-copy_from_lzss_window_to_unp-217.patch 2024-11-03 12:30:44.000000000 +0000 @@ -0,0 +1,122 @@ +From: "Dustin L. Howett" +Date: Thu, 9 May 2024 18:59:17 -0500 +Subject: rar4 reader: protect copy_from_lzss_window_to_unp() (#2172) +Origin: https://github.com/libarchive/libarchive/commit/eac15e252010c1189a5c0f461364dbe2cd2a68b1 +Bug: https://github.com/libarchive/libarchive/pull/2172 +Bug-Debian: https://bugs.debian.org/1086155 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2024-20696 + +copy_from_lzss_window_to_unp unnecessarily took an `int` parameter where +both of its callers were holding a `size_t`. + +A lzss opcode chain could be constructed that resulted in a negative +copy length, which when passed into memcpy would result in a very, very +large positive number. + +Switching copy_from_lzss_window_to_unp to take a `size_t` allows it to +properly bounds-check length. + +In addition, this patch also ensures that `length` is not itself larger +than the destination buffer. + +Security: CVE-2024-20696 +--- + libarchive/archive_read_support_format_rar.c | 28 +++++++++++++------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c +index 4fc6626cacfd..5776df4bd944 100644 +--- a/libarchive/archive_read_support_format_rar.c ++++ b/libarchive/archive_read_support_format_rar.c +@@ -432,7 +432,7 @@ static int make_table_recurse(struct archive_read *, struct huffman_code *, int, + struct huffman_table_entry *, int, int); + static int expand(struct archive_read *, int64_t *); + static int copy_from_lzss_window_to_unp(struct archive_read *, const void **, +- int64_t, int); ++ int64_t, size_t); + static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *); + static int parse_filter(struct archive_read *, const uint8_t *, uint16_t, + uint8_t); +@@ -2060,7 +2060,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, + bs = rar->unp_buffer_size - rar->unp_offset; + else + bs = (size_t)rar->bytes_uncopied; +- ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, (int)bs); ++ ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, bs); + if (ret != ARCHIVE_OK) + return (ret); + rar->offset += bs; +@@ -2213,7 +2213,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, + bs = rar->unp_buffer_size - rar->unp_offset; + else + bs = (size_t)rar->bytes_uncopied; +- ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, (int)bs); ++ ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, bs); + if (ret != ARCHIVE_OK) + return (ret); + rar->offset += bs; +@@ -3094,11 +3094,16 @@ copy_from_lzss_window(struct archive_read *a, void *buffer, + + static int + copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, +- int64_t startpos, int length) ++ int64_t startpos, size_t length) + { + int windowoffs, firstpart; + struct rar *rar = (struct rar *)(a->format->data); + ++ if (length > rar->unp_buffer_size) ++ { ++ goto fatal; ++ } ++ + if (!rar->unp_buffer) + { + if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL) +@@ -3110,17 +3115,17 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, + } + + windowoffs = lzss_offset_for_position(&rar->lzss, startpos); +- if(windowoffs + length <= lzss_size(&rar->lzss)) { ++ if(windowoffs + length <= (size_t)lzss_size(&rar->lzss)) { + memcpy(&rar->unp_buffer[rar->unp_offset], &rar->lzss.window[windowoffs], + length); +- } else if (length <= lzss_size(&rar->lzss)) { ++ } else if (length <= (size_t)lzss_size(&rar->lzss)) { + firstpart = lzss_size(&rar->lzss) - windowoffs; + if (firstpart < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file data"); + return (ARCHIVE_FATAL); + } +- if (firstpart < length) { ++ if ((size_t)firstpart < length) { + memcpy(&rar->unp_buffer[rar->unp_offset], + &rar->lzss.window[windowoffs], firstpart); + memcpy(&rar->unp_buffer[rar->unp_offset + firstpart], +@@ -3130,9 +3135,7 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, + &rar->lzss.window[windowoffs], length); + } + } else { +- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, +- "Bad RAR file data"); +- return (ARCHIVE_FATAL); ++ goto fatal; + } + rar->unp_offset += length; + if (rar->unp_offset >= rar->unp_buffer_size) +@@ -3140,6 +3143,11 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, + else + *buffer = NULL; + return (ARCHIVE_OK); ++ ++fatal: ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Bad RAR file data"); ++ return (ARCHIVE_FATAL); + } + + static const void * +-- +2.45.2 + diff -Nru libarchive-3.6.2/debian/patches/series libarchive-3.6.2/debian/patches/series --- libarchive-3.6.2/debian/patches/series 2024-06-02 14:38:00.000000000 +0000 +++ libarchive-3.6.2/debian/patches/series 2024-11-03 12:30:44.000000000 +0000 @@ -4,3 +4,4 @@ fix-OOB-in-rar-e8-filter-2135.patch fix-OOB-in-rar-delta-filter-2148.patch fix-OOB-in-rar-audio-filter-2149.patch +rar4-reader-protect-copy_from_lzss_window_to_unp-217.patch