stackleak: Support Clang stack depth tracking
Subsystems (21)
Kees Cook
maintainerv4 cover stackleak: Support Clang stack depth tracking
v4:
- rebase on for-next/hardening tree (took subset of v3 patches)
- improve commit logs for x86 and arm64 changes (Mike, Will, Ard)
v3: https://lore.kernel.org/lkml/[email protected]/
v2: https://lore.kernel.org/lkml/[email protected]/
v1: https://lore.kernel.org/lkml/[email protected]/
Hi,
These are the remaining changes needed to support Clang stack depth tracking for kstack_erase (nee stackleak).
Thanks!
-Kees
Kees Cook (4):
arm64: Handle KCOV __init vs inline mismatches
x86: Handle KCOV __init vs inline mismatches init.h: Disable sanitizer coverage for __init and __head
kstack_erase: Support Clang stack depth tracking
security/Kconfig.hardening | 5 ++++- scripts/Makefile.kstack_erase | 6 ++++++ arch/arm64/include/asm/acpi.h | 2 +- arch/x86/include/asm/acpi.h | 4 ++-- arch/x86/include/asm/init.h | 2 +- arch/x86/include/asm/realmode.h | 2 +- include/linux/acpi.h | 4 ++-- include/linux/bootconfig.h | 2 +- include/linux/efi.h | 2 +- include/linux/init.h | 4 +++- include/linux/memblock.h | 2 +- include/linux/smp.h | 2 +- arch/x86/kernel/kvm.c | 2 +- arch/x86/mm/init_64.c | 2 +- kernel/kexec_handover.c | 4 ++-- 15 files changed, 28 insertions(+), 17 deletions(-)
Signature · 1 line
2.34.1
Kees Cook
maintainerPATCH v4 1/4 arm64: Handle KCOV __init vs inline mismatches
GCC appears to have kind of fragile inlining heuristics, in the sense that it can change whether or not it inlines something based on optimizations. It looks like the kcov instrumentation being added (or in this case, removed) from a function changes the optimization results, and some functions marked "inline" are _not_ inlined. In that case, we end up with __init code calling a function not marked __init, and we get the build warnings I'm trying to eliminate in the coming patch that adds __no_sanitize_coverage to __init functions:
WARNING: modpost: vmlinux: section mismatch in reference: acpi_get_enable_method+0x1c (section: .text.unlikely) -> acpi_psci_present (section: .init.text)
This problem is somewhat fragile (though using either __always_inline or __init will deterministically solve it), but we've tripped over this before with GCC and the solution has usually been to just use __always_inline and move on.
For arm64 this requires forcing one ACPI function to be inlined with __always_inline.
---
Cc: Will Deacon <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Jonathan Cameron <[email protected]>
Cc: Gavin Shan <[email protected]>
Cc: "Russell King (Oracle)" <[email protected]>
Cc: James Morse <[email protected]>
Cc: Oza Pawandeep <[email protected]>
Cc: Anshuman Khandual <[email protected]>
Cc: <[email protected]>
--- arch/arm64/include/asm/acpi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/acpi.h +1 -1
@@ -150,7 +150,7 @@ acpi_set_mailbox_entry(int cpu, struct acpi_madt_generic_interrupt *processor) {}#endif -static inline const char *acpi_get_enable_method (int cpu) +static __always_inline const char *acpi_get_enable_method(int cpu) {if (acpi_psci_present ())return "psci" ;
Signature · 1 line
2.34.1
Re: [PATCH v4 1/4] arm64: Handle KCOV __init vs inline mismatches
Quoted 40 lines · Kees Cook
GCC appears to have kind of fragile inlining heuristics, in the sense that it can change whether or not it inlines something based on optimizations. It looks like the kcov instrumentation being added (or in this case, removed) from a function changes the optimization results, and some functions marked "inline" are _not_ inlined. In that case, we end up with
__initcode calling a function not marked__init, and we get the build warnings I'm trying to eliminate in the coming patch that adds__no_sanitize_coverageto__initfunctions:WARNING: modpost: vmlinux: section mismatch in reference:
acpi_get_enable_method+0x1c(section: .text.unlikely) ->acpi_psci_present(section: .init.text)This problem is somewhat fragile (though using either
__always_inlineor__initwill deterministically solve it), but we've tripped over this before with GCC and the solution has usually been to just use__always_inlineand move on.For arm64 this requires forcing one ACPI function to be inlined with
__always_inline.Signed-off-by Kees Cook <[email protected]>---
Cc: Will Deacon <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Jonathan Cameron <[email protected]>
Cc: Gavin Shan <[email protected]>
Cc: "Russell King (Oracle)" <[email protected]>
Cc: James Morse <[email protected]>
Cc: Oza Pawandeep <[email protected]>
Cc: Anshuman Khandual <[email protected]>
Cc: <[email protected]>--- arch/arm64/include/asm/acpi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/arm64/include/asm/acpi.h +0
-0
arch/arm64/include/asm/acpi.h acpi_set_mailbox_entry(int cpu, struct acpi_madt_generic_interrupt *processor) · line 156
Quoted 8 lines
arch/arm64/include/asm/acpi.h +1
-1@@ -150,7 +150,7 @@ acpi_set_mailbox_entry(int cpu, struct acpi_madt_generic_interrupt *processor) {}#endif -static inline const char *acpi_get_enable_method (int cpu) +static __always_inline const char *acpi_get_enable_method(int cpu) {if (acpi_psci_present ())return "psci" ;
Thanks for improving the commit message:
Will
Kees Cook
maintainerPATCH v4 2/4 x86: Handle KCOV __init vs inline mismatches
In reply to Kees CookGCC appears to have kind of fragile inlining heuristics, in the sense that it can change whether or not it inlines something based on optimizations. It looks like the kcov instrumentation being added (or in this case, removed) from a function changes the optimization results, and some functions marked "inline" are _not_ inlined. In that case, we end up with __init code calling a function not marked __init, and we get the build warnings I'm trying to eliminate in the coming patch that adds __no_sanitize_coverage to __init functions:
WARNING: modpost: vmlinux: section mismatch in reference: xbc_exit+0x8 (section: .text.unlikely) -> _xbc_exit (section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference: real_mode_size_needed+0x15 (section: .text.unlikely) -> real_mode_blob_end (section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference: __set_percpu_decrypted+0x16 (section: .text.unlikely) -> early_set_memory_decrypted (section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference: memblock_alloc_from+0x26 (section: .text.unlikely) -> memblock_alloc_try_nid (section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference: acpi_arch_set_root_pointer+0xc (section: .text.unlikely) -> x86_init (section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference: acpi_arch_get_root_pointer+0x8 (section: .text.unlikely) -> x86_init (section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference: efi_config_table_is_usable+0x16 (section: .text.unlikely) -> xen_efi_config_table_is_usable (section: .init.text)
This problem is somewhat fragile (though using either __always_inline or __init will deterministically solve it), but we've tripped over this before with GCC and the solution has usually been to just use __always_inline and move on.
For x86 this means forcing several functions to be inline with __always_inline.
---
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Mike Rapoport <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: Vitaly Kuznetsov <[email protected]>
Cc: Henrique de Moraes Holschuh <[email protected]>
Cc: Hans de Goede <[email protected]>
Cc: "Ilpo Järvinen" <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Michal Wilczynski <[email protected]>
Cc: Juergen Gross <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: "Kirill A. Shutemov" <[email protected]>
Cc: Roger Pau Monne <[email protected]>
Cc: David Woodhouse <[email protected]>
Cc: Usama Arif <[email protected]>
Cc: "Guilherme G. Piccoli" <[email protected]>
Cc: Thomas Huth <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
--- arch/x86/include/asm/acpi.h | 4 ++-- arch/x86/include/asm/realmode.h | 2 +- include/linux/acpi.h | 4 ++-- include/linux/bootconfig.h | 2 +- include/linux/efi.h | 2 +- include/linux/memblock.h | 2 +- include/linux/smp.h | 2 +- arch/x86/kernel/kvm.c | 2 +- arch/x86/mm/init_64.c | 2 +- kernel/kexec_handover.c | 4 ++-- 10 files changed, 13 insertions(+), 13 deletions(-)
arch/x86/include/asm/acpi.h +2 -2
@@ -158,13 +158,13 @@ static inline bool acpi_has_cpu_in_madt(void) }#define ACPI_HAVE_ARCH_SET_ROOT_POINTER -static inline void acpi_arch_set_root_pointer (u64 addr) +static __always_inline void acpi_arch_set_root_pointer(u64 addr) { x86_init.acpi.set_root_pointer (addr); }#define ACPI_HAVE_ARCH_GET_ROOT_POINTER -static inline u64 acpi_arch_get_root_pointer (void ) +static __always_inline u64 acpi_arch_get_root_pointer(void) {return x86_init.acpi.get_root_pointer (); }
arch/x86/include/asm/realmode.h +1 -1
@@ -78,7 +78,7 @@ extern unsigned char secondary_startup_64[];extern unsigned char secondary_startup_64_no_verify[];#endif -static inline size_t real_mode_size_needed (void ) +static __always_inline size_t real_mode_size_needed(void) {if (real_mode_header)return 0 ;/* already allocated. */
include/linux/acpi.h +2 -2
@@ -759,13 +759,13 @@ int acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count)#endif #ifndef ACPI_HAVE_ARCH_SET_ROOT_POINTER -static inline void acpi_arch_set_root_pointer (u64 addr) +static __always_inline void acpi_arch_set_root_pointer(u64 addr) { }#endif #ifndef ACPI_HAVE_ARCH_GET_ROOT_POINTER -static inline u64 acpi_arch_get_root_pointer (void ) +static __always_inline u64 acpi_arch_get_root_pointer(void) {return 0 ; }
include/linux/bootconfig.h +1 -1
@@ -290,7 +290,7 @@ int __init xbc_get_info(int *node_size, size_t *data_size);/* XBC cleanup data structures */ void __init _xbc_exit (bool early); -static inline void xbc_exit (void ) +static __always_inline void xbc_exit(void) {_xbc_exit (false); }
include/linux/efi.h +1 -1
@@ -1336,7 +1336,7 @@ struct linux_efi_initrd {bool xen_efi_config_table_is_usable (const efi_guid_t *guid,unsigned long table); -static inline +static __always_inline bool efi_config_table_is_usable(const efi_guid_t *guid, unsigned long table) {if (!IS_ENABLED (CONFIG_XEN_EFI ))
include/linux/memblock.h +1 -1
@@ -463,7 +463,7 @@ static inline void *memblock_alloc_raw(phys_addr_t size, NUMA_NO_NODE); } -static inline void *memblock_alloc_from (phys_addr_t size, +static __always_inline void *memblock_alloc_from(phys_addr_t size,phys_addr_t align,phys_addr_t min_addr) {
include/linux/smp.h +1 -1
@@ -221,7 +221,7 @@ static inline void wake_up_all_idle_cpus(void) { }#ifdef CONFIG_UP_LATE_INIT extern void __init up_late_init (void ); -static inline void smp_init (void ) {up_late_init (); } +static __always_inline void smp_init(void) { up_late_init(); }#else static inline void smp_init (void ) { }#endif
arch/x86/kernel/kvm.c +1 -1
@@ -420,7 +420,7 @@ static u64 kvm_steal_clock(int cpu)return steal; } -static inline void __set_percpu_decrypted (void *ptr,unsigned long size) +static inline __init void __set_percpu_decrypted (void *ptr,unsigned long size) {early_set_memory_decrypted ((unsigned long ) ptr, size); }
arch/x86/mm/init_64.c +1 -1
@@ -805,7 +805,7 @@ kernel_physical_mapping_change(unsigned long paddr_start, }#ifndef CONFIG_NUMA -static inline void x86_numa_init (void ) +static __always_inline void x86_numa_init(void) {memblock_set_node (0 ,PHYS_ADDR_MAX , &memblock.memory,0 ); }
kernel/kexec_handover.c +2 -2
@@ -310,8 +310,8 @@ static int kho_mem_serialize(struct kho_serialization *ser)return -ENOMEM ; } -static void deserialize_bitmap (unsigned int order, -struct khoser_mem_bitmap_ptr *elm) +static void __init deserialize_bitmap (unsigned int order, +struct khoser_mem_bitmap_ptr *elm) {struct kho_mem_phys_bits *bitmap =KHOSER_LOAD_PTR (elm->bitmap);unsigned long bit;
Signature · 1 line
2.34.1
Re: [PATCH v4 2/4] x86: Handle KCOV __init vs inline mismatches
Quoted 22 lines · Kees Cook
GCC appears to have kind of fragile inlining heuristics, in the sense that it can change whether or not it inlines something based on optimizations. It looks like the kcov instrumentation being added (or in this case, removed) from a function changes the optimization results, and some functions marked "inline" are _not_ inlined. In that case, we end up with
__initcode calling a function not marked__init, and we get the build warnings I'm trying to eliminate in the coming patch that adds__no_sanitize_coverageto__initfunctions:WARNING: modpost: vmlinux: section mismatch in reference:
xbc_exit+0x8(section: .text.unlikely) ->_xbc_exit(section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference:real_mode_size_needed+0x15(section: .text.unlikely) ->real_mode_blob_end(section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference:__set_percpu_decrypted+0x16(section: .text.unlikely) ->early_set_memory_decrypted(section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference:memblock_alloc_from+0x26(section: .text.unlikely) ->memblock_alloc_try_nid(section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference:acpi_arch_set_root_pointer+0xc(section: .text.unlikely) ->x86_init(section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference:acpi_arch_get_root_pointer+0x8(section: .text.unlikely) ->x86_init(section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference:efi_config_table_is_usable+0x16(section: .text.unlikely) ->xen_efi_config_table_is_usable(section: .init.text)This problem is somewhat fragile (though using either
__always_inlineor__initwill deterministically solve it), but we've tripped over this before with GCC and the solution has usually been to just use__always_inlineand move on.
Quoted 4 lines
For x86 this means forcing several functions to be inline with
__always_inline.Signed-off-by Kees Cook <[email protected]>
For memblock bit:
Signature · 2 lines
Sincerely yours, Mike.
Re: [PATCH v4 2/4] x86: Handle KCOV __init vs inline mismatches
In reply to Kees CookQuoted 35 lines · Kees Cook
GCC appears to have kind of fragile inlining heuristics, in the sense that it can change whether or not it inlines something based on optimizations. It looks like the kcov instrumentation being added (or in this case, removed) from a function changes the optimization results, and some functions marked "inline" are _not_ inlined. In that case, we end up with
__initcode calling a function not marked__init, and we get the build warnings I'm trying to eliminate in the coming patch that adds__no_sanitize_coverageto__initfunctions:WARNING: modpost: vmlinux: section mismatch in reference:
xbc_exit+0x8(section: .text.unlikely) ->_xbc_exit(section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference:real_mode_size_needed+0x15(section: .text.unlikely) ->real_mode_blob_end(section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference:__set_percpu_decrypted+0x16(section: .text.unlikely) ->early_set_memory_decrypted(section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference:memblock_alloc_from+0x26(section: .text.unlikely) ->memblock_alloc_try_nid(section: .init.text)
WARNING: modpost: vmlinux: section mismatch in reference:acpi_arch_set_root_pointer+0xc(section: .text.unlikely) ->x86_init(section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference:acpi_arch_get_root_pointer+0x8(section: .text.unlikely) ->x86_init(section: .init.data)
WARNING: modpost: vmlinux: section mismatch in reference:efi_config_table_is_usable+0x16(section: .text.unlikely) ->xen_efi_config_table_is_usable(section: .init.text)This problem is somewhat fragile (though using either
__always_inlineor__initwill deterministically solve it), but we've tripped over this before with GCC and the solution has usually been to just use__always_inlineand move on.
Quoted 4 lines
For x86 this means forcing several functions to be inline with
__always_inline.Signed-off-by Kees Cook <[email protected]>
In my randconfig tests, I got these ones as well:
WARNING: modpost: vmlinux: section mismatch in reference: early_page_ext_enabled+0x14 (section: .text.unlikely) -> early_ page_ext (section: .init.data)
x86_64-linux-ld: lm75.c:(.text+0xd25): undefined reference to `i3c_device_do_priv_xfers'
And one more with a private patch of mine.
These are the fixups that make it build for arm/arm64/x86 randconfigs for me, so you could fold them as well in as well. I have already sent the i3c patch for upstream but not the page_ext.h patch.
include/linux/page_ext.h +2 -2
@@ -57,7 +57,7 @@ extern bool early_page_ext;extern unsigned long page_ext_size;extern void pgdat_page_ext_init (struct pglist_data *pgdat); -static inline bool early_page_ext_enabled (void ) +static __always_inline bool early_page_ext_enabled(void) {return early_page_ext; }
@@ -189,7 +189,7 @@ static inline struct page_ext *page_ext_iter_get(const struct page_ext_iter *ite#else /* !CONFIG_PAGE_EXTENSION */ struct page_ext ; -static inline bool early_page_ext_enabled (void ) +static __always_inline bool early_page_ext_enabled(void) {return false; }
include/linux/i3c/device.h +2 -2
@@ -245,7 +245,7 @@ void i3c_driver_unregister(struct i3c_driver *drv);* * Return: 0 if both registrations succeeds, a negative error code otherwise. */ -static inline int i3c_i2c_driver_register (struct i3c_driver *i3cdrv, +static __always_inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,struct i2c_driver *i2cdrv) {int ret;
@@ -270,7 +270,7 @@ static inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,* Note that when CONFIG_I3C is not enabled, this function only unregisters the * @i2cdrv. */ -static inline void i3c_i2c_driver_unregister (struct i3c_driver *i3cdrv, +static __always_inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv,struct i2c_driver *i2cdrv) {if (IS_ENABLED (CONFIG_I3C ))
As I understand, the underlying problem is less gcc inlining being fragile, but more that gcc does not inline functions when they have different __no_sanitize_coverage attributes.
Arnd
Kees Cook
maintainerPATCH v4 3/4 init.h: Disable sanitizer coverage for __init and __head
In reply to Kees CookWhile __noinstr already contained __no_sanitize_coverage, it needs to be added to __init and __head section markings to support the Clang implementation of CONFIG_KSTACK_ERASE. This is to make sure the stack depth tracking callback is not executed in unsupported contexts.
The other sanitizer coverage options (trace-pc and trace-cmp) aren't needed in __head nor __init either ("We are interested in code coverage as a function of a syscall inputs"[1]), so this is fine to disable for them as well.
---
Cc: Marco Elver <[email protected]>
Cc: Andrey Konovalov <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: "Kirill A. Shutemov" <[email protected]>
Cc: Hou Wenlong <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Masahiro Yamada <[email protected]>
Cc: "Peter Zijlstra (Intel)" <[email protected]>
Cc: Luis Chamberlain <[email protected]>
Cc: Sami Tolvanen <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Christophe Leroy <[email protected]>
Cc: <[email protected]>
--- arch/x86/include/asm/init.h | 2 +- include/linux/init.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-)
arch/x86/include/asm/init.h +1 -1
@@ -5,7 +5,7 @@#if defined(CONFIG_CC_IS_CLANG ) &&CONFIG_CLANG_VERSION <170000 #define __head __section(".head.text") __no_sanitize_undefined __no_stack_protector#else -#define __head __section(".head.text") __no_sanitize_undefined +#define __head __section(".head.text") __no_sanitize_undefined __no_sanitize_coverage#endif struct x86_mapping_info {
include/linux/init.h +3 -1
@@ -49,7 +49,9 @@/* These are for everybody (although not all archs will actually discard it in modules) */ -#define __init __section(".init.text") __cold __latent_entropy __noinitretpoline +#define __init __section(".init.text") __cold __latent_entropy \ + __noinitretpoline \ + __no_sanitize_coverage#define __initdata __section(".init.data")#define __initconst __section(".init.rodata")#define __exitdata __section(".exit.data")
Signature · 1 line
2.34.1
kernel test robot
build botRe: [PATCH v4 3/4] init.h: Disable sanitizer coverage for __init and __head
kernel test robot noticed the following build errors:
Hi Kees,
kernel test robot noticed the following build errors:
[auto build test ERROR on next-20250723]
[also build test ERROR on v6.16-rc7]
[cannot apply to tip/x86/core arm64/for-next/core soc/for-next linus/master v6.16-rc7 v6.16-rc6 v6.16-rc5] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Kees-Cook/arm64-Handle-KCOV-__init-vs-inline-mismatches/20250724-135311 base: next-20250723 patch link: https://lore.kernel.org/r/20250724055029.3623499-3-kees%40kernel.org patch subject: [PATCH v4 3/4] init.h: Disable sanitizer coverage for __init and __head config: arm64-randconfig-002-20250725 (https://download.01.org/0day-ci/archive/20250725/[email protected]/config) compiler: aarch64-linux-gcc (GCC) 12.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250725/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
aarch64-linux-ld: Unexpected GOT/PLT entries detected!
aarch64-linux-ld: Unexpected run-time procedure linkages detected!
aarch64-linux-ld: arch/arm/xen/enlighten.o: in function `xen_guest_init':
>> enlighten.c:(.init.text+0x364): undefined reference to `xen_efi_runtime_setup'
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Kees Cook
maintainerPATCH v4 4/4 kstack_erase: Support Clang stack depth tracking
In reply to Kees CookWire up CONFIG_KSTACK_ERASE to Clang 21's new stack depth tracking callback[1] option.
---
Cc: Arnd Bergmann <[email protected]>
Cc: Masahiro Yamada <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Marco Elver <[email protected]>
Cc: Andrey Konovalov <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
--- security/Kconfig.hardening | 5 ++++- scripts/Makefile.kstack_erase | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-)
security/Kconfig.hardening +4 -1
@@ -82,10 +82,13 @@ choice endchoice +config CC_HAS_SANCOV_STACK_DEPTH_CALLBACK + def_bool $(cc-option,-fsanitize-coverage-stack-depth-callback-min=1) + config KSTACK_ERASE bool "Poison kernel stack before returning from syscalls" depends on HAVE_ARCH_KSTACK_ERASE - depends on GCC_PLUGINS + depends on GCC_PLUGINS || CC_HAS_SANCOV_STACK_DEPTH_CALLBACK help This option makes the kernel erase the kernel stack before returning from system calls. This has the effect of leaving
scripts/Makefile.kstack_erase +6 -0
@@ -8,6 +8,12 @@ kstack-erase-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK_VERBOSE) += -fplugin-arg-stack DISABLE_KSTACK_ERASE := -fplugin-arg-stackleak_plugin-disable endif +ifdef CONFIG_CC_IS_CLANG +kstack-erase-cflags-y += -fsanitize-coverage=stack-depth +kstack-erase-cflags-y += -fsanitize-coverage-stack-depth-callback-min=$(CONFIG_KSTACK_ERASE_TRACK_MIN_SIZE) +DISABLE_KSTACK_ERASE := -fno-sanitize-coverage=stack-depth +endif + KSTACK_ERASE_CFLAGS := $(kstack-erase-cflags-y) export STACKLEAK_CFLAGS DISABLE_KSTACK_ERASE
Signature · 1 line
2.34.1
Re: [PATCH v4 4/4] kstack_erase: Support Clang stack depth tracking
Quoted 5 lines · Kees Cook
Wire up
CONFIG_KSTACK_ERASEto Clang 21's new stack depth tracking callback[1] option.
Quoted 14 lines
---
Cc: Arnd Bergmann <[email protected]>
Cc: Masahiro Yamada <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Marco Elver <[email protected]>
Cc: Andrey Konovalov <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
---
Nathan Chancellor
maintainerHi Kees,
Quoted 11 lines · Kees Cook
v4:
- rebase on for-next/hardening tree (took subset of v3 patches)
- improve commit logs for x86 and arm64 changes (Mike, Will, Ard)
v3: https://lore.kernel.org/lkml/[email protected]/
v2: https://lore.kernel.org/lkml/[email protected]/
v1: https://lore.kernel.org/lkml/[email protected]/Hi,
These are the remaining changes needed to support Clang stack depth tracking for
kstack_erase(nee stackleak).
A few build issues that I see when building next-20250725, which seem related to this series.
1. I see
ld.lld: error: undefined symbol: __sanitizer_cov_stack_depth
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
referenced by
atags_to_fdt.c
arch/arm/boot/compressed/atags_to_fdt.o:(atags_to_fdt)
make[5]: *** [arch/arm/boot/compressed/Makefile:152: arch/arm/boot/compressed/vmlinux] Error 1
when building ARCH=arm allmodconfig on next-20250725. The following diff appears to cure that one.
arch/arm/boot/compressed/Makefile +1 -2
@@ -9,7 +9,6 @@ OBJS = HEAD = head.o OBJS += misc.o decompress.o -CFLAGS_decompress.o += $(DISABLE_KSTACK_ERASE) ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y) OBJS += debug.o AFLAGS_head.o += -DDEBUG
@@ -96,7 +95,7 @@ KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin \ -I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \ - -I$(obj) + -I$(obj) $(DISABLE_KSTACK_ERASE) ccflags-remove-$(CONFIG_FUNCTION_TRACER) += -pg asflags-y := -DZIMAGE
--
2. I see
kernel/kstack_erase.c:168:2: warning: function with attribute 'no_caller_saved_registers' should only call a function with attribute 'no_caller_saved_registers' or be compiled with '-mgeneral-regs-only' [-Wexcessive-regsave]
168 | BUILD_BUG_ON(CONFIG_KSTACK_ERASE_TRACK_MIN_SIZE > KSTACK_ERASE_SEARCH_DEPTH);
| ^
include/linux/build_bug.h:50:2: note: expanded from macro 'BUILD_BUG_ON'
50 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
| ^
include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG'
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
| ^
include/linux/compiler_types.h:568:2: note: expanded from macro 'compiletime_assert'
568 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
include/linux/compiler_types.h:556:2: note: expanded from macro '_compiletime_assert'
556 | __compiletime_assert(condition, msg, prefix, suffix)
| ^
include/linux/compiler_types.h:549:4: note: expanded from macro '__compiletime_assert'
549 | prefix ## suffix(); \
| ^
<scratch space>:97:1: note: expanded from here
97 | __compiletime_assert_521
| ^
kernel/kstack_erase.c:168:2: note: '__compiletime_assert_521' declared here
include/linux/build_bug.h:50:2: note: expanded from macro 'BUILD_BUG_ON'
50 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
| ^
include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG'
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
| ^
include/linux/compiler_types.h:568:2: note: expanded from macro 'compiletime_assert'
568 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
include/linux/compiler_types.h:556:2: note: expanded from macro '_compiletime_assert'
556 | __compiletime_assert(condition, msg, prefix, suffix)
| ^
include/linux/compiler_types.h:546:26: note: expanded from macro '__compiletime_assert'
546 | __noreturn extern void prefix ## suffix(void) \
| ^
<scratch space>:96:1: note: expanded from here
96 | __compiletime_assert_521
| ^
kernel/kstack_erase.c:172:11: warning: function with attribute 'no_caller_saved_registers' should only call a function with attribute 'no_caller_saved_registers' or be compiled with '-mgeneral-regs-only' [-Wexcessive-regsave]
172 | if (sp < current->lowest_stack &&
| ^
arch/x86/include/asm/current.h:28:17: note: expanded from macro 'current'
28 | #define current get_current()
| ^
arch/x86/include/asm/current.h:20:44: note: 'get_current' declared here
20 | static __always_inline struct task_struct *get_current(void)
| ^
kernel/kstack_erase.c:173:37: warning: function with attribute 'no_caller_saved_registers' should only call a function with attribute 'no_caller_saved_registers' or be compiled with '-mgeneral-regs-only' [-Wexcessive-regsave]
173 | sp >= stackleak_task_low_bound(current)) {
| ^ arch/x86/include/asm/current.h:28:17: note: expanded from macro 'current'
28 | #define current get_current()
| ^
arch/x86/include/asm/current.h:20:44: note: 'get_current' declared here
20 | static __always_inline struct task_struct *get_current(void)
| ^
when building ARCH=i386 allmodconfig.
3. I see
In file included from kernel/fork.c:96:
include/linux/kstack_erase.h:29:37: error: passing 'const struct task_struct *' to parameter of type 'struct task_struct *' discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
29 | return (unsigned long)end_of_stack(tsk) + sizeof(unsigned long);
| ^~~ include/linux/sched/task_stack.h:56:63: note: passing argument to parameter 'p' here
56 | static inline unsigned long *end_of_stack(struct task_struct *p)
| ^
when building ARCH=loongarch allmodconfig, which does not support CONFIG_THREAD_INFO_IN_TASK it seems.
Cheers,
Nathan
Kees Cook
maintainerQuoted 2 lines · Nathan Chancellor
A few build issues that I see when building next-20250725, which seem related to this series.
AH! Thank you for letting me know!
Quoted 8 lines
1. I see
ld.lld: error: undefined symbol:
__sanitizer_cov_stack_depthQuoted 2 lines
Quoted 2 lines
Quoted 2 lines
referenced by
atags_to_fdt.c
arch/arm/boot/compressed/atags_to_fdt.o:(atags_to_fdt)make[5]: *** [
arch/arm/boot/compressed/Makefile:152:arch/arm/boot/compressed/vmlinux] Error 1when building ARCH=arm allmodconfig on next-20250725. The following diff appears to cure that one.
Ah-ha perfect. Yes, that matches what I was expecting to fix it, I was just about to start working on it, but you beat me to it. :) The same was reported here:
https://lore.kernel.org/all/CA+G9fYtBk8qnpWvoaFwymCx5s5i-5KXtPGpmf=_+UKJddCOnLA@mail.gmail.com
Quoted 5 lines
2. I see
kernel/kstack_erase.c:168:2: warning: function with attribute 'no_caller_saved_registers' should only call a function with attribute 'no_caller_saved_registers' or be compiled with '-mgeneral-regs-only' [-Wexcessive-regsave]
[...]
when building ARCH=i386 allmodconfig.
Oh, hm, I will figure that out.
Quoted 4 lines
3. I see
In file included from
kernel/fork.c:96:
include/linux/kstack_erase.h:29:37: error: passing 'const structtask_struct*' to parameter of type 'structtask_struct*' discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
Quoted 8 lines
29 | return (unsigned long)end_of_stack(tsk) + sizeof(unsigned long); | ^~~
include/linux/sched/task_stack.h:56:63: note: passing argument to parameter 'p' here
56 | static inline unsigned long *end_of_stack(structtask_struct*p)
| ^when building ARCH=loongarch allmodconfig, which does not support
CONFIG_THREAD_INFO_IN_TASKit seems.
Oh, eek. Yeah, I'll need to make an explicit dependency I guess? ("How did this ever work?")
Thanks again!
Signature · 1 line
Kees Cook
Kees Cook
maintainerQuoted 2 lines · Nathan Chancellor
ld.lld: error: undefined symbol:
__sanitizer_cov_stack_depthQuoted 1 line
Quoted 1 line
Quoted 1 line
referenced by
atags_to_fdt.c
Proposed fix:
https://lore.kernel.org/lkml/[email protected]/
Quoted 1 line
kernel/kstack_erase.c:168:2: warning: function with attribute 'no_caller_saved_registers' should only call a function with attribute 'no_caller_saved_registers' or be compiled with '-mgeneral-regs-only' [-Wexcessive-regsave]
Proposed fix:
https://lore.kernel.org/lkml/[email protected]/
Quoted 7 lines
In file included from
kernel/fork.c:96:
include/linux/kstack_erase.h:29:37: error: passing 'const structtask_struct*' to parameter of type 'structtask_struct*' discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]29 | return (unsigned long)end_of_stack(tsk) + sizeof(unsigned long); | ^~~
include/linux/sched/task_stack.h:56:63: note: passing argument to parameter 'p' here
56 | static inline unsigned long *end_of_stack(structtask_struct*p)
| ^
Proposed fix:
https://lore.kernel.org/lkml/[email protected]/
Thanks for the reports! :)
-Kees
Signature · 1 line
Kees Cook