Thread (98 messages) 98 messages, 13 authors, 2018-06-26

Re: [PATCH 06/10] x86/cet: Add arch_prctl functions for shadow stack

From: Andy Lutomirski <luto@kernel.org>
Date: 2018-06-08 04:38:21
Also in: linux-arch, linux-mm, lkml

On Thu, Jun 7, 2018 at 9:10 PM H.J. Lu [off-list ref] wrote:
On Thu, Jun 7, 2018 at 4:01 PM, Andy Lutomirski [off-list ref] wrote:
quoted
On Thu, Jun 7, 2018 at 3:02 PM H.J. Lu [off-list ref] wrote:
quoted
On Thu, Jun 7, 2018 at 2:01 PM, Andy Lutomirski [off-list ref] wrote:
quoted
On Thu, Jun 7, 2018 at 1:33 PM Yu-cheng Yu [off-list ref] wrote:
quoted
On Thu, 2018-06-07 at 11:48 -0700, Andy Lutomirski wrote:
quoted
On Thu, Jun 7, 2018 at 7:41 AM Yu-cheng Yu [off-list ref] wrote:
quoted
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.
quoted
(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.
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help