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

Add optional support for executable space protections #13387

Merged
merged 4 commits into from
Mar 11, 2020
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
4 changes: 4 additions & 0 deletions Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ ifneq (,$(filter mpu_stack_guard,$(USEMODULE)))
FEATURES_REQUIRED += cortexm_mpu
endif

ifneq (,$(filter mpu_noexec_ram,$(USEMODULE)))
FEATURES_REQUIRED += cortexm_mpu
endif

ifneq (,$(filter auto_init_gnrc_netif,$(USEMODULE)))
USEMODULE += gnrc_netif_init_devs
endif
Expand Down
2 changes: 1 addition & 1 deletion core/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ int __attribute__((used)) sched_run(void)

#ifdef MODULE_MPU_STACK_GUARD
mpu_configure(
1, /* MPU region 1 */
2, /* MPU region 2 */
(uintptr_t)sched_active_thread->stack_start + 31, /* Base Address (rounded up) */
MPU_ATTR(1, AP_RO_RO, 0, 1, 0, 1, MPU_SIZE_32B) /* Attributes and Size */
);
Expand Down
22 changes: 20 additions & 2 deletions cpu/cortexm_common/vectors_cortexm.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @author Joakim Gebart <joakim.gebart@eistec.se>
* @author Sören Tempel <tempel@uni-bremen.de>
*
* @}
*/
Expand Down Expand Up @@ -139,11 +140,28 @@ void reset_handler_default(void)
}
#endif /* CPU_HAS_BACKUP_RAM */

#ifdef MODULE_MPU_STACK_GUARD
#if defined(MODULE_MPU_STACK_GUARD) || defined(MODULE_MPU_NOEXEC_RAM)
mpu_enable();
#endif

#ifdef MODULE_MPU_NOEXEC_RAM
/* Mark the RAM non executable. This is a protection mechanism which
* makes exploitation of buffer overflows significantly harder.
*
* This marks the memory region from 0x20000000 to 0x3FFFFFFF as non
* executable. This is the Cortex-M SRAM region used for on-chip RAM.
*/
mpu_configure(
0, /* Region 0 (lowest priority) */
(uintptr_t)&_sram, /* RAM base address */
MPU_ATTR(1, AP_RW_RW, 0, 1, 0, 1, MPU_SIZE_512M) /* Allow read/write but no exec */
);
#endif

#ifdef MODULE_MPU_STACK_GUARD
if (((uintptr_t)&_sstack) != SRAM_BASE) {
mpu_configure(
0, /* MPU region 0 */
1, /* MPU region 1 */
(uintptr_t)&_sstack + 31, /* Base Address (rounded up) */
MPU_ATTR(1, AP_RO_RO, 0, 1, 0, 1, MPU_SIZE_32B) /* Attributes and Size */
);
Expand Down
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ PSEUDOMODULES += log_printfnoformat
PSEUDOMODULES += log_color
PSEUDOMODULES += lora
PSEUDOMODULES += mpu_stack_guard
PSEUDOMODULES += mpu_noexec_ram
PSEUDOMODULES += nanocoap_%
PSEUDOMODULES += netdev_default
PSEUDOMODULES += netstats
Expand Down
5 changes: 5 additions & 0 deletions tests/mpu_noexec_ram/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include ../Makefile.tests_common

USEMODULE += mpu_noexec_ram

include $(RIOTBASE)/Makefile.include
10 changes: 10 additions & 0 deletions tests/mpu_noexec_ram/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# mpu_noexec_ram

Tests for the `mpu_noexec_ram` pseudomodule. As this module is currently
only supported on Cortex M devices, the test case is a bit ARM specific.

## Output

With `USEMODULE += mpu_noexec_ram` in `Makefile` this application should
execute a kernel panic from the `MEM MANAGE HANDLER`. Without this
pseudomodule activated, it will run into a hard fault.
51 changes: 51 additions & 0 deletions tests/mpu_noexec_ram/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 Sören Tempel <tempel@uni-bremen.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup tests
* @{
*
* @file
* @brief Test application for the mpu_noexec_stack pseudo-module
*
* @author Sören Tempel <tempel@uni-bremen.de>
*
* @}
*/

#include <stdio.h>
#include <stdint.h>

#include "cpu.h"
#include "mpu.h"

/* RIOT's MPU headers gracefully fail when no MPU is present.
* Use this to catch if RIOT's features are correctly gating MPU use.
*/
#if !__MPU_PRESENT
#error "(!__MPU_PRESENT)"
#endif

#define JMPBUF_SIZE 3

int main(void)
{
uint32_t buf[JMPBUF_SIZE];

/* Fill the buffer with invalid instructions */
for (unsigned i = 0; i < JMPBUF_SIZE; i++) {
buf[i] = UINT32_MAX;
}

puts("Attempting to jump to stack buffer ...\n");
__asm__ volatile ("BX %0"
: /* no output operands */
: "r" ((uint8_t*)&buf + 1)); /* LSB must be set for thumb2 */

return 0;
}
18 changes: 18 additions & 0 deletions tests/mpu_noexec_ram/tests/01-run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env python3

# Copyright (C) 2020 Sören Tempel <tempel@uni-bremen.de>
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.

import sys
from testrunner import run


def testfunc(child):
child.expect_exact("MEM MANAGE HANDLER\r\n")


if __name__ == "__main__":
sys.exit(run(testfunc, timeout=10))