Thread (7 messages) 7 messages, 3 authors, 2016-08-25

[PATCH] arm64: Introduce execute-only page access permissions

From: Kees Cook <hidden>
Date: 2016-08-25 15:29:48
Also in: linux-mm, lkml

On Thu, Aug 25, 2016 at 6:30 AM, Will Deacon [off-list ref] wrote:
On Tue, Aug 16, 2016 at 05:18:24PM +0100, Catalin Marinas wrote:
quoted
On Mon, Aug 15, 2016 at 10:45:09AM -0700, Kees Cook wrote:
quoted
On Mon, Aug 15, 2016 at 3:47 AM, Catalin Marinas
[off-list ref] wrote:
quoted
On Fri, Aug 12, 2016 at 11:23:03AM -0700, Kees Cook wrote:
quoted
On Thu, Aug 11, 2016 at 10:44 AM, Catalin Marinas
[off-list ref] wrote:
quoted
The ARMv8 architecture allows execute-only user permissions by clearing
the PTE_UXN and PTE_USER bits. However, the kernel running on a CPU
implementation without User Access Override (ARMv8.2 onwards) can still
access such page, so execute-only page permission does not protect
against read(2)/write(2) etc. accesses. Systems requiring such
protection must enable features like SECCOMP.
So, UAO CPUs will bypass this protection in userspace if using
read/write on a memory-mapped file?
It's the other way around. CPUs prior to ARMv8.2 (when UAO was
introduced) or with the CONFIG_ARM64_UAO disabled can still access
user execute-only memory regions while running in kernel mode via the
copy_*_user, (get|put)_user etc. routines. So a way user can bypass this
protection is by using such address as argument to read/write file
operations.
Ah, okay. So exec-only for _userspace_ will always work, but exec-only
for _kernel_ will only work on ARMv8.2 with CONFIG_ARM64_UAO?
Yes (mostly). With UAO, we changed the user access routines in the
kernel to use the LDTR/STTR instructions which always behave
unprivileged even when executed in kernel mode (unless the UAO bit is
set to override this restriction, needed for set_fs(KERNEL_DS)).

Even with UAO, we still have two cases where the kernel cannot perform
unprivileged accesses (LDTR/STTR) since they don't have an exclusives
equivalent (LDXR/STXR). These are in-user futex atomic ops and the SWP
emulation for 32-bit binaries (armv8_deprecated.c). But these require
write permission, so they would always fault even when running in the
kernel. futex_atomic_cmpxchg_inatomic() is able to return the old value
without a write (if it differs from "oldval") but it doesn't look like
such value could leak to user space.
If this was an issue, couldn't we add a dummy LDTR before the LDXR, and
have the fixup handler return -EFAULT?

Either way, this series looks technically fine to me:

Reviewed-by: Will Deacon <redacted>

but it would be good for some security-focussed person (Hi, Kees!) to
comment on whether or not this is useful, given the caveats you've
described. If it is, I can queue it for 4.9.
Hi!

It is a good building block for frustrating ROP attacks or other
things that rely on memory content exposure. It's still unclear to me
how much traction it'll get until the devices that support it are
widely in the hands of people, but I'd rather have the infrastructure
available than not. :)

-Kees


-- 
Kees Cook
Nexus Security
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help