mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default
@ 2024-11-25 15:35 Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 1/9] sandbox: asm: support inclusion from sandbox os support code Ahmad Fatoum
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox

In order to implement initjmp, we have two ways with available
functionality: The sigaltstack we are currently using and
makecontext/swapcontext. makecontext/swapcontext are unfortunately
deprecated in favor of POSIX threads and the sigaltstack runs afoul of
AddressSanitizer when compiled with clang.

This series fixes this by using the already existent assembly
implementations

Ahmad Fatoum (9):
  sandbox: asm: support inclusion from sandbox os support code
  test: self: setjmp: add simple initial testcase
  sandbox: source/invoke um Makefiles provided by host architecture
  sandbox: setjmp: mark C version as __weak
  sandbox: use native setjmp/longjmp/initjmp implementation by default
  sandbox: retire HAVE_ARCH_ASAN
  bthread: move asan fiber API into header
  test: self: setjmp: make compatible with ASAN
  bthread: fix use of ASAN fiber stack switch API

 Makefile                           |  2 +
 arch/Kconfig                       |  3 ++
 arch/arm/include/asm/setjmp.h      |  2 +
 arch/arm/um/Makefile               | 12 +++++
 arch/kvx/include/asm/setjmp.h      |  2 +
 arch/kvx/um/Makefile               |  6 +++
 arch/mips/include/asm/setjmp.h     |  2 +
 arch/mips/um/Makefile              |  6 +++
 arch/openrisc/include/asm/setjmp.h |  2 +
 arch/openrisc/um/Makefile          |  6 +++
 arch/powerpc/include/asm/setjmp.h  |  2 +
 arch/powerpc/um/Makefile           |  6 +++
 arch/riscv/include/asm/setjmp.h    |  2 +
 arch/riscv/um/Makefile             |  6 +++
 arch/sandbox/Kconfig               | 10 +++-
 arch/sandbox/Makefile              |  9 ++++
 arch/sandbox/include/asm/setjmp.h  | 44 +++++++++++++++-
 arch/sandbox/os/setjmp.c           |  6 +--
 arch/x86/include/asm/setjmp.h      |  2 +
 arch/x86/um/Makefile               | 12 +++++
 common/Kconfig                     |  3 --
 common/Kconfig.debug               |  5 +-
 common/bthread.c                   | 67 ++++++-----------------
 include/asm-generic/setjmp.h       | 27 ++++++++++
 scripts/subarch.include            | 11 ++++
 test/self/setjmp.c                 | 85 ++++++++++++++++++++++--------
 26 files changed, 260 insertions(+), 80 deletions(-)
 create mode 100644 arch/arm/um/Makefile
 create mode 100644 arch/kvx/um/Makefile
 create mode 100644 arch/mips/um/Makefile
 create mode 100644 arch/openrisc/um/Makefile
 create mode 100644 arch/powerpc/um/Makefile
 create mode 100644 arch/riscv/um/Makefile
 create mode 100644 arch/x86/um/Makefile
 create mode 100644 include/asm-generic/setjmp.h
 create mode 100644 scripts/subarch.include

-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/9] sandbox: asm: support inclusion from sandbox os support code
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 2/9] test: self: setjmp: add simple initial testcase Ahmad Fatoum
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

This will be needed in a later commit, when we start using it without
including normal barebox headers.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/sandbox/include/asm/setjmp.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h
index a300758c3d6c..dcc3b4e86712 100644
--- a/arch/sandbox/include/asm/setjmp.h
+++ b/arch/sandbox/include/asm/setjmp.h
@@ -4,7 +4,7 @@
 #define __SETJMP_H_
 
 struct jmp_buf_data {
-	unsigned char opaque[512] __aligned(16);
+	unsigned char opaque[512] __attribute__((__aligned__(16)));
 };
 
 typedef struct jmp_buf_data jmp_buf[1];
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/9] test: self: setjmp: add simple initial testcase
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 1/9] sandbox: asm: support inclusion from sandbox os support code Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 3/9] sandbox: source/invoke um Makefiles provided by host architecture Ahmad Fatoum
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

Instead of having a single complicate test, let's first have a simple
test than the existing two tests to make debugging easier.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 test/self/setjmp.c | 75 +++++++++++++++++++++++++++++++++-------------
 1 file changed, 54 insertions(+), 21 deletions(-)

diff --git a/test/self/setjmp.c b/test/self/setjmp.c
index 1cbb44bdf941..deac584d736d 100644
--- a/test/self/setjmp.c
+++ b/test/self/setjmp.c
@@ -14,6 +14,29 @@
 
 BSELFTEST_GLOBALS();
 
