> On May 17, 2019, at 9:20 AM, Stephen Smalley <[email protected]> wrote:
> 
>> On 5/17/19 11:09 AM, Sean Christopherson wrote:
>>> 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).
> 
> I don't think we want to require EXECMEM (or equivalently both FILE__WRITE 
> and FILE__EXECUTE to /dev/sgx/enclave) for making any EPC page executable, 
> only if the page is also writable or previously modified.  The intent is to 
> prevent arbitrary code execution without EXECMEM (or 
> FILE__WRITE|FILE__EXECUTE), while still allowing enclaves to be created 
> without EXECMEM as long as the EPC page mapping is only ever mapped RX and 
> its initial contents came from an unmodified file mapping that was PROT_EXEC 
> (and hence already checked via FILE__EXECUTE).

That agrees with my thoughts. Actually plumbing everything together so this 
works could be a bit interesting.  I assume it’ll need a special case in 
SELinux or maybe a new vm_op.

Reply via email to