@@ -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 \
@@ -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 */
@@ -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 */
@@ -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) */
@@ -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
@@ -149,8 +151,6 @@
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 */
@@ -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
@@ -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 */
@@ -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) */
new file mode 100644
@@ -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 */
@@ -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 */
@@ -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");
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> --- tools/include/nolibc/Makefile | 1 + tools/include/nolibc/arch-aarch64.h | 6 +++--- tools/include/nolibc/arch-arm.h | 6 +++--- tools/include/nolibc/arch-i386.h | 6 +++--- tools/include/nolibc/arch-loongarch.h | 6 +++--- tools/include/nolibc/arch-mips.h | 6 +++--- tools/include/nolibc/arch-riscv.h | 6 +++--- tools/include/nolibc/arch-x86_64.h | 6 +++--- tools/include/nolibc/compiler.h | 15 +++++++++++++++ tools/include/nolibc/stackprotector.h | 10 +++------- tools/testing/selftests/nolibc/nolibc-test.c | 4 ++-- 11 files changed, 42 insertions(+), 30 deletions(-)