diff options
author | Samuel Sapalski <samuel.sapalski@nokia.com> | 2021-03-03 16:31:22 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-03-12 10:45:10 +0100 |
commit | f25d254dfd4243698c31a4f3153d4ac72aa9e9bd (patch) | |
tree | 0d4f56adcaf9880ba2189f88a291cefd2ec93117 /archival/libarchive | |
parent | cbfdeba6609b702432886ecf3e2786818a2bc55b (diff) | |
download | busybox-w32-f25d254dfd4243698c31a4f3153d4ac72aa9e9bd.tar.gz busybox-w32-f25d254dfd4243698c31a4f3153d4ac72aa9e9bd.tar.bz2 busybox-w32-f25d254dfd4243698c31a4f3153d4ac72aa9e9bd.zip |
decompress_gunzip: Fix DoS if gzip is corrupt
On certain corrupt gzip files, huft_build will set the error bit on
the result pointer. If afterwards abort_unzip is called huft_free
might run into a segmentation fault or an invalid pointer to
free(p).
In order to mitigate this, we check in huft_free if the error bit
is set and clear it before the linked list is freed.
Signed-off-by: Samuel Sapalski <samuel.sapalski@nokia.com>
Signed-off-by: Peter Kaestle <peter.kaestle@nokia.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'archival/libarchive')
-rw-r--r-- | archival/libarchive/decompress_gunzip.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index eb3b64930..e93cd5005 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c | |||
@@ -220,10 +220,20 @@ static const uint8_t border[] ALIGN1 = { | |||
220 | * each table. | 220 | * each table. |
221 | * t: table to free | 221 | * t: table to free |
222 | */ | 222 | */ |
223 | #define BAD_HUFT(p) ((uintptr_t)(p) & 1) | ||
224 | #define ERR_RET ((huft_t*)(uintptr_t)1) | ||
223 | static void huft_free(huft_t *p) | 225 | static void huft_free(huft_t *p) |
224 | { | 226 | { |
225 | huft_t *q; | 227 | huft_t *q; |
226 | 228 | ||
229 | /* | ||
230 | * If 'p' has the error bit set we have to clear it, otherwise we might run | ||
231 | * into a segmentation fault or an invalid pointer to free(p) | ||
232 | */ | ||
233 | if (BAD_HUFT(p)) { | ||
234 | p = (huft_t*)((uintptr_t)(p) ^ (uintptr_t)(ERR_RET)); | ||
235 | } | ||
236 | |||
227 | /* Go through linked list, freeing from the malloced (t[-1]) address. */ | 237 | /* Go through linked list, freeing from the malloced (t[-1]) address. */ |
228 | while (p) { | 238 | while (p) { |
229 | q = (--p)->v.t; | 239 | q = (--p)->v.t; |
@@ -289,8 +299,6 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current | |||
289 | * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table | 299 | * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table |
290 | * is given: "fixed inflate" decoder feeds us such data. | 300 | * is given: "fixed inflate" decoder feeds us such data. |
291 | */ | 301 | */ |
292 | #define BAD_HUFT(p) ((uintptr_t)(p) & 1) | ||
293 | #define ERR_RET ((huft_t*)(uintptr_t)1) | ||
294 | static huft_t* huft_build(const unsigned *b, const unsigned n, | 302 | static huft_t* huft_build(const unsigned *b, const unsigned n, |
295 | const unsigned s, const struct cp_ext *cp_ext, | 303 | const unsigned s, const struct cp_ext *cp_ext, |
296 | unsigned *m) | 304 | unsigned *m) |