+static jmp_buf jbuf;
+
+static void test_setjmp_simple(void)
+{
+	total_tests++;
+
+	pr_debug("%s: saving jmp_buf\n", __func__);
+
+	switch (setjmp(jbuf)) {
+	case 0:
+		break;
+	case 42:
+		pr_debug("%s: returned from longjmp\n", __func__);
+		return;
+	default:
+		printf("%s: unexpected value from setjmp\n", __func__);
+		failed_tests++;
+	}
+
+	pr_debug("%s: attempting longjmp\n", __func__);
+	longjmp(jbuf, 42);
+}
+
 static __noreturn void raise_longjmp(jmp_buf jbuf, int i, int n)
 {
 	while (i < n)
@@ -22,28 +45,8 @@ static __noreturn void raise_longjmp(jmp_buf jbuf, int i, int n)
 	longjmp(jbuf, n);
 }
 
-static jmp_buf jbuf;
-
-static void __noreturn initjmp_entry(void)
+static void test_setjmp_loop(void)
 {
-	volatile u32 arr[256];
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(arr); i++)
-		writel(i, &arr[i]);
-
-	/* ensure arr[] is allocated on stack */
-	OPTIMIZER_HIDE_VAR(i);
-	if (i == 0)
-		initjmp_entry();
-
-	longjmp(jbuf, 0x1337);
-}
-
-static void test_setjmp(void)
-{
-	void *stack;
-	jmp_buf ijbuf;
 	volatile int i;
 	int ret;
 
@@ -71,6 +74,29 @@ static void test_setjmp(void)
 		failed_tests++;
 	}
 
+}
+
+static void __noreturn initjmp_entry(void)
+{
+	volatile u32 arr[256];
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(arr); i++)
+		writel(i, &arr[i]);
+
+	/* ensure arr[] is allocated on stack */
+	OPTIMIZER_HIDE_VAR(i);
+	if (i == 0)
+		initjmp_entry();
+
+	longjmp(jbuf, 0x1337);
+}
+
+static void test_initjmp(void)
+{
+	void *stack;
+	jmp_buf ijbuf;
+
 	stack = memalign(16, CONFIG_STACK_SIZE);
 	if (WARN_ON(!stack)) {
 		skipped_tests++;
@@ -95,4 +121,11 @@ static void test_setjmp(void)
 
 	free(stack);
 }
+
+static void test_setjmp(void)
+{
+	test_setjmp_simple();
+	test_setjmp_loop();
+	test_initjmp();
+}
 bselftest(core, test_setjmp);
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/9] sandbox: source/invoke um Makefiles provided by host architecture
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 1/9] sandbox: asm: support inclusion from sandbox os support code Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 2/9] test: self: setjmp: add simple initial testcase Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 4/9] sandbox: setjmp: mark C version as __weak Ahmad Fatoum
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

It can make sense to use an existing arch's implementation for low-level
things like setjmp/longjmp. Copy the Linux scheme that enables this.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 Makefile                |  2 ++
 arch/sandbox/Makefile   |  9 +++++++++
 scripts/subarch.include | 11 +++++++++++
 3 files changed, 22 insertions(+)
 create mode 100644 scripts/subarch.include

diff --git a/Makefile b/Makefile
index aa66d0cf3b38..bc75c6335177 100644
--- a/Makefile
+++ b/Makefile
@@ -321,6 +321,8 @@ KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(S
 BUILDSYSTEM_VERSION =
 export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION BUILDSYSTEM_VERSION
 
+include $(srctree)/scripts/subarch.include
+
 # Cross compiling and selecting different set of gcc/bin-utils
 # ---------------------------------------------------------------------------
 #
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 8f6425760619..157e856c59b1 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -19,6 +19,14 @@ board-y := arch/sandbox/board
 BOARD	:= $(board-y)/
 lds-y   := $(BOARD)/barebox.lds
 
+HEADER_ARCH 	:= $(SUBARCH)
+HOST_DIR := arch/$(HEADER_ARCH)
+
+-include $(srctree)/$(HOST_DIR)/Makefile.um
+
+common-y += $(HOST_DIR)/um/
+
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include
 
 TEXT_BASE = $(CONFIG_TEXT_BASE)
 KBUILD_CFLAGS += -Dmalloc=barebox_malloc -Dcalloc=barebox_calloc \
@@ -49,6 +57,7 @@ machdirs := $(patsubst %,arch/sandbox/mach-%/,$(machine-y))
 KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
 
 archprepare: maketools
+	$(Q)$(MAKE) $(build)=$(HOST_DIR)/um
 
 PHONY += maketools
 
diff --git a/scripts/subarch.include b/scripts/subarch.include
new file mode 100644
index 000000000000..caf3c641b52a
--- /dev/null
+++ b/scripts/subarch.include
@@ -0,0 +1,11 @@
+# SUBARCH tells the usermode build what the underlying arch is.  That is set
+# first, and if a usermode build is happening, the "ARCH=sandbox" on the command
+# line overrides the setting of ARCH below.  If a native build is happening,
+# then ARCH is assigned, getting whatever value it gets normally, and
+# SUBARCH is subsequently ignored.
+
+SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
+				  -e s/arm.*/arm/ -e s/sa110/arm/ \
+				  -e s/aarch64.*/arm/ \
+				  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
+				  -e s/riscv.*/riscv/)
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 4/9] sandbox: setjmp: mark C version as __weak
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
                   ` (2 preceding siblings ...)
  2024-11-25 15:35 ` [PATCH 3/9] sandbox: source/invoke um Makefiles provided by host architecture Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 5/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

