Message

This series intends to make the new SGX subsystem to work with the existing LSM
architecture smoothly so that, say, SGX cannot be abused to work around
restrictions set forth by LSM modules/policies.
This patch is based on and could be applied cleanly on top of Jarkko Sakkinen’s
SGX patch series v20 (https://patchwork.kernel.org/cover/10905141/).
For those who haven’t followed closely, the whole discussion started from the
primary question of how to prevent creating an executable enclave page from a
regular memory page that is NOT executable as prohibited by LSM
modules/policies. And that can be translated into 2 relating questions in
practice, i.e. 1) how to determine the allowed initial protections of enclave
pages when they are being loaded and 2) how to determine the allowed
protections of enclave pages at runtime. Those who are familiar with LSM may
notice that, for regular files, #1 is determined by security_mmap_file() while
#2 is covered by security_file_mprotect(). Those 2 hooks however are
insufficient for enclaves due to the distinct composition and lifespan of
enclave pages. Specifically, security_mmap_file() only passes in the file but
is not specific on which portion of the file being mmap()’ed, with the
assumption that all pages of the same file shall have the same set of
allowed/disallowed protections. But that assumption is no longer true for
enclaves for 2 reasons: a) pages of an enclave may be loaded from different
image files with different attributes and b) enclave pages retain contents
across munmap()/mmap(), therefore, say, if a policy prohibits execution of
modified pages, then pages flagged modified have to stay modified across
munmap()/mmap() so that the policy cannot be circumvented by remapping (i.e.
munmap() followed by mmap() on the same range). But the lack of range
information in security_mmap_file()’s arguments simply blocks LSM modules from
tracking enclave pages properly.
A rational solution would always involve tracking the correspondence between
enclave pages and their origin (e.g. files from which they were loaded), which
is similar to tracking regular memory pages and their origin via vm_file of
struct vm_area_struct. But given the longer lifespan of enclave pages (than
VMAs they are mapped into), such correspondence has to be stored in a separate
data structure outside of VMAs. In theory, the correspondence could be stored
either in LSM or in the SGX subsystem. This series has picked the former
because firstly, such information is useful only within LSM so it makes more
sense to keep it as “LSM internal” and secondly, keeping the data structure
inside LSM would allow additional information to be cached in LSM modules
without affecting the rest of the kernel, while lastly, those data structures
would be gone when LSM is disabled hence would not impose any unnecessary
overhead. As you can see in the SELinux implementation of those new hooks
enclosed in this series, options are offered (via kernel command line
parameter) to system administrators between accurate auditing (decisions made
at the time of request) and low memory/performance overhead (decisions
made/cached ahead of time at page instantiation). And that’s one of the
benefits of keeping everything inside LSM.
Those who are familiar with this topic and related discussions may also notice
that, Sean Christopherson has sent out an RFC patch recently to address the
same problem as this series. He adopted the other approach of tracking
page/origin correspondence inside the SGX subsystem. However, to reduce memory
overhead in practice, he cached the FSM (Finite State Machine) instead of
page/origin correspondences. By “FSM”, I mean policy FSM defined as sets of
states and events that may trigger state transitions. Generally speaking, any
LSM module has its own definition of FSM and usually uses attributes attached
to files to argument the FSM, then it advances the FSM as events are observed
and gives out decision based on the current FSM state. Sean’s implementation
attempts to move the FSM into the SGX subsystem, and by caching the arguments
returned by LSM it tries to monitor events and reach the same decisions by
itself. So from architecture perspective, that model has to face tough
challenges in reality, such as how to support multiple LSM modules that employ
different FSMs to govern page protection transitions. Implementation wise, his
model also imposes unwanted restrictions specifically to SGX2, such as:
- Complicated/Restricted UAPI – Enclave loaders are required to provide
“maximal protection” at page load time, but such information is NOT always
available. For example, Graphene containers may run different applications
comprised of different set of executables and/or shared objects. Some of
them may contain self-modifying code (or text relocation) while others
don’t. The generic enclave loader usually doesn’t have such information so
wouldn’t be able to provide it ahead of time.
- Inefficient Auditing – Audit logs are supposed to help system
administrators to determine the set of minimally needed permissions and to
detect abnormal behaviors. But consider the “maximal protection” model, if
“maximal protection” is set to be too permissive, then audit log wouldn’t
be able to detect anomalies; or if “maximal protection” is too restrictive,
then audit log cannot identify the file violating the policy. In either
case the audit log cannot fulfill its purposes.
- Inability to support #PF driven EPC allocation in SGX2 – For those
unfamiliar with SGX2 software flows, an SGX2 enclave requests a page by
issuing EACCEPT on the address that a new page is wanted, and the resulted
#PF is expected to be handled by the kernel by EAUG’ing an EPC page at the
fault address, and then the enclave would be resumed and the faulting
EACCEPT retried, and succeed. The key requirement is to allow mmap()’ing
non-existing enclave pages so that the SGX module/subsystem could respond
to #PFs by EAUG’ing new pages. Sean’s implementation doesn’t allow
mmap()’ing non-existing pages for variety of reasons and therefore blocks
this major SGX2 usage.
History:
- This is version 2 of this patch series, with the following changes per
comments/requests from the community:
+ A new data structure – EMA (Enclave Memory Area) is introduced to track
range/origin correspondences for enclaves. EMAs are maintained by the LSM
framework to be shared among all LSM modules. EMAs are allocated for
enclave files only so will not impose overhead to regular
applications/files.
+ Improved auditing – A new kernel command line option
“lsm.ema.cache_decisions” is introduced, if on, would cause LSM modules
to make/cache decisions at page instantiation (i.e. enclave_load() hook)
instead of at time of request (i.e. file_mprotect() hook), in order to
save memory by NOT keeping enclave source files open. System
administrators are expected to run LSM in permissive mode along with this
option off to figure out the minimal permissions necessary, then turn it
back on in enforcing mode to minimize memory/performance overheads.
+ In the SELinux implementation of the new hooks, FILE__EXECUTE on the file
containing SIGSTRUCT is interpreted as approval for launch, while
FILE__EXECMOD is interpreted as allowing anonymous pages (i.e. pages
EAUG’ed, or EADD’ed from an anonymous source page) to be executable.
Allowed protections for other pages loaded from files are dictated by the
source files’ FILE__EXECUTE/FILE__EXECMOD. This series intentionally
avoids defining new permissions so that user mode tools could continue to
work by treating enclave files the same way as regular executables and/or
shared objects.
- v1 – https://patchwork.kernel.org/cover/10984127/
Cedric Xing (3):
x86/sgx: Add SGX specific LSM hooks
x86/sgx: Call LSM hooks from SGX subsystem/module
x86/sgx: Implement SGX specific hooks in SELinux
arch/x86/kernel/cpu/sgx/driver/ioctl.c | 80 ++++++++-
arch/x86/kernel/cpu/sgx/driver/main.c | 16 +-
include/linux/lsm_ema.h | 171 ++++++++++++++++++
include/linux/lsm_hooks.h | 29 ++++
include/linux/security.h | 23 +++
security/Makefile | 1 +
security/lsm_ema.c | 132 ++++++++++++++
security/security.c | 47 ++++-
security/selinux/hooks.c | 229 ++++++++++++++++++++++++-
security/selinux/include/objsec.h | 24 +++
10 files changed, 732 insertions(+), 20 deletions(-)
create mode 100644 include/linux/lsm_ema.h
create mode 100644 security/lsm_ema.c

