[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20191005164408.GB25699@zn.tnic>
Date: Sat, 5 Oct 2019 18:44:08 +0200
From: Borislav Petkov <bp@...en8.de>
To: Jarkko Sakkinen <jarkko.sakkinen@...ux.intel.com>
Cc: linux-kernel@...r.kernel.org, x86@...nel.org,
linux-sgx@...r.kernel.org, akpm@...ux-foundation.org,
dave.hansen@...el.com, sean.j.christopherson@...el.com,
nhorman@...hat.com, npmccallum@...hat.com, serge.ayoun@...el.com,
shay.katz-zamir@...el.com, haitao.huang@...el.com,
andriy.shevchenko@...ux.intel.com, tglx@...utronix.de,
kai.svahn@...el.com, josh@...htriplett.org, luto@...nel.org,
kai.huang@...el.com, rientjes@...gle.com, cedric.xing@...el.com
Subject: Re: [PATCH v22 09/24] x86/sgx: Add functions to allocate and free
EPC pages
On Tue, Sep 03, 2019 at 05:26:40PM +0300, Jarkko Sakkinen wrote:
> Add functions for grabbing EPC pages into use:
>
> * sgx_alloc_page(): Iterate the EPC sections and return the first free
> page, or ERR_PTR(-ENOMEM) when no free pages are available.
> * __sgx_free_page(): Return the page into uninitialized state and move
> it back to the corresponding EPC section structure. Issues WARN()
> when EREMOVE fails.
> * sgx_free_page(): Return the page into uninitialized state and move
> it back to the corresponding EPC section structure. Returns
> ENCLS[EREMOVE] error code back to the caller.
>
> [1] Intel SDM: 40.3 INTELĀ® SGX SYSTEM LEAF FUNCTION REFERENCE
>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@...ux.intel.com>
> Co-developed-by: Sean Christopherson <sean.j.christopherson@...el.com>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@...el.com>
> ---
> arch/x86/kernel/cpu/sgx/main.c | 90 ++++++++++++++++++++++++++++++++++
> arch/x86/kernel/cpu/sgx/sgx.h | 4 ++
> 2 files changed, 94 insertions(+)
>
> diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
> index e2317f6e4374..6b4727df72ca 100644
> --- a/arch/x86/kernel/cpu/sgx/main.c
> +++ b/arch/x86/kernel/cpu/sgx/main.c
> @@ -9,6 +9,7 @@
> #include <linux/sched/signal.h>
> #include <linux/slab.h>
> #include "arch.h"
> +#include "encls.h"
> #include "sgx.h"
>
> struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS];
> @@ -16,6 +17,95 @@ EXPORT_SYMBOL_GPL(sgx_epc_sections);
>
> int sgx_nr_epc_sections;
>
> +static struct sgx_epc_page *sgx_section_get_page(
That fits into 80 cols (oh well, 81) and even if not, a trailing opening
arg brace is ugly.
> + struct sgx_epc_section *section)
> +{
> + struct sgx_epc_page *page;
> +
> + if (!section->free_cnt)
> + return NULL;
> +
> + page = list_first_entry(§ion->page_list,
> + struct sgx_epc_page, list);
That fits in 80-cols too. Why break it?
> + list_del_init(&page->list);
> + section->free_cnt--;
> + return page;
> +}
> +
> +/**
> + * sgx_alloc_page - Allocate an EPC page
> + *
> + * Try to grab a page from the free EPC page list.
> + *
> + * Return:
> + * a pointer to a &struct sgx_epc_page instance,
> + * -errno on error
> + */
> +struct sgx_epc_page *sgx_alloc_page(void)
> +{
> + struct sgx_epc_section *section;
> + struct sgx_epc_page *page;
> + int i;
> +
> + for (i = 0; i < sgx_nr_epc_sections; i++) {
> + section = &sgx_epc_sections[i];
> + spin_lock(§ion->lock);
> + page = sgx_section_get_page(section);
> + spin_unlock(§ion->lock);
> +
> + if (page)
> + return page;
> + }
> +
> + return ERR_PTR(-ENOMEM);
> +}
> +EXPORT_SYMBOL_GPL(sgx_alloc_page);
That export gets removed later too. But you know already...
> +
> +/**
> + * __sgx_free_page - Free an EPC page
> + * @page: pointer a previously allocated EPC page
> + *
> + * EREMOVE an EPC page and insert it back to the list of free pages.
> + *
> + * Return:
> + * 0 on success
> + * SGX error code if EREMOVE fails
> + */
> +int __sgx_free_page(struct sgx_epc_page *page)
> +{
> + struct sgx_epc_section *section = sgx_epc_section(page);
> + int ret;
Shouldn't you be grabbing the lock here already?
Or nothing can happen to that page from another thread after you
ENCLS[EREMOVE] it and before it is added to the ->page_list of the
section?
> +
> + ret = __eremove(sgx_epc_addr(page));
> + if (ret)
> + return ret;
> +
> + spin_lock(§ion->lock);
> + list_add_tail(&page->list, §ion->page_list);
> + section->free_cnt++;
> + spin_unlock(§ion->lock);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(__sgx_free_page);
> +
> +/**
> + * sgx_free_page - Free an EPC page and WARN on failure
> + * @page: pointer to a previously allocated EPC page
> + *
> + * EREMOVE an EPC page and insert it back to the list of free pages, and WARN
> + * if EREMOVE fails. For use when the call site cannot (or chooses not to)
> + * handle failure, i.e. the page is leaked on failure.
> + */
> +void sgx_free_page(struct sgx_epc_page *page)
> +{
> + int ret;
> +
> + ret = __sgx_free_page(page);
> + WARN(ret > 0, "sgx: EREMOVE returned %d (0x%x)", ret, ret);
That will potentially flood dmesg. Why are we even accommodating such
callers? They either handle the error or they don't get to alloc EPC
pages. There's also __must_check with which you can enforce the error
code checking or we simply don't allow not handling failure. Fullstop.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
Powered by blists - more mailing lists