In a later commit, we will start allowing overriding
setjmp/longjmp/initjmp by arch-specific implementations.

Prepare this by marking the existing implementation __weak.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/sandbox/os/setjmp.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/sandbox/os/setjmp.c b/arch/sandbox/os/setjmp.c
index 7f686b0fc6e9..cbf1182ed591 100644
--- a/arch/sandbox/os/setjmp.c
+++ b/arch/sandbox/os/setjmp.c
@@ -78,7 +78,7 @@ static void coroutine_trampoline(int signal)
 	coroutine_bootstrap(tr_state.entry);
 }
 
-int initjmp(_jmp_buf jmp, void (*func)(void), void *stack_top)
+int __attribute__((weak)) initjmp(_jmp_buf jmp, void (*func)(void), void *stack_top)
 {
 	struct sigaction sa;
 	struct sigaction osa;
@@ -169,12 +169,12 @@ int initjmp(_jmp_buf jmp, void (*func)(void), void *stack_top)
 	return 0;
 }
 
-int  __attribute__((returns_twice)) barebox_setjmp(_jmp_buf jmp)
+int __attribute__((weak,returns_twice)) barebox_setjmp(_jmp_buf jmp)
 {
 	return sigsetjmp(jmp, 0);
 }
 
-void __attribute((noreturn)) barebox_longjmp(_jmp_buf jmp, int ret)
+void __attribute__((weak,noreturn)) barebox_longjmp(_jmp_buf jmp, int ret)
 {
 	siglongjmp(jmp, ret);
 }
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 5/9] sandbox: use native setjmp/longjmp/initjmp implementation by default
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
                   ` (3 preceding siblings ...)
  2024-11-25 15:35 ` [PATCH 4/9] sandbox: setjmp: mark C version as __weak Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 6/9] sandbox: retire HAVE_ARCH_ASAN Ahmad Fatoum
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

In order to implement initjmp, we have two ways with available
functionality: The sigaltstack we are currently using and
makecontext/swapcontext. makecontext/swapcontext are unfortunately
deprecated in favor of POSIX threads and the sigaltstack runs afoul of
AddressSanitizer.

Let's therefore use the assembly version if we are using ASAN.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/um/Makefile      | 12 ++++++++++++
 arch/kvx/um/Makefile      |  6 ++++++
 arch/mips/um/Makefile     |  6 ++++++
 arch/openrisc/um/Makefile |  6 ++++++
 arch/powerpc/um/Makefile  |  6 ++++++
 arch/riscv/um/Makefile    |  6 ++++++
 arch/sandbox/Kconfig      |  8 ++++++++
 arch/x86/um/Makefile      | 12 ++++++++++++
 8 files changed, 62 insertions(+)
 create mode 100644 arch/arm/um/Makefile
 create mode 100644 arch/kvx/um/Makefile
 create mode 100644 arch/mips/um/Makefile
 create mode 100644 arch/openrisc/um/Makefile
 create mode 100644 arch/powerpc/um/Makefile
 create mode 100644 arch/riscv/um/Makefile
 create mode 100644 arch/x86/um/Makefile

diff --git a/arch/arm/um/Makefile b/arch/arm/um/Makefile
new file mode 100644
index 000000000000..380f59fdade2
--- /dev/null
+++ b/arch/arm/um/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj- := __dummy__.o
+
+ifeq ($(CONFIG_32BIT),y)
+	BITS := 32
+else
+	BITS := 64
+endif
+
+AFLAGS_../lib$(BITS)/setjmp.pbl.o := -Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp
+pbl-$(CONFIG_SANDBOX_SJLJ_ASM) += ../lib$(BITS)/setjmp.o
diff --git a/arch/kvx/um/Makefile b/arch/kvx/um/Makefile
new file mode 100644
index 000000000000..367946d33ac3
--- /dev/null
+++ b/arch/kvx/um/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj- := __dummy__.o
+
+AFLAGS_../lib/setjmp.pbl.o := -Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp
+pbl-$(CONFIG_SANDBOX_SJLJ_ASM) += ../lib/setjmp.o
diff --git a/arch/mips/um/Makefile b/arch/mips/um/Makefile
new file mode 100644
index 000000000000..367946d33ac3
--- /dev/null
+++ b/arch/mips/um/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj- := __dummy__.o
+
+AFLAGS_../lib/setjmp.pbl.o := -Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp
+pbl-$(CONFIG_SANDBOX_SJLJ_ASM) += ../lib/setjmp.o
diff --git a/arch/openrisc/um/Makefile b/arch/openrisc/um/Makefile
new file mode 100644
index 000000000000..367946d33ac3
--- /dev/null
+++ b/arch/openrisc/um/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj- := __dummy__.o
+
+AFLAGS_../lib/setjmp.pbl.o := -Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp
+pbl-$(CONFIG_SANDBOX_SJLJ_ASM) += ../lib/setjmp.o
diff --git a/arch/powerpc/um/Makefile b/arch/powerpc/um/Makefile
new file mode 100644
index 000000000000..367946d33ac3
--- /dev/null
+++ b/arch/powerpc/um/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj- := __dummy__.o
+
+AFLAGS_../lib/setjmp.pbl.o := -Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp
+pbl-$(CONFIG_SANDBOX_SJLJ_ASM) += ../lib/setjmp.o
diff --git a/arch/riscv/um/Makefile b/arch/riscv/um/Makefile
new file mode 100644
index 000000000000..367946d33ac3
--- /dev/null
+++ b/arch/riscv/um/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj- := __dummy__.o
+
+AFLAGS_../lib/setjmp.pbl.o := -Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp
+pbl-$(CONFIG_SANDBOX_SJLJ_ASM) += ../lib/setjmp.o
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index caff3a138fea..4cc3b201c399 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -65,6 +65,14 @@ config CMD_SANDBOX_CPUINFO
 	help
 	  Say yes here to get a dummy cpuinfo command.
 
+config SANDBOX_SJLJ_ASM
+	bool "use setjmp/longjmp/initjmp implemented in assembly" if COMPILE_TEST
+	default y
+	help
+	  sandbox has a C implementation of initjmp, which can run afoul of code
+	  hardening measures like ASAN. The assembly version isn't immune to these
+	  issues, but it's easier to reason about than the sigaltstack hack.
+
 config SDL
 	bool
 
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile
new file mode 100644
index 000000000000..d3764221a4c6
--- /dev/null
+++ b/arch/x86/um/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj- := __dummy__.o
+
+ifeq ($(CONFIG_32BIT),y)
+	BITS := 32
+else
+	BITS := 64
+endif
+
+AFLAGS_../lib/setjmp_$(BITS).o := -Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp
+obj-$(CONFIG_SANDBOX_SJLJ_ASM) += ../lib/setjmp_$(BITS).o
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 6/9] sandbox: retire HAVE_ARCH_ASAN
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
                   ` (4 preceding siblings ...)
  2024-11-25 15:35 ` [PATCH 5/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 7/9] bthread: move asan fiber API into header Ahmad Fatoum
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

For non-sandbox platforms, the config option is CONFIG_KASAN, so there
will not be any further platforms make using of HAVE_ARCH_ASAN.

Replace it by SANDBOX instead.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/sandbox/Kconfig | 1 -
 common/Kconfig       | 3 ---
 common/Kconfig.debug | 5 ++++-
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 4cc3b201c399..d4379c4d68db 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -7,7 +7,6 @@ config SANDBOX
 	select OFTREE
 	select GPIOLIB
 	select ARCH_HAS_UBSAN_SANITIZE_ALL
-	select HAVE_ARCH_ASAN
 	select HAS_DMA
 	select BLOCK
 	select BLOCK_WRITE
diff --git a/common/Kconfig b/common/Kconfig
index 9a63556378db..708caa6040a9 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1312,9 +1312,6 @@ config DDR_SPD
 	bool
 	select CRC_ITU_T
 
-config HAVE_ARCH_ASAN
-	bool
-
 config ARCH_USE_SYM_ANNOTATIONS
 	bool
 	help
diff --git a/common/Kconfig.debug b/common/Kconfig.debug
index 989f3ccc2a20..ea6864ac4d91 100644
--- a/common/Kconfig.debug
+++ b/common/Kconfig.debug
@@ -126,11 +126,14 @@ source "lib/kasan/Kconfig"
 
 config ASAN
 	bool "ASAN: runtime memory debugger"
