Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers/mtd: Add check for integer overflow #20587

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 90 additions & 14 deletions drivers/mtd_emulated/mtd_emulated.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
static int _init(mtd_dev_t *dev)
{
mtd_emulated_t *mtd = (mtd_emulated_t *)dev;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change, sneaking it in to make the file happy in uncrustify.

assert(mtd);

if (!mtd->init_done) {
Expand All @@ -32,7 +33,14 @@ static int _read(mtd_dev_t *dev, void *dest, uint32_t addr, uint32_t count)
assert(mtd);
assert(dest);

if ((addr + count) > mtd->size) {
uint32_t addr_count;

if (__builtin_add_overflow(addr, count, &addr_count)) {
/* check for integer overflow */
return -EOVERFLOW;
}

if (addr_count > mtd->size) {
/* addr + count must not exceed the size of memory */
return -EOVERFLOW;
}
Expand All @@ -51,11 +59,32 @@ static int _read_page(mtd_dev_t *dev, void *dest,
assert(mtd);
assert(dest);

if (((page * mtd->base.page_size) + offset + size) > mtd->size) {
uint32_t page_addr;

if (__builtin_mul_overflow(page, mtd->base.page_size, &page_addr)) {
/* check for integer overflow */
return -EOVERFLOW;
}

uint32_t offset_size;

if (__builtin_add_overflow(offset, size, &offset_size)) {
/* check for integer overflow */
return -EOVERFLOW;
}

uint32_t page_addr_offset_size;

if (__builtin_add_overflow(page_addr, offset_size, &page_addr_offset_size)) {
/* check for integer overflow */
return -EOVERFLOW;
}

if (page_addr_offset_size > mtd->size) {
/* page addr + offset + size must not exceed the size of memory */
return -EOVERFLOW;
}
memcpy(dest, mtd->memory + (page * mtd->base.page_size) + offset, size);
memcpy(dest, mtd->memory + page_addr + offset, size);

return size;
}
Expand All @@ -70,13 +99,37 @@ int _write_page(mtd_dev_t *dev, const void *src,
assert(mtd);
assert(src);

if (/* offset must be smaller than the page size */
(offset >= mtd->base.page_size) ||
if (offset >= mtd->base.page_size) {
/* offset must be smaller than the page size */
return -EOVERFLOW;
}

uint32_t page_addr;

if (__builtin_mul_overflow(page, mtd->base.page_size, &page_addr)) {
/* check for integer overflow */
return -EOVERFLOW;
}

uint32_t offset_size;

if (__builtin_add_overflow(offset, size, &offset_size)) {
/* check for integer overflow */
return -EOVERFLOW;
}

uint32_t page_addr_offset_size;

if (__builtin_add_overflow(page_addr, offset_size, &page_addr_offset_size)) {
/* check for integer overflow */
return -EOVERFLOW;
}

if (page_addr_offset_size > mtd->size) {
/* page addr + offset + size must not exceed the size of memory */
((page * mtd->base.page_size) + offset + size) > mtd->size) {
return -EOVERFLOW;
}
memcpy(mtd->memory + (page * mtd->base.page_size) + offset, src, size);
memcpy(mtd->memory + page_addr + offset, src, size);

return size;
}
Expand All @@ -88,12 +141,25 @@ static int _erase(mtd_dev_t *dev, uint32_t addr, uint32_t count)
(void)mtd;
assert(mtd);

if (/* addr must be aligned on a sector boundary */
(addr % (mtd->base.pages_per_sector * mtd->base.page_size) != 0) ||
uint32_t addr_count;

if (__builtin_add_overflow(addr, count, &addr_count)) {
/* check for integer overflow */
return -EOVERFLOW;
}

if (addr % (mtd->base.pages_per_sector * mtd->base.page_size) != 0) {
/* addr must be aligned on a sector boundary */
return -EOVERFLOW;
}

if (count % (mtd->base.pages_per_sector * mtd->base.page_size) != 0) {
/* count must be a multiple of a sector size. */
(count % (mtd->base.pages_per_sector * mtd->base.page_size) != 0) ||
return -EOVERFLOW;
}

if (addr_count > mtd->size) {
/* addr + count must not exceed the size of memory */
((addr + count) > mtd->size)) {
return -EOVERFLOW;
}

Expand All @@ -109,10 +175,20 @@ static int _erase_sector(mtd_dev_t *dev, uint32_t sector, uint32_t num)
(void)mtd;
assert(mtd);

if (/* sector must not exceed the number of sectors */
(sector >= mtd->base.sector_count) ||
uint32_t sector_num;

if (__builtin_add_overflow(sector, num, &sector_num)) {
/* check for integer overflow */
return -EOVERFLOW;
}

if (sector >= mtd->base.sector_count) {
/* sector must not exceed the number of sectors */
return -EOVERFLOW;
}

if (sector_num > mtd->base.sector_count) {
/* sector + num must not exceed the number of sectors */
((sector + num) > mtd->base.sector_count)) {
return -EOVERFLOW;
}

Expand Down
2 changes: 2 additions & 0 deletions tests/pkg/littlefs/Makefile.ci
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ BOARD_INSUFFICIENT_MEMORY := \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-l011k4 \
olimex-msp430-h1611 \
samd10-xmini \
stk3200 \
stm32f030f4-demo \
telosb \
#
Loading