On Fri, May 15, 2020 at 03:44:00AM +0300, Jarkko Sakkinen wrote:
+long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+ struct sgx_encl *encl = filep->private_data;
+ int ret, encl_flags;
+
+ encl_flags = atomic_fetch_or(SGX_ENCL_IOCTL, &encl->flags);
+ if (encl_flags & SGX_ENCL_IOCTL)
+ return -EBUSY;
+
+ if (encl_flags & SGX_ENCL_DEAD)
+ return -EFAULT;
Returning immediately is wrong as it leaves SGX_ENCL_IOCTL set. This results
in the application seeing -EBUSY on future ioctls() instead of -EFAULT. Can be
fixed as below. Do you want me to send a formal patch on linux-sgx?
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index 77757a74644d..df35a79e915c 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -751,8 +751,10 @@ long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
if (encl_flags & SGX_ENCL_IOCTL)
return -EBUSY;
- if (encl_flags & SGX_ENCL_DEAD)
- return -EFAULT;
+ if (encl_flags & SGX_ENCL_DEAD) {
+ ret = -EFAULT;
+ goto out;
+ }
switch (cmd) {
case SGX_IOC_ENCLAVE_CREATE:@@ -772,6 +774,7 @@ long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
break;
}
+out:
atomic_andnot(SGX_ENCL_IOCTL, &encl->flags);
return ret;
+
+ switch (cmd) {
+ case SGX_IOC_ENCLAVE_CREATE:
+ ret = sgx_ioc_enclave_create(encl, (void __user *)arg);
+ break;
+ case SGX_IOC_ENCLAVE_ADD_PAGES:
+ ret = sgx_ioc_enclave_add_pages(encl, (void __user *)arg);
+ break;
+ case SGX_IOC_ENCLAVE_INIT:
+ ret = sgx_ioc_enclave_init(encl, (void __user *)arg);
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+
+ atomic_andnot(SGX_ENCL_IOCTL, &encl->flags);
+
+ return ret;
+}