-	depends on HAVE_ARCH_ASAN
+	depends on SANDBOX
 	help
 	  Enables ASAN (AddressSANitizer) - runtime memory debugger,
 	  designed to find out-of-bounds accesses and use-after-free bugs.
 
+	  This is the hosted implementation for sandbox as opposed to
+	  KASAN, which is the bare-metal implementation.
+
 config COMPILE_TEST
 	bool "compile-test drivers of other platforms"
 	default n
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 7/9] bthread: move asan fiber API into header
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
                   ` (5 preceding siblings ...)
  2024-11-25 15:35 ` [PATCH 6/9] sandbox: retire HAVE_ARCH_ASAN Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 8/9] test: self: setjmp: make compatible with ASAN Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 9/9] bthread: fix use of ASAN fiber stack switch API Ahmad Fatoum
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

Using the ASAN fibre API is essential, so the cooperative scheduling we
implement on top isn't flagged by AddressSanitizer.

To prepare using that code elsewhere later, move it to a common header.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/Kconfig                       |  3 ++
 arch/arm/include/asm/setjmp.h      |  2 +
 arch/kvx/include/asm/setjmp.h      |  2 +
 arch/mips/include/asm/setjmp.h     |  2 +
 arch/openrisc/include/asm/setjmp.h |  2 +
 arch/powerpc/include/asm/setjmp.h  |  2 +
 arch/riscv/include/asm/setjmp.h    |  2 +
 arch/sandbox/Kconfig               |  1 +
 arch/sandbox/include/asm/setjmp.h  | 42 ++++++++++++++++++++
 arch/x86/include/asm/setjmp.h      |  2 +
 common/bthread.c                   | 64 ++++++++----------------------
 include/asm-generic/setjmp.h       | 27 +++++++++++++
 12 files changed, 104 insertions(+), 47 deletions(-)
 create mode 100644 include/asm-generic/setjmp.h

diff --git a/arch/Kconfig b/arch/Kconfig
index ad47dbf78d6c..671e6a0e979d 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -18,3 +18,6 @@ config ARCH_HAS_CTRLC
 #
 config ARCH_DMA_DEFAULT_COHERENT
 	bool
+
+config ARCH_HAS_ASAN_FIBER_API
+	bool
diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h
index 0cee5bfdda60..d28235e56c36 100644
--- a/arch/arm/include/asm/setjmp.h
+++ b/arch/arm/include/asm/setjmp.h
@@ -28,4 +28,6 @@ void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 
 int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top);
 
+#include <asm-generic/setjmp.h>
+
 #endif /* _SETJMP_H_ */
diff --git a/arch/kvx/include/asm/setjmp.h b/arch/kvx/include/asm/setjmp.h
index 3c23576e6e82..7a09b182f251 100644
--- a/arch/kvx/include/asm/setjmp.h
+++ b/arch/kvx/include/asm/setjmp.h
@@ -12,4 +12,6 @@ int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *sta
 int setjmp(jmp_buf jmp) __attribute__((returns_twice));
 void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 
+#include <asm-generic/setjmp.h>
+
 #endif /* _ASM_KVX_SETJMP_H_ */
diff --git a/arch/mips/include/asm/setjmp.h b/arch/mips/include/asm/setjmp.h
index 39e01e27dfc0..af25678573e7 100644
--- a/arch/mips/include/asm/setjmp.h
+++ b/arch/mips/include/asm/setjmp.h
@@ -29,4 +29,6 @@ int setjmp(jmp_buf jmp) __attribute__((returns_twice));
 void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top);
 
+#include <asm-generic/setjmp.h>
+
 #endif /* _MIPS_BITS_SETJMP_H */
diff --git a/arch/openrisc/include/asm/setjmp.h b/arch/openrisc/include/asm/setjmp.h
index ee73306d189d..d652e8a3cbcc 100644
--- a/arch/openrisc/include/asm/setjmp.h
+++ b/arch/openrisc/include/asm/setjmp.h
@@ -14,4 +14,6 @@ int setjmp(jmp_buf jmp) __attribute__((returns_twice));
 void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top);
 
+#include <asm-generic/setjmp.h>
+
 #endif /* _OR1K_BITS_SETJMP_H */
diff --git a/arch/powerpc/include/asm/setjmp.h b/arch/powerpc/include/asm/setjmp.h
index 91bfcdb7f442..1ece16bb7ea7 100644
--- a/arch/powerpc/include/asm/setjmp.h
+++ b/arch/powerpc/include/asm/setjmp.h
@@ -18,4 +18,6 @@ void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 
 int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top);
 
