Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp486237pxb; Wed, 18 Nov 2020 09:22:42 -0800 (PST) X-Google-Smtp-Source: ABdhPJysmXYBfAHoPUOA76K7VJ7/xNU8OqqtpxzDPk6K1GirAw2KeRfYVDRRczRGvlM2uIRvB4gm X-Received: by 2002:a05:6402:229a:: with SMTP id cw26mr28057581edb.271.1605720162066; Wed, 18 Nov 2020 09:22:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605720162; cv=none; d=google.com; s=arc-20160816; b=FsH7lYqwrHiegogoCQMqoTkfNCXTsxOtLRFnj4+p+nbSvOme7b6kNJEzS7vpsvVSg3 yVnMO4MhpPaIim77noMoq1zSHTxBTs+/b4QjHjKUI9wWH+ShrNFc8d2jmE/OhMLkvnvt 59ey8PPSjQ1tm7yBV3POGq/g58bXUqV428SeNqouXPj5/S9p4eNjGJrIaLrTxLpwym8R XD47lqwpmpJc7/ill4RAj/R8UhA7zMQ6Q5pGZFtKdYs9GpsJTNyfnJG4upUuVp2nUe4r RdOwx+MdoXYjzCCPfERiJTDJnlX9csZ5Py9pGj3I4HvfZVcvNMYK8CNf6rR9UlzCHOMn 51FA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:robot-unsubscribe :robot-id:message-id:mime-version:references:in-reply-to:cc:subject :to:reply-to:sender:from:dkim-signature:dkim-signature:date; bh=GmxCj/7ZnJBKISZdax6TrGFzzg4ya64APGcVFhXUJww=; b=kaIeHpAG1sQOiIriQ2AL6SiUdMs7+mbhPV7craBIXd5pKe1FFOoBWyi7u0ZsiL7e39 w8tExs/ayX5Jfqqit0T7DpaMRiDKNIsYoMlaM9XFJacJrB3YE/EnhPGCLhzq75aPYWd+ thEcalY8V8J1m6XOkK8UWfMi7GCP9RAPd2h9yfgoJofTCIXDrkjUw2rq6NS5rEsNij5P 4MEcKgw1EEzEvxWPva/JRUhivrzXiYtYvOxPnlnJZPuoUTo4qVTTMH7HstXU8wG3XT9T lECkPEdW/l6jpr9U9cNOrXp3rjSeMx/wAgkogQ/aactn6vV05bYI1cwDhxNkqgs/871J 6TGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=turMRdcc; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=ZFYcSOE0; 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=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id o22si15232460ejb.569.2020.11.18.09.22.17; Wed, 18 Nov 2020 09:22:42 -0800 (PST) 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=@linutronix.de header.s=2020 header.b=turMRdcc; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=ZFYcSOE0; 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=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728092AbgKRRSV (ORCPT + 99 others); Wed, 18 Nov 2020 12:18:21 -0500 Received: from Galois.linutronix.de ([193.142.43.55]:56162 "EHLO galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728062AbgKRRSS (ORCPT ); Wed, 18 Nov 2020 12:18:18 -0500 Date: Wed, 18 Nov 2020 17:18:15 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1605719896; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GmxCj/7ZnJBKISZdax6TrGFzzg4ya64APGcVFhXUJww=; b=turMRdccUT+iBqIzr0XJwgqC6MpBjsN/bN96HEHm299rdaX4SfTySh6k43u8FClkGUTRmj AICpbiG1lgV2WCtgscOWL8rRwsLTwLX1Jcs7tcm5wOcWmECSLO5UJlILhCWYbnMGA3g4Zw 5wylOPaao+bwcFnKJSFWJJ+0Tr8+zq+MffUEWGB6sitqx+8gpl+w0uhWRLyPaiEKbiU7e4 javuLQ7ssYiN7prmRcyv2ELaZ+t437jlqm9QUGxVpiLTx8z1RGO10CwVB/X06H9uDT30rH XLaPpr6r3PuvRl1SPTEL7IFwbT/6XKru46bl9VC+z9w/BZVCkX/kqvpic174vg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1605719896; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GmxCj/7ZnJBKISZdax6TrGFzzg4ya64APGcVFhXUJww=; b=ZFYcSOE0Qqk+9tuBL0cbhJ+OdbS+8caMw/oq39yCTG+ENG1IM0kzOEEZmhEob2DCuSPp0h j6eS/A4/qHVdQ5Dw== From: "tip-bot2 for Dave Hansen" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/sgx] x86/sgx: Clarify 'laundry_list' locking Cc: Jarkko Sakkinen , Dave Hansen , Borislav Petkov , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20201116222531.4834-1-dave.hansen@intel.com> References: <20201116222531.4834-1-dave.hansen@intel.com> MIME-Version: 1.0 Message-ID: <160571989541.11244.7999952600961117627.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The following commit has been merged into the x86/sgx branch of tip: Commit-ID: 67655b57f8f59467506463055d9a8398d2836377 Gitweb: https://git.kernel.org/tip/67655b57f8f59467506463055d9a8398d2836377 Author: Dave Hansen AuthorDate: Mon, 16 Nov 2020 14:25:31 -08:00 Committer: Borislav Petkov CommitterDate: Wed, 18 Nov 2020 18:16:28 +01:00 x86/sgx: Clarify 'laundry_list' locking Short Version: The SGX section->laundry_list structure is effectively thread-local, but declared next to some shared structures. Its semantics are clear as mud. Fix that. No functional changes. Compile tested only. Long Version: The SGX hardware keeps per-page metadata. This can provide things like permissions, integrity and replay protection. It also prevents things like having an enclave page mapped multiple times or shared between enclaves. But, that presents a problem for kexec()'d kernels (or any other kernel that does not run immediately after a hardware reset). This is because the last kernel may have been rude and forgotten to reset pages, which would trigger the "shared page" sanity check. To fix this, the SGX code "launders" the pages by running the EREMOVE instruction on all pages at boot. This is slow and can take a long time, so it is performed off in the SGX-specific ksgxd instead of being synchronous at boot. The init code hands the list of pages to launder in a per-SGX-section list: ->laundry_list. The only code to touch this list is the init code and ksgxd. This means that no locking is necessary for ->laundry_list. However, a lock is required for section->page_list, which is accessed while creating enclaves and by ksgxd. This lock (section->lock) is acquired by ksgxd while also processing ->laundry_list. It is easy to confuse the purpose of the locking as being for ->laundry_list and ->page_list. Rename ->laundry_list to ->init_laundry_list to make it clear that this is not normally used at runtime. Also add some comments clarifying the locking, and reorganize 'sgx_epc_section' to put 'lock' near the things it protects. Note: init_laundry_list is 128 bytes of wasted space at runtime. It could theoretically be dynamically allocated and then freed after the laundering process. But it would take nearly 128 bytes of extra instructions to do that. Signed-off-by: Jarkko Sakkinen Signed-off-by: Dave Hansen Signed-off-by: Borislav Petkov Link: https://lkml.kernel.org/r/20201116222531.4834-1-dave.hansen@intel.com --- arch/x86/kernel/cpu/sgx/main.c | 14 ++++++++------ arch/x86/kernel/cpu/sgx/sgx.h | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 3426785..c519fc5 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -36,13 +36,15 @@ static void sgx_sanitize_section(struct sgx_epc_section *section) LIST_HEAD(dirty); int ret; - while (!list_empty(§ion->laundry_list)) { + /* init_laundry_list is thread-local, no need for a lock: */ + while (!list_empty(§ion->init_laundry_list)) { if (kthread_should_stop()) return; + /* needed for access to ->page_list: */ spin_lock(§ion->lock); - page = list_first_entry(§ion->laundry_list, + page = list_first_entry(§ion->init_laundry_list, struct sgx_epc_page, list); ret = __eremove(sgx_get_epc_virt_addr(page)); @@ -56,7 +58,7 @@ static void sgx_sanitize_section(struct sgx_epc_section *section) cond_resched(); } - list_splice(&dirty, §ion->laundry_list); + list_splice(&dirty, §ion->init_laundry_list); } static bool sgx_reclaimer_age(struct sgx_epc_page *epc_page) @@ -418,7 +420,7 @@ static int ksgxd(void *p) sgx_sanitize_section(&sgx_epc_sections[i]); /* Should never happen. */ - if (!list_empty(&sgx_epc_sections[i].laundry_list)) + if (!list_empty(&sgx_epc_sections[i].init_laundry_list)) WARN(1, "EPC section %d has unsanitized pages.\n", i); } @@ -635,13 +637,13 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size, section->phys_addr = phys_addr; spin_lock_init(§ion->lock); INIT_LIST_HEAD(§ion->page_list); - INIT_LIST_HEAD(§ion->laundry_list); + INIT_LIST_HEAD(§ion->init_laundry_list); for (i = 0; i < nr_pages; i++) { section->pages[i].section = index; section->pages[i].flags = 0; section->pages[i].owner = NULL; - list_add_tail(§ion->pages[i].list, §ion->laundry_list); + list_add_tail(§ion->pages[i].list, §ion->init_laundry_list); } section->free_cnt = nr_pages; diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index a188a68..5fa42d1 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -34,15 +34,24 @@ struct sgx_epc_page { * physical memory e.g. for memory areas of the each node. This structure is * used to store EPC pages for one EPC section and virtual memory area where * the pages have been mapped. + * + * 'lock' must be held before accessing 'page_list' or 'free_cnt'. */ struct sgx_epc_section { unsigned long phys_addr; void *virt_addr; - struct list_head page_list; - struct list_head laundry_list; struct sgx_epc_page *pages; - unsigned long free_cnt; + spinlock_t lock; + struct list_head page_list; + unsigned long free_cnt; + + /* + * Pages which need EREMOVE run on them before they can be + * used. Only safe to be accessed in ksgxd and init code. + * Not protected by locks. + */ + struct list_head init_laundry_list; }; extern struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS];