Re: [PATCH 06/10] x86/cet: Add arch_prctl functions for shadow stack
From: Andy Lutomirski
Date: Fri Jun 08 2018 - 00:38:24 EST
On Thu, Jun 7, 2018 at 9:10 PM H.J. Lu <hjl.tools@xxxxxxxxx> wrote:
>
> On Thu, Jun 7, 2018 at 4:01 PM, Andy Lutomirski <luto@xxxxxxxxxx> wrote:
> > On Thu, Jun 7, 2018 at 3:02 PM H.J. Lu <hjl.tools@xxxxxxxxx> wrote:
> >>
> >> On Thu, Jun 7, 2018 at 2:01 PM, Andy Lutomirski <luto@xxxxxxxxxx> wrote:
> >> > On Thu, Jun 7, 2018 at 1:33 PM Yu-cheng Yu <yu-cheng.yu@xxxxxxxxx> wrote:
> >> >>
> >> >> On Thu, 2018-06-07 at 11:48 -0700, Andy Lutomirski wrote:
> >> >> > On Thu, Jun 7, 2018 at 7:41 AM Yu-cheng Yu <yu-cheng.yu@xxxxxxxxx> wrote:
> >> >> > >
> >> >> > > The following operations are provided.
> >> >> > >
> >> >> > > ARCH_CET_STATUS:
> >> >> > > return the current CET status
> >> >> > >
> >> >> > > ARCH_CET_DISABLE:
> >> >> > > disable CET features
> >> >> > >
> >> >> > > ARCH_CET_LOCK:
> >> >> > > lock out CET features
> >> >> > >
> >> >> > > ARCH_CET_EXEC:
> >> >> > > set CET features for exec()
> >> >> > >
> >> >> > > ARCH_CET_ALLOC_SHSTK:
> >> >> > > allocate a new shadow stack
> >> >> > >
> >> >> > > ARCH_CET_PUSH_SHSTK:
> >> >> > > put a return address on shadow stack
> >> >> > >
> >> >> > > ARCH_CET_ALLOC_SHSTK and ARCH_CET_PUSH_SHSTK are intended only for
> >> >> > > the implementation of GLIBC ucontext related APIs.
> >> >> >
> >> >> > Please document exactly what these all do and why. I don't understand
> >> >> > what purpose ARCH_CET_LOCK and ARCH_CET_EXEC serve. CET is opt in for
> >> >> > each ELF program, so I think there should be no need for a magic
> >> >> > override.
> >> >>
> >> >> CET is initially enabled if the loader has CET capability. Then the
> >> >> loader decides if the application can run with CET. If the application
> >> >> cannot run with CET (e.g. a dependent library does not have CET), then
> >> >> the loader turns off CET before passing to the application. When the
> >> >> loader is done, it locks out CET and the feature cannot be turned off
> >> >> anymore until the next exec() call.
> >> >
> >> > Why is the lockout necessary? If user code enables CET and tries to
> >> > run code that doesn't support CET, it will crash. I don't see why we
> >> > need special code in the kernel to prevent a user program from calling
> >> > arch_prctl() and crashing itself. There are already plenty of ways to
> >> > do that :)
> >>
> >> On CET enabled machine, not all programs nor shared libraries are
> >> CET enabled. But since ld.so is CET enabled, all programs start
> >> as CET enabled. ld.so will disable CET if a program or any of its shared
> >> libraries aren't CET enabled. ld.so will lock up CET once it is done CET
> >> checking so that CET can't no longer be disabled afterwards.
> >
> > Yeah, I got that. No one has explained *why*.
>
> It is to prevent malicious code from disabling CET.
>
By the time malicious code issue its own syscalls, you've already lost
the battle. I could probably be convinced that a lock-CET-on feature
that applies *only* to the calling thread and is not inherited by
clone() is a decent idea, but I'd want to see someone who understands
the state of the art in exploit design justify it. You're also going
to need to figure out how to make CRIU work if you allow locking CET
on.
A priori, I think we should just not provide a lock mechanism.
> > (Also, shouldn't the vDSO itself be marked as supporting CET?)
>
> No. vDSO is loaded by kernel. vDSO in CET kernel is CET
> compatible.
>
I think the vDSO should do its best to act like a real DSO. That
means that, if the vDSO supports CET, it should advertise support for
CET using the Linux ABI. Since you're going to require GCC 8 anyway,
this should be a single line of code in the Makefile.