package/xz: add patch for GHSA-5qpq-xqfv-j9pg

This fixes the following vulnerability:
XZ Utils: Invalid write if a decoder is reinitialized after allocation failure
See https://github.com/tukaani-project/xz/security/advisories/GHSA-5qpq-xqfv-j9pg

There is still no CVE number assigned to the issue.

(alternative to commit 6f125a6530)
Signed-off-by: Titouan Christophe <titouan.christophe@mind.be>
Signed-off-by: Thomas Perale <thomas.perale@mind.be>
This commit is contained in:
Titouan Christophe
2026-09-14 16:14:16 +02:00
committed by Thomas Perale
parent 110d3ecb81
commit 0fe3e2e604
2 changed files with 128 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
From: Lasse Collin <lasse.collin@tukaani.org>
Date: Wed, 9 Sep 2026 14:14:40 +0300
Subject: liblzma: Make lzma_lz_decoder_init() safe to reinit after alloc failure
If memory allocation fails and the resulting coder state is reused,
ensure that memory allocation is attempted again. However, coders that
are initialized via lzma_next_filter_init() shouldn't be reinitialized
after failure; they should be cleaned up with lzma_next_end().
Reported-by: GitHub user christos-cantina-security (christos-spearbit)
(cherry picked from commit fe4d763d566a38ad61d4c5022520c25578a3a464)
---
Upstream: https://github.com/tukaani-project/xz/commit/0917f6d0f03d9add15dda27e0bf2ebfc22aaf67a
Signed-off-by: Titouan Christophe <titouan.christophe@mind.be>
---
src/liblzma/lz/lz_decoder.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/liblzma/lz/lz_decoder.c b/src/liblzma/lz/lz_decoder.c
index 92913f225..18669300e 100644
--- a/src/liblzma/lz/lz_decoder.c
+++ b/src/liblzma/lz/lz_decoder.c
@@ -276,6 +276,7 @@ lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
// Allocate and initialize the dictionary.
if (coder->dict.size != alloc_size) {
+ coder->dict.size = 0;
lzma_free(coder->dict.buf, allocator);
coder->dict.buf = lzma_alloc(alloc_size, allocator);
if (coder->dict.buf == NULL)

View File

@@ -0,0 +1,97 @@
From: Lasse Collin <lasse.collin@tukaani.org>
Date: Wed, 9 Sep 2026 14:14:40 +0300
Subject: liblzma: Clean up after a filter chain initialization error
Filter coders are initialized using lzma_next_filter_init(). If filter
chain initialization fails, the entire filter chain should be cleaned up
with lzma_next_end(). lzma_raw_encoder_init() and lzma_raw_decoder_init()
have always done this via lzma_raw_coder_init() in filter_common.c.
(Separate cleanup is weird, but it must have made sense to the young me.)
The following decoders initialize LZMA1 filter directly without using the
raw filter chain API. This avoids needlessly pulling in all other filters
when a program is linked against static liblzma. These functions didn't
call lzma_next_end() after an initialization error, which left the state
available for later reinitialization.
- lzma_alone_decoder()
- lzma_lzip_decoder()
- lzma_auto_decoder() [*]
- lzma_microlzma_decoder()
[*] lzma_auto_decoder() is only indirectly affected due to the first two
functions. lzma_auto_decoder() itself doesn't need a fix.
There are also encoder functions that initialize the LZMA1 encoder
directly. They don't have this issue because the whole lzma_stream
is cleaned up when encoder initialization fails.
Reported-by: GitHub user christos-cantina-security (christos-spearbit)
(cherry picked from commit e5e63d50eac1b4357a5a7a0abd3c5f99a5c47881)
---
Upstream: https://github.com/tukaani-project/xz/commit/0130b7524227d0bb9f405ecaf0af632a767fa735
Signed-off-by: Titouan Christophe <titouan.christophe@mind.be>
---
src/liblzma/common/alone_decoder.c | 8 ++++++--
src/liblzma/common/lzip_decoder.c | 8 ++++++--
src/liblzma/common/microlzma_decoder.c | 8 ++++++--
3 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/src/liblzma/common/alone_decoder.c b/src/liblzma/common/alone_decoder.c
index 78af65157..b2b049b5c 100644
--- a/src/liblzma/common/alone_decoder.c
+++ b/src/liblzma/common/alone_decoder.c
@@ -151,8 +151,12 @@ alone_decode(void *coder_ptr, const lzma_allocator *allocator,
}
};
- return_if_error(lzma_next_filter_init(&coder->next,
- allocator, filters));
+ const lzma_ret ret = lzma_next_filter_init(&coder->next,
+ allocator, filters);
+ if (ret != LZMA_OK) {
+ lzma_next_end(&coder->next, allocator);
+ return ret;
+ }
coder->sequence = SEQ_CODE;
break;
diff --git a/src/liblzma/common/lzip_decoder.c b/src/liblzma/common/lzip_decoder.c
index 651a0ae71..30c50286d 100644
--- a/src/liblzma/common/lzip_decoder.c
+++ b/src/liblzma/common/lzip_decoder.c
@@ -238,8 +238,12 @@ lzip_decode(void *coder_ptr, const lzma_allocator *allocator,
}
};
- return_if_error(lzma_next_filter_init(&coder->lzma_decoder,
- allocator, filters));
+ const lzma_ret ret = lzma_next_filter_init(
+ &coder->lzma_decoder, allocator, filters);
+ if (ret != LZMA_OK) {
+ lzma_next_end(&coder->lzma_decoder, allocator);
+ return ret;
+ }
coder->crc32 = 0;
coder->sequence = SEQ_LZMA_STREAM;
diff --git a/src/liblzma/common/microlzma_decoder.c b/src/liblzma/common/microlzma_decoder.c
index 882cb2c80..a7720cc2a 100644
--- a/src/liblzma/common/microlzma_decoder.c
+++ b/src/liblzma/common/microlzma_decoder.c
@@ -108,8 +108,12 @@ microlzma_decode(void *coder_ptr, const lzma_allocator *allocator,
}
};
- return_if_error(lzma_next_filter_init(&coder->lzma,
- allocator, filters));
+ const lzma_ret ret = lzma_next_filter_init(&coder->lzma,
+ allocator, filters);
+ if (ret != LZMA_OK) {
+ lzma_next_end(&coder->lzma, allocator);
+ return ret;
+ }
// Pass one dummy 0x00 byte to the LZMA decoder since that
// is what it expects the first byte to be.