lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAMj1kXHd6__0Hcu1UyK+1obsK3bNsQh=1uBVWoaNsX1iTLx6CA@mail.gmail.com>
Date: Tue, 8 Jul 2025 23:06:52 +1000
From: Ard Biesheuvel <ardb@...nel.org>
To: Gerd Hoffmann <kraxel@...hat.com>
Cc: linux-efi@...r.kernel.org, open list <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v2] efi: add ovmf debug log driver

On Tue, 8 Jul 2025 at 22:56, Gerd Hoffmann <kraxel@...hat.com> wrote:
>
> Recent OVMF versions (edk2-stable202508 + newer) can write their debug
> log to a memory buffer.  This driver exposes the log content via sysfs
> (/sys/firmware/efi/ovmf_debug_log).
>
> Signed-off-by: Gerd Hoffmann <kraxel@...hat.com>
> ---
>  include/linux/efi.h                   |   2 +
>  drivers/firmware/efi/efi.c            |   8 ++
>  drivers/firmware/efi/ovmf-debug-log.c | 136 ++++++++++++++++++++++++++
>  drivers/firmware/efi/Kconfig          |   8 ++
>  drivers/firmware/efi/Makefile         |   1 +
>  5 files changed, 155 insertions(+)
>  create mode 100644 drivers/firmware/efi/ovmf-debug-log.c
>

Thanks, I've queued this up now.


> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index 7d63d1d75f22..a71830608422 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -439,6 +439,7 @@ void efi_native_runtime_setup(void);
>
>  /* OVMF protocol GUIDs */
>  #define OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL_GUID       EFI_GUID(0xc5a010fe, 0x38a7, 0x4531,  0x8a, 0x4a, 0x05, 0x00, 0xd2, 0xfd, 0x16, 0x49)
> +#define OVMF_MEMORY_LOG_TABLE_GUID             EFI_GUID(0x95305139, 0xb20f, 0x4723, 0x84, 0x25, 0x62, 0x7c, 0x88, 0x8f, 0xf1, 0x21)
>
>  typedef struct {
>         efi_guid_t guid;
> @@ -642,6 +643,7 @@ extern struct efi {
>         unsigned long                   esrt;                   /* ESRT table */
>         unsigned long                   tpm_log;                /* TPM2 Event Log table */
>         unsigned long                   tpm_final_log;          /* TPM2 Final Events Log table */
> +       unsigned long                   ovmf_debug_log;
>         unsigned long                   mokvar_table;           /* MOK variable config table */
>         unsigned long                   coco_secret;            /* Confidential computing secret table */
>         unsigned long                   unaccepted;             /* Unaccepted memory table */
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index e57bff702b5f..3161f918ce53 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -45,6 +45,7 @@ struct efi __read_mostly efi = {
>         .esrt                   = EFI_INVALID_TABLE_ADDR,
>         .tpm_log                = EFI_INVALID_TABLE_ADDR,
>         .tpm_final_log          = EFI_INVALID_TABLE_ADDR,
> +       .ovmf_debug_log         = EFI_INVALID_TABLE_ADDR,
>  #ifdef CONFIG_LOAD_UEFI_KEYS
>         .mokvar_table           = EFI_INVALID_TABLE_ADDR,
>  #endif
> @@ -473,6 +474,10 @@ static int __init efisubsys_init(void)
>                 platform_device_register_simple("efi_secret", 0, NULL, 0);
>  #endif
>
> +       if (IS_ENABLED(CONFIG_OVMF_DEBUG_LOG) &&
> +           efi.ovmf_debug_log != EFI_INVALID_TABLE_ADDR)
> +               platform_device_register_simple("ovmf_debug_log", 0, NULL, 0);
> +
>         return 0;
>
>  err_remove_group:
> @@ -617,6 +622,9 @@ static const efi_config_table_type_t common_tables[] __initconst = {
>         {LINUX_EFI_MEMRESERVE_TABLE_GUID,       &mem_reserve,           "MEMRESERVE"    },
>         {LINUX_EFI_INITRD_MEDIA_GUID,           &initrd,                "INITRD"        },
>         {EFI_RT_PROPERTIES_TABLE_GUID,          &rt_prop,               "RTPROP"        },
> +#ifdef CONFIG_OVMF_DEBUG_LOG
> +       {OVMF_MEMORY_LOG_TABLE_GUID,            &efi.ovmf_debug_log,    "OvmfDebugLog"  },
> +#endif
>  #ifdef CONFIG_EFI_RCI2_TABLE
>         {DELLEMC_EFI_RCI2_TABLE_GUID,           &rci2_table_phys                        },
>  #endif
> diff --git a/drivers/firmware/efi/ovmf-debug-log.c b/drivers/firmware/efi/ovmf-debug-log.c
> new file mode 100644
> index 000000000000..d4fec178fa9f
> --- /dev/null
> +++ b/drivers/firmware/efi/ovmf-debug-log.c
> @@ -0,0 +1,136 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/efi.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/kobject.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/sysfs.h>
> +
> +#define OVMF_DEBUG_LOG_MAGIC1  0x3167646d666d766f  // "ovmfmdg1"
> +#define OVMF_DEBUG_LOG_MAGIC2  0x3267646d666d766f  // "ovmfmdg2"
> +
> +struct ovmf_debug_log_header {
> +       u64    magic1;
> +       u64    magic2;
> +       u64    hdr_size;
> +       u64    log_size;
> +       u64    lock; // edk2 spinlock
> +       u64    head_off;
> +       u64    tail_off;
> +       u64    truncated;
> +       u8     fw_version[128];
> +};
> +
> +static struct ovmf_debug_log_header *hdr;
> +static u8 *logbuf;
> +static u64 logbufsize;
> +
> +static ssize_t ovmf_log_read(struct file *filp, struct kobject *kobj,
> +                            const struct bin_attribute *attr, char *buf,
> +                            loff_t offset, size_t count)
> +{
> +       u64 start, end;
> +
> +       start = hdr->head_off + offset;
> +       if (hdr->head_off > hdr->tail_off && start >= hdr->log_size)
> +               start -= hdr->log_size;
> +
> +       end = start + count;
> +       if (start > hdr->tail_off) {
> +               if (end > hdr->log_size)
> +                       end = hdr->log_size;
> +       } else {
> +               if (end > hdr->tail_off)
> +                       end = hdr->tail_off;
> +       }
> +
> +       if (start > logbufsize || end > logbufsize)
> +               return 0;
> +       if (start >= end)
> +               return 0;
> +
> +       memcpy(buf, logbuf + start, end - start);
> +       return end - start;
> +}
> +
> +static struct bin_attribute ovmf_log_bin_attr = {
> +       .attr = {
> +               .name = "ovmf_debug_log",
> +               .mode = 0444,
> +       },
> +       .read = ovmf_log_read,
> +};
> +
> +static int ovmf_log_probe(struct platform_device *dev)
> +{
> +       u64 size;
> +       int ret = -EINVAL;
> +
> +       if (efi.ovmf_debug_log == EFI_INVALID_TABLE_ADDR) {
> +               dev_err(&dev->dev, "OVMF debug log: not available\n");
> +               return -EINVAL;
> +       }
> +
> +       /* map + verify header */
> +       hdr = memremap(efi.ovmf_debug_log, sizeof(*hdr), MEMREMAP_WB);
> +       if (!hdr) {
> +               dev_err(&dev->dev, "OVMF debug log: header map failed\n");
> +               return -EINVAL;
> +       }
> +
> +       if (hdr->magic1 != OVMF_DEBUG_LOG_MAGIC1 ||
> +           hdr->magic2 != OVMF_DEBUG_LOG_MAGIC2) {
> +               dev_err(&dev->dev, "OVMF debug log: magic mismatch\n");
> +               goto err_unmap;
> +       }
> +
> +       size = hdr->hdr_size + hdr->log_size;
> +       dev_info(&dev->dev, "firmware version: \"%s\"\n", hdr->fw_version);
> +       dev_info(&dev->dev, "log buffer size: %lluk\n", size / 1024);
> +
> +       /* map complete log buffer */
> +       memunmap(hdr);
> +       hdr = memremap(efi.ovmf_debug_log, size, MEMREMAP_WB);
> +       if (!hdr) {
> +               dev_err(&dev->dev, "OVMF debug log: buffer map failed\n");
> +               return -EINVAL;
> +       }
> +       logbuf = (void *)hdr + hdr->hdr_size;
> +       logbufsize = hdr->log_size;
> +
> +       ovmf_log_bin_attr.size = size;
> +       ret = sysfs_create_bin_file(efi_kobj, &ovmf_log_bin_attr);
> +       if (ret != 0) {
> +               dev_err(&dev->dev, "OVMF debug log: sysfs register failed\n");
> +               goto err_unmap;
> +       }
> +
> +       return 0;
> +
> +err_unmap:
> +       memunmap(hdr);
> +       return ret;
> +}
> +
> +static void ovmf_log_remove(struct platform_device *dev)
> +{
> +       memunmap(hdr);
> +}
> +
> +static struct platform_driver ovmf_log_driver = {
> +       .probe = ovmf_log_probe,
> +       .remove = ovmf_log_remove,
> +       .driver = {
> +               .name = "ovmf_debug_log",
> +       },
> +};
> +
> +module_platform_driver(ovmf_log_driver);
> +
> +MODULE_DESCRIPTION("OVMF debug log");
> +MODULE_AUTHOR("Gerd Hoffmann <kraxel@...hat.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:ovmf_debug_log");
> diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
> index db8c5c03d3a2..ac0a03ec3452 100644
> --- a/drivers/firmware/efi/Kconfig
> +++ b/drivers/firmware/efi/Kconfig
> @@ -263,6 +263,14 @@ config EFI_COCO_SECRET
>           virt/coco/efi_secret module to access the secrets, which in turn
>           allows userspace programs to access the injected secrets.
>
> +config OVMF_DEBUG_LOG
> +       tristate "Expose OVMF firmware debug log via sysfs"
> +       depends on EFI
> +       help
> +         Recent OVMF versions (edk2-stable202508 + newer) can write
> +         their debug log to a memory buffer.  This driver exposes the
> +         log content via sysfs (/sys/firmware/efi/ovmf_debug_log).
> +
>  config UNACCEPTED_MEMORY
>         bool
>         depends on EFI_STUB
> diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
> index a2d0009560d0..8efbcf699e4f 100644
> --- a/drivers/firmware/efi/Makefile
> +++ b/drivers/firmware/efi/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_APPLE_PROPERTIES)                += apple-properties.o
>  obj-$(CONFIG_EFI_RCI2_TABLE)           += rci2-table.o
>  obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE)    += embedded-firmware.o
>  obj-$(CONFIG_LOAD_UEFI_KEYS)           += mokvar-table.o
> +obj-$(CONFIG_OVMF_DEBUG_LOG)           += ovmf-debug-log.o
>
>  obj-$(CONFIG_SYSFB)                    += sysfb_efi.o
>
> --
> 2.50.0
>
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