Skip to content

Commit 447c1f0

Browse files
committed
fix: more robust address range checks in svhandler_flash_*
1 parent febc4fe commit 447c1f0

1 file changed

Lines changed: 64 additions & 35 deletions

File tree

lib/board/supervise.c

Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,63 @@
3030

3131
#ifndef EMULATOR
3232

33+
bool do_memory_ranges_overlap(size_t range1Start, size_t range1End, size_t range2Start, size_t range2End) {
34+
if (range1Start <= range2Start) {
35+
return range2Start < range1End;
36+
} else {
37+
return range1Start < range2End;
38+
}
39+
}
40+
41+
bool allow_svhandler_flash_sector(const FlashSector* sector) {
42+
return sector->use == FLASH_STORAGE1 ||
43+
sector->use == FLASH_STORAGE2 ||
44+
sector->use == FLASH_STORAGE3 ||
45+
sector->use == FLASH_UNUSED0 ||
46+
sector->use == FLASH_APP;
47+
}
48+
49+
bool allow_svhandler_flash_sector_num(int sector) {
50+
for (const FlashSector *s = flash_sector_map; s->use != FLASH_INVALID; s++) {
51+
if (s->sector == sector) return allow_svhandler_flash_sector(s);
52+
}
53+
return false;
54+
}
55+
56+
bool allow_svhandler_flash_range(size_t start, size_t end) {
57+
// Protect from overflow.
58+
if (start > end) return false;
59+
60+
// Disallow non-flash writes.
61+
if (start < FLASH_ORIGIN || end > FLASH_END) return false;
62+
63+
// Disallow writes to any sectors which aren't allowed.
64+
bool startAllowed = false;
65+
bool endAllowed = false;
66+
for (const FlashSector* s = flash_sector_map; s->use != FLASH_INVALID; s++) {
67+
if (allow_svhandler_flash_sector(s)) {
68+
if (!startAllowed &&
69+
start + 1 > start &&
70+
do_memory_ranges_overlap(start, start + 1, s->start, s->start + s->len)) {
71+
startAllowed = true;
72+
}
73+
if (!endAllowed &&
74+
end - 1 < end &&
75+
do_memory_ranges_overlap(end - 1, end, s->start, s->start + s->len)) {
76+
endAllowed = true;
77+
}
78+
} else {
79+
if (do_memory_ranges_overlap(start, end, s->start, s->start + s->len)) return false;
80+
}
81+
}
82+
83+
// Ensure writes start and end in allowed sectors. As long as flash_sector_map consists of
84+
// contiguous sectors, this will ensure no writes can target flash outside the map.
85+
if (!startAllowed || !endAllowed) return false;
86+
87+
return true;
88+
}
89+
3390
/// Return context from user isr processing
3491
void svc_busr_return(void) {
3592
__asm__ __volatile__("svc %0" ::"i"(SVC_BUSR_RET) : "memory");
@@ -76,13 +133,10 @@ bool svc_flash_pgm_word(uint32_t beginAddr, uint32_t data) {
76133
}
77134

78135
void svhandler_flash_erase_sector(void) {
79-
uint32_t sector = _param_1;
136+
uint8_t sector = _param_1;
80137

81-
// Do not allow firmware to erase bootstrap or bootloader sectors.
82-
if ((sector == FLASH_BOOTSTRAP_SECTOR) ||
83-
(sector >= FLASH_BOOT_SECTOR_FIRST && sector <= FLASH_BOOT_SECTOR_LAST)) {
84-
return;
85-
}
138+
// Verify requested sector is allowed.
139+
if (!allow_svhandler_flash_sector_num(sector)) return;
86140

87141
// Unlock flash.
88142
flash_clear_status_flags();
@@ -111,25 +165,8 @@ void svhandler_flash_pgm_blk(void) {
111165
uint32_t data = _param_2;
112166
uint32_t length = _param_3;
113167

114-
// Protect from overflow.
115-
if (beginAddr + length < beginAddr) return;
116-
117-
// Do not allow firmware to erase bootstrap or bootloader sectors.
118-
if (((beginAddr >= BSTRP_FLASH_SECT_START) &&
119-
(beginAddr <= (BSTRP_FLASH_SECT_START + BSTRP_FLASH_SECT_LEN - 1))) ||
120-
(((beginAddr + length) >= BSTRP_FLASH_SECT_START) &&
121-
((beginAddr + length) <=
122-
(BSTRP_FLASH_SECT_START + BSTRP_FLASH_SECT_LEN - 1)))) {
123-
return;
124-
}
125-
126-
if (((beginAddr >= BLDR_FLASH_SECT_START) &&
127-
(beginAddr <= (BLDR_FLASH_SECT_START + 2 * BLDR_FLASH_SECT_LEN - 1))) ||
128-
(((beginAddr + length) >= BLDR_FLASH_SECT_START) &&
129-
((beginAddr + length) <=
130-
(BLDR_FLASH_SECT_START + 2 * BLDR_FLASH_SECT_LEN - 1)))) {
131-
return;
132-
}
168+
// Verify requested address range is allowed.
169+
if (!allow_svhandler_flash_range(beginAddr, beginAddr + length)) return;
133170

134171
// Unlock flash.
135172
flash_clear_status_flags();
@@ -157,16 +194,8 @@ void svhandler_flash_pgm_word(void) {
157194
uint32_t dst = _param_1;
158195
uint32_t src = _param_2;
159196

160-
// Do not allow firmware to erase bootstrap or bootloader sectors.
161-
if ((dst >= BSTRP_FLASH_SECT_START) &&
162-
(dst <= (BSTRP_FLASH_SECT_START + BSTRP_FLASH_SECT_LEN))) {
163-
return;
164-
}
165-
166-
if ((dst >= BLDR_FLASH_SECT_START) &&
167-
(dst <= (BLDR_FLASH_SECT_START + 2 * BLDR_FLASH_SECT_LEN))) {
168-
return;
169-
}
197+
// Verify requested address range is allowed.
198+
if (!allow_svhandler_flash_range(dst, dst + sizeof(uint32_t))) return;
170199

171200
// Unlock flash.
172201
flash_clear_status_flags();

0 commit comments

Comments
 (0)