Commit 2142b7f0 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'hardening-v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull kernel hardening updates from Kees Cook:

 - Add arm64 Shadow Call Stack support for GCC 12 (Dan Li)

 - Avoid memset with stack offset randomization under Clang (Marco
   Elver)

 - Clean up stackleak plugin to play nice with .noinstr (Kees Cook)

 - Check stack depth for greater usercopy hardening coverage (Kees Cook)

* tag 'hardening-v5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  arm64: Add gcc Shadow Call Stack support
  m68k: Implement "current_stack_pointer"
  xtensa: Implement "current_stack_pointer"
  usercopy: Check valid lifetime via stack depth
  stack: Constrain and fix stack offset randomization with Clang builds
  stack: Introduce CONFIG_RANDOMIZE_KSTACK_OFFSET
  gcc-plugins/stackleak: Ignore .noinstr.text and .entry.text
  gcc-plugins/stackleak: Exactly match strings instead of prefixes
  gcc-plugins/stackleak: Provide verbose mode
parents fd2d7a4a afcf5441
...@@ -599,21 +599,22 @@ config STACKPROTECTOR_STRONG ...@@ -599,21 +599,22 @@ config STACKPROTECTOR_STRONG
config ARCH_SUPPORTS_SHADOW_CALL_STACK config ARCH_SUPPORTS_SHADOW_CALL_STACK
bool bool
help help
An architecture should select this if it supports Clang's Shadow An architecture should select this if it supports the compiler's
Call Stack and implements runtime support for shadow stack Shadow Call Stack and implements runtime support for shadow stack
switching. switching.
config SHADOW_CALL_STACK config SHADOW_CALL_STACK
bool "Clang Shadow Call Stack" bool "Shadow Call Stack"
depends on CC_IS_CLANG && ARCH_SUPPORTS_SHADOW_CALL_STACK depends on ARCH_SUPPORTS_SHADOW_CALL_STACK
depends on DYNAMIC_FTRACE_WITH_REGS || !FUNCTION_GRAPH_TRACER depends on DYNAMIC_FTRACE_WITH_REGS || !FUNCTION_GRAPH_TRACER
help help
This option enables Clang's Shadow Call Stack, which uses a This option enables the compiler's Shadow Call Stack, which
shadow stack to protect function return addresses from being uses a shadow stack to protect function return addresses from
overwritten by an attacker. More information can be found in being overwritten by an attacker. More information can be found
Clang's documentation: in the compiler's documentation:
https://clang.llvm.org/docs/ShadowCallStack.html - Clang: https://clang.llvm.org/docs/ShadowCallStack.html
- GCC: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#Instrumentation-Options
Note that security guarantees in the kernel differ from the Note that security guarantees in the kernel differ from the
ones documented for user space. The kernel must store addresses ones documented for user space. The kernel must store addresses
...@@ -1159,16 +1160,30 @@ config HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET ...@@ -1159,16 +1160,30 @@ config HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
to the compiler, so it will attempt to add canary checks regardless to the compiler, so it will attempt to add canary checks regardless
of the static branch state. of the static branch state.
config RANDOMIZE_KSTACK_OFFSET_DEFAULT config RANDOMIZE_KSTACK_OFFSET
bool "Randomize kernel stack offset on syscall entry" bool "Support for randomizing kernel stack offset on syscall entry" if EXPERT
default y
depends on HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET depends on HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
depends on INIT_STACK_NONE || !CC_IS_CLANG || CLANG_VERSION >= 140000
help help
The kernel stack offset can be randomized (after pt_regs) by The kernel stack offset can be randomized (after pt_regs) by
roughly 5 bits of entropy, frustrating memory corruption roughly 5 bits of entropy, frustrating memory corruption
attacks that depend on stack address determinism or attacks that depend on stack address determinism or
cross-syscall address exposures. This feature is controlled cross-syscall address exposures.
by kernel boot param "randomize_kstack_offset=on/off", and this
config chooses the default boot state. The feature is controlled via the "randomize_kstack_offset=on/off"
kernel boot param, and if turned off has zero overhead due to its use
of static branches (see JUMP_LABEL).
If unsure, say Y.
config RANDOMIZE_KSTACK_OFFSET_DEFAULT
bool "Default state of kernel stack offset randomization"
depends on RANDOMIZE_KSTACK_OFFSET
help
Kernel stack offset randomization is controlled by kernel boot param
"randomize_kstack_offset=on/off", and this config chooses the default
boot state.
config ARCH_OPTIONAL_KERNEL_RWX config ARCH_OPTIONAL_KERNEL_RWX
def_bool n def_bool n
......
...@@ -5,6 +5,7 @@ config ARM ...@@ -5,6 +5,7 @@ config ARM
select ARCH_32BIT_OFF_T select ARCH_32BIT_OFF_T
select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE if HAVE_KRETPROBES && FRAME_POINTER && !ARM_UNWIND select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE if HAVE_KRETPROBES && FRAME_POINTER && !ARM_UNWIND
select ARCH_HAS_BINFMT_FLAT select ARCH_HAS_BINFMT_FLAT
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL if MMU select ARCH_HAS_DEBUG_VIRTUAL if MMU
select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE
select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_ELF_RANDOMIZE
......
...@@ -19,6 +19,7 @@ config ARM64 ...@@ -19,6 +19,7 @@ config ARM64
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2 select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
select ARCH_HAS_CACHE_LINE_SIZE select ARCH_HAS_CACHE_LINE_SIZE
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DMA_PREP_COHERENT select ARCH_HAS_DMA_PREP_COHERENT
...@@ -1257,7 +1258,7 @@ config HW_PERF_EVENTS ...@@ -1257,7 +1258,7 @@ config HW_PERF_EVENTS
def_bool y def_bool y
depends on ARM_PMU depends on ARM_PMU
# Supported by clang >= 7.0 # Supported by clang >= 7.0 or GCC >= 12.0.0
config CC_HAVE_SHADOW_CALL_STACK config CC_HAVE_SHADOW_CALL_STACK
def_bool $(cc-option, -fsanitize=shadow-call-stack -ffixed-x18) def_bool $(cc-option, -fsanitize=shadow-call-stack -ffixed-x18)
......
...@@ -4,6 +4,7 @@ config M68K ...@@ -4,6 +4,7 @@ config M68K
default y default y
select ARCH_32BIT_OFF_T select ARCH_32BIT_OFF_T
select ARCH_HAS_BINFMT_FLAT select ARCH_HAS_BINFMT_FLAT
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DMA_PREP_COHERENT if HAS_DMA && MMU && !COLDFIRE select ARCH_HAS_DMA_PREP_COHERENT if HAS_DMA && MMU && !COLDFIRE
select ARCH_HAS_SYNC_DMA_FOR_DEVICE if HAS_DMA select ARCH_HAS_SYNC_DMA_FOR_DEVICE if HAS_DMA
select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
......
...@@ -24,6 +24,8 @@ static inline struct task_struct *get_current(void) ...@@ -24,6 +24,8 @@ static inline struct task_struct *get_current(void)
#define current get_current() #define current get_current()
#endif /* CONFNIG_MMU */ #endif /* CONFIG_MMU */
register unsigned long current_stack_pointer __asm__("sp");
#endif /* !(_M68K_CURRENT_H) */ #endif /* !(_M68K_CURRENT_H) */
...@@ -108,6 +108,7 @@ config PPC ...@@ -108,6 +108,7 @@ config PPC
select ARCH_ENABLE_MEMORY_HOTPLUG select ARCH_ENABLE_MEMORY_HOTPLUG
select ARCH_ENABLE_MEMORY_HOTREMOVE select ARCH_ENABLE_MEMORY_HOTREMOVE
select ARCH_HAS_COPY_MC if PPC64 select ARCH_HAS_COPY_MC if PPC64
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_WX if STRICT_KERNEL_RWX select ARCH_HAS_DEBUG_WX if STRICT_KERNEL_RWX
......
...@@ -60,6 +60,7 @@ config S390 ...@@ -60,6 +60,7 @@ config S390
select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM
select ARCH_ENABLE_MEMORY_HOTREMOVE select ARCH_ENABLE_MEMORY_HOTREMOVE
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2 select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VM_PGTABLE select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_WX select ARCH_HAS_DEBUG_WX
select ARCH_HAS_DEVMEM_IS_ALLOWED select ARCH_HAS_DEVMEM_IS_ALLOWED
......
...@@ -7,6 +7,7 @@ config SUPERH ...@@ -7,6 +7,7 @@ config SUPERH
select ARCH_HAVE_CUSTOM_GPIO_H select ARCH_HAVE_CUSTOM_GPIO_H
select ARCH_HAVE_NMI_SAFE_CMPXCHG if (GUSA_RB || CPU_SH4A) select ARCH_HAVE_NMI_SAFE_CMPXCHG if (GUSA_RB || CPU_SH4A)
select ARCH_HAS_BINFMT_FLAT if !MMU select ARCH_HAS_BINFMT_FLAT if !MMU
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_PTE_SPECIAL
......
...@@ -69,6 +69,7 @@ config X86 ...@@ -69,6 +69,7 @@ config X86
select ARCH_ENABLE_THP_MIGRATION if X86_64 && TRANSPARENT_HUGEPAGE select ARCH_ENABLE_THP_MIGRATION if X86_64 && TRANSPARENT_HUGEPAGE
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
select ARCH_HAS_CACHE_LINE_SIZE select ARCH_HAS_CACHE_LINE_SIZE
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE if !X86_PAE select ARCH_HAS_DEBUG_VM_PGTABLE if !X86_PAE
select ARCH_HAS_DEVMEM_IS_ALLOWED select ARCH_HAS_DEVMEM_IS_ALLOWED
......
...@@ -3,6 +3,7 @@ config XTENSA ...@@ -3,6 +3,7 @@ config XTENSA
def_bool y def_bool y
select ARCH_32BIT_OFF_T select ARCH_32BIT_OFF_T
select ARCH_HAS_BINFMT_FLAT if !MMU select ARCH_HAS_BINFMT_FLAT if !MMU
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DMA_PREP_COHERENT if MMU select ARCH_HAS_DMA_PREP_COHERENT if MMU
select ARCH_HAS_SYNC_DMA_FOR_CPU if MMU select ARCH_HAS_SYNC_DMA_FOR_CPU if MMU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE if MMU select ARCH_HAS_SYNC_DMA_FOR_DEVICE if MMU
......
...@@ -26,6 +26,8 @@ static inline struct task_struct *get_current(void) ...@@ -26,6 +26,8 @@ static inline struct task_struct *get_current(void)
#define current get_current() #define current get_current()
register unsigned long current_stack_pointer __asm__("a1");
#else #else
#define GET_CURRENT(reg,sp) \ #define GET_CURRENT(reg,sp) \
......
...@@ -19,14 +19,14 @@ struct stackframe { ...@@ -19,14 +19,14 @@ struct stackframe {
static __always_inline unsigned long *stack_pointer(struct task_struct *task) static __always_inline unsigned long *stack_pointer(struct task_struct *task)
{ {
unsigned long *sp; unsigned long sp;
if (!task || task == current) if (!task || task == current)
__asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp)); sp = current_stack_pointer;
else else
sp = (unsigned long *)task->thread.sp; sp = task->thread.sp;
return sp; return (unsigned long *)sp;
} }
void walk_stackframe(unsigned long *sp, void walk_stackframe(unsigned long *sp,
......
...@@ -36,9 +36,8 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) ...@@ -36,9 +36,8 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
#ifdef CONFIG_DEBUG_STACKOVERFLOW #ifdef CONFIG_DEBUG_STACKOVERFLOW
/* Debugging check for stack overflow: is there less than 1KB free? */ /* Debugging check for stack overflow: is there less than 1KB free? */
{ {
unsigned long sp; unsigned long sp = current_stack_pointer;
__asm__ __volatile__ ("mov %0, a1\n" : "=a" (sp));
sp &= THREAD_SIZE - 1; sp &= THREAD_SIZE - 1;
if (unlikely(sp < (sizeof(thread_info) + 1024))) if (unlikely(sp < (sizeof(thread_info) + 1024)))
......
...@@ -97,6 +97,10 @@ ...@@ -97,6 +97,10 @@
#define KASAN_ABI_VERSION 4 #define KASAN_ABI_VERSION 4
#endif #endif
#ifdef CONFIG_SHADOW_CALL_STACK
#define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
#endif
#if __has_attribute(__no_sanitize_address__) #if __has_attribute(__no_sanitize_address__)
#define __no_sanitize_address __attribute__((no_sanitize_address)) #define __no_sanitize_address __attribute__((no_sanitize_address))
#else #else
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#ifndef _LINUX_RANDOMIZE_KSTACK_H #ifndef _LINUX_RANDOMIZE_KSTACK_H
#define _LINUX_RANDOMIZE_KSTACK_H #define _LINUX_RANDOMIZE_KSTACK_H
#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/percpu-defs.h> #include <linux/percpu-defs.h>
...@@ -16,8 +17,20 @@ DECLARE_PER_CPU(u32, kstack_offset); ...@@ -16,8 +17,20 @@ DECLARE_PER_CPU(u32, kstack_offset);
* alignment. Also, since this use is being explicitly masked to a max of * alignment. Also, since this use is being explicitly masked to a max of
* 10 bits, stack-clash style attacks are unlikely. For more details see * 10 bits, stack-clash style attacks are unlikely. For more details see
* "VLAs" in Documentation/process/deprecated.rst * "VLAs" in Documentation/process/deprecated.rst
*
* The normal __builtin_alloca() is initialized with INIT_STACK_ALL (currently
* only with Clang and not GCC). Initializing the unused area on each syscall
* entry is expensive, and generating an implicit call to memset() may also be
* problematic (such as in noinstr functions). Therefore, if the compiler
* supports it (which it should if it initializes allocas), always use the
* "uninitialized" variant of the builtin.
*/ */
void *__builtin_alloca(size_t size); #if __has_builtin(__builtin_alloca_uninitialized)
#define __kstack_alloca __builtin_alloca_uninitialized
#else
#define __kstack_alloca __builtin_alloca
#endif
/* /*
* Use, at most, 10 bits of entropy. We explicitly cap this to keep the * Use, at most, 10 bits of entropy. We explicitly cap this to keep the
* "VLA" from being unbounded (see above). 10 bits leaves enough room for * "VLA" from being unbounded (see above). 10 bits leaves enough room for
...@@ -36,7 +49,7 @@ void *__builtin_alloca(size_t size); ...@@ -36,7 +49,7 @@ void *__builtin_alloca(size_t size);
if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \ if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \
&randomize_kstack_offset)) { \ &randomize_kstack_offset)) { \
u32 offset = raw_cpu_read(kstack_offset); \ u32 offset = raw_cpu_read(kstack_offset); \
u8 *ptr = __builtin_alloca(KSTACK_OFFSET_MAX(offset)); \ u8 *ptr = __kstack_alloca(KSTACK_OFFSET_MAX(offset)); \
/* Keep allocation even after "ptr" loses scope. */ \ /* Keep allocation even after "ptr" loses scope. */ \
asm volatile("" :: "r"(ptr) : "memory"); \ asm volatile("" :: "r"(ptr) : "memory"); \
} \ } \
...@@ -50,5 +63,9 @@ void *__builtin_alloca(size_t size); ...@@ -50,5 +63,9 @@ void *__builtin_alloca(size_t size);
raw_cpu_write(kstack_offset, offset); \ raw_cpu_write(kstack_offset, offset); \
} \ } \
} while (0) } while (0)
#else /* CONFIG_RANDOMIZE_KSTACK_OFFSET */
#define add_random_kstack_offset() do { } while (0)
#define choose_random_kstack_offset(rand) do { } while (0)
#endif /* CONFIG_RANDOMIZE_KSTACK_OFFSET */
#endif #endif
...@@ -853,7 +853,7 @@ static void __init mm_init(void) ...@@ -853,7 +853,7 @@ static void __init mm_init(void)
pti_init(); pti_init();
} }
#ifdef CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET #ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
DEFINE_STATIC_KEY_MAYBE_RO(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, DEFINE_STATIC_KEY_MAYBE_RO(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT,
randomize_kstack_offset); randomize_kstack_offset);
DEFINE_PER_CPU(u32, kstack_offset); DEFINE_PER_CPU(u32, kstack_offset);
......
...@@ -744,6 +744,15 @@ config IDLE_PAGE_TRACKING ...@@ -744,6 +744,15 @@ config IDLE_PAGE_TRACKING
config ARCH_HAS_CACHE_LINE_SIZE config ARCH_HAS_CACHE_LINE_SIZE
bool bool
config ARCH_HAS_CURRENT_STACK_POINTER
bool
help
In support of HARDENED_USERCOPY performing stack variable lifetime
checking, an architecture-agnostic way to find the stack pointer
is needed. Once an architecture defines an unsigned long global
register alias named "current_stack_pointer", this config can be
selected.
config ARCH_HAS_PTE_DEVMAP config ARCH_HAS_PTE_DEVMAP
bool bool
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* Returns: * Returns:
* NOT_STACK: not at all on the stack * NOT_STACK: not at all on the stack
* GOOD_FRAME: fully within a valid stack frame * GOOD_FRAME: fully within a valid stack frame
* GOOD_STACK: fully on the stack (when can't do frame-checking) * GOOD_STACK: within the current stack (when can't frame-check exactly)
* BAD_STACK: error condition (invalid stack position or bad stack frame) * BAD_STACK: error condition (invalid stack position or bad stack frame)
*/ */
static noinline int check_stack_object(const void *obj, unsigned long len) static noinline int check_stack_object(const void *obj, unsigned long len)
...@@ -55,6 +55,17 @@ static noinline int check_stack_object(const void *obj, unsigned long len) ...@@ -55,6 +55,17 @@ static noinline int check_stack_object(const void *obj, unsigned long len)
if (ret) if (ret)
return ret; return ret;
/* Finally, check stack depth if possible. */
#ifdef CONFIG_ARCH_HAS_CURRENT_STACK_POINTER
if (IS_ENABLED(CONFIG_STACK_GROWSUP)) {
if ((void *)current_stack_pointer < obj + len)
return BAD_STACK;
} else {
if (obj < (void *)current_stack_pointer)
return BAD_STACK;
}
#endif
return GOOD_STACK; return GOOD_STACK;
} }
...@@ -280,7 +291,15 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user) ...@@ -280,7 +291,15 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user)
*/ */
return; return;
default: default:
usercopy_abort("process stack", NULL, to_user, 0, n); usercopy_abort("process stack", NULL, to_user,
#ifdef CONFIG_ARCH_HAS_CURRENT_STACK_POINTER
IS_ENABLED(CONFIG_STACK_GROWSUP) ?
ptr - (void *)current_stack_pointer :
(void *)current_stack_pointer - ptr,
#else
0,
#endif
n);
} }
/* Check for bad heap object. */ /* Check for bad heap object. */
......
...@@ -37,6 +37,8 @@ gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \ ...@@ -37,6 +37,8 @@ gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \
+= -fplugin-arg-stackleak_plugin-track-min-size=$(CONFIG_STACKLEAK_TRACK_MIN_SIZE) += -fplugin-arg-stackleak_plugin-track-min-size=$(CONFIG_STACKLEAK_TRACK_MIN_SIZE)
gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \ gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \
+= -fplugin-arg-stackleak_plugin-arch=$(SRCARCH) += -fplugin-arg-stackleak_plugin-arch=$(SRCARCH)
gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK_VERBOSE) \
+= -fplugin-arg-stackleak_plugin-verbose
ifdef CONFIG_GCC_PLUGIN_STACKLEAK ifdef CONFIG_GCC_PLUGIN_STACKLEAK
DISABLE_STACKLEAK_PLUGIN += -fplugin-arg-stackleak_plugin-disable DISABLE_STACKLEAK_PLUGIN += -fplugin-arg-stackleak_plugin-disable
endif endif
......
...@@ -429,6 +429,23 @@ static unsigned int stackleak_cleanup_execute(void) ...@@ -429,6 +429,23 @@ static unsigned int stackleak_cleanup_execute(void)
return 0; return 0;
} }
/*
* STRING_CST may or may not be NUL terminated:
* https://gcc.gnu.org/onlinedocs/gccint/Constant-expressions.html
*/
static inline bool string_equal(tree node, const char *string, int length)
{
if (TREE_STRING_LENGTH(node) < length)
return false;
if (TREE_STRING_LENGTH(node) > length + 1)
return false;
if (TREE_STRING_LENGTH(node) == length + 1 &&
TREE_STRING_POINTER(node)[length] != '\0')
return false;
return !memcmp(TREE_STRING_POINTER(node), string, length);
}
#define STRING_EQUAL(node, str) string_equal(node, str, strlen(str))
static bool stackleak_gate(void) static bool stackleak_gate(void)
{ {
tree section; tree section;
...@@ -438,13 +455,17 @@ static bool stackleak_gate(void) ...@@ -438,13 +455,17 @@ static bool stackleak_gate(void)
if (section && TREE_VALUE(section)) { if (section && TREE_VALUE(section)) {
section = TREE_VALUE(TREE_VALUE(section)); section = TREE_VALUE(TREE_VALUE(section));
if (!strncmp(TREE_STRING_POINTER(section), ".init.text", 10)) if (STRING_EQUAL(section, ".init.text"))
return false;
if (STRING_EQUAL(section, ".devinit.text"))
return false;
if (STRING_EQUAL(section, ".cpuinit.text"))
return false; return false;
if (!strncmp(TREE_STRING_POINTER(section), ".devinit.text", 13)) if (STRING_EQUAL(section, ".meminit.text"))
return false; return false;
if (!strncmp(TREE_STRING_POINTER(section), ".cpuinit.text", 13)) if (STRING_EQUAL(section, ".noinstr.text"))
return false; return false;
if (!strncmp(TREE_STRING_POINTER(section), ".meminit.text", 13)) if (STRING_EQUAL(section, ".entry.text"))
return false; return false;
} }
......
...@@ -174,6 +174,16 @@ config GCC_PLUGIN_STACKLEAK ...@@ -174,6 +174,16 @@ config GCC_PLUGIN_STACKLEAK
* https://grsecurity.net/ * https://grsecurity.net/
* https://pax.grsecurity.net/ * https://pax.grsecurity.net/
config GCC_PLUGIN_STACKLEAK_VERBOSE
bool "Report stack depth analysis instrumentation" if EXPERT
depends on GCC_PLUGIN_STACKLEAK
depends on !COMPILE_TEST # too noisy
help
This option will cause a warning to be printed each time the
stackleak plugin finds a function it thinks needs to be
instrumented. This is useful for comparing coverage between
builds.
config STACKLEAK_TRACK_MIN_SIZE config STACKLEAK_TRACK_MIN_SIZE
int "Minimum stack frame size of functions tracked by STACKLEAK" int "Minimum stack frame size of functions tracked by STACKLEAK"
default 100 default 100
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment