All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: Demi Marie Obenour <demi@invisiblethingslab.com>
Cc: "Juergen Gross" <jgross@suse.com>,
	"Stefano Stabellini" <sstabellini@kernel.org>,
	"Oleksandr Tyshchenko" <oleksandr_tyshchenko@epam.com>,
	"Kees Cook" <keescook@chromium.org>,
	"Anton Vorontsov" <anton@enomsg.org>,
	"Colin Cross" <ccross@android.com>,
	"Tony Luck" <tony.luck@intel.com>,
	"Marek Marczykowski-Górecki" <marmarek@invisiblethingslab.com>,
	xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org,
	linux-efi@vger.kernel.org
Subject: Re: [PATCH v4 1/2] Avoid using EFI tables Xen may have clobbered
Date: Fri, 30 Sep 2022 18:25:53 +0200	[thread overview]
Message-ID: <CAMj1kXH5tos5XVDUCcuEJG+fSNZBnY-xA1nb+Juu3H7AsM0DiQ@mail.gmail.com> (raw)
In-Reply-To: <f3b624e99adfdbbfc1976a60a73a6b5950e1840d.1664298147.git.demi@invisiblethingslab.com>

On Fri, 30 Sept 2022 at 01:02, Demi Marie Obenour
<demi@invisiblethingslab.com> wrote:
>
> Memory of type EFI_CONVENTIONAL_MEMORY, EFI_LOADER_CODE, EFI_LOADER_DATA,
> EFI_BOOT_SERVICES_CODE, and EFI_BOOT_SERVICES_DATA may be clobbered by
> Xen before Linux gets to start using it.  Therefore, Linux under Xen
> must not use EFI tables from such memory.  Most of the remaining EFI
> memory types are not suitable for EFI tables, leaving only
> EFI_ACPI_RECLAIM_MEMORY, EFI_RUNTIME_SERVICES_DATA, and
> EFI_RUNTIME_SERVICES_CODE.  When running under Xen, Linux should only
> use tables that are located in one of these types of memory.
>
> This patch ensures this, and also adds a function
> (xen_config_table_memory_region_max()) that will be used later to
> replace the usage of the EFI memory map in esrt.c when running under
> Xen.  This function can also be used in mokvar-table.c and efi-bgrt.c,
> but I have not implemented this.
>
> Signed-off-by: Demi Marie Obenour <demi@invisiblethingslab.com>
> ---
>  drivers/firmware/efi/efi.c |  8 +++++---
>  drivers/xen/efi.c          | 35 +++++++++++++++++++++++++++++++++++
>  include/linux/efi.h        |  9 +++++++++
>  3 files changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index e4080ad96089abd7f84745dd8461c548bcbb7685..d344f3ff73d1c5ed0c67e3251a9502e66719741d 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -574,7 +574,6 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
>         unsigned long table;
>         int i;
>
> -       pr_info("");

Why are you removing these prints?

