On Fri, May 17, 2019 at 09:53:06AM -0400, Stephen Smalley wrote:
On 5/16/19 6:23 PM, Xing, Cedric wrote:
I thought EXECMOD applied to files (and memory mappings backed by
them) but
I was probably wrong. It sounds like EXECMOD applies to the whole
process so
would allow all pages within a process's address space to be
modified then
executed, regardless the backing files. Am I correct this time?
No, you were correct the first time I think; EXECMOD is used to control
whether a process can make executable a private file mapping that has
previously been modified (e.g. text relocation); it is a special case to
support text relocations without having to allow full EXECMEM (i.e.
execute
arbitrary memory).
SELinux checks relevant to W^X include:
- EXECMEM: mmap/mprotect PROT_EXEC an anonymous mapping (regardless of
PROT_WRITE, since we know the content has to have been written at some
point) or a private file mapping that is also PROT_WRITE.
- EXECMOD: mprotect PROT_EXEC a private file mapping that has been
previously modified, typically for text relocations,
- FILE__WRITE: mmap/mprotect PROT_WRITE a shared file mapping,
- FILE__EXECUTE: mmap/mprotect PROT_EXEC a file mapping.
(ignoring EXECSTACK and EXECHEAP here since they aren't really
relevant to
this discussion)
So if you want to ensure W^X, then you wouldn't allow EXECMEM for the
process, EXECMOD by the process to any file, and the combination of both
FILE__WRITE and FILE__EXECUTE by the process to any file.
If the /dev/sgx/enclave mappings are MAP_SHARED and you aren't using an
anonymous inode, then I would expect that only the FILE__WRITE and
FILE__EXECUTE checks are relevant.
Yep, I was just typing this up in a different thread:
I think we may want to change the SGX API to alloc an anon inode for each
enclave instead of hanging every enclave off of the /dev/sgx/enclave
inode.
Because /dev/sgx/enclave is NOT private, SELinux's file_map_prot_check()
will only require FILE__WRITE and FILE__EXECUTE to mprotect() enclave
VMAs
to RWX. Backing each enclave with an anon inode will make SELinux treat
EPC memory like anonymous mappings, which is what we want (I think), e.g.
making *any* EPC page executable will require PROCESS__EXECMEM (SGX is
64-bit only at this point, so SELinux will always have default_noexec).