diff mbox series

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

Message ID CAMe9rOqKkgBp7PN9m-L7-r33brXO+Eu_=-7n74B=nS9FEujJhQ@mail.gmail.com
State New
Headers show
Series V4 [PATCH 04/12] x86/CET: Extend arch_prctl syscall for CET control | expand

Commit Message

H.J. Lu July 24, 2018, 4:13 p.m. UTC
On Tue, Jul 24, 2018 at 8:56 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> 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.

Like this?

Comments

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

> On Tue, Jul 24, 2018 at 8:56 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> > 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.
> 
> Like this?

That's the sort of comment I'd expect, yes (this is not otherwise a review 
of the patch).
Carlos O'Donell July 24, 2018, 7:16 p.m. UTC | #2
On 07/24/2018 12:13 PM, H.J. Lu wrote:
> On Tue, Jul 24, 2018 at 8:56 AM, Joseph Myers <joseph@codesourcery.com> wrote:
>> 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.
> Like this?
> 
> 
> -- H.J.
> 
> 
> 0001-x86-CET-Extend-arch_prctl-syscall-for-CET-control.patch
> 
> 
> From 8244c8532d22976c3d92ec25bcefeb3a7854123f 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
> if <asm/prctl.h> from the required kernel header files contains CET
> arch_prctl bits.
> 
>  /* 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>.

OK for 2.28.

This follows the review from Joseph:
* Do not use bits/ for internal headers.
* Expects sys/prctl.h to provide the values.
* Provides an internal asm/prctl.h that mirrors the kernel-provided
  file and which will be deleted when the constants appear upstream.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  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>

OK.

> +
>  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];

OK.

>    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>

OK. Include additional asm/prctl.h which can be removed later.

> +
>  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

OK.

>  }
>  
>  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);

OK.

>  }
>  
>  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);

OK.

>  }
> 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..f67f3299b9
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h

OK, not a delivered public header.

> @@ -0,0 +1,32 @@
> +/* 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_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 */

OK.

> 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>

OK.

>  # include <ldsodefs.h>
>  # include <cpu-features.h>
>  # include <cpu-features.c>
> -- 2.17.1
Sergey Senozhatsky Aug. 13, 2018, 4:51 a.m. UTC | #3
Hello,

On (07/24/18 09:13), H.J. Lu wrote:
> >>
> >> OK for master?

Did you happen to hear of any regressions related to ARCH_CET prctl?
I just noticed that every app now does -EINVAL ARCH_CET prctl syscalls:

[..]
[    5.197696] systemctl: Unsupported prctl 3001
[    5.197702] process: systemctl: Unsupported common prctl 3001
[    5.207016] checkemail: Unsupported prctl 3001
[    5.207023] process: checkemail: Unsupported common prctl 3001
[    5.207245] bash: Unsupported prctl 3001
[    5.207251] process: bash: Unsupported common prctl 3001
[    5.209795] fetchmail: Unsupported prctl 3001
[    5.209801] process: fetchmail: Unsupported common prctl 3001
[    5.211082] tty: Unsupported prctl 3001
[    5.211087] process: tty: Unsupported common prctl 3001
[    5.212223] pidof: Unsupported prctl 3001
[    5.212228] process: pidof: Unsupported common prctl 3001
[    5.233192] dircolors: Unsupported prctl 3001
[    5.233200] process: dircolors: Unsupported common prctl 3001
[    8.862025] startx: Unsupported prctl 3001
[    8.862031] process: startx: Unsupported common prctl 3001
[    8.864556] tty: Unsupported prctl 3001
[    8.864561] process: tty: Unsupported common prctl 3001
[    8.865664] expr: Unsupported prctl 3001
[..]

