lkml.org 
[lkml]   [2019]   [May]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: SGX vs LSM (Re: [PATCH v20 00/28] Intel SGX1 support)
    On Fri, May 17, 2019 at 02:05:39PM -0400, Stephen Smalley wrote:
    > On 5/17/19 1:12 PM, Andy Lutomirski wrote:
    > >
    > >How can that work? Unless the API changes fairly radically, users
    > >fundamentally need to both write and execute the enclave. Some of it will
    > >be written only from already executable pages, and some privilege should be
    > >needed to execute any enclave page that was not loaded like this.
    >
    > I'm not sure what the API is. Let's say they do something like this:
    >
    > fd = open("/dev/sgx/enclave", O_RDONLY);
    > addr = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
    > stuff addr into ioctl args
    > ioctl(fd, ENCLAVE_CREATE, &ioctlargs);
    > ioctl(fd, ENCLAVE_ADD_PAGE, &ioctlargs);
    > ioctl(fd, ENCLAVE_INIT, &ioctlargs);

    That's rougly the flow, except that that all enclaves need to have RW and
    X EPC pages.

    > The important points are that they do not open /dev/sgx/enclave with write
    > access (otherwise they will trigger FILE__WRITE at open time, and later
    > encounter FILE__EXECUTE as well during mmap, thereby requiring both to be
    > allowed to /dev/sgx/enclave), and that they do not request PROT_WRITE to the
    > resulting mapping (otherwise they will trigger FILE__WRITE at mmap time).
    > Then only FILE__READ and FILE__EXECUTE are required to /dev/sgx/enclave in
    > policy.
    >
    > If they switch to an anon inode, then any mmap PROT_EXEC of the opened file
    > will trigger an EXECMEM check, at least as currently implemented, as we have
    > no useful backing inode information.

    Yep, and that's by design in the overall proposal. The trick is that
    ENCLAVE_ADD takes a source VMA and copies the contents *and* the
    permissions from the source VMA. The source VMA points at regular memory
    that was mapped and populated using existing mechanisms for loading DSOs.

    E.g. at a high level:

    source_fd = open("/home/sean/path/to/my/enclave", O_RDONLY);
    for_each_chunk {
    <hand waving - mmap()/mprotect() the enclave file into regular memory>
    }

    enclave_fd = open("/dev/sgx/enclave", O_RDWR); /* allocs anon inode */
    enclave_addr = mmap(NULL, size, PROT_READ, MAP_SHARED, enclave_fd, 0);

    ioctl(enclave_fd, ENCLAVE_CREATE, {enclave_addr});
    for_each_chunk {
    struct sgx_enclave_add ioctlargs = {
    .offset = chunk.offset,
    .source = chunk.addr,
    .size = chunk.size,
    .type = chunk.type, /* SGX specific metadata */
    }
    ioctl(fd, ENCLAVE_ADD, &ioctlargs); /* modifies enclave's VMAs */
    }
    ioctl(fd, ENCLAVE_INIT, ...);


    Userspace never explicitly requests PROT_EXEC on enclave_fd, but SGX also
    ensures userspace isn't bypassing LSM policies by virtue of copying the
    permissions for EPC VMAs from regular VMAs that have already gone through
    LSM checks.

    \
     
     \ /
      Last update: 2019-05-17 21:28    [W:6.397 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site