tools/nolibc: add autodetection for stackprotector support
authorThomas Weißschuh <linux@weissschuh.net>
Sun, 21 May 2023 09:36:34 +0000 (11:36 +0200)
committerPaul E. McKenney <paulmck@kernel.org>
Fri, 9 Jun 2023 18:46:08 +0000 (11:46 -0700)
The stackprotector support in nolibc should be enabled iff it is also
enabled in the compiler.
Use the preprocessor defines added by gcc and clang if stackprotector
support is enable to automatically do so in nolibc.

This completely removes the need for any user-visible API.

To avoid inlining the lengthy preprocessor check into every user
introduce a new header compiler.h that abstracts the logic away.

As the define NOLIBC_STACKPROTECTOR is now not user-relevant anymore
prefix it with an underscore.

Suggested-by: Willy Tarreau <w@1wt.eu>
Link: https://lore.kernel.org/lkml/20230520133237.GA27501@1wt.eu/
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
tools/include/nolibc/Makefile
tools/include/nolibc/arch-aarch64.h
tools/include/nolibc/arch-arm.h
tools/include/nolibc/arch-i386.h
tools/include/nolibc/arch-loongarch.h
tools/include/nolibc/arch-mips.h
tools/include/nolibc/arch-riscv.h
tools/include/nolibc/arch-x86_64.h
tools/include/nolibc/compiler.h [new file with mode: 0644]
tools/include/nolibc/stackprotector.h
tools/testing/selftests/nolibc/nolibc-test.c

index e37c3ac86e238f9c67a2bcf5cece1104b9a2aefc..64d67b080744e6601f9a46b252b14d89cb7901f9 100644 (file)
@@ -26,6 +26,7 @@ endif
 nolibc_arch := $(patsubst arm64,aarch64,$(ARCH))
 arch_file := arch-$(nolibc_arch).h
 all_files := \
+               compiler.h \
                ctype.h \
                errno.h \
                nolibc.h \
index 6a859131c530103bac4bedaf8ad387e1f708da1c..64ec65b4ee38dc9d5ba9dc02f286a8354d55a05e 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _NOLIBC_ARCH_AARCH64_H
 #define _NOLIBC_ARCH_AARCH64_H
 
+#include "compiler.h"
+
 /* The struct returned by the newfstatat() syscall. Differs slightly from the
  * x86_64's stat one by field ordering, so be careful.
  */
