Re: [RFC PATCH v1 2/3] LSM/x86/sgx: Implement SGX specific hooks in SELinux

From: Stephen Smalley
Date: Thu Jun 13 2019 - 13:07:28 EST


On 6/11/19 6:02 PM, Sean Christopherson wrote:
On Tue, Jun 11, 2019 at 09:40:25AM -0400, Stephen Smalley wrote:
I haven't looked at this code closely, but it feels like a lot of
SGX-specific logic embedded into SELinux that will have to be repeated or
reused for every security module. Does SGX not track this state itself?

SGX does track equivalent state.

There are three proposals on the table (I think):

1. Require userspace to explicitly specificy (maximal) enclave page
permissions at build time. The enclave page permissions are provided
to, and checked by, LSMs at enclave build time.

Pros: Low-complexity kernel implementation, straightforward auditing
Cons: Sullies the SGX UAPI to some extent, may increase complexity of
SGX2 enclave loaders.

2. Pre-check LSM permissions and dynamically track mappings to enclave
pages, e.g. add an SGX mprotect() hook to restrict W->X and WX
based on the pre-checked permissions.

Pros: Does not impact SGX UAPI, medium kernel complexity
Cons: Auditing is complex/weird, requires taking enclave-specific
lock during mprotect() to query/update tracking.

3. Implement LSM hooks in SGX to allow LSMs to track enclave regions
from cradle to grave, but otherwise defer everything to LSMs.

Pros: Does not impact SGX UAPI, maximum flexibility, precise auditing
Cons: Most complex and "heaviest" kernel implementation of the three,
pushes more SGX details into LSMs.

My RFC series[1] implements #1. My understanding is that Andy (Lutomirski)
prefers #2. Cedric's RFC series implements #3.

Perhaps the easiest way to make forward progress is to rule out the
options we absolutely *don't* want by focusing on the potentially blocking
issue with each option:

#1 - SGX UAPI funkiness

#2 - Auditing complexity, potential enclave lock contention

#3 - Pushing SGX details into LSMs and complexity of kernel implementation


[1] https://lkml.kernel.org/r/20190606021145.12604-1-sean.j.christopherson@xxxxxxxxx

Given the complexity tradeoff, what is the clear motivating example for why #1 isn't the obvious choice? That the enclave loader has no way of knowing a priori whether the enclave will require W->X or WX? But aren't we better off requiring enclaves to be explicitly marked as needing such so that we can make a more informed decision about whether to load them in the first place?