aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/x86_64
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2024-01-05 09:32:37 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2024-01-09 13:55:51 -0300
commitb7fc4a07f206a640e6d807d72f5c1ee3ea7a25b6 (patch)
tree51669d2e37be82d006f4f665f47274ed78273cbb /sysdeps/unix/sysv/linux/x86_64
parent46e713be5770b19568fab074afbc7d992b0c3624 (diff)
downloadglibc-b7fc4a07f206a640e6d807d72f5c1ee3ea7a25b6.zip
glibc-b7fc4a07f206a640e6d807d72f5c1ee3ea7a25b6.tar.gz
glibc-b7fc4a07f206a640e6d807d72f5c1ee3ea7a25b6.tar.bz2
x86: Move CET infrastructure to x86_64
The CET is only supported for x86_64 and there is no plan to add kernel support for i386. Move the Makefile rules and files from the generic x86 folder to x86_64 one. Checked on x86_64-linux-gnu and i686-linux-gnu.
Diffstat (limited to 'sysdeps/unix/sysv/linux/x86_64')
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/Makefile27
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/include/asm/prctl.h22
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/tst-cet-property-1.c44
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/tst-cet-property-2.c63
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/tst-cet-property-dep-2.S63
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/tst-cet-setcontext-1.c126
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/tst-cet-vfork-1.c79
7 files changed, 424 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/x86_64/Makefile b/sysdeps/unix/sysv/linux/x86_64/Makefile
index 06b8739..4223feb 100644
--- a/sysdeps/unix/sysv/linux/x86_64/Makefile
+++ b/sysdeps/unix/sysv/linux/x86_64/Makefile
@@ -64,3 +64,30 @@ $(objpfx)libx86-64-isa-level.so: $(objpfx)libx86-64-isa-level-1.so
cp $< $@
endif
endif # $(subdir) == elf
+
+ifneq ($(enable-cet),no)
+ifeq ($(subdir),elf)
+tests += tst-cet-property-1 tst-cet-property-2
+
+CFLAGS-tst-cet-property-1.o += -fcf-protection
+ASFLAGS-tst-cet-property-dep-2.o += -fcf-protection
+
+$(objpfx)tst-cet-property-2: $(objpfx)tst-cet-property-dep-2.o
+$(objpfx)tst-cet-property-2.out: $(objpfx)tst-cet-property-2 \
+ $(objpfx)tst-cet-property-1.out
+ env $(run-program-env) $(test-via-rtld-prefix) \
+ $(objpfx)tst-cet-property-2 \
+ < $(objpfx)tst-cet-property-1.out > $@; \
+ $(evaluate-test)
+endif
+
+ifeq ($(subdir),posix)
+tests += tst-cet-vfork-1
+CFLAGS-tst-cet-vfork-1.c += -mshstk
+endif
+
+ifeq ($(subdir),stdlib)
+tests += tst-cet-setcontext-1
+CFLAGS-tst-cet-setcontext-1.c += -mshstk
+endif
+endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/include/asm/prctl.h b/sysdeps/unix/sysv/linux/x86_64/include/asm/prctl.h
new file mode 100644
index 0000000..2f51132
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/include/asm/prctl.h
@@ -0,0 +1,22 @@
+/* FIXME: CET arch_prctl bits should come from the kernel header files.
+ This file should be removed if <asm/prctl.h> from the required kernel
+ header files contains CET arch_prctl bits. */
+
+#include_next <asm/prctl.h>
+
+#ifndef ARCH_SHSTK_ENABLE
+/* Enable SHSTK features in unsigned long int features. */
+# define ARCH_SHSTK_ENABLE 0x5001
+/* Disable SHSTK features in unsigned long int features. */
+# define ARCH_SHSTK_DISABLE 0x5002
+/* Lock SHSTK features in unsigned long int features. */
+# define ARCH_SHSTK_LOCK 0x5003
+/* Unlock SHSTK features in unsigned long int features. */
+# define ARCH_SHSTK_UNLOCK 0x5004
+/* Return SHSTK features in unsigned long int features. */
+# define ARCH_SHSTK_STATUS 0x5005
+
+/* ARCH_SHSTK_ features bits */
+# define ARCH_SHSTK_SHSTK 0x1
+# define ARCH_SHSTK_WRSS 0x2
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-1.c b/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-1.c
new file mode 100644
index 0000000..e13c752
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-1.c
@@ -0,0 +1,44 @@
+/* Test CET property note parser.
+ Copyright (C) 2018-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <elf.h>
+#include <tcb-offsets.h>
+
+/* This test prints out "IBT" if Intel indirect branch tracking (IBT)
+ is enabled at run-time, which is checked by tst-cet-property-2 to
+ verify that the IBT violation is caught on IBT machines. */
+
+static int
+do_test (void)
+{
+ unsigned int feature_1;
+#ifdef __x86_64__
+# define SEG_REG "fs"
+#else
+# define SEG_REG "gs"
+#endif
+ asm ("movl %%" SEG_REG ":%P1, %0"
+ : "=r" (feature_1) : "i" (FEATURE_1_OFFSET));
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0)
+ printf ("IBT\n");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-2.c b/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-2.c
new file mode 100644
index 0000000..5274a09
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-2.c
@@ -0,0 +1,63 @@
+/* Test CET property note parser for [BZ #23467].
+ Copyright (C) 2018-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <support/check.h>
+
+extern void bar (void);
+
+void
+__attribute__ ((noclone, noinline))
+test (void (*func_p) (void))
+{
+ func_p ();
+}
+
+/* bar contains an IBT violation if it is called indirectly via a
+ function pointer. On IBT machines, it should lead to segfault
+ unless IBT is disabled by error. */
+
+static void
+sig_handler (int signo)
+{
+ exit (EXIT_SUCCESS);
+}
+
+static int
+do_test (void)
+{
+ char buf[4];
+
+ if (scanf ("%3s", buf) != 1)
+ FAIL_UNSUPPORTED ("IBT not supported");
+
+ if (strcmp (buf, "IBT") != 0)
+ FAIL_UNSUPPORTED ("IBT not supported");
+
+ TEST_VERIFY_EXIT (signal (SIGSEGV, &sig_handler) != SIG_ERR);
+
+ /* Call bar via a function pointer to force an IBT violation. */
+ test (bar);
+
+ return EXIT_FAILURE;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-dep-2.S b/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-dep-2.S
new file mode 100644
index 0000000..6a8dd8b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/tst-cet-property-dep-2.S
@@ -0,0 +1,63 @@
+/* Test CET property note parser.
+ Copyright (C) 2018-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <cet.h>
+
+ .text
+ .p2align 4,,15
+ .globl bar
+ .type bar, @function
+/* Since this function doesn't start with ENDBR, it should lead to the
+ IBT violation when called indirectly. */
+bar:
+ .cfi_startproc
+ ret
+ .cfi_endproc
+ .size bar, .-bar
+
+#if __SIZEOF_PTRDIFF_T__ == 8
+# define ALIGN 3
+#elif __SIZEOF_PTRDIFF_T__ == 4
+# define ALIGN 2
+#endif
+
+/* In NT_GNU_PROPERTY_TYPE_0 note, add a GNU_PROPERTY_STACK_SIZE property
+ before the GNU_PROPERTY_X86_FEATURE_1_AND property. */
+ .section ".note.gnu.property", "a"
+ .p2align ALIGN
+ .long 1f - 0f /* name length */
+ .long 5f - 2f /* data length */
+ .long 5 /* note type */
+0: .asciz "GNU" /* vendor name */
+1:
+ .p2align ALIGN
+2:
+ .long 1 /* pr_type. */
+ .long 4f - 3f /* pr_datasz. */
+3:
+#if __SIZEOF_PTRDIFF_T__ == 8
+ .long 0x800
+ .long 0x800
+#else
+ .long 0x08000800
+#endif
+4:
+ .p2align ALIGN
+5:
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/sysdeps/unix/sysv/linux/x86_64/tst-cet-setcontext-1.c b/sysdeps/unix/sysv/linux/x86_64/tst-cet-setcontext-1.c
new file mode 100644
index 0000000..388931f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/tst-cet-setcontext-1.c
@@ -0,0 +1,126 @@
+/* Check getcontext and setcontext on the context from makecontext
+ with shadow stack.
+ Copyright (C) 2018-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <ucontext.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdatomic.h>
+#include <x86intrin.h>
+
+static ucontext_t ctx[5];
+static atomic_int done;
+
+static void
+__attribute__((noinline, noclone))
+f2 (void)
+{
+ printf ("start f2\n");
+ done++;
+ if (setcontext (&ctx[2]) != 0)
+ {
+ printf ("%s: setcontext: %m\n", __FUNCTION__);
+ exit (EXIT_FAILURE);
+ }
+}
+
+static void
+f1 (void)
+{
+ printf ("start f1\n");
+ if (getcontext (&ctx[2]) != 0)
+ {
+ printf ("%s: getcontext: %m\n", __FUNCTION__);
+ exit (EXIT_FAILURE);
+ }
+ if (done)
+ exit (EXIT_SUCCESS);
+ f2 ();
+}
+
+static int
+do_test (void)
+{
+ char st1[32768];
+ puts ("making contexts");
+ if (getcontext (&ctx[0]) != 0)
+ {
+ printf ("%s: getcontext: %m\n", __FUNCTION__);
+ exit (EXIT_FAILURE);
+ }
+ if (getcontext (&ctx[1]) != 0)
+ {
+ printf ("%s: getcontext: %m\n", __FUNCTION__);
+ exit (EXIT_FAILURE);
+ }
+
+ ctx[3].uc_stack.ss_sp = st1;
+ ctx[3].uc_stack.ss_size = sizeof st1;
+ ctx[3].uc_link = &ctx[0];
+ makecontext (&ctx[3], (void (*) (void)) f1, 0);
+
+ ctx[1].uc_stack.ss_sp = st1;
+ ctx[1].uc_stack.ss_size = sizeof st1;
+ ctx[1].uc_link = &ctx[0];
+ makecontext (&ctx[1], (void (*) (void)) f1, 0);
+
+ ctx[4].uc_stack.ss_sp = st1;
+ ctx[4].uc_stack.ss_size = sizeof st1;
+ ctx[4].uc_link = &ctx[0];
+ makecontext (&ctx[4], (void (*) (void)) f1, 0);
+
+ /* NB: When shadow stack is enabled, makecontext calls map_shadow_stack
+ to allocate a new shadow stack which can be unmapped. The base
+ address and size of the new shadow stack are returned in __ssp[1]
+ and __ssp[2]. makecontext is called for CTX1, CTX3 and CTX4. But
+ only CTX1 is used. New shadow stacks are allocated in the order
+ of CTX3, CTX1, CTX4. It is very likely that CTX1's shadow stack is
+ placed between CTX3 and CTX4. We munmap CTX3's and CTX4's shadow
+ stacks to create gaps above and below CTX1's shadow stack. We check
+ that setcontext CTX1 works correctly in this case. */
+ if (_get_ssp () != 0)
+ {
+ if (ctx[3].__ssp[1] != 0
+ && munmap ((void *) (uintptr_t) ctx[3].__ssp[1],
+ (size_t) ctx[3].__ssp[2]) != 0)
+ {
+ printf ("%s: munmap: %m\n", __FUNCTION__);
+ exit (EXIT_FAILURE);
+ }
+
+ if (ctx[4].__ssp[1] != 0
+ && munmap ((void *) (uintptr_t) ctx[4].__ssp[1],
+ (size_t) ctx[4].__ssp[2]) != 0)
+ {
+ printf ("%s: munmap: %m\n", __FUNCTION__);
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ if (setcontext (&ctx[1]) != 0)
+ {
+ printf ("%s: setcontext: %m\n", __FUNCTION__);
+ exit (EXIT_FAILURE);
+ }
+ exit (EXIT_FAILURE);
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/tst-cet-vfork-1.c b/sysdeps/unix/sysv/linux/x86_64/tst-cet-vfork-1.c
new file mode 100644
index 0000000..56d7753
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/tst-cet-vfork-1.c
@@ -0,0 +1,79 @@
+/* Verify that child of the vfork-calling function can't return when
+ shadow stack is in use.
+ Copyright (C) 2020-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <x86intrin.h>
+#include <support/test-driver.h>
+
+__attribute__ ((noclone, noinline))
+static void
+do_test_1 (void)
+{
+ pid_t p1;
+
+ /* NB: Since child return pops shadow stack which is shared with
+ parent, child must not return after vfork. */
+
+ if ((p1 = vfork ()) == 0)
+ {
+ /* Child return should trigger SIGSEGV due to shadow stack
+ mismatch. */
+ return;
+ }
+ else if (p1 == -1)
+ {
+ puts ("vfork failed");
+ _exit (EXIT_FAILURE);
+ }
+
+ int r;
+ if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+ {
+ puts ("waitpid failed");
+ _exit (EXIT_FAILURE);
+ }
+
+ if (!WIFSIGNALED (r) || WTERMSIG (r) != SIGSEGV)
+ {
+ puts ("Child not terminated with SIGSEGV");
+ _exit (EXIT_FAILURE);
+ }
+
+ /* Parent exits immediately so that parent returns without triggering
+ SIGSEGV when shadow stack is in use. */
+ _exit (EXIT_SUCCESS);
+}
+
+static int
+do_test (void)
+{
+ /* NB: This test should trigger SIGSEGV with shadow stack enabled. */
+ if (_get_ssp () == 0)
+ return EXIT_UNSUPPORTED;
+ do_test_1 ();
+ /* Child exits immediately so that child returns without triggering
+ SIGSEGV when shadow stack is in use. */
+ _exit (EXIT_FAILURE);
+}
+
+#include <support/test-driver.c>