Skip to content

Commit 5a6b8c6

Browse files
authored
Merge pull request #693 from danielinux/fix-delta-boundary-checks
[delta] Add bounds checks for delta image
2 parents f13dbc0 + c9d94d6 commit 5a6b8c6

File tree

3 files changed

+85
-5
lines changed

3 files changed

+85
-5
lines changed

src/delta.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
106106
uint32_t src_off;
107107
uint16_t sz;
108108
uint32_t copy_sz;
109+
uint32_t resume_sz;
109110
if (!ctx)
110111
return -1;
111112
if (len < BLOCK_HDR_SIZE)
@@ -115,10 +116,13 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
115116
uint8_t *pp = patch_read_cache(ctx);
116117
if (ctx->matching) {
117118
/* Resume matching block from previous sector */
118-
sz = ctx->blk_sz;
119-
if (sz > len)
120-
sz = len;
121-
memcpy(dst + dst_off, ctx->src_base + ctx->blk_off, sz);
119+
resume_sz = ctx->blk_sz;
120+
if (resume_sz > len)
121+
resume_sz = len;
122+
if (ctx->blk_off > ctx->src_size ||
123+
resume_sz > ctx->src_size - ctx->blk_off)
124+
return -1;
125+
memcpy(dst + dst_off, ctx->src_base + ctx->blk_off, resume_sz);
122126
if (ctx->blk_sz > len) {
123127
ctx->blk_sz -= len;
124128
ctx->blk_off += len;
@@ -127,7 +131,7 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
127131
ctx->blk_sz = 0;
128132
ctx->matching = 0;
129133
}
130-
dst_off += sz;
134+
dst_off += resume_sz;
131135
continue;
132136
}
133137
if (*pp == ESC) {
@@ -142,6 +146,9 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
142146
src_off = (hdr->off[0] << 16) + (hdr->off[1] << 8) +
143147
hdr->off[2];
144148
sz = (hdr->sz[0] << 8) + hdr->sz[1];
149+
if (src_off > ctx->src_size ||
150+
sz > ctx->src_size - src_off)
151+
return -1;
145152
ctx->matching = 1;
146153
if (sz > (len - dst_off)) {
147154
copy_sz = len - dst_off;

src/update_flash.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,11 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
441441
uint16_t base_hash_sz;
442442
uint8_t *base_hash;
443443

444+
if (boot->fw_size == 0) {
445+
/* Resume after powerfail can leave boot header erased; bound by partition size. */
446+
boot->fw_size = WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE;
447+
}
448+
444449
/* Use biggest size for the swap */
445450
total_size = boot->fw_size + IMAGE_HEADER_SIZE;
446451
if ((update->fw_size + IMAGE_HEADER_SIZE) > total_size)

tools/unit-tests/unit-delta.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,71 @@ START_TEST(test_wb_patch_init_invalid)
4848
}
4949
END_TEST
5050

51+
START_TEST(test_wb_patch_src_bounds_invalid)
52+
{
53+
WB_PATCH_CTX patch_ctx;
54+
uint8_t src[SRC_SIZE] = {0};
55+
uint8_t patch[PATCH_SIZE] = {0};
56+
uint8_t dst[DELTA_BLOCK_SIZE] = {0};
57+
int ret;
58+
59+
/* ESC + header with src_off beyond src_size */
60+
patch[0] = ESC;
61+
patch[1] = 0x00; /* off[0] */
62+
patch[2] = 0x10; /* off[1] -> 0x0010FF */
63+
patch[3] = 0xFF; /* off[2] */
64+
patch[4] = 0x00; /* sz[0] */
65+
patch[5] = 0x10; /* sz[1] -> 16 */
66+
67+
ret = wb_patch_init(&patch_ctx, src, SRC_SIZE, patch, BLOCK_HDR_SIZE);
68+
ck_assert_int_eq(ret, 0);
69+
70+
ret = wb_patch(&patch_ctx, dst, sizeof(dst));
71+
ck_assert_int_eq(ret, -1);
72+
}
73+
END_TEST
74+
75+
START_TEST(test_wb_patch_resume_bounds_invalid)
76+
{
77+
WB_PATCH_CTX patch_ctx;
78+
uint8_t src[SRC_SIZE] = {0};
79+
uint8_t patch[PATCH_SIZE] = {0};
80+
uint8_t dst[DELTA_BLOCK_SIZE] = {0};
81+
int ret;
82+
83+
ret = wb_patch_init(&patch_ctx, src, SRC_SIZE, patch, BLOCK_HDR_SIZE);
84+
ck_assert_int_eq(ret, 0);
85+
86+
patch_ctx.matching = 1;
87+
patch_ctx.blk_off = SRC_SIZE + 1;
88+
patch_ctx.blk_sz = 4;
89+
90+
ret = wb_patch(&patch_ctx, dst, sizeof(dst));
91+
ck_assert_int_eq(ret, -1);
92+
}
93+
END_TEST
94+
95+
START_TEST(test_wb_patch_resume_large_len)
96+
{
97+
WB_PATCH_CTX patch_ctx;
98+
uint8_t src[SRC_SIZE] = {0};
99+
uint8_t patch[PATCH_SIZE] = {0};
100+
uint8_t dst[DST_SIZE] = {0};
101+
uint32_t len = 70000;
102+
int ret;
103+
104+
src[0] = 0xA5;
105+
ret = wb_patch_init(&patch_ctx, src, SRC_SIZE, patch, BLOCK_HDR_SIZE);
106+
ck_assert_int_eq(ret, 0);
107+
108+
patch_ctx.matching = 1;
109+
patch_ctx.blk_off = 0;
110+
patch_ctx.blk_sz = len;
111+
112+
ret = wb_patch(&patch_ctx, dst, len);
113+
ck_assert_int_eq(ret, -1);
114+
}
115+
END_TEST
51116

52117
START_TEST(test_wb_diff_init_invalid)
53118
{
@@ -162,6 +227,9 @@ Suite *patch_diff_suite(void)
162227

163228
tcase_add_test(tc_wolfboot_delta, test_wb_patch_init_invalid);
164229
tcase_add_test(tc_wolfboot_delta, test_wb_diff_init_invalid);
230+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_src_bounds_invalid);
231+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_resume_bounds_invalid);
232+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_resume_large_len);
165233
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff);
166234
suite_add_tcase(s, tc_wolfboot_delta);
167235

0 commit comments

Comments
 (0)