diff options
| author | Virendra Thakur <virendra.thakur@kpit.com> | 2022-02-24 20:41:59 +0530 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-03-09 17:30:48 +0000 |
| commit | 6bba192936c25702316589ca59403daa1bf574da (patch) | |
| tree | 764f551fcb2b865b1a8843008125639a7aebfdf6 | |
| parent | 9426c3c83d2a06ae3941d833b76d58ad04e2a294 (diff) | |
| download | poky-6bba192936c25702316589ca59403daa1bf574da.tar.gz | |
libarchive: Fix for CVE-2021-36976
Add patch to fix CVE-2021-36976
CVE-2021-36976 fix are provided by below mentioned pull request.
1) https://github.com/libarchive/libarchive/pull/1491
2) https://github.com/libarchive/libarchive/pull/1492
3) https://github.com/libarchive/libarchive/pull/1493
(From OE-Core rev: 6c356aec8dabc08bd98da3106780896dc7b52501)
Signed-off-by: Virendra Thakur <virendra.thakur@kpit.com>
Signed-off-by: virendra thakur <thakur.virendra1810@gmail.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
4 files changed, 540 insertions, 1 deletions
diff --git a/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-1.patch b/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-1.patch new file mode 100644 index 0000000000..fca53fc9b6 --- /dev/null +++ b/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-1.patch | |||
| @@ -0,0 +1,321 @@ | |||
| 1 | From 05ebb55896d10a9737dad9ae0303f7f45489ba6f Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Grzegorz Antoniak <ga@anadoxin.org> | ||
| 3 | Date: Sat, 13 Feb 2021 09:08:13 +0100 | ||
| 4 | Subject: [PATCH] RAR5 reader: fixed out of bounds read in some files | ||
| 5 | |||
| 6 | Added more range checks in the bit stream reading functions | ||
| 7 | (read_bits_16 and read_bits_32) in order to better guard against out of | ||
| 8 | memory reads. | ||
| 9 | |||
| 10 | This commit contains a test with OSSFuzz sample #30448. | ||
| 11 | |||
| 12 | Upstream-Status: Backport [https://git.launchpad.net/ubuntu/+source/libarchive/plain/debian/patches/CVE-2021-36976-1.patch?h=applied/3.4.3-2ubuntu0.1] | ||
| 13 | CVE: CVE-2021-36976 | ||
| 14 | Signed-off-by: Virendra Thakur <virendra.thakur@kpit.com> | ||
| 15 | --- | ||
| 16 | Makefile.am | 1 + | ||
| 17 | libarchive/archive_read_support_format_rar5.c | 108 ++++++++++-------- | ||
| 18 | libarchive/test/test_read_format_rar5.c | 16 +++ | ||
| 19 | ...r5_decode_number_out_of_bounds_read.rar.uu | 10 ++ | ||
| 20 | 4 files changed, 89 insertions(+), 46 deletions(-) | ||
| 21 | create mode 100644 libarchive/test/test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu | ||
| 22 | |||
| 23 | --- a/Makefile.am | ||
| 24 | +++ b/Makefile.am | ||
| 25 | @@ -883,6 +883,7 @@ libarchive_test_EXTRA_DIST=\ | ||
| 26 | libarchive/test/test_read_format_rar5_arm_filter_on_window_boundary.rar.uu \ | ||
| 27 | libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu \ | ||
| 28 | libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \ | ||
| 29 | + libarchive/test/test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu \ | ||
| 30 | libarchive/test/test_read_format_raw.bufr.uu \ | ||
| 31 | libarchive/test/test_read_format_raw.data.gz.uu \ | ||
| 32 | libarchive/test/test_read_format_raw.data.Z.uu \ | ||
| 33 | --- a/libarchive/archive_read_support_format_rar5.c | ||
| 34 | +++ b/libarchive/archive_read_support_format_rar5.c | ||
| 35 | @@ -1012,7 +1012,16 @@ static int read_var_sized(struct archive | ||
| 36 | return ret; | ||
| 37 | } | ||
| 38 | |||
| 39 | -static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) { | ||
| 40 | +static int read_bits_32(struct archive_read* a, struct rar5* rar, | ||
| 41 | + const uint8_t* p, uint32_t* value) | ||
| 42 | +{ | ||
| 43 | + if(rar->bits.in_addr >= rar->cstate.cur_block_size) { | ||
| 44 | + archive_set_error(&a->archive, | ||
| 45 | + ARCHIVE_ERRNO_PROGRAMMER, | ||
| 46 | + "Premature end of stream during extraction of data (#1)"); | ||
| 47 | + return ARCHIVE_FATAL; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24; | ||
| 51 | bits |= p[rar->bits.in_addr + 1] << 16; | ||
| 52 | bits |= p[rar->bits.in_addr + 2] << 8; | ||
| 53 | @@ -1023,7 +1032,16 @@ static int read_bits_32(struct rar5* rar | ||
| 54 | return ARCHIVE_OK; | ||
| 55 | } | ||
| 56 | |||
| 57 | -static int read_bits_16(struct rar5* rar, const uint8_t* p, uint16_t* value) { | ||
| 58 | +static int read_bits_16(struct archive_read* a, struct rar5* rar, | ||
| 59 | + const uint8_t* p, uint16_t* value) | ||
| 60 | +{ | ||
| 61 | + if(rar->bits.in_addr >= rar->cstate.cur_block_size) { | ||
| 62 | + archive_set_error(&a->archive, | ||
| 63 | + ARCHIVE_ERRNO_PROGRAMMER, | ||
| 64 | + "Premature end of stream during extraction of data (#2)"); | ||
| 65 | + return ARCHIVE_FATAL; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16; | ||
| 69 | bits |= (int) p[rar->bits.in_addr + 1] << 8; | ||
| 70 | bits |= (int) p[rar->bits.in_addr + 2]; | ||
| 71 | @@ -1039,8 +1057,8 @@ static void skip_bits(struct rar5* rar, | ||
| 72 | } | ||
| 73 | |||
| 74 | /* n = up to 16 */ | ||
| 75 | -static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n, | ||
| 76 | - int* value) | ||
| 77 | +static int read_consume_bits(struct archive_read* a, struct rar5* rar, | ||
| 78 | + const uint8_t* p, int n, int* value) | ||
| 79 | { | ||
| 80 | uint16_t v; | ||
| 81 | int ret, num; | ||
| 82 | @@ -1051,7 +1069,7 @@ static int read_consume_bits(struct rar5 | ||
| 83 | return ARCHIVE_FATAL; | ||
| 84 | } | ||
| 85 | |||
| 86 | - ret = read_bits_16(rar, p, &v); | ||
| 87 | + ret = read_bits_16(a, rar, p, &v); | ||
| 88 | if(ret != ARCHIVE_OK) | ||
| 89 | return ret; | ||
| 90 | |||
| 91 | @@ -2425,13 +2443,13 @@ static int create_decode_tables(uint8_t* | ||
| 92 | static int decode_number(struct archive_read* a, struct decode_table* table, | ||
| 93 | const uint8_t* p, uint16_t* num) | ||
| 94 | { | ||
| 95 | - int i, bits, dist; | ||
| 96 | + int i, bits, dist, ret; | ||
| 97 | uint16_t bitfield; | ||
| 98 | uint32_t pos; | ||
| 99 | struct rar5* rar = get_context(a); | ||
| 100 | |||
| 101 | - if(ARCHIVE_OK != read_bits_16(rar, p, &bitfield)) { | ||
| 102 | - return ARCHIVE_EOF; | ||
| 103 | + if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &bitfield))) { | ||
| 104 | + return ret; | ||
| 105 | } | ||
| 106 | |||
| 107 | bitfield &= 0xfffe; | ||
| 108 | @@ -2537,14 +2555,6 @@ static int parse_tables(struct archive_r | ||
| 109 | for(i = 0; i < HUFF_TABLE_SIZE;) { | ||
| 110 | uint16_t num; | ||
| 111 | |||
| 112 | - if((rar->bits.in_addr + 6) >= rar->cstate.cur_block_size) { | ||
| 113 | - /* Truncated data, can't continue. */ | ||
| 114 | - archive_set_error(&a->archive, | ||
| 115 | - ARCHIVE_ERRNO_FILE_FORMAT, | ||
| 116 | - "Truncated data in huffman tables (#2)"); | ||
| 117 | - return ARCHIVE_FATAL; | ||
| 118 | - } | ||
| 119 | - | ||
| 120 | ret = decode_number(a, &rar->cstate.bd, p, &num); | ||
| 121 | if(ret != ARCHIVE_OK) { | ||
| 122 | archive_set_error(&a->archive, | ||
| 123 | @@ -2561,8 +2571,8 @@ static int parse_tables(struct archive_r | ||
| 124 | /* 16..17: repeat previous code */ | ||
| 125 | uint16_t n; | ||
| 126 | |||
| 127 | - if(ARCHIVE_OK != read_bits_16(rar, p, &n)) | ||
| 128 | - return ARCHIVE_EOF; | ||
| 129 | + if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n))) | ||
| 130 | + return ret; | ||
| 131 | |||
| 132 | if(num == 16) { | ||
| 133 | n >>= 13; | ||
| 134 | @@ -2590,8 +2600,8 @@ static int parse_tables(struct archive_r | ||
| 135 | /* other codes: fill with zeroes `n` times */ | ||
| 136 | uint16_t n; | ||
| 137 | |||
| 138 | - if(ARCHIVE_OK != read_bits_16(rar, p, &n)) | ||
| 139 | - return ARCHIVE_EOF; | ||
| 140 | + if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n))) | ||
| 141 | + return ret; | ||
| 142 | |||
| 143 | if(num == 18) { | ||
| 144 | n >>= 13; | ||
| 145 | @@ -2707,22 +2717,22 @@ static int parse_block_header(struct arc | ||
| 146 | } | ||
| 147 | |||
| 148 | /* Convenience function used during filter processing. */ | ||
| 149 | -static int parse_filter_data(struct rar5* rar, const uint8_t* p, | ||
| 150 | - uint32_t* filter_data) | ||
| 151 | +static int parse_filter_data(struct archive_read* a, struct rar5* rar, | ||
| 152 | + const uint8_t* p, uint32_t* filter_data) | ||
| 153 | { | ||
| 154 | - int i, bytes; | ||
| 155 | + int i, bytes, ret; | ||
| 156 | uint32_t data = 0; | ||
| 157 | |||
| 158 | - if(ARCHIVE_OK != read_consume_bits(rar, p, 2, &bytes)) | ||
| 159 | - return ARCHIVE_EOF; | ||
| 160 | + if(ARCHIVE_OK != (ret = read_consume_bits(a, rar, p, 2, &bytes))) | ||
| 161 | + return ret; | ||
| 162 | |||
| 163 | bytes++; | ||
| 164 | |||
| 165 | for(i = 0; i < bytes; i++) { | ||
| 166 | uint16_t byte; | ||
| 167 | |||
| 168 | - if(ARCHIVE_OK != read_bits_16(rar, p, &byte)) { | ||
| 169 | - return ARCHIVE_EOF; | ||
| 170 | + if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &byte))) { | ||
| 171 | + return ret; | ||
| 172 | } | ||
| 173 | |||
| 174 | /* Cast to uint32_t will ensure the shift operation will not | ||
| 175 | @@ -2765,16 +2775,17 @@ static int parse_filter(struct archive_r | ||
| 176 | uint16_t filter_type; | ||
| 177 | struct filter_info* filt = NULL; | ||
| 178 | struct rar5* rar = get_context(ar); | ||
| 179 | + int ret; | ||
| 180 | |||
| 181 | /* Read the parameters from the input stream. */ | ||
| 182 | - if(ARCHIVE_OK != parse_filter_data(rar, p, &block_start)) | ||
| 183 | - return ARCHIVE_EOF; | ||
| 184 | + if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_start))) | ||
| 185 | + return ret; | ||
| 186 | |||
| 187 | - if(ARCHIVE_OK != parse_filter_data(rar, p, &block_length)) | ||
| 188 | - return ARCHIVE_EOF; | ||
| 189 | + if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_length))) | ||
| 190 | + return ret; | ||
| 191 | |||
| 192 | - if(ARCHIVE_OK != read_bits_16(rar, p, &filter_type)) | ||
| 193 | - return ARCHIVE_EOF; | ||
| 194 | + if(ARCHIVE_OK != (ret = read_bits_16(ar, rar, p, &filter_type))) | ||
| 195 | + return ret; | ||
| 196 | |||
| 197 | filter_type >>= 13; | ||
| 198 | skip_bits(rar, 3); | ||
| 199 | @@ -2814,8 +2825,8 @@ static int parse_filter(struct archive_r | ||
| 200 | if(filter_type == FILTER_DELTA) { | ||
| 201 | int channels; | ||
| 202 | |||
| 203 | - if(ARCHIVE_OK != read_consume_bits(rar, p, 5, &channels)) | ||
| 204 | - return ARCHIVE_EOF; | ||
| 205 | + if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels))) | ||
| 206 | + return ret; | ||
| 207 | |||
| 208 | filt->channels = channels + 1; | ||
| 209 | } | ||
| 210 | @@ -2823,10 +2834,11 @@ static int parse_filter(struct archive_r | ||
| 211 | return ARCHIVE_OK; | ||
| 212 | } | ||
| 213 | |||
| 214 | -static int decode_code_length(struct rar5* rar, const uint8_t* p, | ||
| 215 | - uint16_t code) | ||
| 216 | +static int decode_code_length(struct archive_read* a, struct rar5* rar, | ||
| 217 | + const uint8_t* p, uint16_t code) | ||
| 218 | { | ||
| 219 | int lbits, length = 2; | ||
| 220 | + | ||
| 221 | if(code < 8) { | ||
| 222 | lbits = 0; | ||
| 223 | length += code; | ||
| 224 | @@ -2838,7 +2850,7 @@ static int decode_code_length(struct rar | ||
| 225 | if(lbits > 0) { | ||
| 226 | int add; | ||
| 227 | |||
| 228 | - if(ARCHIVE_OK != read_consume_bits(rar, p, lbits, &add)) | ||
| 229 | + if(ARCHIVE_OK != read_consume_bits(a, rar, p, lbits, &add)) | ||
| 230 | return -1; | ||
| 231 | |||
| 232 | length += add; | ||
| 233 | @@ -2933,7 +2945,7 @@ static int do_uncompress_block(struct ar | ||
| 234 | continue; | ||
| 235 | } else if(num >= 262) { | ||
| 236 | uint16_t dist_slot; | ||
| 237 | - int len = decode_code_length(rar, p, num - 262), | ||
| 238 | + int len = decode_code_length(a, rar, p, num - 262), | ||
| 239 | dbits, | ||
| 240 | dist = 1; | ||
| 241 | |||
| 242 | @@ -2975,12 +2987,12 @@ static int do_uncompress_block(struct ar | ||
| 243 | uint16_t low_dist; | ||
| 244 | |||
| 245 | if(dbits > 4) { | ||
| 246 | - if(ARCHIVE_OK != read_bits_32( | ||
| 247 | - rar, p, &add)) { | ||
| 248 | + if(ARCHIVE_OK != (ret = read_bits_32( | ||
| 249 | + a, rar, p, &add))) { | ||
| 250 | /* Return EOF if we | ||
| 251 | * can't read more | ||
| 252 | * data. */ | ||
| 253 | - return ARCHIVE_EOF; | ||
| 254 | + return ret; | ||
| 255 | } | ||
| 256 | |||
| 257 | skip_bits(rar, dbits - 4); | ||
| 258 | @@ -3015,11 +3027,11 @@ static int do_uncompress_block(struct ar | ||
| 259 | /* dbits is one of [0,1,2,3] */ | ||
| 260 | int add; | ||
| 261 | |||
| 262 | - if(ARCHIVE_OK != read_consume_bits(rar, | ||
| 263 | - p, dbits, &add)) { | ||
| 264 | + if(ARCHIVE_OK != (ret = read_consume_bits(a, rar, | ||
| 265 | + p, dbits, &add))) { | ||
| 266 | /* Return EOF if we can't read | ||
| 267 | * more data. */ | ||
| 268 | - return ARCHIVE_EOF; | ||
| 269 | + return ret; | ||
| 270 | } | ||
| 271 | |||
| 272 | dist += add; | ||
| 273 | @@ -3076,7 +3088,11 @@ static int do_uncompress_block(struct ar | ||
| 274 | return ARCHIVE_FATAL; | ||
| 275 | } | ||
| 276 | |||
| 277 | - len = decode_code_length(rar, p, len_slot); | ||
| 278 | + len = decode_code_length(a, rar, p, len_slot); | ||
| 279 | + if (len == -1) { | ||
| 280 | + return ARCHIVE_FATAL; | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | rar->cstate.last_len = len; | ||
| 284 | |||
| 285 | if(ARCHIVE_OK != copy_string(a, len, dist)) | ||
| 286 | --- a/libarchive/test/test_read_format_rar5.c | ||
| 287 | +++ b/libarchive/test/test_read_format_rar5.c | ||
| 288 | @@ -1271,3 +1271,20 @@ DEFINE_TEST(test_read_format_rar5_block_ | ||
| 289 | |||
| 290 | EPILOGUE(); | ||
| 291 | } | ||
| 292 | + | ||
| 293 | +DEFINE_TEST(test_read_format_rar5_decode_number_out_of_bounds_read) | ||
| 294 | +{ | ||
| 295 | + /* oss fuzz 30448 */ | ||
| 296 | + | ||
| 297 | + char buf[4096]; | ||
| 298 | + PROLOGUE("test_read_format_rar5_decode_number_out_of_bounds_read.rar"); | ||
| 299 | + | ||
| 300 | + /* Return codes of those calls are ignored, because this sample file | ||
| 301 | + * is invalid. However, the unpacker shouldn't produce any SIGSEGV | ||
| 302 | + * errors during processing. */ | ||
| 303 | + | ||
| 304 | + (void) archive_read_next_header(a, &ae); | ||
| 305 | + while(0 < archive_read_data(a, buf, sizeof(buf))) {} | ||
| 306 | + | ||
| 307 | + EPILOGUE(); | ||
| 308 | +} | ||
| 309 | --- /dev/null | ||
| 310 | +++ b/libarchive/test/test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu | ||
| 311 | @@ -0,0 +1,10 @@ | ||
| 312 | +begin 644 test_read_format_rar5_decode_number_out_of_bounds_read.rar | ||
| 313 | +M4F%R(1H'`0!3@"KT`P+G(@(0("`@@`L!!"`@("`@(($D_[BJ2"!::7!)210V | ||
| 314 | +M+0#ZF#)Q!`+>YPW_("`@("``_R````````````````````````````!__P`` | ||
| 315 | +M``````!T72`@/EW_(/\@("`@("`@("`@("`@("`@("`@("`@("`@(/\@("`@ | ||
| 316 | +M("`@("#_("`@("`@("`@("`@("`@("`@("`@("`@("#_("`@("`@("`@_R`@ | ||
| 317 | +M("`@("`@("`@("`@("`@("`@("`@("`@_R`@("`@("`@(/\@("`@("`@("`@ | ||
| 318 | +M("`@("`@("`@("`@("`@(/\@("`@("`@("#_("`@("`@("`@("`@("`@("`@ | ||
| 319 | +E("`@("`@("#_("`@("`@("`@_R`@("`@("`@("`@("`@("`@(``` | ||
| 320 | +` | ||
| 321 | +end | ||
diff --git a/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-2.patch b/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-2.patch new file mode 100644 index 0000000000..b5da44ec7b --- /dev/null +++ b/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-2.patch | |||
| @@ -0,0 +1,121 @@ | |||
| 1 | From 17f4e83c0f0fc3bacf4b2bbacb01f987bb5aff5f Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Grzegorz Antoniak <ga@anadoxin.org> | ||
| 3 | Date: Fri, 12 Feb 2021 20:18:31 +0100 | ||
| 4 | Subject: [PATCH] RAR5 reader: fix invalid memory access in some files | ||
| 5 | |||
| 6 | RAR5 reader uses several variables to manage the window buffer during | ||
| 7 | extraction: the buffer itself (`window_buf`), the current size of the | ||
| 8 | window buffer (`window_size`), and a helper variable (`window_mask`) | ||
| 9 | that is used to constrain read and write offsets to the window buffer. | ||
| 10 | |||
| 11 | Some specially crafted files can force the unpacker to update the | ||
| 12 | `window_mask` variable to a value that is out of sync with current | ||
| 13 | buffer size. If the `window_mask` will be bigger than the actual buffer | ||
| 14 | size, then an invalid access operation can happen (SIGSEGV). | ||
| 15 | |||
| 16 | This commit ensures that if the `window_size` and `window_mask` will be | ||
| 17 | changed, the window buffer will be reallocated to the proper size, so no | ||
| 18 | invalid memory operation should be possible. | ||
| 19 | |||
| 20 | This commit contains a test file from OSSFuzz #30442. | ||
| 21 | |||
| 22 | Upstream-Status: Backport [https://git.launchpad.net/ubuntu/+source/libarchive/plain/debian/patches/CVE-2021-36976-2.patch?h=applied/3.4.3-2ubuntu0.1] | ||
| 23 | CVE: CVE-2021-36976 | ||
| 24 | Signed-off-by: Virendra Thakur <virendra.thakur@kpit.com> | ||
| 25 | |||
| 26 | --- | ||
| 27 | Makefile.am | 1 + | ||
| 28 | libarchive/archive_read_support_format_rar5.c | 27 ++++++++++++++----- | ||
| 29 | libarchive/test/test_read_format_rar5.c | 17 ++++++++++++ | ||
| 30 | ...mat_rar5_window_buf_and_size_desync.rar.uu | 11 ++++++++ | ||
| 31 | 4 files changed, 50 insertions(+), 6 deletions(-) | ||
| 32 | create mode 100644 libarchive/test/test_read_format_rar5_window_buf_and_size_desync.rar.uu | ||
| 33 | |||
| 34 | --- a/Makefile.am | ||
| 35 | +++ b/Makefile.am | ||
| 36 | @@ -884,6 +884,7 @@ libarchive_test_EXTRA_DIST=\ | ||
| 37 | libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu \ | ||
| 38 | libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \ | ||
| 39 | libarchive/test/test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu \ | ||
| 40 | + libarchive/test/test_read_format_rar5_window_buf_and_size_desync.rar.uu \ | ||
| 41 | libarchive/test/test_read_format_raw.bufr.uu \ | ||
| 42 | libarchive/test/test_read_format_raw.data.gz.uu \ | ||
| 43 | libarchive/test/test_read_format_raw.data.Z.uu \ | ||
| 44 | --- a/libarchive/archive_read_support_format_rar5.c | ||
| 45 | +++ b/libarchive/archive_read_support_format_rar5.c | ||
| 46 | @@ -1730,14 +1730,29 @@ static int process_head_file(struct arch | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | - /* If we're currently switching volumes, ignore the new definition of | ||
| 51 | - * window_size. */ | ||
| 52 | - if(rar->cstate.switch_multivolume == 0) { | ||
| 53 | - /* Values up to 64M should fit into ssize_t on every | ||
| 54 | - * architecture. */ | ||
| 55 | - rar->cstate.window_size = (ssize_t) window_size; | ||
| 56 | + if(rar->cstate.window_size < (ssize_t) window_size && | ||
| 57 | + rar->cstate.window_buf) | ||
| 58 | + { | ||
| 59 | + /* If window_buf has been allocated before, reallocate it, so | ||
| 60 | + * that its size will match new window_size. */ | ||
| 61 | + | ||
| 62 | + uint8_t* new_window_buf = | ||
| 63 | + realloc(rar->cstate.window_buf, window_size); | ||
| 64 | + | ||
| 65 | + if(!new_window_buf) { | ||
| 66 | + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, | ||
| 67 | + "Not enough memory when trying to realloc the window " | ||
| 68 | + "buffer."); | ||
| 69 | + return ARCHIVE_FATAL; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + rar->cstate.window_buf = new_window_buf; | ||
| 73 | } | ||
| 74 | |||
| 75 | + /* Values up to 64M should fit into ssize_t on every | ||
| 76 | + * architecture. */ | ||
| 77 | + rar->cstate.window_size = (ssize_t) window_size; | ||
| 78 | + | ||
| 79 | if(rar->file.solid > 0 && rar->file.solid_window_size == 0) { | ||
| 80 | /* Solid files have to have the same window_size across | ||
| 81 | whole archive. Remember the window_size parameter | ||
| 82 | --- a/libarchive/test/test_read_format_rar5.c | ||
| 83 | +++ b/libarchive/test/test_read_format_rar5.c | ||
| 84 | @@ -1206,6 +1206,23 @@ DEFINE_TEST(test_read_format_rar5_differ | ||
| 85 | EPILOGUE(); | ||
| 86 | } | ||
| 87 | |||
| 88 | +DEFINE_TEST(test_read_format_rar5_window_buf_and_size_desync) | ||
| 89 | +{ | ||
| 90 | + /* oss fuzz 30442 */ | ||
| 91 | + | ||
| 92 | + char buf[4096]; | ||
| 93 | + PROLOGUE("test_read_format_rar5_window_buf_and_size_desync.rar"); | ||
| 94 | + | ||
| 95 | + /* Return codes of those calls are ignored, because this sample file | ||
| 96 | + * is invalid. However, the unpacker shouldn't produce any SIGSEGV | ||
| 97 | + * errors during processing. */ | ||
| 98 | + | ||
| 99 | + (void) archive_read_next_header(a, &ae); | ||
| 100 | + while(0 < archive_read_data(a, buf, 46)) {} | ||
| 101 | + | ||
| 102 | + EPILOGUE(); | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | DEFINE_TEST(test_read_format_rar5_arm_filter_on_window_boundary) | ||
| 106 | { | ||
| 107 | char buf[4096]; | ||
| 108 | --- /dev/null | ||
| 109 | +++ b/libarchive/test/test_read_format_rar5_window_buf_and_size_desync.rar.uu | ||
| 110 | @@ -0,0 +1,11 @@ | ||
| 111 | +begin 644 test_read_format_rar5_window_buf_and_size_desync.rar | ||
| 112 | +M4F%R(1H'`0`]/-[E`@$`_P$`1#[Z5P("`PL``BXB"?\`!(@B@0`)6.-AF?_1 | ||
| 113 | +M^0DI&0GG(F%R(0<:)`!3@"KT`P+G(@O_X[\``#&``(?!!0$$[:L``$.M*E)A | ||
| 114 | +M<B$`O<\>P0";/P1%``A*2DI*2DYQ<6TN9'%*2DI*2DI*``!D<F--``````"Z | ||
| 115 | +MNC*ZNKJZNFYO=&%I;+JZNKJZNKJZOKJZ.KJZNKJZNKKZU@4%````0$!`0$!` | ||
| 116 | +M0$!`0$!`0$!`0$#_________/T#`0$!`0$!`-UM`0$!`0$!`0$!`0$!`0$!` | ||
| 117 | +M0$!`0'!,J+:O!IZ-WN4'@`!3*F0````````````````````````````````` | ||
| 118 | +M``````````````#T`P)287(A&@<!`%.`*O0#`N<B`_,F@`'[__\``(`4`01S | ||
| 119 | +J'`/H/O\H@?\D`#O9GIZ>GN<B"_]%``(``&1RGIZ>GIZ>8_^>GE/_``!. | ||
| 120 | +` | ||
| 121 | +end | ||
diff --git a/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-3.patch b/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-3.patch new file mode 100644 index 0000000000..0e1549f229 --- /dev/null +++ b/meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-3.patch | |||
| @@ -0,0 +1,93 @@ | |||
| 1 | From 313bcd7ac547f7cc25945831f63507420c0874d7 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Grzegorz Antoniak <ga@anadoxin.org> | ||
| 3 | Date: Sat, 13 Feb 2021 10:13:22 +0100 | ||
| 4 | Subject: [PATCH] RAR5 reader: add more checks for invalid extraction | ||
| 5 | parameters | ||
| 6 | |||
| 7 | Some specially crafted files declare invalid extraction parameters that | ||
| 8 | can confuse the RAR5 reader. | ||
| 9 | |||
| 10 | One of the arguments is the declared window size parameter that the | ||
| 11 | archive file can declare for each file stored in the archive. Some | ||
| 12 | crafted files declare window size equal to 0, which is clearly wrong. | ||
| 13 | |||
| 14 | This commit adds additional safety checks decreasing the tolerance of | ||
| 15 | the RAR5 format. | ||
| 16 | |||
| 17 | This commit also contains OSSFuzz sample #30459. | ||
| 18 | --- | ||
| 19 | Makefile.am | 1 + | ||
| 20 | libarchive/archive_read_support_format_rar5.c | 10 ++++++++++ | ||
| 21 | libarchive/test/test_read_format_rar5.c | 19 +++++++++++++++++++ | ||
| 22 | ...t_rar5_bad_window_sz_in_mltarc_file.rar.uu | 7 +++++++ | ||
| 23 | 4 files changed, 37 insertions(+) | ||
| 24 | create mode 100644 libarchive/test/test_read_format_rar5_bad_window_sz_in_mltarc_file.rar.uu | ||
| 25 | |||
| 26 | Upstream-Status: Backport [https://github.com/libarchive/libarchive/pull/1493/commits/313bcd7ac547f7cc25945831f63507420c0874d7] | ||
| 27 | CVE: CVE-2021-36976 | ||
| 28 | Signed-off-by: Virendra Thakur <virendra.thakur@kpit.com> | ||
| 29 | |||
| 30 | --- libarchive-3.4.2.orig/Makefile.am | ||
| 31 | +++ libarchive-3.4.2/Makefile.am | ||
| 32 | @@ -882,6 +882,7 @@ libarchive_test_EXTRA_DIST=\ | ||
| 33 | libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \ | ||
| 34 | libarchive/test/test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu \ | ||
| 35 | libarchive/test/test_read_format_rar5_window_buf_and_size_desync.rar.uu \ | ||
| 36 | + libarchive/test/test_read_format_rar5_bad_window_sz_in_mltarc_file.rar.uu \ | ||
| 37 | libarchive/test/test_read_format_raw.bufr.uu \ | ||
| 38 | libarchive/test/test_read_format_raw.data.gz.uu \ | ||
| 39 | libarchive/test/test_read_format_raw.data.Z.uu \ | ||
| 40 | --- libarchive-3.4.2.orig/libarchive/archive_read_support_format_rar5.c | ||
| 41 | +++ libarchive-3.4.2/libarchive/archive_read_support_format_rar5.c | ||
| 42 | @@ -3637,6 +3637,16 @@ static int do_uncompress_file(struct arc | ||
| 43 | rar->cstate.initialized = 1; | ||
| 44 | } | ||
| 45 | |||
| 46 | + /* Don't allow extraction if window_size is invalid. */ | ||
| 47 | + if(rar->cstate.window_size == 0) { | ||
| 48 | + archive_set_error(&a->archive, | ||
| 49 | + ARCHIVE_ERRNO_FILE_FORMAT, | ||
| 50 | + "Invalid window size declaration in this file"); | ||
| 51 | + | ||
| 52 | + /* This should never happen in valid files. */ | ||
| 53 | + return ARCHIVE_FATAL; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | if(rar->cstate.all_filters_applied == 1) { | ||
| 57 | /* We use while(1) here, but standard case allows for just 1 | ||
| 58 | * iteration. The loop will iterate if process_block() didn't | ||
| 59 | --- libarchive-3.4.2.orig/libarchive/test/test_read_format_rar5.c | ||
| 60 | +++ libarchive-3.4.2/libarchive/test/test_read_format_rar5.c | ||
| 61 | @@ -1305,3 +1305,22 @@ DEFINE_TEST(test_read_format_rar5_decode | ||
| 62 | |||
| 63 | EPILOGUE(); | ||
| 64 | } | ||
| 65 | + | ||
| 66 | +DEFINE_TEST(test_read_format_rar5_bad_window_size_in_multiarchive_file) | ||
| 67 | +{ | ||
| 68 | + /* oss fuzz 30459 */ | ||
| 69 | + | ||
| 70 | + char buf[4096]; | ||
| 71 | + PROLOGUE("test_read_format_rar5_bad_window_sz_in_mltarc_file.rar"); | ||
| 72 | + | ||
| 73 | + /* This file is damaged, so those functions should return failure. | ||
| 74 | + * Additionally, SIGSEGV shouldn't be raised during execution | ||
| 75 | + * of those functions. */ | ||
| 76 | + | ||
| 77 | + (void) archive_read_next_header(a, &ae); | ||
| 78 | + while(0 < archive_read_data(a, buf, sizeof(buf))) {} | ||
| 79 | + (void) archive_read_next_header(a, &ae); | ||
| 80 | + while(0 < archive_read_data(a, buf, sizeof(buf))) {} | ||
| 81 | + | ||
| 82 | + EPILOGUE(); | ||
| 83 | +} | ||
| 84 | --- /dev/null | ||
| 85 | +++ libarchive-3.4.2/libarchive/test/test_read_format_rar5_bad_window_sz_in_mltarc_file.rar.uu | ||
| 86 | @@ -0,0 +1,7 @@ | ||
| 87 | +begin 644 test_read_format_rar5_bad_window_size_in_multiarchive_file.rar | ||
| 88 | +M4F%R(1H'`0`]/-[E`@$`_R`@1#[Z5P("`PL`("`@@"(`"?\@("#___\@("`@ | ||
| 89 | +M("`@("`@("`@4X`J]`,"YR(#$($@("`@``$@("`@@<L0("`@("`@("`@("`@ | ||
| 90 | +M("`@(""LCTJA`P$%`B`@`2!3@"KT`P+G(@,@("`@_P,!!B`@(/___R`@(('+ | ||
| 91 | +5$"`OX2`@[.SL[.S_("`@("`@("`@ | ||
| 92 | +` | ||
| 93 | +end | ||
diff --git a/meta/recipes-extended/libarchive/libarchive_3.4.2.bb b/meta/recipes-extended/libarchive/libarchive_3.4.2.bb index 0ab40fc096..b7426a1be8 100644 --- a/meta/recipes-extended/libarchive/libarchive_3.4.2.bb +++ b/meta/recipes-extended/libarchive/libarchive_3.4.2.bb | |||
| @@ -32,7 +32,11 @@ PACKAGECONFIG[mbedtls] = "--with-mbedtls,--without-mbedtls,mbedtls," | |||
| 32 | 32 | ||
| 33 | EXTRA_OECONF += "--enable-largefile" | 33 | EXTRA_OECONF += "--enable-largefile" |
| 34 | 34 | ||
| 35 | SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz" | 35 | SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz \ |
| 36 | file://CVE-2021-36976-1.patch \ | ||
| 37 | file://CVE-2021-36976-2.patch \ | ||
| 38 | file://CVE-2021-36976-3.patch \ | ||
| 39 | " | ||
| 36 | 40 | ||
| 37 | SRC_URI[md5sum] = "d953ed6b47694dadf0e6042f8f9ff451" | 41 | SRC_URI[md5sum] = "d953ed6b47694dadf0e6042f8f9ff451" |
| 38 | SRC_URI[sha256sum] = "b60d58d12632ecf1e8fad7316dc82c6b9738a35625746b47ecdcaf4aed176176" | 42 | SRC_URI[sha256sum] = "b60d58d12632ecf1e8fad7316dc82c6b9738a35625746b47ecdcaf4aed176176" |
