Commit b455ab22 authored by Flavio Ceolin's avatar Flavio Ceolin Committed by David Leach
Browse files

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: default avatarFlavio Ceolin <flavio.ceolin@intel.com>
parent 4c5eabfa
Loading
Loading
Loading
Loading
+9 −1
Changes for arch/arm/core/cortex_m/mpu/arm_mpu_v7_internal.h: 9 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
#define ZEPHYR_ARCH_ARM_CORE_CORTEX_M_MPU_ARM_MPU_V7_INTERNAL_H_


#include <sys/math_extras.h>

#define LOG_LEVEL CONFIG_MPU_LOG_LEVEL
#include <logging/log.h>

@@ -184,6 +186,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;

	MPU->RNR = r_index;
	r_addr_start = MPU->RBAR & MPU_RBAR_ADDR_Msk;
@@ -191,7 +194,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;
	}

+8 −1
Changes for arch/arm/core/cortex_m/mpu/nxp_mpu.c: 8 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -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;
	}