Skip to content

Disallow unprivileged critical sections with MPU wrappers v2#1427

Open
archigup wants to merge 1 commit into
FreeRTOS:mainfrom
archigup:fix/mpu-v2-disallow-unpriv-critical-sections
Open

Disallow unprivileged critical sections with MPU wrappers v2#1427
archigup wants to merge 1 commit into
FreeRTOS:mainfrom
archigup:fix/mpu-v2-disallow-unpriv-critical-sections

Conversation

@archigup

Copy link
Copy Markdown
Member

Description

When using MPU wrappers version 2 (configUSE_MPU_WRAPPERS_V1 == 0), unprivileged tasks cannot safely enter critical sections, but the current ARMv7-M MPU ports allow it and fail silently.

vPortEnterCritical()/vPortExitCritical() handle an unprivileged caller by raising privilege via portRAISE_PRIVILEGE() before writing BASEPRI. portRAISE_PRIVILEGE() issues svc portSVC_RAISE_PRIVILEGE, but the portSVC_RAISE_PRIVILEGE case in the SVC handler is compiled only for MPU wrappers v1 (#if ( configUSE_MPU_WRAPPERS_V1 == 1 )). Under v2 the SVC falls through to the no-op default case, privilege is never raised, and the subsequent BASEPRI write from unprivileged mode is ignored by the hardware. The critical section appears to succeed but never masks interrupts, producing latent, hard-to-debug faults.

This is made worse by the defaults: configUSE_MPU_WRAPPERS_V1 defaults to 0 (v2) and configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS defaults to 1, so the dangerous combination is the out-of-the-box configuration.

Changes

In the four ARMv7-M MPU ports (GCC/ARM_CM3_MPU, GCC/ARM_CM4_MPU, IAR/ARM_CM4F_MPU, RVDS/ARM_CM4_MPU):

  • When configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is left undefined under v2, it now defaults to 0 (instead of 1), so the default configuration is safe.
  • When it is explicitly set to 1 under v2, a compile-time #error rejects the unsupported configuration loudly rather than letting it fail silently at run time.
  • Behaviour under MPU wrappers v1 is unchanged (still defaults to 1 with the existing security #warning, and explicit 0/1 are both honoured).

ARMv8-M ports are unaffected: they do not expose configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS and their critical-section primitives are PRIVILEGED_FUNCTIONs that never attempt the privilege raise.

Fixes #1378

Test Steps

Verified the preprocessor logic across all relevant config permutations:

configUSE_MPU_WRAPPERS_V1 configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS Result
0 (v2) undefined defaults to 0, no error
0 (v2) 1 compile-time #error
0 (v2) 0 0, no error
1 (v1) undefined 1 + existing #warning
1 (v1) 1 1, no error

Checklist:

  • I have tested my changes. No regression in existing tests.
  • I have modified and/or added unit-tests to cover the code changes in this Pull Request.

N/A — this is a compile-time configuration guard; verified via preprocessor evaluation of all config permutations (table above).

Related Issue

#1378

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

@archigup archigup force-pushed the fix/mpu-v2-disallow-unpriv-critical-sections branch from 198a622 to ccb3d1f Compare June 12, 2026 21:43
When using MPU wrappers version 2 (configUSE_MPU_WRAPPERS_V1 == 0),
portRAISE_PRIVILEGE() is a no-op because the portSVC_RAISE_PRIVILEGE
handler is compiled only for MPU wrappers version 1. As a result, an
unprivileged task that calls taskENTER_CRITICAL() does not actually raise
its privilege, so the subsequent BASEPRI write is ignored by the hardware
and the critical section silently fails to mask interrupts. This produces
latent, hard-to-debug faults.

configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is therefore not supported with
MPU wrappers version 2. In the ARMv7-M MPU ports:

- When the option is left undefined under v2, default it to 0 instead of 1
  so the dangerous default configuration is safe.
- When the option is explicitly set to 1 under v2, raise a compile-time
  #error so the unsupported configuration is rejected loudly rather than
  failing silently at run time.

Behaviour for MPU wrappers version 1 is unchanged.
@archigup archigup force-pushed the fix/mpu-v2-disallow-unpriv-critical-sections branch from ccb3d1f to 54dcd46 Compare June 12, 2026 21:53
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] When using MPU_WRAPPERS v2, prevent critical sections in unprivileged tasks

2 participants