Fix ioctl SGX_IOC_GET_EPID_GROUP_ID for EBUSY error

SGX SDK's sgx_init_quote may return SGX_ERROR_BUSY, which is previously not
handled. The implementation of ioctl for /dev/sgx is now fixed to handle this
error.
This commit is contained in:
Tate, Hongliang Tian 2020-01-20 07:40:52 +00:00
parent c6bcbaf442
commit 986d1d2e44
3 changed files with 41 additions and 12 deletions

@ -74,8 +74,13 @@ impl InnerAgent {
); );
assert!(status == sgx_status_t::SGX_SUCCESS); assert!(status == sgx_status_t::SGX_SUCCESS);
if (retval != sgx_status_t::SGX_SUCCESS) { if retval != sgx_status_t::SGX_SUCCESS {
return_errno!(EINVAL, "occlum_ocall_sgx_init_quote failed"); match retval {
sgx_status_t::SGX_ERROR_BUSY => {
return_errno!(EBUSY, "occlum_ocall_sgx_init_quote is temporarily busy")
}
_ => return_errno!(EINVAL, "occlum_ocall_sgx_init_quote failed"),
}
} }
} }

@ -5,6 +5,9 @@ sgx_status_t occlum_ocall_sgx_init_quote(
sgx_target_info_t* target_info, sgx_target_info_t* target_info,
sgx_epid_group_id_t* epid_group_id) sgx_epid_group_id_t* epid_group_id)
{ {
// Intel's manual:
// It's suggested that the caller should wait (typically several seconds
// to ten of seconds) and retry this API if SGX_ERROR_BUSY is returned.
return sgx_init_quote(target_info, epid_group_id); return sgx_init_quote(target_info, epid_group_id);
} }

@ -44,6 +44,9 @@ typedef struct {
#define SGXIOC_GET_EPID_GROUP_ID _IOR('s', 1, sgx_epid_group_id_t) #define SGXIOC_GET_EPID_GROUP_ID _IOR('s', 1, sgx_epid_group_id_t)
#define SGXIOC_GEN_QUOTE _IOWR('s', 2, sgxioc_gen_quote_arg_t) #define SGXIOC_GEN_QUOTE _IOWR('s', 2, sgxioc_gen_quote_arg_t)
// The max number of retries if ioctl returns EBUSY
#define IOCTL_MAX_RETRIES 20
typedef int(*sgx_ioctl_test_body_t)(int sgx_fd); typedef int(*sgx_ioctl_test_body_t)(int sgx_fd);
static int do_SGXIOC_IS_EDDM_SUPPORTED(int sgx_fd) { static int do_SGXIOC_IS_EDDM_SUPPORTED(int sgx_fd) {
@ -57,11 +60,26 @@ static int do_SGXIOC_IS_EDDM_SUPPORTED(int sgx_fd) {
return 0; return 0;
} }
static int do_SGXIOC_GET_EPID_GROUP_ID(int sgx_fd) { static int do_SGXIOC_GET_EPID_GROUP_ID(int sgx_fd) {
int nretries = 0;
while (nretries < IOCTL_MAX_RETRIES) {
sgx_epid_group_id_t epid_group_id = { 0 }; sgx_epid_group_id_t epid_group_id = { 0 };
if (ioctl(sgx_fd, SGXIOC_GET_EPID_GROUP_ID, &epid_group_id) < 0) { int ret = ioctl(sgx_fd, SGXIOC_GET_EPID_GROUP_ID, &epid_group_id);
if (ret == 0) {
break;
}
else if (errno != EBUSY) {
THROW_ERROR("failed to ioctl /dev/sgx"); THROW_ERROR("failed to ioctl /dev/sgx");
} }
printf("WARN: /dev/sgx is temporarily busy. Try again after 1 second.");
sleep(1);
nretries++;
}
if (nretries == IOCTL_MAX_RETRIES) {
THROW_ERROR("failed to ioctl /dev/sgx due to timeout");
}
return 0; return 0;
} }
@ -77,19 +95,22 @@ static int do_SGXIOC_GEN_QUOTE(int sgx_fd) {
.quote_buf_len = sizeof(quote_buf), // input .quote_buf_len = sizeof(quote_buf), // input
.quote = { .as_buf = (uint8_t*) quote_buf } // output .quote = { .as_buf = (uint8_t*) quote_buf } // output
}; };
int nretries = 0;
while (1) { while (nretries < IOCTL_MAX_RETRIES) {
int ret = ioctl(sgx_fd, SGXIOC_GEN_QUOTE, &gen_quote_arg); int ret = ioctl(sgx_fd, SGXIOC_GEN_QUOTE, &gen_quote_arg);
if (ret == 0) { if (ret == 0) {
break; break;
} }
else if (errno == EAGAIN) { else if (errno != EBUSY) {
printf("WARN: /dev/sgx is temporarily busy. Try again after 1 second.");
sleep(1);
}
else {
THROW_ERROR("failed to ioctl /dev/sgx"); THROW_ERROR("failed to ioctl /dev/sgx");
} }
printf("WARN: /dev/sgx is temporarily busy. Try again after 1 second.");
sleep(1);
nretries++;
}
if (nretries == IOCTL_MAX_RETRIES) {
THROW_ERROR("failed to ioctl /dev/sgx due to timeout");
} }
sgx_quote_t* quote = (sgx_quote_t*)quote_buf; sgx_quote_t* quote = (sgx_quote_t*)quote_buf;