Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <5930553c4721863d05921789c4a1681d@bu.edu>
Date: Sun, 6 Sep 2026 19:15:29 +0000
From: Khosro Moeini <khosro@...edu>
To: musl@...ts.openwall.com
Cc: khosro@...edu
Subject: [PATCH v2] x86_64: add CET shadow stack support

Enable CET shadow stack on x86_64 when the executable and all loaded
shared objects have the GNU_PROPERTY_X86_FEATURE_1_SHSTK bit set in
their .note.gnu.property note. If shadow stack is enabled for a process
dlopen of an object without the shadow stack property note fails.
Unlike glibc, this implementation does not check environment variables.
All the changes are guarded by SHSTK_ENABLED which is set through
the --enable-cet configuration option.

Signed-off-by: Khosro Moeini <khosro@...edu>
---
Thanks for the feedback. Regarding the concerns discussed in the older
thread:

sigaltstack: The main program and its signal handlers use the same
shadow stack, so there won't be resource problems. Please see:
    https://docs.kernel.org/next/x86/shstk.html#signal

ucontext: removed from POSIX and not supported in musl 

threads: musl uses clone for thread creation so shadow stack allocation
is handled by the kernel. pthread_cancel is fine as it only changes the
program counter.

setjmp and longjmp: setjmp and sigsetjmp are modified to store the
shadow stack pointer in __ss[2] and longjmp restores it.

vfork: vfork is modified to directly jmp back to caller when in child,
instead of going through __syscall_ret to not pop from the shadow stack,
which is shared with parent.

Changes since the last patch:
I separated the arch-dependent and independent code. shstk_arch.h is
the arch-dependent header and has the shadow stack related syscalls
and defines the arch-specific macros.

This patch is entirely hand-written.

Please CC on reply. Thanks.

 Makefile                                      |  11 +-
 arch/generic/shstk_arch.h                     |  35 ++++++
 arch/x86_64/note.s                            |  12 ++
 arch/x86_64/shstk_arch.h                      |  40 ++++++
 configure                                     |  29 +++++
 ldso/dynlink.c                                |  25 ++++
 src/env/__libc_start_main.c                   |  12 ++
 src/internal/shstk.h                          |  30 +++++
 src/ldso/shstk.c                              | 117 ++++++++++++++++++
 src/process/x86_64/{vfork.s => vfork.S}       |  13 ++
 src/setjmp/x86_64/{longjmp.s => longjmp.S}    |  24 ++++
 src/setjmp/x86_64/{setjmp.s => setjmp.S}      |   6 +
 .../x86_64/{sigsetjmp.s => sigsetjmp.S}       |  17 +++
 13 files changed, 367 insertions(+), 4 deletions(-)
 create mode 100644 arch/generic/shstk_arch.h
 create mode 100644 arch/x86_64/note.s
 create mode 100644 arch/x86_64/shstk_arch.h
 create mode 100644 src/internal/shstk.h
 create mode 100644 src/ldso/shstk.c
 rename src/process/x86_64/{vfork.s => vfork.S} (35%)
 rename src/setjmp/x86_64/{longjmp.s => longjmp.S} (52%)
 rename src/setjmp/x86_64/{setjmp.s => setjmp.S} (82%)
 rename src/signal/x86_64/{sigsetjmp.s => sigsetjmp.S} (56%)

diff --git a/Makefile b/Makefile
index 3ad88b3..0aa23b3 100644
--- a/Makefile
+++ b/Makefile
@@ -45,6 +45,7 @@ CPPFLAGS =
 CFLAGS =
 CFLAGS_AUTO = -Os -pipe
 CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc 
+ASM_NOTE =
 
 CFLAGS_ALL = $(CFLAGS_C99FSE)
 CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
@@ -135,16 +136,18 @@ CC_CMD = $(CC) $(CFLAGS_ALL) -c -o $@ $<
 
 # Choose invocation of assembler to be used
 ifeq ($(ADD_CFI),yes)
-	AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
+	AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< $(ASM_NOTE) | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
 else
-	AS_CMD = $(CC_CMD)
+	AS_CMD = cat $< $(ASM_NOTE) | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
 endif
 
+ASCPP_CMD = cat $< $(ASM_NOTE) | $(CC) $(CFLAGS_ALL) -iquote $(dir $<) -x assembler-with-cpp -c -o $@ -
+
 obj/%.o: $(srcdir)/%.s
 	$(AS_CMD)
 
 obj/%.o: $(srcdir)/%.S
