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 /meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-1.patch | |
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>
Diffstat (limited to 'meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-1.patch')
-rw-r--r-- | meta/recipes-extended/libarchive/libarchive/CVE-2021-36976-1.patch | 321 |
1 files changed, 321 insertions, 0 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 | ||