Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp333511pxa; Wed, 5 Aug 2020 02:18:06 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyzrcrNPrAYSOcMiC+ndik7IKMbvoLvDp/L3AzzzTZP76yJW2sQZbsCyGWLY/TVuR9J6GaU X-Received: by 2002:a17:906:c1c3:: with SMTP id bw3mr2406316ejb.8.1596619086262; Wed, 05 Aug 2020 02:18:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1596619086; cv=none; d=google.com; s=arc-20160816; b=wPgO3fl9c0dFZ3WPxR69ur/pPvV0hXmNGvpx6A0pNO0ydUD+cEuT5Eg/vl1KUaA7IP qmnFP6zbISQIqf5e1lMecxbjbdqR1bE4vdrEC/daseMn+EzAHYp7KF9lXayheIgkjXq4 6Gt/agBpRuHE8aKbrwO433Wj3v1WZRUVbU3FMCTMhG/mS3GV9aa1MH3k8N88Gk75FIKH /bNNg7JT1fsUqyA2k34qLbH18g4WuADtHBMXf3TMokxGWfSZ4LE+Jil7f5FbnqRvgRPK 3R1sVzDsSakepKhWabKX3D7nMRN3b/XgB0gWRmW1QWz1YNUEvLBklEBl4dfsYzszBzcv EgfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :ironport-sdr:dkim-signature; bh=8ErOvF97Bx0lhY3aVo3dAaUZvbmZ/E3Jr3Kc9DUw8G0=; b=pmRmzZbW7//tq9fvqjb2ajLkRMGvVDExEXku54wIOzj35BE1o/xal0ZhY0NJZVYtJ4 tctaCebntOCiQA9320ntoW5uUIvzxGja8kum19mqI7gJwoyWNbQY6H0EpHLksmKBR/XP FifovSbSyrHmfGuc8WUCD6fzTE0ACjXmU1Z5aWfp9/C7+V/0nGPsrwCX92ZMEhTdMcvX H5Zh6h9DSRDQqV1v5q/XvvtBUzhcxT427qN2qrBKUeRSJFBG3+HrO7twcxQinu1LuP6Q krj3v1l+E5+cnVTpj7nE7ID84Vjk2/hIebfCb+iurveBL0Tb2TujvCXpKCqJ7on0zEk4 ujWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amazon.com header.s=amazon201209 header.b=LMZuq5Gr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r4si812176edo.611.2020.08.05.02.16.45; Wed, 05 Aug 2020 02:18:06 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@amazon.com header.s=amazon201209 header.b=LMZuq5Gr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728524AbgHEJQ2 (ORCPT + 99 others); Wed, 5 Aug 2020 05:16:28 -0400 Received: from smtp-fw-6002.amazon.com ([52.95.49.90]:58975 "EHLO smtp-fw-6002.amazon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728560AbgHEJMw (ORCPT ); Wed, 5 Aug 2020 05:12:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1596618771; x=1628154771; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8ErOvF97Bx0lhY3aVo3dAaUZvbmZ/E3Jr3Kc9DUw8G0=; b=LMZuq5Gryp4iYCH8/v92AVSoHufSKAsqbj1VKguR7LCz4gnYs04Qb43A Ay5MF8sxILge3sd3KTy35vAIZjQIlexkbMdr98TXW84VxGwFNmq+X4Kso Cxl04NqNn4+piqg/A9SX5GyBfDrCos3uMwwJ9jKksV3gLziEDMAEmO8I0 A=; IronPort-SDR: ms1v7GVv1aopFINL+vzep475nRoSlVgVscAq/HzQE4RDHLoDezIwPgdd7FuHk7Z9b5FJ5aK809 EL2+DQDPv+ig== X-IronPort-AV: E=Sophos;i="5.75,436,1589241600"; d="scan'208";a="46143707" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-2c-1968f9fa.us-west-2.amazon.com) ([10.43.8.6]) by smtp-border-fw-out-6002.iad6.amazon.com with ESMTP; 05 Aug 2020 09:12:50 +0000 Received: from EX13MTAUEA002.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan3.pdx.amazon.com [10.170.41.166]) by email-inbound-relay-2c-1968f9fa.us-west-2.amazon.com (Postfix) with ESMTPS id 37E8CA1F62; Wed, 5 Aug 2020 09:12:48 +0000 (UTC) Received: from EX13D16EUB003.ant.amazon.com (10.43.166.99) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 5 Aug 2020 09:12:47 +0000 Received: from 38f9d34ed3b1.ant.amazon.com (10.43.162.248) by EX13D16EUB003.ant.amazon.com (10.43.166.99) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 5 Aug 2020 09:12:37 +0000 From: Andra Paraschiv To: linux-kernel CC: Anthony Liguori , Benjamin Herrenschmidt , Colm MacCarthaigh , "David Duncan" , Bjoern Doebel , "David Woodhouse" , Frank van der Linden , Alexander Graf , Greg KH , "Karen Noel" , Martin Pohlack , Matt Wilson , Paolo Bonzini , Balbir Singh , Stefano Garzarella , "Stefan Hajnoczi" , Stewart Smith , "Uwe Dannowski" , Vitaly Kuznetsov , kvm , ne-devel-upstream , Andra Paraschiv Subject: [PATCH v6 13/18] nitro_enclaves: Add logic for terminating an enclave Date: Wed, 5 Aug 2020 12:10:12 +0300 Message-ID: <20200805091017.86203-14-andraprs@amazon.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: <20200805091017.86203-1-andraprs@amazon.com> References: <20200805091017.86203-1-andraprs@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.162.248] X-ClientProxiedBy: EX13D37UWA003.ant.amazon.com (10.43.160.25) To EX13D16EUB003.ant.amazon.com (10.43.166.99) Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org An enclave is associated with an fd that is returned after the enclave creation logic is completed. This enclave fd is further used to setup enclave resources. Once the enclave needs to be terminated, the enclave fd is closed. Add logic for enclave termination, that is mapped to the enclave fd release callback. Free the internal enclave info used for bookkeeping. Signed-off-by: Alexandru Vasile Signed-off-by: Andra Paraschiv Reviewed-by: Alexander Graf --- Changelog v5 -> v6 * Update documentation to kernel-doc format. * Use directly put_page() instead of unpin_user_pages(), to match the get_user_pages() calls. v4 -> v5 * Release the reference to the NE PCI device on enclave fd release. * Adapt the logic to cpumask enclave vCPU ids and CPU cores. * Remove sanity checks for situations that shouldn't happen, only if buggy system or broken logic at all. v3 -> v4 * Use dev_err instead of custom NE log pattern. v2 -> v3 * Remove the WARN_ON calls. * Update static calls sanity checks. * Update kzfree() calls to kfree(). v1 -> v2 * Add log pattern for NE. * Remove the BUG_ON calls. * Update goto labels to match their purpose. * Add early exit in release() if there was a slot alloc error in the fd creation path. --- drivers/virt/nitro_enclaves/ne_misc_dev.c | 168 ++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c index c7eb1146a6c0..6a1b8a0084c4 100644 --- a/drivers/virt/nitro_enclaves/ne_misc_dev.c +++ b/drivers/virt/nitro_enclaves/ne_misc_dev.c @@ -1083,6 +1083,173 @@ static long ne_enclave_ioctl(struct file *file, unsigned int cmd, unsigned long return 0; } +/** + * ne_enclave_remove_all_mem_region_entries() - Remove all memory region entries + * from the enclave data structure. + * @ne_enclave : Private data associated with the current enclave. + * + * Context: Process context. This function is called with the ne_enclave mutex held. + */ +static void ne_enclave_remove_all_mem_region_entries(struct ne_enclave *ne_enclave) +{ + unsigned long i = 0; + struct ne_mem_region *ne_mem_region = NULL; + struct ne_mem_region *ne_mem_region_tmp = NULL; + + list_for_each_entry_safe(ne_mem_region, ne_mem_region_tmp, + &ne_enclave->mem_regions_list, + mem_region_list_entry) { + list_del(&ne_mem_region->mem_region_list_entry); + + for (i = 0; i < ne_mem_region->nr_pages; i++) + put_page(ne_mem_region->pages[i]); + + kfree(ne_mem_region->pages); + + kfree(ne_mem_region); + } +} + +/** + * ne_enclave_remove_all_vcpu_id_entries() - Remove all vCPU id entries from + * the enclave data structure. + * @ne_enclave : Private data associated with the current enclave. + * + * Context: Process context. This function is called with the ne_enclave mutex held. + */ +static void ne_enclave_remove_all_vcpu_id_entries(struct ne_enclave *ne_enclave) +{ + unsigned int cpu = 0; + unsigned int i = 0; + + mutex_lock(&ne_cpu_pool.mutex); + + for (i = 0; i < ne_enclave->avail_cpu_cores_size; i++) { + for_each_cpu(cpu, ne_enclave->avail_cpu_cores[i]) + /* Update the available NE CPU pool. */ + cpumask_set_cpu(cpu, ne_cpu_pool.avail_cores[i]); + + free_cpumask_var(ne_enclave->avail_cpu_cores[i]); + } + + mutex_unlock(&ne_cpu_pool.mutex); + + kfree(ne_enclave->avail_cpu_cores); + + free_cpumask_var(ne_enclave->vcpu_ids); +} + +/** + * ne_pci_dev_remove_enclave_entry() - Remove the enclave entry from the data + * structure that is part of the NE PCI + * device private data. + * @ne_enclave : Private data associated with the current enclave. + * @ne_pci_dev : Private data associated with the PCI device. + * + * Context: Process context. This function is called with the ne_pci_dev enclave + * mutex held. + */ +static void ne_pci_dev_remove_enclave_entry(struct ne_enclave *ne_enclave, + struct ne_pci_dev *ne_pci_dev) +{ + struct ne_enclave *ne_enclave_entry = NULL; + struct ne_enclave *ne_enclave_entry_tmp = NULL; + + list_for_each_entry_safe(ne_enclave_entry, ne_enclave_entry_tmp, + &ne_pci_dev->enclaves_list, enclave_list_entry) { + if (ne_enclave_entry->slot_uid == ne_enclave->slot_uid) { + list_del(&ne_enclave_entry->enclave_list_entry); + + break; + } + } +} + +/** + * ne_enclave_release() - Release function provided by the enclave file. + * @inode: Inode associated with this file release function. + * @file: File associated with this release function. + * + * Context: Process context. + * Return: + * * 0 on success. + * * Negative return value on failure. + */ +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 = NULL; + 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; + + ne_pci_dev = pci_get_drvdata(ne_enclave->pdev); + + /* + * 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(ne_enclave->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(ne_enclave->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); + + pci_dev_put(ne_enclave->pdev); + + 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; +} + /** * ne_enclave_poll() - Poll functionality used for enclave out-of-band events. * @file: File associated with this poll function. @@ -1112,6 +1279,7 @@ static const struct file_operations ne_enclave_fops = { .llseek = noop_llseek, .poll = ne_enclave_poll, .unlocked_ioctl = ne_enclave_ioctl, + .release = ne_enclave_release, }; /** -- 2.20.1 (Apple Git-117) Amazon Development Center (Romania) S.R.L. registered office: 27A Sf. Lazar Street, UBC5, floor 2, Iasi, Iasi County, 700045, Romania. Registered in Romania. Registration number J22/2621/2005.