Skip to content

Commit fefd74e

Browse files
committed
Reject oversized delta source offsets
F/2267
1 parent ea6700f commit fefd74e

4 files changed

Lines changed: 44 additions & 0 deletions

File tree

src/delta.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ struct BLOCK_HDR_PACKED block_hdr {
4040
};
4141

4242
#define BLOCK_HDR_SIZE (sizeof (struct block_hdr))
43+
#define BLOCK_OFF_MAX 0xFFFFFFU
4344

4445
#if defined(EXT_ENCRYPTED) && defined(__WOLFBOOT)
4546
#include "image.h"
@@ -300,6 +301,8 @@ int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len)
300301
*/
301302
match_len = BLOCK_HDR_SIZE;
302303
blk_start = pa - ctx->src_a;
304+
if (blk_start > BLOCK_OFF_MAX)
305+
return -1;
303306
b_start = ctx->off_b;
304307
pa+= BLOCK_HDR_SIZE;
305308
ctx->off_b += BLOCK_HDR_SIZE;
@@ -362,6 +365,8 @@ int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len)
362365
*/
363366
match_len = BLOCK_HDR_SIZE;
364367
blk_start = pb - ctx->src_b;
368+
if (blk_start > BLOCK_OFF_MAX)
369+
return -1;
365370
pb+= BLOCK_HDR_SIZE;
366371
ctx->off_b += BLOCK_HDR_SIZE;
367372
while ((pb < pb_limit) &&

tools/delta/bmdiff.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ int main(int argc, char *argv[])
9797
exit(3);
9898
}
9999
len2 = st.st_size;
100+
if (len2 > MAX_SRC_SIZE) {
101+
printf("%s: file too large\n", argv[2]);
102+
exit(3);
103+
}
100104
buffer = mmap(NULL, len2, PROT_READ, MAP_SHARED, fd2, 0);
101105
if (buffer == (void *)(-1)) {
102106
perror("mmap");

tools/keytools/sign.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,6 +2241,10 @@ static int base_diff(const char *f_base, uint8_t *pubkey, uint32_t pubkey_sz, in
22412241
goto cleanup;
22422242
}
22432243
len2 = st.st_size;
2244+
if (len2 > MAX_SRC_SIZE) {
2245+
printf("%s: file too large\n", CMD.output_image_file);
2246+
goto cleanup;
2247+
}
22442248
buffer = mmap(NULL, len2, PROT_READ, MAP_SHARED, fd2, 0);
22452249
if (buffer == (void *)(-1)) {
22462250
perror("mmap");
@@ -2276,6 +2280,10 @@ static int base_diff(const char *f_base, uint8_t *pubkey, uint32_t pubkey_sz, in
22762280
fseek(f2, 0L, SEEK_END);
22772281
len2 = ftell(f2);
22782282
fseek(f2, 0L, SEEK_SET);
2283+
if (len2 > MAX_SRC_SIZE) {
2284+
printf("%s: file too large\n", CMD.output_image_file);
2285+
goto cleanup;
2286+
}
22792287
buffer = malloc(len2);
22802288
if (buffer == NULL) {
22812289
fprintf(stderr, "Error malloc for buffer %d\n", len2);

tools/unit-tests/unit-delta.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#define PATCH_SIZE 8192
3535
#define DST_SIZE 4096
3636
#define DIFF_SIZE 8192
37+
#define DELTA_OFFSET_LIMIT (1U << 24)
3738

3839

3940
START_TEST(test_wb_patch_init_invalid)
@@ -238,6 +239,31 @@ START_TEST(test_wb_diff_preserves_main_loop_header_margin_for_escape)
238239
}
239240
END_TEST
240241

242+
START_TEST(test_wb_diff_rejects_match_offsets_beyond_24_bits)
243+
{
244+
WB_DIFF_CTX diff_ctx;
245+
uint8_t *src_a;
246+
uint8_t src_b[BLOCK_HDR_SIZE + 1] = {0};
247+
uint8_t patch[DELTA_BLOCK_SIZE] = {0};
248+
size_t src_a_size = DELTA_OFFSET_LIMIT + BLOCK_HDR_SIZE;
249+
int ret;
250+
251+
src_a = calloc(1, src_a_size);
252+
ck_assert_ptr_nonnull(src_a);
253+
254+
memset(src_a + DELTA_OFFSET_LIMIT, 0x5a, BLOCK_HDR_SIZE);
255+
memset(src_b, 0x5a, BLOCK_HDR_SIZE);
256+
257+
ret = wb_diff_init(&diff_ctx, src_a, src_a_size, src_b, sizeof(src_b));
258+
ck_assert_int_eq(ret, 0);
259+
260+
ret = wb_diff(&diff_ctx, patch, sizeof(patch));
261+
ck_assert_int_eq(ret, -1);
262+
263+
free(src_a);
264+
}
265+
END_TEST
266+
241267
static void initialize_buffers(uint8_t *src_a, uint8_t *src_b, size_t size)
242268
{
243269
uint32_t pseudo_rand = 0;
@@ -348,6 +374,7 @@ Suite *patch_diff_suite(void)
348374
tcase_add_test(tc_wolfboot_delta, test_wb_diff_self_match_extends_to_src_b_end);
349375
tcase_add_test(tc_wolfboot_delta, test_wb_diff_preserves_trailing_header_margin_for_escape);
350376
tcase_add_test(tc_wolfboot_delta, test_wb_diff_preserves_main_loop_header_margin_for_escape);
377+
tcase_add_test(tc_wolfboot_delta, test_wb_diff_rejects_match_offsets_beyond_24_bits);
351378
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff);
352379
suite_add_tcase(s, tc_wolfboot_delta);
353380

0 commit comments

Comments
 (0)