Comments

On Thu, Jun 27, 2019 at 11:56:18AM -0700, Cedric Xing wrote:
I think it is fine to have these patch sets as a discussion starters but
it does not make any sense to me to upstream LSM changes with the SGX
foundations.
This is exactly the same situation as with KVM changes. The patch set is
already way too big to fit to the standards [1].
The eye should be on whether the uapi (e.g. device files, ioctl's) will
work for LSM's in a legit way. Do we need more of these different
flavors of experimental LSM changes or can we make some conclusions with
the real issue we are trying to deal with?
[1] "Do not send more than 15 patches at once to the vger mailing lists!!!"
https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html#select-the-recipients-for-your-patch
/Jarkko

> The eye should be on whether the uapi (e.g. device files, ioctl's) will> work for LSM's in a legit way. Do we need more of these different> flavors of experimental LSM changes or can we make some conclusions with> the real issue we are trying to deal with?
Anyway, sending v21 soonish. Finished it on Thu but have been waiting
any internal QA feedback. If nothing pops up, I'll send it tmrw.
/Jarkko

On Thu, Jul 04, 2019 at 02:22:21AM +0300, Jarkko Sakkinen wrote:
> > The eye should be on whether the uapi (e.g. device files, ioctl's) will> > work for LSM's in a legit way. Do we need more of these different> > flavors of experimental LSM changes or can we make some conclusions with> > the real issue we are trying to deal with?> > Anyway, sending v21 soonish. Finished it on Thu but have been waiting> any internal QA feedback. If nothing pops up, I'll send it tmrw.
Ugh, the point I forgot to add was that it contains update to
SGX_IOC_ENCLAVE_ADD_PAGE that is relevant for the discussion (probably
the same as Sean proposed cannot recall if I did tuning to it).
/Jarkko

On 7/3/2019 4:16 PM, Jarkko Sakkinen wrote:
> On Thu, Jun 27, 2019 at 11:56:18AM -0700, Cedric Xing wrote:> > I think it is fine to have these patch sets as a discussion starters but> it does not make any sense to me to upstream LSM changes with the SGX> foundations.
Guess LSM is a gating factor, because otherwise SGX could be abused to
make executable EPC from pages that are otherwise not allowed to be
executable. Am I missing anything?
> > This is exactly the same situation as with KVM changes. The patch set is> already way too big to fit to the standards [1].> > The eye should be on whether the uapi (e.g. device files, ioctl's) will> work for LSM's in a legit way. Do we need more of these different> flavors of experimental LSM changes or can we make some conclusions with> the real issue we are trying to deal with?> > [1] "Do not send more than 15 patches at once to the vger mailing lists!!!"> https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html#select-the-recipients-for-your-patch> > /Jarkko>

On Fri, 2019-07-05 at 22:04 -0700, Xing, Cedric wrote:
> On 7/3/2019 4:16 PM, Jarkko Sakkinen wrote:> > On Thu, Jun 27, 2019 at 11:56:18AM -0700, Cedric Xing wrote:> > > > I think it is fine to have these patch sets as a discussion starters but> > it does not make any sense to me to upstream LSM changes with the SGX> > foundations.> > Guess LSM is a gating factor, because otherwise SGX could be abused to > make executable EPC from pages that are otherwise not allowed to be > executable. Am I missing anything?
No, but what was the point? LSM is always additional gating factor.
Does not make a case for any of the proposed LSM changes.
/Jarrko