On Wed, Nov 04, 2020 at 11:55:57AM +0200, Topi Miettinen wrote:
On 4.11.2020 11.29, Florian Weimer wrote:[...]
* Will Deacon:
Is there real value in this seccomp filter if it only looks at mprotect(),
or was it just implemented because it's easy to do and sounds like a good
idea?
It seems bogus to me. Everyone will just create alias mappings instead,
just like they did for the similar SELinux feature. See “Example code
to avoid execmem violations” in:
<https://www.akkadia.org/drepper/selinux-mem.html>
[...]As you can see, this reference implementation creates a PROT_WRITE
mapping aliased to a PROT_EXEC mapping, so it actually reduces security
compared to something that generates the code in an anonymous mapping
and calls mprotect to make it executable.
If a service legitimately needs executable and writable mappings (due to
JIT, trampolines etc), it's easy to disable the filter whenever really
needed with "MemoryDenyWriteExecute=no" (which is the default) in case of
systemd or a TE rule like "allow type_t self:process { execmem };" for
SELinux. But this shouldn't be the default case, since there are many
services which don't need W&X.
I think Drepper's point is that separate X and W mappings, with enough
randomisation, would be more secure than allowing W&X at the same
address (but, of course, less secure than not having W at all, though
that's not always possible).
I'd also question what is the value of BTI if it can be easily circumvented
by removing PROT_BTI with mprotect()?
Well, BTI is a protection against JOP attacks. The assumption here is
that an attacker cannot invoke mprotect() to disable PROT_BTI. If it
can, it's probably not worth bothering with a subsequent JOP attack, it
can already call functions directly.
I see MDWX not as a way of detecting attacks but rather plugging
inadvertent security holes in certain programs. On arm64, such hardening
currently gets in the way of another hardening feature, BTI.