-	$(CC_CMD)
+	$(ASCPP_CMD)
 
 obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC_CMD)
@@ -153,7 +156,7 @@ obj/%.lo: $(srcdir)/%.s
 	$(AS_CMD)
 
 obj/%.lo: $(srcdir)/%.S
-	$(CC_CMD)
+	$(ASCPP_CMD)
 
 obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
 	$(CC_CMD)
diff --git a/arch/generic/shstk_arch.h b/arch/generic/shstk_arch.h
new file mode 100644
index 0000000..3c28dd3
--- /dev/null
+++ b/arch/generic/shstk_arch.h
@@ -0,0 +1,35 @@
+#ifndef SHSTK_ARCH_H
+#define SHSTK_ARCH_H
+
+#if SHSTK_ENABLED
+
+#include <errno.h>
+#include <features.h>
+
+#define GNU_PROPERTY_FEATURE_1_AND   0xc0000002
+
+#define GNU_PROPERTY_FEATURE_1_SHSTK (1U << 1)
+
+#define ARCH_SHSTK_ENABLE 0x5001
+#define ARCH_SHSTK_LOCK   0x5003
+#define ARCH_SHSTK_STATUS 0x5005
+
+#define ARCH_SHSTK_SHSTK  1
+
+extern hidden unsigned long __shstk_status;
+
+static inline int __init_shstk_status(void)
+{
+	return -ENOTSUP;
+}
+
+static inline int __lock_shstk(void)
+{
+	return -ENOTSUP;
+}
+
+#define SHSTK_ENABLE() do { } while (0)
+
+#endif
+
+#endif
diff --git a/arch/x86_64/note.s b/arch/x86_64/note.s
new file mode 100644
index 0000000..cb03e5a
--- /dev/null
+++ b/arch/x86_64/note.s
@@ -0,0 +1,12 @@
+/* .note.gnu.property is 8-byte aligned in 64-bit objects */
+.section .note.gnu.property,"a"
+.balign 8
+.long 4          /* n_namesz: sizeof "GNU" */
+.long 16         /* n_descsz: one 8-byte-padded property */
+.long 5          /* n_type: NT_GNU_PROPERTY_TYPE_0 */
+.asciz "GNU"
+.long 0xc0000002 /* pr_type: GNU_PROPERTY_X86_FEATURE_1_AND */
+.long 4          /* pr_datasz */
+.long 2          /* GNU_PROPERTY_X86_FEATURE_1_SHSTK */
+.long 0          /* padding to 8-byte alignment */
+.previous
diff --git a/arch/x86_64/shstk_arch.h b/arch/x86_64/shstk_arch.h
new file mode 100644
index 0000000..c9c3561
--- /dev/null
+++ b/arch/x86_64/shstk_arch.h
@@ -0,0 +1,40 @@
+#ifndef SHSTK_ARCH_H
+#define SHSTK_ARCH_H
+
+#if SHSTK_ENABLED
+
+#include "syscall.h"
+
+#define GNU_PROPERTY_FEATURE_1_AND   0xc0000002
+
+#define GNU_PROPERTY_FEATURE_1_SHSTK (1U << 1)
+
+#define ARCH_SHSTK_ENABLE 0x5001
+#define ARCH_SHSTK_LOCK   0x5003
+#define ARCH_SHSTK_STATUS 0x5005
+
+#define ARCH_SHSTK_SHSTK  1
+
+extern hidden unsigned long __shstk_status;
+
+static inline int __init_shstk_status(void)
+{
+	return syscall(SYS_arch_prctl, ARCH_SHSTK_STATUS, &__shstk_status);
+}
+
+static inline int __lock_shstk(void)
+{
+	return syscall(SYS_arch_prctl, ARCH_SHSTK_LOCK, -1UL);
+}
+
+#define SHSTK_ENABLE() do { \
+       unsigned long ret; \
+       __asm__ __volatile__ ( "syscall" \
+               : "=a"(ret) \
+               : "a"(SYS_arch_prctl), "D"(ARCH_SHSTK_ENABLE), "S"(ARCH_SHSTK_SHSTK) \
+               : "rcx", "r11", "memory" ); \
+       } while (0)
+
+#endif
+
+#endif
diff --git a/configure b/configure
index bc9fbe4..a278c81 100755
--- a/configure
+++ b/configure
@@ -34,6 +34,7 @@ Optional features:
   --enable-wrapper=...    build given musl toolchain wrapper [auto]
   --disable-shared        inhibit building shared library [enabled]
   --disable-static        inhibit building static library [enabled]