Which is, maybe fine, though I'm not entirely sure since I don't
really see ARCH_CET being supported by any arch (neither in linux-next
nor in Linus' tree), so maybe as of now those syscalls are unneeded.

The part where, I believe, these -EINVAL prctls begin to backfire is
valgrind - I can't run it anymore with glibc 2.28. It gives me the
following error:

:
:valgrind: the 'impossible' happened:
:   Unsupported arch_prctl option
:
:host stacktrace:
:==3118==    at 0x580441BA: show_sched_status_wrk (m_libcassert.c:355)
:==3118==    by 0x580442D4: report_and_quit (m_libcassert.c:426)
:==3118==    by 0x58044517: panic (m_libcassert.c:502)
:==3118==    by 0x58044517: vgPlain_core_panic_at (m_libcassert.c:507)
:==3118==    by 0x5804454A: vgPlain_core_panic (m_libcassert.c:512)
:==3118==    by 0x580DAE22: vgSysWrap_amd64_linux_sys_arch_prctl_before (syswrap-amd64-linux.c:286)
:==3118==    by 0x580A0C23: vgPlain_client_syscall (syswrap-main.c:1857)
:==3118==    by 0x5809D48A: handle_syscall (scheduler.c:1126)
:==3118==    by 0x5809EBB6: vgPlain_scheduler (scheduler.c:1443)
:==3118==    by 0x580AED50: thread_wrapper (syswrap-linux.c:103)
:==3118==    by 0x580AED50: run_a_thread_NORETURN (syswrap-linux.c:156)
:
:sched status:
:  running_tid=1
:
:Thread 1: status = VgTs_Runnable (lwpid 3118)
:==3118==    at 0x401A035: ??? (in /usr/lib/ld-2.28.so)
:==3118==    by 0xBFEBFBFE: ???
:

strace shows 2 prctl calls issued by valgrind, one of them is
-EINVAL ARCH_CET:

arch_prctl(0x3001 /* ARCH_??? */, 0x7ffc4c366a30) = -1 EINVAL (Invalid argument)
arch_prctl(ARCH_SET_FS, 0x7f215f02f500) = 0

So my assumption is that arch_prctl(0x3001) disappoints valgrind to
the point of no return.

Any thoughts? Can ARCH_CET prctls be disabled somehow?

	-ss
Florian Weimer Aug. 13, 2018, 11:10 a.m. UTC | #4
On 08/13/2018 06:51 AM, Sergey Senozhatsky wrote:
> [    8.864561] process: tty: Unsupported common prctl 3001
> [    8.865664] expr: Unsupported prctl 3001
> [..]
> 
> Which is, maybe fine, though I'm not entirely sure since I don't
> really see ARCH_CET being supported by any arch (neither in linux-next
> nor in Linus' tree), so maybe as of now those syscalls are unneeded.

Which kernel version is that?  The above looks like a kernel bug because 
there doesn't seem to be any rate limiting.

> The part where, I believe, these -EINVAL prctls begin to backfire is
> valgrind - I can't run it anymore with glibc 2.28. It gives me the
> following error:

valgrind has already been fixed:

   https://bugs.kde.org/show_bug.cgi?id=396887

Thanks,
Florian
Zack Weinberg Aug. 13, 2018, 11:48 a.m. UTC | #5
On Mon, Aug 13, 2018 at 7:10 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 08/13/2018 06:51 AM, Sergey Senozhatsky wrote:
>>
>> [    8.864561] process: tty: Unsupported common prctl 3001
>> [    8.865664] expr: Unsupported prctl 3001
>> [..]
>>
>> Which is, maybe fine, though I'm not entirely sure since I don't
>> really see ARCH_CET being supported by any arch (neither in linux-next
>> nor in Linus' tree), so maybe as of now those syscalls are unneeded.

Has any hardware with CET support shipped to the general public yet?

Could we perhaps use cpuid or similar to detect hardware support, and
not bother probing for kernel support if it's not there?

zw
Sergey Senozhatsky Aug. 13, 2018, 12:36 p.m. UTC | #6
On (08/13/18 13:10), Florian Weimer wrote:
> On 08/13/2018 06:51 AM, Sergey Senozhatsky wrote:
> > [    8.864561] process: tty: Unsupported common prctl 3001
> > [    8.865664] expr: Unsupported prctl 3001
> > [..]
> > 
> > Which is, maybe fine, though I'm not entirely sure since I don't
> > really see ARCH_CET being supported by any arch (neither in linux-next
> > nor in Linus' tree), so maybe as of now those syscalls are unneeded.
> 
> Which kernel version is that?  The above looks like a kernel bug because
> there doesn't seem to be any rate limiting.

Oh, my bad. Sorry, I should have mentioned that it was my own kernel
modification just to see how often I get -EINVAL prctl syscalls.

> > The part where, I believe, these -EINVAL prctls begin to backfire is
> > valgrind - I can't run it anymore with glibc 2.28. It gives me the
> > following error:
> 
> valgrind has already been fixed:
> 
>   https://bugs.kde.org/show_bug.cgi?id=396887

Nice, thanks for the info!

The fact that there are so many -EINVAL syscalls is still a bit
misleading, tho.

	-ss
Carlos O'Donell Aug. 13, 2018, 5:11 p.m. UTC | #7
On 08/13/2018 08:36 AM, Sergey Senozhatsky wrote:
> On (08/13/18 13:10), Florian Weimer wrote:
>> On 08/13/2018 06:51 AM, Sergey Senozhatsky wrote:
>>> [    8.864561] process: tty: Unsupported common prctl 3001
>>> [    8.865664] expr: Unsupported prctl 3001
>>> [..]
>>>
>>> Which is, maybe fine, though I'm not entirely sure since I don't
>>> really see ARCH_CET being supported by any arch (neither in linux-next
>>> nor in Linus' tree), so maybe as of now those syscalls are unneeded.
>>
>> Which kernel version is that?  The above looks like a kernel bug because
>> there doesn't seem to be any rate limiting.
> 
> Oh, my bad. Sorry, I should have mentioned that it was my own kernel
> modification just to see how often I get -EINVAL prctl syscalls.

You should only see them at startup when we query the kernel for support.

Like *all* glibc features we query for support to see if we're running on
a new enough kernel to enable the feature.

The is similar to how set_robust_list() was handled for robust mutexes and
checking for kernel support in 2.6.17.

>>> The part where, I believe, these -EINVAL prctls begin to backfire is
>>> valgrind - I can't run it anymore with glibc 2.28. It gives me the
>>> following error:
>>
>> valgrind has already been fixed:
>>
>>   https://bugs.kde.org/show_bug.cgi?id=396887
> 
> Nice, thanks for the info!
> 
> The fact that there are so many -EINVAL syscalls is still a bit
> misleading, tho.

Is it? You get a '-1' ENOENT return for every process when it starts and
tries to look for /etc/ld.so.preload. This is similar.

Unless you know exactly what the runtime is doing there will be syscalls
that return errors, particularly when testing for newer features.
Sergey Senozhatsky Aug. 14, 2018, 12:46 a.m. UTC | #8
On (08/13/18 13:11), Carlos O'Donell wrote:
> > Oh, my bad. Sorry, I should have mentioned that it was my own kernel
> > modification just to see how often I get -EINVAL prctl syscalls.
> 
> You should only see them at startup when we query the kernel for support.

Right. I'm not arguing, one extra syscall per-process is not a big deal.

> Like *all* glibc features we query for support to see if we're running on
> a new enough kernel to enable the feature.
[..]
> Is it? You get a '-1' ENOENT return for every process when it starts and
> tries to look for /etc/ld.so.preload. This is similar.

These all are valid points, sure. But, somehow, testing for a feature
that no kernel or HW supports looks *a bit* different. /etc/ld.so.preload
at least exists on some hosts, while ARCH_CET does not. Maybe it's OK.
My only real problem with ARCH_CET was valgrind.

	-ss
Carlos O'Donell Aug. 14, 2018, 3:02 a.m. UTC | #9
On 08/13/2018 08:46 PM, Sergey Senozhatsky wrote:
> These all are valid points, sure. But, somehow, testing for a feature
> that no kernel or HW supports looks *a bit* different. /etc/ld.so.preload
> at least exists on some hosts, while ARCH_CET does not. Maybe it's OK.
> My only real problem with ARCH_CET was valgrind.

Yes, the valgrind issue is a bummer, but we'll get that fixed in the downstream
distributions with a new valgrind version. If you are using bleeding edge glibc
you may also sometimes need the most recent developer tooling to understand
what it's doing :-}

I would also hope that all of our users are happy to have hardware enablement
early before hardware is available to consumers :-)
diff mbox series

Patch

From 8244c8532d22976c3d92ec25bcefeb3a7854123f 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
if <asm/prctl.h> from the required kernel header files contains CET
arch_prctl bits.

 /* 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..f67f3299b9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
@@ -0,0 +1,32 @@ 
+/* 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_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