+#include <asm-generic/setjmp.h>
+
 #endif /* _SETJMP_H_ */
diff --git a/arch/riscv/include/asm/setjmp.h b/arch/riscv/include/asm/setjmp.h
index 468fc4b10aaf..6604ba402bd9 100644
--- a/arch/riscv/include/asm/setjmp.h
+++ b/arch/riscv/include/asm/setjmp.h
@@ -24,4 +24,6 @@ void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 
 int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top);
 
+#include <asm-generic/setjmp.h>
+
 #endif /* _SETJMP_H_ */
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index d4379c4d68db..932bfd15d212 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -43,6 +43,7 @@ config 64BIT
 	default CC_IS_64BIT
 	select ARCH_DMA_ADDR_T_64BIT
 	select PHYS_ADDR_T_64BIT
+	select ARCH_HAS_ASAN_FIBER_API if ASAN
 
 config 32BIT
 	def_bool !64BIT
diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h
index dcc3b4e86712..65a6d5aafa87 100644
--- a/arch/sandbox/include/asm/setjmp.h
+++ b/arch/sandbox/include/asm/setjmp.h
@@ -1,4 +1,9 @@
 /* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This file is included both in arch/sandbox/os along with
+ * system headers and outside with barebox headers, so we avoid
+ * including any other headers here.
+ */
 
 #ifndef __SETJMP_H_
 #define __SETJMP_H_
@@ -14,4 +19,41 @@ void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
 
 int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top);
 
+#define start_switch_fiber start_switch_fiber
+#define finish_switch_fiber finish_switch_fiber
+
+void __sanitizer_start_switch_fiber(void **fake_stack_save,
+                                    const void *bottom, size_t size)
+    __attribute__((visibility("default")));
+
+void __sanitizer_finish_switch_fiber(void *fake_stack_save,
+                                     const void **bottom_old, size_t *size_old)
+    __attribute__((visibility("default")));
+
+static inline void finish_switch_fiber(void *fake_stack_save,
+                                       void **initial_bottom,
+                                       unsigned *initial_stack_size)
+{
+#ifdef CONFIG_ARCH_HAS_ASAN_FIBER_API
+    const void *bottom_old;
+    size_t size_old;
+
+    __sanitizer_finish_switch_fiber(fake_stack_save,
+                                    &bottom_old, &size_old);
+
+    if (initial_bottom && !*initial_bottom) {
+        *initial_bottom = (void *)bottom_old;
+        *initial_stack_size = size_old;
+    }
+#endif
+}
+
+static inline void start_switch_fiber(void **fake_stack_save,
+                                      const void *bottom, unsigned size)
+{
+#ifdef CONFIG_ARCH_HAS_ASAN_FIBER_API
+    __sanitizer_start_switch_fiber(fake_stack_save, bottom, size);
+#endif
+}
+
 #endif
diff --git a/arch/x86/include/asm/setjmp.h b/arch/x86/include/asm/setjmp.h
index 5af5e624895c..e0f5771b06ba 100644
--- a/arch/x86/include/asm/setjmp.h
+++ b/arch/x86/include/asm/setjmp.h
@@ -41,4 +41,6 @@ void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn)) __sjlj_attr;
 
 int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top) __sjlj_attr;
 
+#include <asm-generic/setjmp.h>
+
 #endif
diff --git a/common/bthread.c b/common/bthread.c
index d40c0b0f9e3a..943f4c22b346 100644
--- a/common/bthread.c
+++ b/common/bthread.c
@@ -15,10 +15,6 @@
 #include <asm/setjmp.h>
 #include <linux/overflow.h>
 
