summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--sysdeps/unix/sysv/linux/x86/Makefile15
-rw-r--r--sysdeps/unix/sysv/linux/x86/tst-cet-property-1.c44
-rw-r--r--sysdeps/unix/sysv/linux/x86/tst-cet-property-2.c63
-rw-r--r--sysdeps/unix/sysv/linux/x86/tst-cet-property-dep-2.S63
-rw-r--r--sysdeps/x86/dl-prop.h29
6 files changed, 220 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 75796ee7d6..669bc3c8ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2018-07-30 H.J. Lu <hongjiu.lu@intel.com>
+ [BZ #23467]
+ * sysdeps/unix/sysv/linux/x86/Makefile (tests): Add
+ tst-cet-property-1 and tst-cet-property-2 if CET is enabled.
+ (CFLAGS-tst-cet-property-1.o): New.
+ (ASFLAGS-tst-cet-property-dep-2.o): Likewise.
+ ($(objpfx)tst-cet-property-2): Likewise.
+ ($(objpfx)tst-cet-property-2.out): Likewise.
+ * sysdeps/unix/sysv/linux/x86/tst-cet-property-1.c: New file.
+ * sysdeps/unix/sysv/linux/x86/tst-cet-property-2.c: Likewise.
+ * sysdeps/unix/sysv/linux/x86/tst-cet-property-dep-2.S: Likewise.
+ * sysdeps/x86/dl-prop.h (_dl_process_cet_property_note): Parse
+ each property item until GNU_PROPERTY_X86_FEATURE_1_AND is found.
+
+2018-07-30 H.J. Lu <hongjiu.lu@intel.com>
+
[BZ #23458]
* sysdeps/x86/Makefile (tests): Add tst-get-cpu-features-static.
diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile
index a30fdb1dc1..7dc4e61756 100644
--- a/sysdeps/unix/sysv/linux/x86/Makefile
+++ b/sysdeps/unix/sysv/linux/x86/Makefile
@@ -25,6 +25,21 @@ tests += tst-saved_mask-1
endif
ifeq ($(enable-cet),yes)
+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),stdlib)
tests += tst-cet-setcontext-1
CFLAGS-tst-cet-setcontext-1.c += -mshstk
diff --git a/sysdeps/unix/sysv/linux/x86/tst-cet-property-1.c b/sysdeps/unix/sysv/linux/x86/tst-cet-property-1.c
new file mode 100644
index 0000000000..21130faefc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/tst-cet-property-1.c
@@ -0,0 +1,44 @@
+/* Test CET property note parser.
+ Copyright (C) 2018 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
+ <http://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/tst-cet-property-2.c b/sysdeps/unix/sysv/linux/x86/tst-cet-property-2.c
new file mode 100644
index 0000000000..0531074ceb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/tst-cet-property-2.c
@@ -0,0 +1,63 @@
+/* Test CET property note parser for [BZ #23467].
+ Copyright (C) 2018 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
+ <http://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[20];
+
+ if (scanf ("%20s", 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/tst-cet-property-dep-2.S b/sysdeps/unix/sysv/linux/x86/tst-cet-property-dep-2.S
new file mode 100644
index 0000000000..5f5cad34d9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/tst-cet-property-dep-2.S
@@ -0,0 +1,63 @@
+/* Test CET property note parser.
+ Copyright (C) 2018 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
+ <http://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/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
index 35d3f16a23..26c3131ac5 100644
--- a/sysdeps/x86/dl-prop.h
+++ b/sysdeps/x86/dl-prop.h
@@ -73,7 +73,7 @@ _dl_process_cet_property_note (struct link_map *l,
unsigned char *ptr = (unsigned char *) (note + 1) + 4;
unsigned char *ptr_end = ptr + note->n_descsz;
- while (ptr < ptr_end)
+ do
{
unsigned int type = *(unsigned int *) ptr;
unsigned int datasz = *(unsigned int *) (ptr + 4);
@@ -82,17 +82,28 @@ _dl_process_cet_property_note (struct link_map *l,
if ((ptr + datasz) > ptr_end)
break;
- if (type == GNU_PROPERTY_X86_FEATURE_1_AND
- && datasz == 4)
+ if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
{
- unsigned int feature_1 = *(unsigned int *) ptr;
- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
- l->l_cet |= lc_ibt;
- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
- l->l_cet |= lc_shstk;
- break;
+ /* The size of GNU_PROPERTY_X86_FEATURE_1_AND is 4
+ bytes. When seeing GNU_PROPERTY_X86_FEATURE_1_AND,
+ we stop the search regardless if its size is correct
+ or not. There is no point to continue if this note
+ is ill-formed. */
+ if (datasz == 4)
+ {
+ unsigned int feature_1 = *(unsigned int *) ptr;
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
+ l->l_cet |= lc_ibt;
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
+ l->l_cet |= lc_shstk;
+ }
+ return;
}
+
+ /* Check the next property item. */
+ ptr += ALIGN_UP (datasz, sizeof (ElfW(Addr)));
}
+ while ((ptr_end - ptr) >= 8);
}
/* NB: Note sections like .note.ABI-tag and .note.gnu.build-id are