in drivers/virt/nitro_enclaves/ne_misc_dev.c [1559:1630]
static int ne_enclave_release(struct inode *inode, struct file *file)
{
struct ne_pci_dev_cmd_reply cmd_reply = {};
struct enclave_stop_req enclave_stop_request = {};
struct ne_enclave *ne_enclave = file->private_data;
struct ne_pci_dev *ne_pci_dev = ne_devs.ne_pci_dev;
struct pci_dev *pdev = ne_pci_dev->pdev;
int rc = -EINVAL;
struct slot_free_req slot_free_req = {};
if (!ne_enclave)
return 0;
/*
* Early exit in case there is an error in the enclave creation logic
* and fput() is called on the cleanup path.
*/
if (!ne_enclave->slot_uid)
return 0;
/*
* Acquire the enclave list mutex before the enclave mutex
* in order to avoid deadlocks with @ref ne_event_work_handler.
*/
mutex_lock(&ne_pci_dev->enclaves_list_mutex);
mutex_lock(&ne_enclave->enclave_info_mutex);
if (ne_enclave->state != NE_STATE_INIT && ne_enclave->state != NE_STATE_STOPPED) {
enclave_stop_request.slot_uid = ne_enclave->slot_uid;
rc = ne_do_request(pdev, ENCLAVE_STOP,
&enclave_stop_request, sizeof(enclave_stop_request),
&cmd_reply, sizeof(cmd_reply));
if (rc < 0) {
dev_err_ratelimited(ne_misc_dev.this_device,
"Error in enclave stop [rc=%d]\n", rc);
goto unlock_mutex;
}
memset(&cmd_reply, 0, sizeof(cmd_reply));
}
slot_free_req.slot_uid = ne_enclave->slot_uid;
rc = ne_do_request(pdev, SLOT_FREE,
&slot_free_req, sizeof(slot_free_req),
&cmd_reply, sizeof(cmd_reply));
if (rc < 0) {
dev_err_ratelimited(ne_misc_dev.this_device,
"Error in slot free [rc=%d]\n", rc);
goto unlock_mutex;
}
ne_pci_dev_remove_enclave_entry(ne_enclave, ne_pci_dev);
ne_enclave_remove_all_mem_region_entries(ne_enclave);
ne_enclave_remove_all_vcpu_id_entries(ne_enclave);
mutex_unlock(&ne_enclave->enclave_info_mutex);
mutex_unlock(&ne_pci_dev->enclaves_list_mutex);
kfree(ne_enclave);
return 0;
unlock_mutex:
mutex_unlock(&ne_enclave->enclave_info_mutex);
mutex_unlock(&ne_pci_dev->enclaves_list_mutex);
return rc;
}