Re: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-12 Thread Jarkko Sakkinen
On Mon, Jun 10, 2019 at 11:17:44AM -0700, Sean Christopherson wrote:
> On Mon, Jun 10, 2019 at 08:45:06PM +0300, Jarkko Sakkinen wrote:
> > On Mon, Jun 10, 2019 at 09:15:33AM -0700, Sean Christopherson wrote:
> > > > 'flags' should would renamed as 'secinfo_flags_mask' even if the name is
> > > > longish. It would use the same values as the SECINFO flags. The field in
> > > > struct sgx_encl_page should have the same name. That would express
> > > > exactly relation between SECINFO and the new field. I would have never
> > > > asked on last iteration why SECINFO is not enough with a better naming.
> > > 
> > > No, these flags do not impact the EPCM protections in any way.  Userspace
> > > can extend the EPCM protections without going through the kernel.  The
> > > protection flags for an enclave page impact VMA/PTE protection bits.
> > > 
> > > IMO, it is best to treat the EPCM as being completely separate from the
> > > kernel's EPC management.
> > 
> > It is a clumsy API if permissions are not taken in the same format for
> > everything. There is no reason not to do it. The way mprotect() callback
> > just interprets the field is as VMA permissions.
> 
> They are two entirely different things.  The explicit protection bits are
> consumed by the kernel, while SECINFO.flags is consumed by the CPU.  The
> intent is to have the protection flags be analogous to mprotect(), the
> fact that they have a similar/identical format to SECINFO is irrelevant.
> 
> Calling the field secinfo_flags_mask is straight up wrong on SGX2, as 
> userspace can use EMODPE to set SECINFO after the page is added.  It's
> also wrong on SGX1 when adding TCS pages since SECINFO.RWX bits for TCS
> pages are forced to zero by hardware.

The new variable tells the limits on which kernel will co-operate with
the enclave. It is way more descriptive than 'flags'.

> > It would also be more future-proof just to have a mask covering all bits
> > of the SECINFO flags field.
> 
> This simply doesn't work, e.g. the PENDING, MODIFIED and PR flags in the
> SECINFO are read-only from a software perspective.

It is easy to validate reserved bits from a SECINFO struct.

/Jarkko


RE: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-12 Thread Xing, Cedric
> From: Christopherson, Sean J
> Sent: Wednesday, June 12, 2019 7:34 AM
> 
> On Tue, Jun 11, 2019 at 05:09:28PM -0700, Andy Lutomirski wrote:
> >
> > On Jun 10, 2019, at 3:28 PM, Xing, Cedric 
> wrote:
> >
> > >> From: Andy Lutomirski [mailto:l...@kernel.org]
> > >> Sent: Monday, June 10, 2019 12:15 PM This seems like an odd
> > >> workflow.  Shouldn't the #PF return back to untrusted userspace so
> > >> that the untrusted user code can make its own decision as to
> > >> whether it wants to EAUG a page there as opposed to, say, killing
> > >> the enclave or waiting to keep resource usage under control?
> > >
> > > This may seem odd to some at the first glance. But if you can think
> > > of how static heap (pre-allocated by EADD before EINIT) works, the
> > > load parses the "metadata" coming with the enclave to decide the
> > > address/size of the heap, EADDs it, and calls it done. In the case
> > > of "dynamic" heap (allocated dynamically by EAUG after EINIT), the
> > > same thing applies - the loader determines the range of the heap,
> > > tells the SGX module about it, and calls it done. Everything else is
> the between the enclave and the SGX module.
> > >
> > > In practice, untrusted code usually doesn't know much about
> > > enclaves, just like it doesn't know much about the shared objects
> > > loaded into its address space either. Without the necessary
> > > knowledge, untrusted code usually just does what it is told (via
> > > o-calls, or return value from e-calls), without judging that's right
> or wrong.
> > >
> > > When it comes to #PF like what I described, of course a signal could
> > > be sent to the untrusted code but what would it do then? Usually
> > > it'd just come back asking for a page at the fault address. So we
> > > figured it'd be more efficient to just have the kernel EAUG at #PF.
> > >
> > > Please don't get me wrong though, as I'm not dictating what the s/w
> > > flow shall be. It's just going to be a choice offered to user mode.
> > > And that choice was planned to be offered via mprotect() - i.e. a
> > > writable vma causes kernel to EAUG while a non-writable vma will
> > > result in a signal (then the user mode could decide whether to
> > > EAUG). The key point is flexibility - as we want to allow all
> > > reasonable s/w flows instead of dictating one over others. We had
> similar discussions on vDSO API before.
> > > And I think you accepted my approach because of its flexibility. Am
> > > I right?
> >
> > As long as user code can turn this off, I have no real objection. But
> > it might make sense to have it be more explicit — have an ioctl set up
> > a range as “EAUG-on-demand”.
> 
> This was part of the motivation behind changing SGX_IOC_ENCLAVE_ADD_PAGE
> to SGX_IOC_ENCLAVE_ADD_REGION and adding a @flags parameter.  E.g.
> adding support for "EAUG-on-demand" regions would just be a new flag.

