diff mbox

V3 [PATCH 04/12] x86/CET: Extend arch_prctl syscall for CET control

Message ID CAMe9rOozV6D0PMC3WVy2Mo5TB5nCrtP2anDPfZb_X3=3kdtiPA@mail.gmail.com
State New, archived
Headers show

Commit Message

H.J. Lu July 24, 2018, 3:52 p.m. UTC
On Tue, Jul 24, 2018 at 8:29 AM, Carlos O'Donell <carlos@redhat.com> wrote:
> On 07/24/2018 10:28 AM, Joseph Myers wrote:
>> On Tue, 24 Jul 2018, H.J. Lu wrote:
>>
>>> Note: sysdeps/unix/sysv/linux/x86/bits/prctl-internal.h should be
>>> renamed to sysdeps/unix/sysv/linux/x86/bits/prctl.h after the CET
>>> kernel interface has been committed into the public kernel.
>>
>> bits/ should not be used for any internal headers; it's purely a naming
>> convention for public headers.  So there should be no
>> bits/prctl-internal.h header.
>
> OK.
>
>> I don't think there should be bits/prctl.h at all either.  Not with this
>> patch (because there isn't anything for it to do), and not once the
>> interface is in the kernel (because existing practice is that we rely on
>> the include of <linux/prctl.h> from <sys/prctl.h> to provide the values to
>> users of glibc).
>
> Good point.
>
>> Rather, for the uses of these constants within glibc, to avoid relying on
>> new kernel headers, provide an x86 include/sys/prctl.h that does
>> #include_next <sys/prctl.h> and then defines these constants if not
>> already defined.  And make sure that header gets a prominent comment
>> naming the upstream kernel version with the constants (once they are
>> upstream), so it's obvious at what point we can remove that header.
>
> OK, that makes sense, so a purely internal header via include/ wrapping
> with the constants there.
>

CET arch_prctl bits should be defined in <asm/prctl.h> from Linux kernel
header files.   Here is the updated patch to add x86 <include/asm/prctl.h>.

OK for master?

Comments

Joseph Myers July 24, 2018, 3:56 p.m. UTC | #1
On Tue, 24 Jul 2018, H.J. Lu wrote:

> CET arch_prctl bits should be defined in <asm/prctl.h> from Linux kernel
> header files.   Here is the updated patch to add x86 <include/asm/prctl.h>.
> 
> OK for master?

I don't think the relevant condition for removing such a wrapper is "after 
the CET kernel interface has been committed into the public kernel".  It's 
after we require kernel headers recent enough to have that interface, 
which may well be several years away.  Once the interface has been 
committed into the public kernel, the wrapper should be updated to name 
the kernel version that has it and to say it should be removed once we 
require kernel headers at least that recent.
diff mbox

Patch

From 630bfa00750c823cd4bea26ca6e1eabfd7abba99 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sat, 7 Jul 2018 07:33:04 -0700
Subject: [PATCH] x86/CET: Extend arch_prctl syscall for CET control

CET arch_prctl bits should be defined in <asm/prctl.h> from Linux kernel
header files.  Add x86 <include/asm/prctl.h> for pre-CET kernel header
files.

Note: sysdeps/unix/sysv/linux/x86/include/asm/prctl.h should be removed
after the CET kernel interface has been committed into the public kernel.

 /* CET features:
    IBT:   GNU_PROPERTY_X86_FEATURE_1_IBT
    SHSTK: GNU_PROPERTY_X86_FEATURE_1_SHSTK
  */

 /* Return CET features in unsigned long long *addr:
      features: addr[0].
      shadow stack base address: addr[1].
      shadow stack size: addr[2].
  */
 # define ARCH_CET_STATUS		0x3001
 /* Disable CET features in unsigned int features.  */
 # define ARCH_CET_DISABLE		0x3002
 /* Lock all CET features.  */
 # define ARCH_CET_LOCK			0x3003
 /* Allocate a new shadow stack with unsigned long long *addr:
      IN: requested shadow stack size: *addr.
      OUT: allocated shadow stack address: *addr.
  */
 # define ARCH_CET_ALLOC_SHSTK		0x3004
 /* Return legacy region bitmap info in unsigned long long *addr:
     address: addr[0].
     size: addr[1].
  */
 # define ARCH_CET_LEGACY_BITMAP	0x3005

	* sysdeps/unix/sysv/linux/x86/include/asm/prctl.h: New file.
	* sysdeps/unix/sysv/linux/x86/cpu-features.c: Include
	<sys/prctl.h> and <asm/prctl.h>.
	(get_cet_status): Call arch_prctl with ARCH_CET_STATUS.
	* sysdeps/unix/sysv/linux/x86/dl-cet.h: Include <sys/prctl.h>
	and <asm/prctl.h>.
	(dl_cet_allocate_legacy_bitmap): Call arch_prctl with
	ARCH_CET_LEGACY_BITMAP.
	(dl_cet_disable_cet): Call arch_prctl with ARCH_CET_DISABLE.
	(dl_cet_lock_cet): Call arch_prctl with ARCH_CET_LOCK.
	* sysdeps/x86/libc-start.c: Include <startup.h>.
---
 sysdeps/unix/sysv/linux/x86/cpu-features.c    |  8 +++++
 sysdeps/unix/sysv/linux/x86/dl-cet.h          | 30 +++++++++++++----
 .../unix/sysv/linux/x86/include/asm/prctl.h   | 32 +++++++++++++++++++
 sysdeps/x86/libc-start.c                      |  3 ++
 4 files changed, 67 insertions(+), 6 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/x86/include/asm/prctl.h

diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
index 7c9df9b794..8566a265b8 100644
--- a/sysdeps/unix/sysv/linux/x86/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c
@@ -17,9 +17,17 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 #if CET_ENABLED
+# include <sys/prctl.h>
+# include <asm/prctl.h>
+
 static inline int __attribute__ ((always_inline))
 get_cet_status (void)
 {
+  unsigned long long cet_status[3];
+  INTERNAL_SYSCALL_DECL (err);
+  if (INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_STATUS,
+			cet_status) == 0)
+    return cet_status[0];
   return 0;
 }
 
diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
index ae81e2f2ca..3fbcfebed5 100644
--- a/sysdeps/unix/sysv/linux/x86/dl-cet.h
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
@@ -15,23 +15,41 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <sys/prctl.h>
+#include <asm/prctl.h>
+
 static inline int __attribute__ ((always_inline))
 dl_cet_allocate_legacy_bitmap (unsigned long *legacy_bitmap)
 {
-  /* FIXME: Need syscall support.  */
-  return -1;
+  /* Allocate legacy bitmap.  */
+  INTERNAL_SYSCALL_DECL (err);
+#ifdef __LP64__
+  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2,
+				 ARCH_CET_LEGACY_BITMAP, legacy_bitmap);
+#else
+  unsigned long long legacy_bitmap_u64[2];
+  int res = INTERNAL_SYSCALL (arch_prctl, err, 2,
+			      ARCH_CET_LEGACY_BITMAP, legacy_bitmap_u64);
+  if (res == 0)
+    {
+      legacy_bitmap[0] = legacy_bitmap_u64[0];
+      legacy_bitmap[1] = legacy_bitmap_u64[1];
+    }
+  return res;
+#endif
 }
 
 static inline int __attribute__ ((always_inline))
 dl_cet_disable_cet (unsigned int cet_feature)
 {
-  /* FIXME: Need syscall support.  */
-  return -1;
+  INTERNAL_SYSCALL_DECL (err);
+  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_DISABLE,
+				 cet_feature);
 }
 
 static inline int __attribute__ ((always_inline))
 dl_cet_lock_cet (void)
 {
-  /* FIXME: Need syscall support.  */
-  return -1;
+  INTERNAL_SYSCALL_DECL (err);
+  return (int) INTERNAL_SYSCALL (arch_prctl, err, 2, ARCH_CET_LOCK, 0);
 }
diff --git a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
new file mode 100644
index 0000000000..c92c4104af
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
@@ -0,0 +1,32 @@ 
+/* FIXME: This file should be removed after the CET kernel interface
+   has been committed into the public kernel.  All CET arch_prctl bits
+   should come from the kernel <asm/prctl.h>.  */
+
+#include_next <asm/prctl.h>
+
+#ifndef ARCH_CET_STATUS
+/* CET features:
+   IBT:   GNU_PROPERTY_X86_FEATURE_1_IBT
+   SHSTK: GNU_PROPERTY_X86_FEATURE_1_SHSTK
+ */
+/* Return CET features in unsigned long long *addr:
+     features: addr[0].
+     shadow stack base address: addr[1].
+     shadow stack size: addr[2].
+ */
+# define ARCH_CET_STATUS	0x3001
+/* Disable CET features in unsigned int features.  */
+# define ARCH_CET_DISABLE	0x3002
+/* Lock all CET features.  */
+# define ARCH_CET_LOCK		0x3003
+/* Allocate a new shadow stack with unsigned long long *addr:
+     IN: requested shadow stack size: *addr.
+     OUT: allocated shadow stack address: *addr.
+ */
+# define ARCH_CET_ALLOC_SHSTK	0x3004
+/* Return legacy region bitmap info in unsigned long long *addr:
+     address: addr[0].
+     size: addr[1].
+ */
+# define ARCH_CET_LEGACY_BITMAP	0x3005
+#endif /* ARCH_CET_STATUS */
diff --git a/sysdeps/x86/libc-start.c b/sysdeps/x86/libc-start.c
index 43aba9d061..eb5335c154 100644
--- a/sysdeps/x86/libc-start.c
+++ b/sysdeps/x86/libc-start.c
@@ -16,6 +16,9 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 #ifndef SHARED
+/* Define I386_USE_SYSENTER to support syscall during startup in static
+   PIE.  */
+# include <startup.h>
 # include <ldsodefs.h>
 # include <cpu-features.h>
 # include <cpu-features.c>
-- 
2.17.1