>         for (i = 0; i < count; i++) {
>                 if (!IS_ENABLED(CONFIG_X86)) {
>                         guid = &config_tables[i].guid;
> @@ -585,7 +584,6 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
>
>                         if (IS_ENABLED(CONFIG_X86_32) &&
>                             tbl64[i].table > U32_MAX) {
> -                               pr_cont("\n");
>                                 pr_err("Table located above 4GB, disabling EFI.\n");
>                                 return -EINVAL;
>                         }
> @@ -594,10 +592,14 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
>                         table = tbl32[i].table;
>                 }
>
> +#ifdef CONFIG_XEN_EFI

We tend to prefer IS_ENABLED() for cases such as this one. That way,
the compiler always gets to see the code inside the conditional block,
which gives better build test coverage (even if CONFIG_XEN_EFI is
disabled).

> +               if (efi_enabled(EFI_PARAVIRT) && !xen_config_table_memory_region_max(table))

So the question here is whether Xen thinks the table should be
disregarded or not. So let's define a prototype that reflects that
purpose, and let the implementation reason about how this should be
achieved.

So

if (IS_ENABLED(CONFIG_XEN_EFI) &&
    efi_enabled(EFI_PARAVIRT) &&
    xen_efi_config_table_valid(guid, table)
        continue

I should note here, though, that EFI_PARAViRT is only set on x86 not
on other architectures that enable CONFIG_XEN_EFI so this will not
work anywhere else.


> +                       continue;
> +#endif
> +
>                 if (!match_config_table(guid, table, common_tables) && arch_tables)
>                         match_config_table(guid, table, arch_tables);
>         }
> -       pr_cont("\n");
>         set_bit(EFI_CONFIG_TABLES, &efi.flags);
>
>         if (efi_rng_seed != EFI_INVALID_TABLE_ADDR) {
> diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c
> index d1ff2186ebb48a7c0981ecb6d4afcbbb25ffcea0..c2274ddfcc63304008ef0fd78fd9fa416f75d073 100644
> --- a/drivers/xen/efi.c
> +++ b/drivers/xen/efi.c
> @@ -28,6 +28,7 @@
>  #include <xen/interface/platform.h>
>  #include <xen/xen.h>
>  #include <xen/xen-ops.h>
> +#include <xen/page.h>
>
>  #include <asm/page.h>
>
> @@ -271,6 +272,40 @@ static void xen_efi_reset_system(int reset_type, efi_status_t status,
>         }
>  }
>
> +__init u64 xen_config_table_memory_region_max(u64 addr)

It is more idiomatic for Linux to put __init after the return type.
And if we adopt my suggestion above, this becomes

bool __init xen_efi_config_table_valid(const efi_guid_t *guid, u64 table)

Alternatively, you could pass the string identifier of the table
instead of the guid (or both) to print in the diagnostic message.


> +{
> +       static_assert(XEN_PAGE_SHIFT == EFI_PAGE_SHIFT,
> +                     "Mismatch between EFI_PAGE_SHIFT and XEN_PAGE_SHIFT");

Is this the only place where this matters? And this never happens on x86, right?

> +       struct xen_platform_op op = {
> +               .cmd = XENPF_firmware_info,
> +               .u.firmware_info = {
> +                       .type = XEN_FW_EFI_INFO,
> +                       .index = XEN_FW_EFI_MEM_INFO,
> +                       .u.efi_info.mem.addr = addr,
> +                       .u.efi_info.mem.size = U64_MAX - addr,
> +               }
> +       };
> +       union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +       int rc = HYPERVISOR_platform_op(&op);
> +
> +       if (rc) {
> +               pr_warn("Failed to lookup header %llu in Xen memory map: error %d\n",
> +                       (unsigned long long)addr, rc);
> +               return 0;
> +       }
> +
> +       switch (info->mem.type) {
> +       case EFI_RUNTIME_SERVICES_CODE:
> +       case EFI_RUNTIME_SERVICES_DATA:
> +       case EFI_ACPI_RECLAIM_MEMORY:

If we are listing all memory types that Xen preserves, you might add
EFI_RESERVED_MEMORY here. Otherwise, please only list the ones that
you need to permit explicitly.

> +               return info->mem.addr + info->mem.size;
> +       default:
> +               pr_warn("Table %llu is in memory of type %d, ignoring it\n",
> +                       (unsigned long long)addr, info->mem.type);
> +               return 0;
> +       }
> +}
> +
>  /*
>   * Set XEN EFI runtime services function pointers. Other fields of struct efi,
>   * e.g. efi.systab, will be set like normal EFI.
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index d2b84c2fec39f0268324d1a38a73ed67786973c9..fc81e4b984398cdb399e7886b2cae7f33bf91613 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -1324,4 +1324,13 @@ struct linux_efi_coco_secret_area {
>  /* Header of a populated EFI secret area */
>  #define EFI_SECRET_TABLE_HEADER_GUID   EFI_GUID(0x1e74f542, 0x71dd, 0x4d66,  0x96, 0x3e, 0xef, 0x42, 0x87, 0xff, 0x17, 0x3b)
>
> +#ifdef CONFIG_XEN_EFI

Please drop this #ifdef

> +/*
> + * Returns the end of the memory region containing the given config table,
> + * or 0 if the given address does not reside in memory that can validly
> + * contain EFI configuration tables.
> + */
> +__init u64 xen_config_table_memory_region_max(u64 addr);

You can drop the __init here

> +#endif
> +
>  #endif /* _LINUX_EFI_H */
> --
> Sincerely,
> Demi Marie Obenour (she/her/hers)
> Invisible Things Lab
>

  parent reply	other threads:[~2022-09-30 16:26 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-29 23:02 [PATCH v4 0/2] EFI improvements for Xen dom0 Demi Marie Obenour
2022-09-29 23:02 ` [PATCH v4 1/2] Avoid using EFI tables Xen may have clobbered Demi Marie Obenour
2022-09-30  6:44   ` Jan Beulich
2022-09-30 16:30     ` Ard Biesheuvel
2022-09-30 17:11       ` Demi Marie Obenour
2022-09-30 18:27         ` Ard Biesheuvel
2022-09-30 18:50           ` Demi Marie Obenour
2022-10-01  0:30           ` Demi Marie Obenour
2022-10-04  8:22             ` Jan Beulich
2022-10-04 15:46               ` Demi Marie Obenour
2022-10-05  6:15                 ` Jan Beulich
2022-10-05 18:11                   ` Demi Marie Obenour
2022-10-05 21:28                     ` Ard Biesheuvel
2022-10-06  1:40                       ` Demi Marie Obenour
2022-10-06  7:31                         ` Ard Biesheuvel
2022-10-06 14:43                           ` Demi Marie Obenour
2022-10-06 16:19                             ` Ard Biesheuvel
2022-10-06 17:22                               ` Demi Marie Obenour
2022-10-06 17:56                                 ` Ard Biesheuvel
2022-10-06  9:22                     ` Jan Beulich
2022-09-30 16:38     ` Demi Marie Obenour
2022-09-30 16:25   ` Ard Biesheuvel [this message]
2022-09-30 18:15     ` Demi Marie Obenour
2022-09-30 18:42       ` Ard Biesheuvel
2022-09-30 19:00         ` Demi Marie Obenour
2022-09-29 23:02 ` [PATCH v4 2/2] Support ESRT in Xen dom0 Demi Marie Obenour
2022-09-30 16:36   ` Ard Biesheuvel
2022-09-30 18:21     ` Demi Marie Obenour
2022-09-30 19:11       ` Ard Biesheuvel
2022-09-30 20:20         ` Demi Marie Obenour
2022-09-30 20:59           ` Ard Biesheuvel
2022-09-30 21:24             ` Ard Biesheuvel
2022-09-30 22:22               ` Demi Marie Obenour
2022-09-30 22:25             ` Demi Marie Obenour

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAMj1kXH5tos5XVDUCcuEJG+fSNZBnY-xA1nb+Juu3H7AsM0DiQ@mail.gmail.com \
    --to=ardb@kernel.org \
    --cc=anton@enomsg.org \
    --cc=ccross@android.com \
    --cc=demi@invisiblethingslab.com \
    --cc=jgross@suse.com \
    --cc=keescook@chromium.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marmarek@invisiblethingslab.com \
    --cc=oleksandr_tyshchenko@epam.com \
    --cc=sstabellini@kernel.org \
    --cc=tony.luck@intel.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.