diff mbox series

[for,v24,2/3] x86/sgx: Destroy enclave if EADD fails

Message ID 20191104200141.5385-2-jarkko.sakkinen@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series [for,v24,1/3] x86/sgx: Use GFP_KERNEL for allocations | expand

Commit Message

Jarkko Sakkinen Nov. 4, 2019, 8:01 p.m. UTC
__sgx_encl_add_page() can only fail in the case of EPCM conflict at least
in non-artificial situations. Also, it consistent semantics in rollback is
something to pursue for. Thus, destroy enclave when the EADD fails as we do
when EEXTEND fails already.

In the cases it is sane to return -EIO. From this the caller can deduce
the failure and knows that the enclave was destroyed. The previous
-EFAULT could happen in numerous situations.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 arch/x86/kernel/cpu/sgx/ioctl.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

Comments

Sean Christopherson Nov. 4, 2019, 8:54 p.m. UTC | #1
On Mon, Nov 04, 2019 at 10:01:40PM +0200, Jarkko Sakkinen wrote:
> __sgx_encl_add_page() can only fail in the case of EPCM conflict at least
> in non-artificial situations.

Huh?  EADD can fail for a variety of reasons.  I can't think of a use case
where userspace _won't_ kill the enclave in response to failure, but that
doesn't justify killing the enclave, e.g. we don't kill the enclave in any
other error path that is just as indicative of a userspace bug.

> Also, it consistent semantics in rollback is something to pursue for.

I don't follow this at all.  How is it inconsistent to state that errors
are handled gracefully unless they're unrecoverable?

> Thus, destroy enclave when the EADD fails as we do when EEXTEND fails
> already.
> 
> In the cases it is sane to return -EIO. From this the caller can deduce
> the failure and knows that the enclave was destroyed. The previous
> -EFAULT could happen in numerous situations.

This should be a separate patch.

> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
>  arch/x86/kernel/cpu/sgx/ioctl.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
> index d53aee5a64c1..289af607f634 100644
> --- a/arch/x86/kernel/cpu/sgx/ioctl.c
> +++ b/arch/x86/kernel/cpu/sgx/ioctl.c
> @@ -338,7 +338,7 @@ static int __sgx_encl_add_page(struct sgx_encl *encl,
>  	kunmap_atomic((void *)pginfo.contents);
>  	put_page(src_page);
>  
> -	return ret ? -EFAULT : 0;
> +	return ret ? -EIO : 0;
>  }
>  
>  static int __sgx_encl_extend(struct sgx_encl *encl,
> @@ -353,7 +353,7 @@ static int __sgx_encl_extend(struct sgx_encl *encl,
>  		if (ret) {
>  			if (encls_failed(ret))
>  				ENCLS_WARN(ret, "EEXTEND");
> -			return -EFAULT;
> +			return -EIO;
>  		}
>  	}
>  
> @@ -413,8 +413,10 @@ static int sgx_encl_add_page(struct sgx_encl *encl,
>  
>  	ret = __sgx_encl_add_page(encl, encl_page, epc_page, secinfo,
>  				  addp->src);
> -	if (ret)
> +	if (ret) {
> +		sgx_encl_destroy(encl);
>  		goto err_out;
> +	}
>  
>  	/*
>  	 * Complete the "add" before doing the "extend" so that the "add"
> @@ -498,10 +500,9 @@ static int sgx_encl_add_page(struct sgx_encl *encl,
>   *
>   * Return:
>   *   0 on success,
> - *   -EINVAL if any input param or the SECINFO contains invalid data,
>   *   -EACCES if an executable source page is located in a noexec partition,
> - *   -ENOMEM if any memory allocation, including EPC, fails,
> - *   -ERESTARTSYS if a pending signal is recognized

Why are you removing the documentation for EINVAL, ENOMEM and ERESTARTSYS?

> + *   -EIO if either ENCLS[EADD] or ENCLS[EEXTEND] fails
> + *   -errno otherwise
>   */
>  static long sgx_ioc_enclave_add_pages(struct sgx_encl *encl, void __user *arg)
>  {
> -- 
> 2.20.1
>
Jarkko Sakkinen Nov. 4, 2019, 10:31 p.m. UTC | #2
On Mon, Nov 04, 2019 at 12:54:01PM -0800, Sean Christopherson wrote:
> On Mon, Nov 04, 2019 at 10:01:40PM +0200, Jarkko Sakkinen wrote:
> > __sgx_encl_add_page() can only fail in the case of EPCM conflict at least
> > in non-artificial situations.
> 
> Huh?  EADD can fail for a variety of reasons.  I can't think of a use case
> where userspace _won't_ kill the enclave in response to failure, but that
> doesn't justify killing the enclave, e.g. we don't kill the enclave in any
> other error path that is just as indicative of a userspace bug.

I think it does because it is the only sane metrics to take and it
also makes the semantics more sound and coherent.

> > Also, it consistent semantics in rollback is something to pursue for.
> 
> I don't follow this at all.  How is it inconsistent to state that errors
> are handled gracefully unless they're unrecoverable?

Always when the user space gets -EIO it will know that enclave ceased
to exist. That is very consistent.

> > Thus, destroy enclave when the EADD fails as we do when EEXTEND fails
> > already.
> > 
> > In the cases it is sane to return -EIO. From this the caller can deduce
> > the failure and knows that the enclave was destroyed. The previous
> > -EFAULT could happen in numerous situations.
> 
> This should be a separate patch.

No it shouldn't because it is so closely connected to the semantics
change.

/Jarkko
diff mbox series

Patch

diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index d53aee5a64c1..289af607f634 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -338,7 +338,7 @@  static int __sgx_encl_add_page(struct sgx_encl *encl,
 	kunmap_atomic((void *)pginfo.contents);
 	put_page(src_page);
 
-	return ret ? -EFAULT : 0;
+	return ret ? -EIO : 0;
 }
 
 static int __sgx_encl_extend(struct sgx_encl *encl,
@@ -353,7 +353,7 @@  static int __sgx_encl_extend(struct sgx_encl *encl,
 		if (ret) {
 			if (encls_failed(ret))
 				ENCLS_WARN(ret, "EEXTEND");
-			return -EFAULT;
+			return -EIO;
 		}
 	}
 
@@ -413,8 +413,10 @@  static int sgx_encl_add_page(struct sgx_encl *encl,
 
 	ret = __sgx_encl_add_page(encl, encl_page, epc_page, secinfo,
 				  addp->src);
-	if (ret)
+	if (ret) {
+		sgx_encl_destroy(encl);
 		goto err_out;
+	}
 
 	/*
 	 * Complete the "add" before doing the "extend" so that the "add"
@@ -498,10 +500,9 @@  static int sgx_encl_add_page(struct sgx_encl *encl,
  *
  * Return:
  *   0 on success,
- *   -EINVAL if any input param or the SECINFO contains invalid data,
  *   -EACCES if an executable source page is located in a noexec partition,
- *   -ENOMEM if any memory allocation, including EPC, fails,
- *   -ERESTARTSYS if a pending signal is recognized
+ *   -EIO if either ENCLS[EADD] or ENCLS[EEXTEND] fails
+ *   -errno otherwise
  */
 static long sgx_ioc_enclave_add_pages(struct sgx_encl *encl, void __user *arg)
 {