+  --enable-cet            build with CET shadow stack support [disabled]
 
 Optional packages:
   --with-malloc=...       choose malloc implementation [mallocng]
@@ -142,6 +143,7 @@ static=yes
 wrapper=auto
 gcc_wrapper=no
 clang_wrapper=no
+cet=no
 malloc_dir=mallocng
 
 for arg ; do
@@ -172,6 +174,8 @@ case "$arg" in
 --disable-wrapper|--enable-wrapper=no) wrapper=no ;;
 --enable-gcc-wrapper|--enable-gcc-wrapper=yes) wrapper=yes ; gcc_wrapper=yes ;;
 --disable-gcc-wrapper|--enable-gcc-wrapper=no) wrapper=no ;;
+--enable-cet|--enable-cet=yes) cet=yes ;;
+--disable-cet|--enable-cet=no) cet=no ;;
 --with-malloc=*) malloc_dir=${arg#*=} ;;
 --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
 --host=*|--target=*) target=${arg#*=} ;;
@@ -759,6 +763,30 @@ fi
 test "$SUBARCH" \
 && printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH"
 
+ASM_NOTE=
+if test "$cet" = yes ; then
+
+if test "$ARCH" != "x86_64" ; then
+fail "$0: error: --enable-cet is only supported on x86_64"
+fi
+
+tryflag CFLAGS_AUTO -fcf-protection=return \
+|| fail "$0: error: --enable-cet requires compiler support for -fcf-protection"
+
+printf "checking whether assembler supports rdssp/incssp instructions... "
+echo "__asm__(\"xor %eax,%eax ; rdsspq %rax ; incsspq %rax\");" > "$tmpc"
+if $CC -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
+printf "yes\n"
+else
+printf "no\n"
+fail "$0: error: --enable-cet requires assembler support for rdssp/incssp"
+fi
+
+CFLAGS_AUTO="$CFLAGS_AUTO -DSHSTK_ENABLED=1"
+
+ASM_NOTE="arch/$ARCH/note.s"
+fi
+
 #
 # Some archs (powerpc) have different possible long double formats
 # that the compiler can be configured for. The logic for whether this
@@ -820,6 +848,7 @@ CFLAGS_AUTO = $CFLAGS_AUTO
 CFLAGS_C99FSE = $CFLAGS_C99FSE
 CFLAGS_MEMOPS = $CFLAGS_MEMOPS
 CFLAGS_NOSSP = $CFLAGS_NOSSP
+ASM_NOTE = $ASM_NOTE
 CPPFLAGS = $CPPFLAGS
 LDFLAGS = $LDFLAGS
 LDFLAGS_AUTO = $LDFLAGS_AUTO
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 10471b2..61c989a 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -23,6 +23,7 @@
 #include "fork_impl.h"
 #include "libc.h"
 #include "dynlink.h"
+#include "shstk.h"
 
 static size_t ldso_page_size;
 /* libc.h may have defined a macro for dynamic PAGE_SIZE already, but
@@ -702,6 +703,9 @@ static void *map_library(int fd, struct dso *dso)
 	size_t dyn=0;
 	size_t tls_image=0;
 	size_t i;
+#if SHSTK_ENABLED
+	Phdr *gnu_prop_ph = NULL;
+#endif
 
 	ssize_t l = read(fd, buf, sizeof buf);
 	eh = buf;
@@ -741,6 +745,10 @@ static void *map_library(int fd, struct dso *dso)
 					ph->p_memsz < DEFAULT_STACK_MAX ?
 					ph->p_memsz : DEFAULT_STACK_MAX;
 			}
+#if SHSTK_ENABLED
+		} else if (ph->p_type == PT_GNU_PROPERTY) {
+			gnu_prop_ph = ph;
+#endif
 		}
 		if (ph->p_type != PT_LOAD) continue;
 		nsegs++;
@@ -862,6 +870,13 @@ done_mapping:
 	dso->base = base;
 	dso->dynv = laddr(dso, dyn);
 	if (dso->tls.size) dso->tls.image = laddr(dso, tls_image);
+#if SHSTK_ENABLED
+	int ret = __try_update_feature_1_and((size_t)base, gnu_prop_ph);
+	if (ret) {
+		errno = ret;
+		goto error;
+	}
+#endif
 	free(allocated_buf);
 	return map;
 noexec:
@@ -1455,6 +1470,10 @@ static void kernel_mapped_dso(struct dso *p)
 					ph->p_memsz < DEFAULT_STACK_MAX ?
 					ph->p_memsz : DEFAULT_STACK_MAX;
 			}
+#if SHSTK_ENABLED
+		} else if (ph->p_type == PT_GNU_PROPERTY) {
+			__update_feature_1_and((size_t)p->base, ph);
+#endif
 		}
 		if (ph->p_type != PT_LOAD) continue;
 		if (ph->p_vaddr < min_addr)
@@ -1637,6 +1656,12 @@ void __init_tls(size_t *auxv)
 {
 }
 
+#if SHSTK_ENABLED
+void __init_feature_1_and(void)
+{
+}
+#endif
+
 static void update_tls_size()
 {
 	libc.tls_cnt = tls_cnt;
diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
index c5b277b..7a1e960 100644
--- a/src/env/__libc_start_main.c
+++ b/src/env/__libc_start_main.c
@@ -6,6 +6,8 @@
 #include "syscall.h"
 #include "atomic.h"
 #include "libc.h"
+#include "shstk.h"
+#include "shstk_arch.h"
 
 static void dummy(void) {}
 weak_alias(dummy, _init);
@@ -89,6 +91,16 @@ int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv,
 static int libc_start_main_stage2(int (*main)(int,char **,char **), int argc, char **argv)
 {
 	char **envp = argv+argc+1;
+
+#if SHSTK_ENABLED
+	__init_feature_1_and();
+	if (__feature_1_and & GNU_PROPERTY_FEATURE_1_SHSTK) {
+		SHSTK_ENABLE();
+		__lock_shstk();
+	}
+	__init_shstk_status();
+#endif
+
 	__libc_start_init();
 
 	/* Pass control to the application */
diff --git a/src/internal/shstk.h b/src/internal/shstk.h
new file mode 100644
index 0000000..8d97c4a
--- /dev/null
+++ b/src/internal/shstk.h
@@ -0,0 +1,30 @@
+#ifndef SHSTK_H
+#define SHSTK_H
+
+#if SHSTK_ENABLED
+
+#include <elf.h>
+#include <stddef.h>
+#include <features.h>
+
+#if ULONG_MAX == 0xffffffff
+typedef Elf32_Addr Addr;
+typedef Elf32_Phdr Phdr;
+typedef Elf32_Nhdr Nhdr;
+#else
+typedef Elf64_Addr Addr;
+typedef Elf64_Phdr Phdr;
+typedef Elf64_Nhdr Nhdr;
+#endif
+
+extern hidden unsigned __feature_1_and;
+
+hidden void __init_feature_1_and(void);
+
+hidden void __update_feature_1_and(size_t base, Phdr *ph);
+
+hidden int __try_update_feature_1_and(size_t base, Phdr *ph);
+
+#endif
+
+#endif
diff --git a/src/ldso/shstk.c b/src/ldso/shstk.c
new file mode 100644
index 0000000..ddcd5aa
--- /dev/null
+++ b/src/ldso/shstk.c
@@ -0,0 +1,117 @@
+#if SHSTK_ENABLED
+
+#include <errno.h>
+#include <string.h>
+#include <stddef.h>
+#include "libc.h"
+#include "shstk.h"
+#include "shstk_arch.h"
+
+hidden unsigned __feature_1_and = -1;
+hidden unsigned long __shstk_status = 0;
+
+#define ALIGNMENT sizeof(Addr)
+#define ALIGN_UP(x,y) ((x)+(y)-1 & -(y))
+#define DESC_HDR_SIZE 8
+
+/* gnu properties are a sequence of type/size/value */
+static unsigned get_feature_from_note(size_t p, size_t len)
+{
+	size_t end = p + len;
+	while (p + DESC_HDR_SIZE <= end) {
+		uint32_t type, datasz;
+		type = *(uint32_t *)p;
+		p += sizeof(uint32_t);
+		datasz = *(uint32_t *)p;
+		p += sizeof(uint32_t);
+		if (p + datasz > end) return 0;
+		if (type == GNU_PROPERTY_FEATURE_1_AND) {
+			uint32_t feature;
+			if (datasz != 4) return 0;
+			feature = *(uint32_t *)p;
+			return feature;
+		}
+		/* kernel v6.18 /fs/bifmt_efl.c:758 says: */
+		/* Properties are supposed to be unique and sorted on pr_type: */
+		if (type > GNU_PROPERTY_FEATURE_1_AND) return 0;
+		p += ALIGN_UP(datasz, ALIGNMENT);
+	}
+	return 0;
+}
+
+static unsigned get_feature_from_header(size_t base, Phdr *ph)
+{
+	if (!ph || ph->p_align != ALIGNMENT) return 0;
+	size_t end = base + ph->p_vaddr + ph->p_memsz;
+	size_t p = base + ph->p_vaddr;
+	while (p + sizeof(Nhdr) <= end) {
+	    Nhdr *nh = (Nhdr *)p;
+		size_t desc_offset = ALIGN_UP(sizeof(Nhdr) + nh->n_namesz, ALIGNMENT); 
+		if (nh->n_namesz == 4
+		    && nh->n_type == NT_GNU_PROPERTY_TYPE_0
+		    && p + desc_offset + nh->n_descsz <= end
+		    && !memcmp((void *)(p + sizeof(Nhdr)), "GNU", 4)) {
+			return get_feature_from_note(p + desc_offset, nh->n_descsz);
+		}
+		p += desc_offset;
+		p += ALIGN_UP(nh->n_descsz, ALIGNMENT);
+	}
+	return 0;
+}
+
+/* four cases here:
+ * (1) feature set, shstk set -> dlopen, should fail if no shstk note
+ * (2) feature set, shstk not set -> initial loading, should update feature
+ * (3) feature not set, shstk not set -> no update needed
+ * (4) feature not set, shstk set -> impossible */
+hidden int __try_update_feature_1_and(size_t base, Phdr *ph)
+{
+	if (!(__feature_1_and & GNU_PROPERTY_FEATURE_1_SHSTK))
+		return 0;
+	/* feature is set */
+	unsigned long dso_features = get_feature_from_header(base, ph);
+	if (!(__shstk_status & ARCH_SHSTK_SHSTK)) {
+		__feature_1_and &= dso_features;
+		return 0;
+	}
+	/* feature and shstk are set */
+	if (dso_features & GNU_PROPERTY_FEATURE_1_SHSTK)
+		return 0;
+	return ENOTSUP;
+}
+
+hidden void __update_feature_1_and(size_t base, Phdr *ph)
+{
+	__feature_1_and &= get_feature_from_header(base, ph);
+}
+
+#define AUX_CNT 38
+extern weak hidden const size_t _DYNAMIC[];
+
+static void static_init_feature_1_and(void)
+{
+	unsigned char *p;
+	Phdr *phdr, *gnu_prop_ph = NULL;
+	size_t base = 0;
+	size_t n;
+	size_t i, aux[AUX_CNT] = { 0 };
+
+	for (i=0; libc.auxv[i]; i+=2)
+		if (libc.auxv[i]<AUX_CNT) aux[libc.auxv[i]] = libc.auxv[i+1];
+
+	for (p=(void *)aux[AT_PHDR],n=aux[AT_PHNUM]; n; n--,p+=aux[AT_PHENT]) {
+		phdr = (void *)p;
+		if (phdr->p_type == PT_PHDR)
+			base = aux[AT_PHDR] - phdr->p_vaddr;
+		if (phdr->p_type == PT_DYNAMIC && _DYNAMIC)
+			base = (size_t)_DYNAMIC - phdr->p_vaddr;
+		if (phdr->p_type == PT_GNU_PROPERTY)
+			gnu_prop_ph = phdr;
+	}
+
+	__feature_1_and = get_feature_from_header(base, gnu_prop_ph);
+}
+
+weak_alias(static_init_feature_1_and, __init_feature_1_and);
+
+#endif
diff --git a/src/process/x86_64/vfork.s b/src/process/x86_64/vfork.S
similarity index 35%
rename from src/process/x86_64/vfork.s
rename to src/process/x86_64/vfork.S
index 9114439..da4aea5 100644
--- a/src/process/x86_64/vfork.s
+++ b/src/process/x86_64/vfork.S
@@ -4,6 +4,19 @@ vfork:
 	pop %rdx
 	mov $58,%eax
 	syscall
+#if SHSTK_ENABLED
+	/* If parent normal return */
+	test %eax,%eax
+	jnz 1f
+	/* If child and no shstk normal return */
+	xor %ecx,%ecx
+	rdsspq %rcx
+	test %rcx,%rcx
+	jz 1f
+	/* If child and shstk jmp instead, no need to call __syscall_ret */
+	jmp *%rdx
+1:
+#endif
 	push %rdx
 	mov %rax,%rdi
 	.hidden __syscall_ret
diff --git a/src/setjmp/x86_64/longjmp.s b/src/setjmp/x86_64/longjmp.S
similarity index 52%
rename from src/setjmp/x86_64/longjmp.s
rename to src/setjmp/x86_64/longjmp.S
index 1b2661c..9169996 100644
--- a/src/setjmp/x86_64/longjmp.s
+++ b/src/setjmp/x86_64/longjmp.S
@@ -5,6 +5,30 @@
 .type longjmp,@function
 _longjmp:
 longjmp:
+#if SHSTK_ENABLED
+	xor %ecx,%ecx
+	rdsspq %rcx
+	test %rcx,%rcx
+	jz 2f
+	/* if shstk is active */
+	mov 88(%rdi),%rdx       /* shadow stack pointer saved by setjmp */
+	sub %rcx,%rdx
+	/* target below current */
+	jb 2f
+	/* slots between current and target */
+	/* 3^2 = 8 = q in incsspq */
+	shr $3,%rdx
+	/* plus the slot setjmp itself returned to */
+	add $1,%rdx
+	/* incssp pops at most 255 slots at a time */
+1:	mov $255,%rcx
+	cmp %rcx,%rdx
+	cmovb %rdx,%rcx
+	incsspq %rcx
+	sub %rcx,%rdx
+	ja 1b
+2:
+#endif
 	xor %eax,%eax
 	cmp $1,%esi             /* CF = val ? 0 : 1 */
 	adc %esi,%eax           /* eax = val + !val */
diff --git a/src/setjmp/x86_64/setjmp.s b/src/setjmp/x86_64/setjmp.S
similarity index 82%
rename from src/setjmp/x86_64/setjmp.s
rename to src/setjmp/x86_64/setjmp.S
index d95e485..47ce57a 100644
--- a/src/setjmp/x86_64/setjmp.s
+++ b/src/setjmp/x86_64/setjmp.S
@@ -18,5 +18,11 @@ setjmp:
 	mov %rdx,48(%rdi)
 	mov (%rsp),%rdx         /* save return addr ptr for new rip */
 	mov %rdx,56(%rdi)
+#if SHSTK_ENABLED
+	/* store shstk pointer in __ss[2] = (72 + 2*8) = 88 */
+	xor %eax,%eax
+	rdsspq %rax
+	mov %rax,88(%rdi)
+#endif
 	xor %eax,%eax           /* always return 0 */
 	ret
diff --git a/src/signal/x86_64/sigsetjmp.s b/src/signal/x86_64/sigsetjmp.S
similarity index 56%
rename from src/signal/x86_64/sigsetjmp.s
rename to src/signal/x86_64/sigsetjmp.S
index 9a7695f..e88d277 100644
--- a/src/signal/x86_64/sigsetjmp.s
+++ b/src/signal/x86_64/sigsetjmp.S
@@ -18,7 +18,24 @@ __sigsetjmp:
 	mov %eax,%esi
 	mov 72+8(%rbx),%rbx
 
+#if SHSTK_ENABLED
+	test %eax,%eax
+	jnz 2f
+
+	/* original call */
+	xor %edx,%edx
+	rdsspq %rdx
+	/* store shstk pointer in __ss[2] */
+	/* rdi holds the jmp_buf now */
+	mov %rdx,88(%rdi)
+#endif
 .hidden __sigsetjmp_tail
 	jmp __sigsetjmp_tail
 
+#if SHSTK_ENABLED
+2:	call __sigsetjmp_tail
+	pop %rdx
+	jmp *%rdx
+#endif
+
 1:	jmp setjmp@PLT
-- 
2.49.1

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.