syscalls: arm: Fix possible overflow in is_in_region function

This function is widely used by functions that validate memory
buffers. Macros used to check permissions, like Z_SYSCALL_MEMORY_READ
and Z_SYSCALL_MEMORY_WRITE, use these functions to check that a
pointers passed by user threads in a syscall.

Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
This commit is contained in:
Flavio Ceolin 2020-03-03 13:52:50 -08:00 committed by Johan Hedberg
commit 8ed4b62dc0
2 changed files with 17 additions and 2 deletions

View file

@ -9,6 +9,8 @@
#define ZEPHYR_ARCH_ARM_CORE_AARCH32_CORTEX_M_MPU_ARM_MPU_V7_INTERNAL_H_
#include <sys/math_extras.h>
#define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
#include <logging/log.h>
@ -200,6 +202,7 @@ static inline int is_in_region(u32_t r_index, u32_t start, u32_t size)
u32_t r_addr_start;
u32_t r_size_lshift;
u32_t r_addr_end;
u32_t end;
/* Lock IRQs to ensure RNR value is correct when reading RBAR, RASR. */
unsigned int key;
@ -216,7 +219,12 @@ static inline int is_in_region(u32_t r_index, u32_t start, u32_t size)
MPU_RASR_SIZE_Pos) + 1;
r_addr_end = r_addr_start + (1UL << r_size_lshift) - 1;
if (start >= r_addr_start && (start + size - 1) <= r_addr_end) {
size = size == 0 ? 0 : size - 1;
if (u32_add_overflow(start, size, &end)) {
return 0;
}
if ((start >= r_addr_start) && (end <= r_addr_end)) {
return 1;
}

View file

@ -10,6 +10,7 @@
#include <soc.h>
#include "arm_core_mpu_dev.h"
#include <sys/__assert.h>
#include <sys/math_extras.h>
#include <linker/linker-defs.h>
#define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
@ -428,11 +429,17 @@ static inline int is_in_region(u32_t r_index, u32_t start, u32_t size)
{
u32_t r_addr_start;
u32_t r_addr_end;
u32_t end;
r_addr_start = SYSMPU->WORD[r_index][0];
r_addr_end = SYSMPU->WORD[r_index][1];
if (start >= r_addr_start && (start + size - 1) <= r_addr_end) {
size = size == 0 ? 0 : size - 1;
if (u32_add_overflow(start, size, &end)) {
return 0;
}
if ((start >= r_addr_start) && (end <= r_addr_end)) {
return 1;
}