esp32: Adds Stack Smashing Protection Feature

These changes add posibility to enable GCC stack protector via menuconfig
for all source files in project.
This commit is contained in:
Alexey Gerenkov 2017-11-15 11:09:54 +03:00
parent b83792f504
commit 692a890232
8 changed files with 147 additions and 0 deletions

35
Kconfig
View File

@ -105,6 +105,41 @@ config CXX_EXCEPTIONS
Enabling this option currently adds an additional 20KB of heap overhead, and 4KB of additional heap is allocated Enabling this option currently adds an additional 20KB of heap overhead, and 4KB of additional heap is allocated
the first time an exception is thrown in user code. the first time an exception is thrown in user code.
choice STACK_CHECK_MODE
prompt "Stack smashing protection mode"
default STACK_CHECK_NONE
help
Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack
smashing attacks. This is done by adding a guard variable to functions with vulnerable objects.
The guards are initialized when a function is entered and then checked when the function exits.
If a guard check fails, program is halted. Protection has the following modes:
- In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, and functions with buffers larger than
8 bytes are protected.
- STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes additional functions to be protected -- those that
have local array definitions, or have references to local frame addresses.
- In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected.
Modes have the following impact on code performance and coverage:
- performance: NORMAL > STRONG > OVERALL
- coverage: NORMAL < STRONG < OVERALL
config STACK_CHECK_NONE
bool "None"
config STACK_CHECK_NORM
bool "Normal"
config STACK_CHECK_STRONG
bool "Strong"
config STACK_CHECK_ALL
bool "Overall"
endchoice
config STACK_CHECK
bool
default !STACK_CHECK_NONE
help
Stack smashing protection.
endmenu # Compiler Options endmenu # Compiler Options
menu "Component config" menu "Component config"

View File

@ -10,6 +10,10 @@ PROJECT_NAME := bootloader
COMPONENTS := esptool_py bootloader_support log spi_flash micro-ecc soc main COMPONENTS := esptool_py bootloader_support log spi_flash micro-ecc soc main
# Clear C and CXX from top level project
CFLAGS =
CXXFLAGS =
#We cannot include the esp32 component directly but we need its includes. #We cannot include the esp32 component directly but we need its includes.
CFLAGS += -I $(IDF_PATH)/components/esp32/include CFLAGS += -I $(IDF_PATH)/components/esp32/include

View File

@ -61,3 +61,7 @@ esp32_out.ld: $(COMPONENT_PATH)/ld/esp32.ld ../include/sdkconfig.h
$(CC) -I ../include -C -P -x c -E $< -o $@ $(CC) -I ../include -C -P -x c -E $< -o $@
COMPONENT_EXTRA_CLEAN := esp32_out.ld COMPONENT_EXTRA_CLEAN := esp32_out.ld
# disable stack protection in files which are involved in initialization of that feature
stack_check.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS))
cpu_start.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS))

View File

@ -0,0 +1,39 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#include "esp_system.h"
#if CONFIG_STACK_CHECK
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include "esp_log.h"
const static char *TAG = "stack_chk";
void *__stack_chk_guard = NULL;
static void __attribute__ ((constructor))
__esp_stack_guard_setup (void)
{
ESP_LOGD(TAG, "Intialize random stack guard");
__stack_chk_guard = (void *)esp_random();
}
void __stack_chk_fail (void)
{
ets_printf("\r\nStack smashing protect failure!\r\n\r\n");
abort();
}
#endif

View File

@ -0,0 +1,25 @@
#include "unity.h"
#if CONFIG_STACK_CHECK
static void recur_and_smash()
{
static int cnt;
volatile uint8_t buf[50];
volatile int num = sizeof(buf)+10;
if (cnt++ < 1) {
recur_and_smash();
}
for (int i = 0; i < num; i++) {
buf[i] = 0;
}
}
TEST_CASE("stack smashing protection", "[stack_check] [ignore]")
{
recur_and_smash();
}
#endif

View File

@ -0,0 +1,25 @@
#include "unity.h"
#if CONFIG_STACK_CHECK
static void recur_and_smash_cxx()
{
static int cnt;
volatile uint8_t buf[50];
volatile int num = sizeof(buf)+10;
if (cnt++ < 1) {
recur_and_smash_cxx();
}
for (int i = 0; i < num; i++) {
buf[i] = 0;
}
}
TEST_CASE("stack smashing protection CXX", "[stack_check] [ignore]")
{
recur_and_smash_cxx();
}
#endif

View File

@ -264,6 +264,19 @@ COMMON_FLAGS = \
-mlongcalls \ -mlongcalls \
-nostdlib -nostdlib
ifndef IS_BOOTLOADER_BUILD
# stack protection (only one option can be selected in menuconfig)
ifdef CONFIG_STACK_CHECK_NORM
COMMON_FLAGS += -fstack-protector
endif
ifdef CONFIG_STACK_CHECK_STRONG
COMMON_FLAGS += -fstack-protector-strong
endif
ifdef CONFIG_STACK_CHECK_ALL
COMMON_FLAGS += -fstack-protector-all
endif
endif
# Optimization flags are set based on menuconfig choice # Optimization flags are set based on menuconfig choice
ifdef CONFIG_OPTIMIZATION_LEVEL_RELEASE ifdef CONFIG_OPTIMIZATION_LEVEL_RELEASE
OPTIMIZATION_FLAGS = -Os OPTIMIZATION_FLAGS = -Os

View File

@ -21,3 +21,5 @@ CONFIG_ULP_COPROC_ENABLED=y
CONFIG_TASK_WDT=n CONFIG_TASK_WDT=n
CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS=y CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS=y
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=7 CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=7
CONFIG_STACK_CHECK_STRONG=y
CONFIG_STACK_CHECK=y