Andrew Geissler | c926e17 | 2021-05-07 16:11:35 -0500 | [diff] [blame^] | 1 | From fe791386ebc270219ca00406c9fdadc5130b64ee Mon Sep 17 00:00:00 2001 |
| 2 | From: Samuel Sapalski <samuel.sapalski@nokia.com> |
| 3 | Date: Wed, 3 Mar 2021 16:31:22 +0100 |
| 4 | Subject: [PATCH] decompress_gunzip: Fix DoS if gzip is corrupt |
| 5 | |
| 6 | On certain corrupt gzip files, huft_build will set the error bit on |
| 7 | the result pointer. If afterwards abort_unzip is called huft_free |
| 8 | might run into a segmentation fault or an invalid pointer to |
| 9 | free(p). |
| 10 | |
| 11 | In order to mitigate this, we check in huft_free if the error bit |
| 12 | is set and clear it before the linked list is freed. |
| 13 | |
| 14 | Signed-off-by: Samuel Sapalski <samuel.sapalski@nokia.com> |
| 15 | Signed-off-by: Peter Kaestle <peter.kaestle@nokia.com> |
| 16 | Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> |
| 17 | |
| 18 | Upstream-Status: Backport |
| 19 | CVE: CVE-2021-28831 |
| 20 | Signed-off-by: Chen Qi <Qi.Chen@windriver.com> |
| 21 | --- |
| 22 | archival/libarchive/decompress_gunzip.c | 12 ++++++++++-- |
| 23 | 1 file changed, 10 insertions(+), 2 deletions(-) |
| 24 | |
| 25 | diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c |
| 26 | index eb3b64930..e93cd5005 100644 |
| 27 | --- a/archival/libarchive/decompress_gunzip.c |
| 28 | +++ b/archival/libarchive/decompress_gunzip.c |
| 29 | @@ -220,10 +220,20 @@ static const uint8_t border[] ALIGN1 = { |
| 30 | * each table. |
| 31 | * t: table to free |
| 32 | */ |
| 33 | +#define BAD_HUFT(p) ((uintptr_t)(p) & 1) |
| 34 | +#define ERR_RET ((huft_t*)(uintptr_t)1) |
| 35 | static void huft_free(huft_t *p) |
| 36 | { |
| 37 | huft_t *q; |
| 38 | |
| 39 | + /* |
| 40 | + * If 'p' has the error bit set we have to clear it, otherwise we might run |
| 41 | + * into a segmentation fault or an invalid pointer to free(p) |
| 42 | + */ |
| 43 | + if (BAD_HUFT(p)) { |
| 44 | + p = (huft_t*)((uintptr_t)(p) ^ (uintptr_t)(ERR_RET)); |
| 45 | + } |
| 46 | + |
| 47 | /* Go through linked list, freeing from the malloced (t[-1]) address. */ |
| 48 | while (p) { |
| 49 | q = (--p)->v.t; |
| 50 | @@ -289,8 +299,6 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current |
| 51 | * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table |
| 52 | * is given: "fixed inflate" decoder feeds us such data. |
| 53 | */ |
| 54 | -#define BAD_HUFT(p) ((uintptr_t)(p) & 1) |
| 55 | -#define ERR_RET ((huft_t*)(uintptr_t)1) |
| 56 | static huft_t* huft_build(const unsigned *b, const unsigned n, |
| 57 | const unsigned s, const struct cp_ext *cp_ext, |
| 58 | unsigned *m) |