We'll end up in some sort of interface eventually. But that's too early to 
discuss.

Currently what we need is the plumbing - i.e. the range has to be mmap()'ed and 
it cannot be PROT_NONE, otherwise vm_ops->fault() will not be reached.

> 
> > But this is all currently irrelevant. We can argue about it when the
> > patches show up. :)


Re: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-12 Thread Sean Christopherson
On Tue, Jun 11, 2019 at 05:09:28PM -0700, Andy Lutomirski wrote:
> 
> On Jun 10, 2019, at 3:28 PM, Xing, Cedric  wrote:
> 
> >> From: Andy Lutomirski [mailto:l...@kernel.org]
> >> Sent: Monday, June 10, 2019 12:15 PM
> >> This seems like an odd workflow.  Shouldn't the #PF return back to
> >> untrusted userspace so that the untrusted user code can make its own
> >> decision as to whether it wants to EAUG a page there as opposed to, say,
> >> killing the enclave or waiting to keep resource usage under control?
> > 
> > This may seem odd to some at the first glance. But if you can think of how
> > static heap (pre-allocated by EADD before EINIT) works, the load parses the
> > "metadata" coming with the enclave to decide the address/size of the heap,
> > EADDs it, and calls it done. In the case of "dynamic" heap (allocated
> > dynamically by EAUG after EINIT), the same thing applies - the loader
> > determines the range of the heap, tells the SGX module about it, and calls
> > it done. Everything else is the between the enclave and the SGX module.
> > 
> > In practice, untrusted code usually doesn't know much about enclaves, just
> > like it doesn't know much about the shared objects loaded into its address
> > space either. Without the necessary knowledge, untrusted code usually just
> > does what it is told (via o-calls, or return value from e-calls), without
> > judging that's right or wrong. 
> > 
> > When it comes to #PF like what I described, of course a signal could be
> > sent to the untrusted code but what would it do then? Usually it'd just
> > come back asking for a page at the fault address. So we figured it'd be
> > more efficient to just have the kernel EAUG at #PF. 
> > 
> > Please don't get me wrong though, as I'm not dictating what the s/w flow
> > shall be. It's just going to be a choice offered to user mode. And that
> > choice was planned to be offered via mprotect() - i.e. a writable vma
> > causes kernel to EAUG while a non-writable vma will result in a signal
> > (then the user mode could decide whether to EAUG). The key point is
> > flexibility - as we want to allow all reasonable s/w flows instead of
> > dictating one over others. We had similar discussions on vDSO API before.
> > And I think you accepted my approach because of its flexibility. Am I
> > right?
> 
> As long as user code can turn this off, I have no real objection. But it
> might make sense to have it be more explicit — have an ioctl set up a range
> as “EAUG-on-demand”.

This was part of the motivation behind changing SGX_IOC_ENCLAVE_ADD_PAGE
to SGX_IOC_ENCLAVE_ADD_REGION and adding a @flags parameter.  E.g. adding
support for "EAUG-on-demand" regions would just be a new flag.

> But this is all currently irrelevant. We can argue about it when the patches
> show up. :)


Re: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-11 Thread Andy Lutomirski



On Jun 10, 2019, at 3:28 PM, Xing, Cedric  wrote:

