From 202eb93834ab2c19ba1f17e170ad912ee57c0ca9 Mon Sep 17 00:00:00 2001 From: Corentin Pane Date: Thu, 20 Aug 2026 10:10:54 +0200 Subject: [PATCH] Mask MPU region base addresses when writing to MPU_RBAR Bits 0-4 are reserved for VALID and REGION, while ADDR spans only bits 5-31. Masking ensures that a misaligned base address cannot modify less significant bits in the attribute reserved for other use. Failing to mask the address may allow a malicious user to pass in misaligned addresses in a user-defined region or as stack buffer which could in turn override the settings for higher-priority kernel-defined regions. This change doesn't guarantee that only properly aligned addresses are written to the ADDR field of the register, but protects the VALID and REGION fields. --- portable/GCC/ARM_CM3_MPU/port.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/portable/GCC/ARM_CM3_MPU/port.c b/portable/GCC/ARM_CM3_MPU/port.c index 96d781d969..00a322161b 100644 --- a/portable/GCC/ARM_CM3_MPU/port.c +++ b/portable/GCC/ARM_CM3_MPU/port.c @@ -95,6 +95,7 @@ typedef void ( * portISR_t )( void ); #define portMPU_REGION_ENABLE ( 0x01UL ) #define portPERIPHERALS_START_ADDRESS 0x40000000UL #define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL +#define portMPU_RBAR_ADDRESS_MASK 0xFFFFFFE0 /* Constants required to access and manipulate the SysTick. */ #define portNVIC_SYSTICK_INT ( 0x00000002UL ) @@ -1136,7 +1137,7 @@ static void prvSetupMPU( void ) if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) { /* First setup the unprivileged flash for unprivileged read only access. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ + portMPU_REGION_BASE_ADDRESS_REG = ( ( ( uint32_t ) __FLASH_segment_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | /* Base address. */ ( portMPU_REGION_VALID ) | ( portUNPRIVILEGED_FLASH_REGION ); @@ -1147,7 +1148,7 @@ static void prvSetupMPU( void ) /* Setup the privileged flash for privileged only access. This is where * the kernel code is * placed. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */ + portMPU_REGION_BASE_ADDRESS_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | /* Base address. */ ( portMPU_REGION_VALID ) | ( portPRIVILEGED_FLASH_REGION ); @@ -1158,7 +1159,7 @@ static void prvSetupMPU( void ) /* Setup the privileged data RAM region. This is where the kernel data * is placed. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ + portMPU_REGION_BASE_ADDRESS_REG = ( ( ( uint32_t ) __privileged_data_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | /* Base address. */ ( portMPU_REGION_VALID ) | ( portPRIVILEGED_RAM_REGION ); @@ -1170,7 +1171,7 @@ static void prvSetupMPU( void ) /* By default allow everything to access the general peripherals. The * system peripherals and registers are protected. */ - portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) | + portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS & portMPU_RBAR_ADDRESS_MASK ) | ( portMPU_REGION_VALID ) | ( portGENERAL_PERIPHERALS_REGION ); @@ -1280,7 +1281,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, { /* No MPU regions are specified so allow access to all RAM. */ xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = - ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ + ( ( ( uint32_t ) __SRAM_segment_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | /* Base address. */ ( portMPU_REGION_VALID ) | ( portSTACK_REGION ); /* Region number. */ @@ -1316,7 +1317,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, { /* Define the region that allows access to the stack. */ xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = - ( ( uint32_t ) pxBottomOfStack ) | + ( ( ( uint32_t ) pxBottomOfStack ) & portMPU_RBAR_ADDRESS_MASK ) | ( portMPU_REGION_VALID ) | ( portSTACK_REGION ); /* Region number. */ @@ -1343,7 +1344,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, * xRegions into the CM3 specific MPU settings that are then * stored in xMPUSettings. */ xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = - ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) | + ( ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK ) | ( portMPU_REGION_VALID ) | ( ul - 1UL ); /* Region number. */