diff --git a/Kconfig b/Kconfig index c641882f8..416a9c2d3 100644 --- a/Kconfig +++ b/Kconfig @@ -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 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 menu "Component config" diff --git a/components/bootloader/subproject/Makefile b/components/bootloader/subproject/Makefile index 198f40f0c..e01dc3c8a 100644 --- a/components/bootloader/subproject/Makefile +++ b/components/bootloader/subproject/Makefile @@ -10,6 +10,10 @@ PROJECT_NAME := bootloader 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. CFLAGS += -I $(IDF_PATH)/components/esp32/include diff --git a/components/esp32/component.mk b/components/esp32/component.mk index 590893a99..ee7b39f83 100644 --- a/components/esp32/component.mk +++ b/components/esp32/component.mk @@ -61,3 +61,7 @@ esp32_out.ld: $(COMPONENT_PATH)/ld/esp32.ld ../include/sdkconfig.h $(CC) -I ../include -C -P -x c -E $< -o $@ 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)) \ No newline at end of file diff --git a/components/esp32/stack_check.c b/components/esp32/stack_check.c new file mode 100644 index 000000000..f79b50a6c --- /dev/null +++ b/components/esp32/stack_check.c @@ -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 diff --git a/components/esp32/test/test_stack_check.c b/components/esp32/test/test_stack_check.c new file mode 100644 index 000000000..5dc9062c5 --- /dev/null +++ b/components/esp32/test/test_stack_check.c @@ -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 diff --git a/components/esp32/test/test_stack_check_cxx.cpp b/components/esp32/test/test_stack_check_cxx.cpp new file mode 100644 index 000000000..5c2c489e7 --- /dev/null +++ b/components/esp32/test/test_stack_check_cxx.cpp @@ -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 diff --git a/make/project.mk b/make/project.mk index 19e4b4250..76a9555cb 100644 --- a/make/project.mk +++ b/make/project.mk @@ -264,6 +264,19 @@ COMMON_FLAGS = \ -mlongcalls \ -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 ifdef CONFIG_OPTIMIZATION_LEVEL_RELEASE OPTIMIZATION_FLAGS = -Os diff --git a/tools/unit-test-app/sdkconfig.defaults b/tools/unit-test-app/sdkconfig.defaults index 6a3fc9dae..aae249f8a 100644 --- a/tools/unit-test-app/sdkconfig.defaults +++ b/tools/unit-test-app/sdkconfig.defaults @@ -21,3 +21,5 @@ CONFIG_ULP_COPROC_ENABLED=y CONFIG_TASK_WDT=n CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS=y CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=7 +CONFIG_STACK_CHECK_STRONG=y +CONFIG_STACK_CHECK=y