>> From: Andy Lutomirski [mailto:l...@kernel.org]
>> Sent: Monday, June 10, 2019 12:15 PM
>> 
>> On Mon, Jun 10, 2019 at 11:29 AM Xing, Cedric 
>> wrote:
>>> 
 From: Christopherson, Sean J
 Sent: Wednesday, June 05, 2019 7:12 PM
 
 +/**
 + * sgx_map_allowed - check vma protections against the associated
 enclave page
 + * @encl:an enclave
 + * @start:   start address of the mapping (inclusive)
 + * @end: end address of the mapping (exclusive)
 + * @prot:protection bits of the mapping
 + *
 + * Verify a userspace mapping to an enclave page would not violate
 +the security
 + * requirements of the *kernel*.  Note, this is in no way related
 +to the
 + * page protections enforced by hardware via the EPCM.  The EPCM
 +protections
 + * can be directly extended by the enclave, i.e. cannot be relied
 +upon by the
 + * kernel for security guarantees of any kind.
 + *
 + * Return:
 + *   0 on success,
 + *   -EACCES if the mapping is disallowed
 + */
 +int sgx_map_allowed(struct sgx_encl *encl, unsigned long start,
 + unsigned long end, unsigned long prot) {
 + struct sgx_encl_page *page;
 + unsigned long addr;
 +
 + prot &= (VM_READ | VM_WRITE | VM_EXEC);
 + if (!prot || !encl)
 + return 0;
 +
 + mutex_lock(>lock);
 +
 + for (addr = start; addr < end; addr += PAGE_SIZE) {
 + page = radix_tree_lookup(>page_tree, addr >>
 PAGE_SHIFT);
 +
 + /*
 +  * Do not allow R|W|X to a non-existent page, or
>> protections
 +  * beyond those of the existing enclave page.
 +  */
 + if (!page || (prot & ~page->prot))
 + return -EACCES;
>>> 
>>> In SGX2, pages will be "mapped" before being populated.
>>> 
>>> Here's a brief summary for those who don't have enough background on
>> how new EPC pages could be added to a running enclave in SGX2:
>>>  - There are 2 new instructions - EACCEPT and EAUG.
>>>  - EAUG is used by SGX module to add (augment) a new page to an
>> existing enclave. The newly added page is *inaccessible* until the
>> enclave *accepts* it.
>>>  - EACCEPT is the instruction for an enclave to accept a new page.
>>> 
>>> And the s/w flow for an enclave to request new EPC pages is expected
>> to be something like the following:
>>>  - The enclave issues EACCEPT at the linear address that it would
>> like a new page.
>>>  - EACCEPT results in #PF, as there's no page at the linear address
>> above.
>>>  - SGX module is notified about the #PF, in form of its vma->vm_ops-
>>> fault() being called by kernel.
>>>  - SGX module EAUGs a new EPC page at the fault address, and resumes
>> the enclave.
>>>  - EACCEPT is reattempted, and succeeds at this time.
>> 
>> This seems like an odd workflow.  Shouldn't the #PF return back to
>> untrusted userspace so that the untrusted user code can make its own
>> decision as to whether it wants to EAUG a page there as opposed to, say,
>> killing the enclave or waiting to keep resource usage under control?
> 
> This may seem odd to some at the first glance. But if you can think of how 
> static heap (pre-allocated by EADD before EINIT) works, the load parses the 
> "metadata" coming with the enclave to decide the address/size of the heap, 
> EADDs it, and calls it done. In the case of "dynamic" heap (allocated 
> dynamically by EAUG after EINIT), the same thing applies - the loader 
> determines the range of the heap, tells the SGX module about it, and calls it 
> done. Everything else is the between the enclave and the SGX module.
> 
> In practice, untrusted code usually doesn't know much about enclaves, just 
> like it doesn't know much about the shared objects loaded into its address 
> space either. Without the necessary knowledge, untrusted code usually just 
> does what it is told (via o-calls, or return value from e-calls), without 
> judging that's right or wrong. 
> 
> When it comes to #PF like what I described, of course a signal could be sent 
> to the untrusted code but what would it do then? Usually it'd just come back 
> asking for a page at the fault address. So we figured it'd be more efficient 
> to just have the kernel EAUG at #PF. 
> 
> Please don't get me wrong though, as I'm not dictating what the s/w flow 
> shall be. It's just going to be a choice offered to user mode. And that 
> choice was planned to be offered via mprotect() - i.e. a writable vma causes 
> kernel to EAUG while a non-writable vma will result in a signal (then the 
> user mode could decide whether to EAUG). The key point is flexibility - as we 
> want to allow all reasonable s/w flows instead of dictating one over others. 
> We had similar discussions on vDSO API before. And I think you accepted my 
> approach 

RE: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-10 Thread Xing, Cedric
> From: Andy Lutomirski [mailto:l...@kernel.org]
> Sent: Monday, June 10, 2019 12:15 PM
> 
> On Mon, Jun 10, 2019 at 11:29 AM Xing, Cedric 
> wrote:
> >
> > > From: Christopherson, Sean J
> > > Sent: Wednesday, June 05, 2019 7:12 PM
> > >
> > > +/**
> > > + * sgx_map_allowed - check vma protections against the associated
> > > enclave page
> > > + * @encl:an enclave
> > > + * @start:   start address of the mapping (inclusive)
> > > + * @end: end address of the mapping (exclusive)
> > > + * @prot:protection bits of the mapping
> > > + *
> > > + * Verify a userspace mapping to an enclave page would not violate
> > > +the security
> > > + * requirements of the *kernel*.  Note, this is in no way related
> > > +to the
> > > + * page protections enforced by hardware via the EPCM.  The EPCM
> > > +protections
> > > + * can be directly extended by the enclave, i.e. cannot be relied
> > > +upon by the
> > > + * kernel for security guarantees of any kind.
> > > + *
> > > + * Return:
> > > + *   0 on success,
> > > + *   -EACCES if the mapping is disallowed
> > > + */
> > > +int sgx_map_allowed(struct sgx_encl *encl, unsigned long start,
> > > + unsigned long end, unsigned long prot) {
> > > + struct sgx_encl_page *page;
> > > + unsigned long addr;
> > > +
> > > + prot &= (VM_READ | VM_WRITE | VM_EXEC);
> > > + if (!prot || !encl)
> > > + return 0;
> > > +
> > > + mutex_lock(>lock);
> > > +
> > > + for (addr = start; addr < end; addr += PAGE_SIZE) {
> > > + page = radix_tree_lookup(>page_tree, addr >>
> > > PAGE_SHIFT);
> > > +
> > > + /*
> > > +  * Do not allow R|W|X to a non-existent page, or
> protections
> > > +  * beyond those of the existing enclave page.
> > > +  */
> > > + if (!page || (prot & ~page->prot))
> > > + return -EACCES;
> >
> > In SGX2, pages will be "mapped" before being populated.
> >
> > Here's a brief summary for those who don't have enough background on
> how new EPC pages could be added to a running enclave in SGX2:
> >   - There are 2 new instructions - EACCEPT and EAUG.
> >   - EAUG is used by SGX module to add (augment) a new page to an
> existing enclave. The newly added page is *inaccessible* until the
> enclave *accepts* it.
> >   - EACCEPT is the instruction for an enclave to accept a new page.
> >
> > And the s/w flow for an enclave to request new EPC pages is expected
> to be something like the following:
> >   - The enclave issues EACCEPT at the linear address that it would
> like a new page.
> >   - EACCEPT results in #PF, as there's no page at the linear address
> above.
> >   - SGX module is notified about the #PF, in form of its vma->vm_ops-
> >fault() being called by kernel.
> >   - SGX module EAUGs a new EPC page at the fault address, and resumes
> the enclave.
> >   - EACCEPT is reattempted, and succeeds at this time.
> 
> This seems like an odd workflow.  Shouldn't the #PF return back to
> untrusted userspace so that the untrusted user code can make its own
> decision as to whether it wants to EAUG a page there as opposed to, say,
> killing the enclave or waiting to keep resource usage under control?

This may seem odd to some at the first glance. But if you can think of how 
static heap (pre-allocated by EADD before EINIT) works, the load parses the 
"metadata" coming with the enclave to decide the address/size of the heap, 
EADDs it, and calls it done. In the case of "dynamic" heap (allocated 
dynamically by EAUG after EINIT), the same thing applies - the loader 
determines the range of the heap, tells the SGX module about it, and calls it 
done. Everything else is the between the enclave and the SGX module.

In practice, untrusted code usually doesn't know much about enclaves, just like 
it doesn't know much about the shared objects loaded into its address space 
either. Without the necessary knowledge, untrusted code usually just does what 
it is told (via o-calls, or return value from e-calls), without judging that's 
right or wrong. 

When it comes to #PF like what I described, of course a signal could be sent to 
the untrusted code but what would it do then? Usually it'd just come back 
asking for a page at the fault address. So we figured it'd be more efficient to 
just have the kernel EAUG at #PF. 

Please don't get me wrong though, as I'm not dictating what the s/w flow shall 
be. It's just going to be a choice offered to user mode. And that choice was 
planned to be offered via mprotect() - i.e. a writable vma causes kernel to 
EAUG while a non-writable vma will result in a signal (then the user mode could 
decide whether to EAUG). The key point is flexibility - as we want to allow all 
reasonable s/w flows instead of dictating one over others. We had similar 
discussions on vDSO API before. And I think you accepted my approach because of 
its flexibility. Am I right?


Re: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-10 Thread Andy Lutomirski
On Mon, Jun 10, 2019 at 11:29 AM Xing, Cedric  wrote:
>
> > From: Christopherson, Sean J
> > Sent: Wednesday, June 05, 2019 7:12 PM
> >
> > +/**
> > + * sgx_map_allowed - check vma protections against the associated
> > enclave page
> > + * @encl:an enclave
> > + * @start:   start address of the mapping (inclusive)
> > + * @end: end address of the mapping (exclusive)
> > + * @prot:protection bits of the mapping
> > + *
> > + * Verify a userspace mapping to an enclave page would not violate the
> > +security
> > + * requirements of the *kernel*.  Note, this is in no way related to
> > +the
> > + * page protections enforced by hardware via the EPCM.  The EPCM
> > +protections
> > + * can be directly extended by the enclave, i.e. cannot be relied upon
> > +by the
> > + * kernel for security guarantees of any kind.
> > + *
> > + * Return:
> > + *   0 on success,
> > + *   -EACCES if the mapping is disallowed
> > + */
> > +int sgx_map_allowed(struct sgx_encl *encl, unsigned long start,
> > + unsigned long end, unsigned long prot) {
> > + struct sgx_encl_page *page;
> > + unsigned long addr;
> > +
> > + prot &= (VM_READ | VM_WRITE | VM_EXEC);
> > + if (!prot || !encl)
> > + return 0;
> > +
> > + mutex_lock(>lock);
> > +
> > + for (addr = start; addr < end; addr += PAGE_SIZE) {
> > + page = radix_tree_lookup(>page_tree, addr >>
> > PAGE_SHIFT);
> > +
> > + /*
> > +  * Do not allow R|W|X to a non-existent page, or protections
> > +  * beyond those of the existing enclave page.
> > +  */
> > + if (!page || (prot & ~page->prot))
> > + return -EACCES;
>
> In SGX2, pages will be "mapped" before being populated.
>
> Here's a brief summary for those who don't have enough background on how new 
> EPC pages could be added to a running enclave in SGX2:
>   - There are 2 new instructions - EACCEPT and EAUG.
>   - EAUG is used by SGX module to add (augment) a new page to an existing 
> enclave. The newly added page is *inaccessible* until the enclave *accepts* 
> it.
>   - EACCEPT is the instruction for an enclave to accept a new page.
>
> And the s/w flow for an enclave to request new EPC pages is expected to be 
> something like the following:
>   - The enclave issues EACCEPT at the linear address that it would like a new 
> page.
>   - EACCEPT results in #PF, as there's no page at the linear address above.
>   - SGX module is notified about the #PF, in form of its vma->vm_ops->fault() 
> being called by kernel.
>   - SGX module EAUGs a new EPC page at the fault address, and resumes the 
> enclave.
>   - EACCEPT is reattempted, and succeeds at this time.

This seems like an odd workflow.  Shouldn't the #PF return back to
untrusted userspace so that the untrusted user code can make its own
decision as to whether it wants to EAUG a page there as opposed to,
say, killing the enclave or waiting to keep resource usage under
control?


RE: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-10 Thread Xing, Cedric
> From: Christopherson, Sean J
> Sent: Wednesday, June 05, 2019 7:12 PM
> 
> +/**
> + * sgx_map_allowed - check vma protections against the associated
> enclave page
> + * @encl:an enclave
> + * @start:   start address of the mapping (inclusive)
> + * @end: end address of the mapping (exclusive)
> + * @prot:protection bits of the mapping
> + *
> + * Verify a userspace mapping to an enclave page would not violate the
> +security
> + * requirements of the *kernel*.  Note, this is in no way related to
> +the
> + * page protections enforced by hardware via the EPCM.  The EPCM
> +protections
> + * can be directly extended by the enclave, i.e. cannot be relied upon
> +by the
> + * kernel for security guarantees of any kind.
> + *
> + * Return:
> + *   0 on success,
> + *   -EACCES if the mapping is disallowed
> + */
> +int sgx_map_allowed(struct sgx_encl *encl, unsigned long start,
> + unsigned long end, unsigned long prot) {
> + struct sgx_encl_page *page;
> + unsigned long addr;
> +
> + prot &= (VM_READ | VM_WRITE | VM_EXEC);
> + if (!prot || !encl)
> + return 0;
> +
> + mutex_lock(>lock);
> +
> + for (addr = start; addr < end; addr += PAGE_SIZE) {
> + page = radix_tree_lookup(>page_tree, addr >>
> PAGE_SHIFT);
> +
> + /*
> +  * Do not allow R|W|X to a non-existent page, or protections
> +  * beyond those of the existing enclave page.
> +  */
> + if (!page || (prot & ~page->prot))
> + return -EACCES;

In SGX2, pages will be "mapped" before being populated.

Here's a brief summary for those who don't have enough background on how new 
EPC pages could be added to a running enclave in SGX2:
  - There are 2 new instructions - EACCEPT and EAUG.
  - EAUG is used by SGX module to add (augment) a new page to an existing 
enclave. The newly added page is *inaccessible* until the enclave *accepts* it.
  - EACCEPT is the instruction for an enclave to accept a new page.

And the s/w flow for an enclave to request new EPC pages is expected to be 
something like the following:
  - The enclave issues EACCEPT at the linear address that it would like a new 
page.
  - EACCEPT results in #PF, as there's no page at the linear address above.
  - SGX module is notified about the #PF, in form of its vma->vm_ops->fault() 
being called by kernel.
  - SGX module EAUGs a new EPC page at the fault address, and resumes the 
enclave.
  - EACCEPT is reattempted, and succeeds at this time.

But with the above check in sgx_map_allowed(), I'm not sure how this will work 
out with SGX2.

> + }
> +
> + mutex_unlock(>lock);
> +
> + return 0;
> +}
> +


Re: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-10 Thread Sean Christopherson
On Mon, Jun 10, 2019 at 08:45:06PM +0300, Jarkko Sakkinen wrote:
> On Mon, Jun 10, 2019 at 09:15:33AM -0700, Sean Christopherson wrote:
> > > 'flags' should would renamed as 'secinfo_flags_mask' even if the name is
> > > longish. It would use the same values as the SECINFO flags. The field in
> > > struct sgx_encl_page should have the same name. That would express
> > > exactly relation between SECINFO and the new field. I would have never
> > > asked on last iteration why SECINFO is not enough with a better naming.
> > 
> > No, these flags do not impact the EPCM protections in any way.  Userspace
> > can extend the EPCM protections without going through the kernel.  The
> > protection flags for an enclave page impact VMA/PTE protection bits.
> > 
> > IMO, it is best to treat the EPCM as being completely separate from the
> > kernel's EPC management.
> 
> It is a clumsy API if permissions are not taken in the same format for
> everything. There is no reason not to do it. The way mprotect() callback
> just interprets the field is as VMA permissions.

They are two entirely different things.  The explicit protection bits are
consumed by the kernel, while SECINFO.flags is consumed by the CPU.  The
intent is to have the protection flags be analogous to mprotect(), the
fact that they have a similar/identical format to SECINFO is irrelevant.

Calling the field secinfo_flags_mask is straight up wrong on SGX2, as 
userspace can use EMODPE to set SECINFO after the page is added.  It's
also wrong on SGX1 when adding TCS pages since SECINFO.RWX bits for TCS
pages are forced to zero by hardware.

> It would also be more future-proof just to have a mask covering all bits
> of the SECINFO flags field.

This simply doesn't work, e.g. the PENDING, MODIFIED and PR flags in the
SECINFO are read-only from a software perspective.


Re: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-10 Thread Jarkko Sakkinen
On Mon, Jun 10, 2019 at 09:15:33AM -0700, Sean Christopherson wrote:
> > 'flags' should would renamed as 'secinfo_flags_mask' even if the name is
> > longish. It would use the same values as the SECINFO flags. The field in
> > struct sgx_encl_page should have the same name. That would express
> > exactly relation between SECINFO and the new field. I would have never
> > asked on last iteration why SECINFO is not enough with a better naming.
> 
> No, these flags do not impact the EPCM protections in any way.  Userspace
> can extend the EPCM protections without going through the kernel.  The
> protection flags for an enclave page impact VMA/PTE protection bits.
> 
> IMO, it is best to treat the EPCM as being completely separate from the
> kernel's EPC management.

It is a clumsy API if permissions are not taken in the same format for
everything. There is no reason not to do it. The way mprotect() callback
just interprets the field is as VMA permissions.

It would also be more future-proof just to have a mask covering all bits
of the SECINFO flags field.

/Jarkko


Re: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-10 Thread Sean Christopherson
On Mon, Jun 10, 2019 at 06:27:17PM +0300, Jarkko Sakkinen wrote:
> On Wed, Jun 05, 2019 at 07:11:42PM -0700, Sean Christopherson wrote:
> > [SNAP]
> 
> Same general criticism as for the previous patch: try to say things as
> they are without anything extra.
> 
> > A third alternative would be to pull the protection bits from the page's
> > SECINFO, i.e. make decisions based on the protections enforced by
> > hardware.  However, with SGX2, userspace can extend the hardware-
> > enforced protections via ENCLU[EMODPE], e.g. can add a page as RW and
> > later convert it to RX.  With SGX2, making a decision based on the
> > initial protections would either create a security hole or force SGX to
> > dynamically track "dirty" pages (see first alternative above).
> > 
> > Signed-off-by: Sean Christopherson 
> 
> 'flags' should would renamed as 'secinfo_flags_mask' even if the name is
> longish. It would use the same values as the SECINFO flags. The field in
> struct sgx_encl_page should have the same name. That would express
> exactly relation between SECINFO and the new field. I would have never
> asked on last iteration why SECINFO is not enough with a better naming.

No, these flags do not impact the EPCM protections in any way.  Userspace
can extend the EPCM protections without going through the kernel.  The
protection flags for an enclave page impact VMA/PTE protection bits.

IMO, it is best to treat the EPCM as being completely separate from the
kernel's EPC management.

> The same field can be also used to cage page type to a subset of values.
> 
> /Jarkko


Re: [RFC PATCH v2 2/5] x86/sgx: Require userspace to define enclave pages' protection bits

2019-06-10 Thread Jarkko Sakkinen
On Wed, Jun 05, 2019 at 07:11:42PM -0700, Sean Christopherson wrote:
> [SNAP]

Same general criticism as for the previous patch: try to say things as
they are without anything extra.

> A third alternative would be to pull the protection bits from the page's
> SECINFO, i.e. make decisions based on the protections enforced by
> hardware.  However, with SGX2, userspace can extend the hardware-
> enforced protections via ENCLU[EMODPE], e.g. can add a page as RW and
> later convert it to RX.  With SGX2, making a decision based on the
> initial protections would either create a security hole or force SGX to
> dynamically track "dirty" pages (see first alternative above).
> 
> Signed-off-by: Sean Christopherson 

'flags' should would renamed as 'secinfo_flags_mask' even if the name is
longish. It would use the same values as the SECINFO flags. The field in
struct sgx_encl_page should have the same name. That would express
exactly relation between SECINFO and the new field. I would have never
asked on last iteration why SECINFO is not enough with a better naming.

The same field can be also used to cage page type to a subset of values.

/Jarkko