Re: SGX vs LSM (Re: [PATCH v20 00/28] Intel SGX1 support)

From: Andy Lutomirski
Date: Thu May 30 2019 - 10:35:05 EST


Hi all-

After an offline discussion with Sean yesterday, here are some updates
to the user API parts of my proposal.

Unfortunately, Sean convinced me that MAXPERM doesn't work the way I
described it because, for SGX2, the enclave loader won't know at load
time whether a given EAUG-ed page will ever be executed. So here's an
update.

First, here are the requrements as I see them, where EXECUTE, EXECMOD,
and EXECMEM could be substituted with other rules at the LSM's
discretion:

- You can create a WX or RWX mapping if and only if you have EXECMEM.

- To create an X mapping of an enclave page that has ever been W, you
need EXECMOD.

- To create an X mapping of an enclave page that came from EADD, you
need EXECUTE on the source file. Optionally, we could also permit
this if you have EXECMOD.

And I have two design proposals. One is static and one is dynamic.
To implement either one, we will probably need a new .may_mprotect vm
operation, and that operation can call an LSM hook. Or we can give
LSMs a way to detect that a given vm_area_struct is an enclave. As I
see it, this is an implementation detail that is certainly solveable.


Static proposal:


EADD takes an execute_intent flag. It calls a new hook:

int security_enclave_load(struct vm_area_struct *source, bool execute_intent);

This hook will fail if execute_intent==true and the caller has neither
EXECUTE, EXECMOD, nor EXECMEM.

EAUG sets execute_intent = false.

EINIT takes a sigstruct pointer. SGX can (when initially upstreamed
or later on once there's demand) call a new hook:

security_enclave_init(struct sigstruct *sigstruct, struct
vm_area_struct *source);

mmap() and mprotect() will require EXECMEM to create WX or RWX
mappings. They will require EXECMOD to create RX or X mappings of an
execute_intent==false page. They require no permissions in the other
cases.


Dynamic proposal:


EADD does not take any special flags. It does something like this internally:

bool execute_intent = true;
int security_enclave_load(struct vm_area_struct *source, bool
*execute_intent);

The implementation of security_enclave_load() may set *execute_intent to false.
The driver records execute_intent after the LSM is done.

mmap() and mprotect() will require EXECMEM to create WX or RWX
mappings. They will require EXECMOD to create RX or X mappings of an
execute_intent==false page. They require no permissions in the other
cases.



A benefit of the static proposal is that audit failures due to a lack
of EXECUTE permission are easy to implement and to understand in the
lods. With the dynamic model, we can only really audit the lack of
EXECMOD or EXECMEM. A benefit of the dynamic model is that we hide
what is arguably a decently large wart from the API.