@@ -172,13 +174,11 @@ struct sys_stat_struct {
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
-#define __ARCH_SUPPORTS_STACK_PROTECTOR
-
 /* startup code */
 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void)
 {
        __asm__ volatile (
-#ifdef NOLIBC_STACKPROTECTOR
+#ifdef _NOLIBC_STACKPROTECTOR
                "bl __stack_chk_init\n"   /* initialize stack protector                     */
 #endif
                "ldr x0, [sp]\n"     /* argc (x0) was in the stack                          */
index 202e64f537dca112cedc7c3fdad36afaee4bb7d9..924169522cf7051ecf6772bef9098648ab47ef47 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _NOLIBC_ARCH_ARM_H
 #define _NOLIBC_ARCH_ARM_H
 
+#include "compiler.h"
+
 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
  * exactly 56 bytes (stops before the unused array). In big endian, the format
  * differs as devices are returned as short only.
@@ -199,13 +201,11 @@ struct sys_stat_struct {
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
-#define __ARCH_SUPPORTS_STACK_PROTECTOR
-
 /* startup code */
 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void)
 {
        __asm__ volatile (
-#ifdef NOLIBC_STACKPROTECTOR
+#ifdef _NOLIBC_STACKPROTECTOR
                "bl __stack_chk_init\n"       /* initialize stack protector                          */
 #endif
                "pop {%r0}\n"                 /* argc was in the stack                               */
index 7c41897a08ce15e8d6057871adaef8c5bc7c8730..37f813912957d4dd04e02d575247314bcdc0bd67 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _NOLIBC_ARCH_I386_H
 #define _NOLIBC_ARCH_I386_H
 
+#include "compiler.h"
+
 /* The struct returned by the stat() syscall, 32-bit only, the syscall returns
  * exactly 56 bytes (stops before the unused array).
  */
@@ -181,8 +183,6 @@ struct sys_stat_struct {
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
-#define __ARCH_SUPPORTS_STACK_PROTECTOR
-
 /* startup code */
 /*
  * i386 System V ABI mandates:
@@ -193,7 +193,7 @@ const unsigned long *_auxv __attribute__((weak));
 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void)
 {
        __asm__ volatile (
-#ifdef NOLIBC_STACKPROTECTOR
+#ifdef _NOLIBC_STACKPROTECTOR
                "call __stack_chk_init\n"   /* initialize stack protector                    */
 #endif
                "pop %eax\n"                /* argc   (first arg, %eax)                      */
index 07e3b1fd7262cd748de186ba2b9f3af4400645e7..d8ea7e787df4b1f8c170e303eef1fa0891946e2d 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _NOLIBC_ARCH_LOONGARCH_H
 #define _NOLIBC_ARCH_LOONGARCH_H
 
+#include "compiler.h"
+
 /* Syscalls for LoongArch :
  *   - stack is 16-byte aligned
  *   - syscall number is passed in a7
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
-#define __ARCH_SUPPORTS_STACK_PROTECTOR
-
 #if __loongarch_grlen == 32
 #define LONGLOG      "2"
 #define SZREG        "4"
@@ -175,7 +175,7 @@ const unsigned long *_auxv __attribute__((weak));
 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void)
 {
        __asm__ volatile (
-#ifdef NOLIBC_STACKPROTECTOR
+#ifdef _NOLIBC_STACKPROTECTOR
                "bl __stack_chk_init\n"               /* initialize stack protector                          */
 #endif
                REG_L        " $a0, $sp, 0\n"         /* argc (a0) was in the stack                          */
index 65c19ccc7f9d1c454fc88e903f01fe651eb579ba..9860236e5340b3859a8390ea32840f0737f78a50 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _NOLIBC_ARCH_MIPS_H
 #define _NOLIBC_ARCH_MIPS_H
 
+#include "compiler.h"
+
 /* The struct returned by the stat() syscall. 88 bytes are returned by the
  * syscall.
  */
@@ -179,8 +181,6 @@ struct sys_stat_struct {
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
-#define __ARCH_SUPPORTS_STACK_PROTECTOR
-
 /* startup code, note that it's called __start on MIPS */
 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) __start(void)
 {
@@ -189,7 +189,7 @@ void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protec
                ".set push\n"
                ".set    noreorder\n"
                ".option pic0\n"
-#ifdef NOLIBC_STACKPROTECTOR
+#ifdef _NOLIBC_STACKPROTECTOR
                "jal __stack_chk_init\n" /* initialize stack protector                         */
                "nop\n"                  /* delayed slot                                       */
 #endif
index d0439249c9c93b890aba154b0a7349197e7639a0..86616aeb77a0e9bff020dd70049f09ad12fb18f3 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _NOLIBC_ARCH_RISCV_H
 #define _NOLIBC_ARCH_RISCV_H
 
+#include "compiler.h"
+
 struct sys_stat_struct {
        unsigned long   st_dev;         /* Device.  */
        unsigned long   st_ino;         /* File serial number.  */
@@ -177,8 +179,6 @@ struct sys_stat_struct {
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
-#define __ARCH_SUPPORTS_STACK_PROTECTOR
-
 /* startup code */
 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void)
 {
@@ -187,7 +187,7 @@ void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protec
                ".option norelax\n"
                "lla   gp, __global_pointer$\n"
                ".option pop\n"
-#ifdef NOLIBC_STACKPROTECTOR
+#ifdef _NOLIBC_STACKPROTECTOR
                "call __stack_chk_init\n"    /* initialize stack protector                          */
 #endif
                REG_L" a0, 0(sp)\n"          /* argc (a0) was in the stack                          */
index e201af15e14256991923bae19d1f95008a92745d..485a7ff72a878887b3d635230bd94cf0d48485d2 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _NOLIBC_ARCH_X86_64_H
 #define _NOLIBC_ARCH_X86_64_H
 
+#include "compiler.h"
+
 /* The struct returned by the stat() syscall, equivalent to stat64(). The
  * syscall returns 116 bytes and stops in the middle of __unused.
  */
@@ -181,8 +183,6 @@ struct sys_stat_struct {
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
-#define __ARCH_SUPPORTS_STACK_PROTECTOR
-
 /* startup code */
 /*
  * x86-64 System V ABI mandates:
@@ -193,7 +193,7 @@ const unsigned long *_auxv __attribute__((weak));
 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void)
 {
        __asm__ volatile (
-#ifdef NOLIBC_STACKPROTECTOR
+#ifdef _NOLIBC_STACKPROTECTOR
                "call __stack_chk_init\n"   /* initialize stack protector                          */
 #endif
                "pop %rdi\n"                /* argc   (first arg, %rdi)                            */
diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h
new file mode 100644 (file)
index 0000000..57da75c
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * NOLIBC compiler support header
+ * Copyright (C) 2023 Thomas Weißschuh <linux@weissschuh.net>
+ */
+#ifndef _NOLIBC_COMPILER_H
+#define _NOLIBC_COMPILER_H
+
+#if defined(__SSP__) || defined(__SSP_STRONG__) || defined(__SSP_ALL__) || defined(__SSP_EXPLICIT__)
+
+#define _NOLIBC_STACKPROTECTOR
+
+#endif /* defined(__SSP__) ... */
+
+#endif /* _NOLIBC_COMPILER_H */
index b0156fc077a0270b764077c7cf307908aa330649..0a89e2b89ca614b16f9c15e2d702c5d025c93754 100644 (file)
@@ -7,13 +7,9 @@
 #ifndef _NOLIBC_STACKPROTECTOR_H
 #define _NOLIBC_STACKPROTECTOR_H
 
-#include "arch.h"
+#include "compiler.h"
 
-#if defined(NOLIBC_STACKPROTECTOR)
-
-#if !defined(__ARCH_SUPPORTS_STACK_PROTECTOR)
-#error "nolibc does not support stack protectors on this arch"
-#endif
+#if defined(_NOLIBC_STACKPROTECTOR)
 
 #include "sys.h"
 #include "stdlib.h"
@@ -49,6 +45,6 @@ void __stack_chk_init(void)
        if (__stack_chk_guard != (uintptr_t) &__stack_chk_guard)
                __stack_chk_guard ^= (uintptr_t) &__stack_chk_guard;
 }
-#endif /* defined(NOLIBC_STACKPROTECTOR) */
+#endif /* defined(_NOLIBC_STACKPROTECTOR) */
 
 #endif /* _NOLIBC_STACKPROTECTOR_H */
index 861b9a74b71ffe5d790598c201854224d8273706..b50b5a8bcc9031528c9b9ab41b24bdd0a1296530 100644 (file)
@@ -802,13 +802,13 @@ static int run_protection(int min, int max)
 
        llen += printf("0 -fstackprotector ");
 
-#if !defined(NOLIBC_STACKPROTECTOR)
+#if !defined(_NOLIBC_STACKPROTECTOR)
        llen += printf("not supported");
        pad_spc(llen, 64, "[SKIPPED]\n");
        return 0;
 #endif
 
-#if defined(NOLIBC_STACKPROTECTOR)
+#if defined(_NOLIBC_STACKPROTECTOR)
        if (!__stack_chk_guard) {
                llen += printf("__stack_chk_guard not initialized");
                pad_spc(llen, 64, "[FAIL]\n");