]> granicus.if.org Git - esp-idf/commitdiff
esp32: Adds Stack Smashing Protection Feature
authorAlexey Gerenkov <alexey@espressif.com>
Wed, 15 Nov 2017 08:09:54 +0000 (11:09 +0300)
committerAlexey Gerenkov <alexey@espressif.com>
Fri, 17 Nov 2017 09:08:36 +0000 (12:08 +0300)
These changes add posibility to enable GCC stack protector via menuconfig
for all source files in project.

Kconfig
components/bootloader/subproject/Makefile
components/esp32/component.mk
components/esp32/stack_check.c [new file with mode: 0644]
components/esp32/test/test_stack_check.c [new file with mode: 0644]
components/esp32/test/test_stack_check_cxx.cpp [new file with mode: 0644]
make/project.mk
tools/unit-test-app/sdkconfig.defaults

diff --git a/Kconfig b/Kconfig
index c641882f840048b9cc0a49c48f1082604ecbb532..416a9c2d3898163442aebd2d2097e64d0d1f4723 100644 (file)
--- 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"
index 198f40f0cc9e89607f4e754b15c17b4172567b58..e01dc3c8a212fd17f01e4a7973946077ab9ef745 100644 (file)
@@ -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
 
index 590893a9930fa2395a6bf6f07ba78d1d791cb5bd..ee7b39f83bd7e23f076b6e07716875cb5e39fc30 100644 (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 $@
 
 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 (file)
index 0000000..f79b50a
--- /dev/null
@@ -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 (file)
index 0000000..5dc9062
--- /dev/null
@@ -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 (file)
index 0000000..5c2c489
--- /dev/null
@@ -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
index 19e4b425044f47a82562409db00b4db1676ebdf3..76a9555cb0718e08f0bbff255bb113ee8982e554 100644 (file)
@@ -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
index 6a3fc9dae6867cd393aa0a026e069cc3993afe7d..aae249f8a1026edcb4c1ad4ff86c60d3d95a784d 100644 (file)
@@ -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