-#if defined CONFIG_ASAN && !defined CONFIG_32BIT
-#define HAVE_FIBER_SANITIZER
-#endif
-
 static struct bthread {
 	void (*threadfn)(void *);
 	void *data;
@@ -27,7 +23,7 @@ static struct bthread {
 	void *stack;
 	u32 stack_size;
 	struct list_head list;
-#ifdef HAVE_FIBER_SANITIZER
+#ifdef CONFIG_ARCH_HAS_ASAN_FIBER_API
 	void *fake_stack_save;
 #endif
 	u8 awake :1;
@@ -45,12 +41,22 @@ struct bthread *current = &main_thread;
 /*
  * When using ASAN, it needs to be told when we switch stacks.
  */
-static void start_switch_fiber(struct bthread *, bool terminate_old);
-static void finish_switch_fiber(struct bthread *);
+static void bthread_finish_switch_fiber(struct bthread *bthread)
+{
+	finish_switch_fiber(bthread->fake_stack_save,
+			    &main_thread.stack, &main_thread.stack_size);
+}
+
+static void bthread_start_switch_fiber(struct bthread *to, bool terminate_old)
+{
+	start_switch_fiber(terminate_old ? &to->fake_stack_save : NULL,
+			   to->stack, to->stack_size);
+}
 
 static void __noreturn bthread_trampoline(void)
 {
-	finish_switch_fiber(current);
+	bthread_finish_switch_fiber(current);
+
 	bthread_reschedule();
 
 	current->threadfn(current->data);
@@ -59,7 +65,7 @@ static void __noreturn bthread_trampoline(void)
 	current->has_stopped = true;
 
 	current = &main_thread;
-	start_switch_fiber(current, true);
+	bthread_start_switch_fiber(current, true);
 	longjmp(current->jmp_buf, 1);
 }
 
@@ -198,7 +204,7 @@ void bthread_schedule(struct bthread *to)
 	struct bthread *from = current;
 	int ret;
 
-	start_switch_fiber(to, false);
+	bthread_start_switch_fiber(to, false);
 
 	ret = setjmp(from->jmp_buf);
 	if (ret == 0) {
@@ -206,41 +212,5 @@ void bthread_schedule(struct bthread *to)
 		longjmp(to->jmp_buf, 1);
 	}
 
-	finish_switch_fiber(from);
+	bthread_finish_switch_fiber(from);
 }
-
-#ifdef HAVE_FIBER_SANITIZER
-
-void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size);
-void __sanitizer_finish_switch_fiber(void *fake_stack_save, const void **bottom_old, size_t *size_old);
-
-static void finish_switch_fiber(struct bthread *bthread)
-{
-	const void *bottom_old;
-	size_t size_old;
-
-	__sanitizer_finish_switch_fiber(bthread->fake_stack_save, &bottom_old, &size_old);
-
-	if (!main_thread.stack) {
-		main_thread.stack = (void *)bottom_old;
-		main_thread.stack_size = size_old;
-	}
-}
-
-static void start_switch_fiber(struct bthread *to, bool terminate_old)
-{
-	__sanitizer_start_switch_fiber(terminate_old ? &to->fake_stack_save : NULL,
-				       to->stack, to->stack_size);
-}
-
-#else
-
-static void finish_switch_fiber(struct bthread *bthread)
-{
-}
-
-static void start_switch_fiber(struct bthread *to, bool terminate_old)
-{
-}
-
-#endif
diff --git a/include/asm-generic/setjmp.h b/include/asm-generic/setjmp.h
new file mode 100644
index 000000000000..fb3e85ad5139
--- /dev/null
+++ b/include/asm-generic/setjmp.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ASAN bookkeeping based on Qemu coroutine-ucontext.c
+ */
+
+#ifndef __ASM_GENERIC_SETJMP_H_
+#define __ASM_GENERIC_SETJMP_H_
+
+#ifndef finish_switch_fiber
+#define finish_switch_fiber finish_switch_fiber
+static inline void finish_switch_fiber(void *fake_stack_save,
+                                       void **initial_bottom,
+                                       unsigned *initial_stack_size)
+{
+}
+#endif
+
+#ifndef start_switch_fiber
+#define start_switch_fiber start_switch_fiber
+static inline void start_switch_fiber(void **fake_stack_save,
+                                      const void *bottom, unsigned size)
+{
+}
+
+#endif
+
+#endif
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 8/9] test: self: setjmp: make compatible with ASAN
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
                   ` (6 preceding siblings ...)
  2024-11-25 15:35 ` [PATCH 7/9] bthread: move asan fiber API into header Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  2024-11-25 15:35 ` [PATCH 9/9] bthread: fix use of ASAN fiber stack switch API Ahmad Fatoum
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

ASAN currently flags the setjmp selftest. Use the newly exported fiber
API to fix this.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 test/self/setjmp.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/test/self/setjmp.c b/test/self/setjmp.c
index deac584d736d..0c7bc003361b 100644
--- a/test/self/setjmp.c
+++ b/test/self/setjmp.c
@@ -76,11 +76,16 @@ static void test_setjmp_loop(void)
 
 }
 
+static void *main_stack;
+static u32 main_stack_size;
+
 static void __noreturn initjmp_entry(void)
 {
 	volatile u32 arr[256];
 	int i;
 
+	finish_switch_fiber(NULL, &main_stack, &main_stack_size);
+
 	for (i = 0; i < ARRAY_SIZE(arr); i++)
 		writel(i, &arr[i]);
 
@@ -89,11 +94,13 @@ static void __noreturn initjmp_entry(void)
 	if (i == 0)
 		initjmp_entry();
 
+	start_switch_fiber(NULL, main_stack, main_stack_size);
 	longjmp(jbuf, 0x1337);
 }
 
 static void test_initjmp(void)
 {
+	void *fake_stack_save = NULL;
 	void *stack;
 	jmp_buf ijbuf;
 
@@ -114,11 +121,14 @@ static void test_initjmp(void)
 	case 0x1337:
 		break;
 	case 0:
+		start_switch_fiber(&fake_stack_save, stack, CONFIG_STACK_SIZE);
 		longjmp(ijbuf, 0x42);
 	default:
 		failed_tests++;
 	}
 
+	finish_switch_fiber(fake_stack_save, &main_stack, &main_stack_size);
+
 	free(stack);
 }
 
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 9/9] bthread: fix use of ASAN fiber stack switch API
  2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
                   ` (7 preceding siblings ...)
  2024-11-25 15:35 ` [PATCH 8/9] test: self: setjmp: make compatible with ASAN Ahmad Fatoum
@ 2024-11-25 15:35 ` Ahmad Fatoum
  8 siblings, 0 replies; 10+ messages in thread
From: Ahmad Fatoum @ 2024-11-25 15:35 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

We misused the fiber API so far and ASAN complained about it.
Fix this.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/bthread.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/common/bthread.c b/common/bthread.c
index 943f4c22b346..d8f1350f2e36 100644
--- a/common/bthread.c
+++ b/common/bthread.c
@@ -23,9 +23,6 @@ static struct bthread {
 	void *stack;
 	u32 stack_size;
 	struct list_head list;
-#ifdef CONFIG_ARCH_HAS_ASAN_FIBER_API
-	void *fake_stack_save;
-#endif
 	u8 awake :1;
 	u8 should_stop :1;
 	u8 should_clean :1;
@@ -41,21 +38,21 @@ struct bthread *current = &main_thread;
 /*
  * When using ASAN, it needs to be told when we switch stacks.
  */
-static void bthread_finish_switch_fiber(struct bthread *bthread)
+static void bthread_finish_switch_fiber(void *stack_save)
 {
-	finish_switch_fiber(bthread->fake_stack_save,
+	finish_switch_fiber(stack_save,
 			    &main_thread.stack, &main_thread.stack_size);
 }
 
-static void bthread_start_switch_fiber(struct bthread *to, bool terminate_old)
+static void bthread_start_switch_fiber(void **stack_save)
 {
-	start_switch_fiber(terminate_old ? &to->fake_stack_save : NULL,
-			   to->stack, to->stack_size);
+	start_switch_fiber(stack_save,
+			   current->stack, current->stack_size);
 }
 
 static void __noreturn bthread_trampoline(void)
 {
-	bthread_finish_switch_fiber(current);
+	bthread_finish_switch_fiber(NULL);
 
 	bthread_reschedule();
 
@@ -65,7 +62,7 @@ static void __noreturn bthread_trampoline(void)
 	current->has_stopped = true;
 
 	current = &main_thread;
-	bthread_start_switch_fiber(current, true);
+	bthread_start_switch_fiber(NULL);
 	longjmp(current->jmp_buf, 1);
 }
 
@@ -202,15 +199,15 @@ void bthread_reschedule(void)
 void bthread_schedule(struct bthread *to)
 {
 	struct bthread *from = current;
+	void *stack_save = NULL;
 	int ret;
 
-	bthread_start_switch_fiber(to, false);
-
 	ret = setjmp(from->jmp_buf);
 	if (ret == 0) {
 		current = to;
+		bthread_start_switch_fiber(&stack_save);
 		longjmp(to->jmp_buf, 1);
 	}
 
-	bthread_finish_switch_fiber(from);
+	bthread_finish_switch_fiber(stack_save);
 }
-- 
2.39.5




^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2024-11-25 15:36 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-11-25 15:35 [PATCH 0/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 1/9] sandbox: asm: support inclusion from sandbox os support code Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 2/9] test: self: setjmp: add simple initial testcase Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 3/9] sandbox: source/invoke um Makefiles provided by host architecture Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 4/9] sandbox: setjmp: mark C version as __weak Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 5/9] sandbox: use native setjmp/longjmp/initjmp implementation by default Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 6/9] sandbox: retire HAVE_ARCH_ASAN Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 7/9] bthread: move asan fiber API into header Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 8/9] test: self: setjmp: make compatible with ASAN Ahmad Fatoum
2024-11-25 15:35 ` [PATCH 9/9] bthread: fix use of ASAN fiber stack switch API Ahmad Fatoum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox