[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[SECURITY PATCH 02/30] commands/boot: Add API to pass context to loader
From: |
Daniel Kiper |
Subject: |
[SECURITY PATCH 02/30] commands/boot: Add API to pass context to loader |
Date: |
Tue, 7 Jun 2022 19:01:11 +0200 |
From: Chris Coulson <chris.coulson@canonical.com>
Loaders rely on global variables for saving context which is consumed
in the boot hook and freed in the unload hook. In the case where a loader
command is executed twice, calling grub_loader_set() a second time executes
the unload hook, but in some cases this runs when the loader's global
context has already been updated, resulting in the updated context being
freed and potential use-after-free bugs when the boot hook is subsequently
called.
This adds a new API, grub_loader_set_ex(), which allows a loader to specify
context that is passed to its boot and unload hooks. This is an alternative
to requiring that loaders call grub_loader_unset() before mutating their
global context.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/boot.c | 66 +++++++++++++++++++++++++++++++++++++++++------
include/grub/loader.h | 5 ++++
2 files changed, 63 insertions(+), 8 deletions(-)
diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c
index bbca81e94..61514788e 100644
--- a/grub-core/commands/boot.c
+++ b/grub-core/commands/boot.c
@@ -27,10 +27,20 @@
GRUB_MOD_LICENSE ("GPLv3+");
-static grub_err_t (*grub_loader_boot_func) (void);
-static grub_err_t (*grub_loader_unload_func) (void);
+static grub_err_t (*grub_loader_boot_func) (void *context);
+static grub_err_t (*grub_loader_unload_func) (void *context);
+static void *grub_loader_context;
static int grub_loader_flags;
+struct grub_simple_loader_hooks
+{
+ grub_err_t (*boot) (void);
+ grub_err_t (*unload) (void);
+};
+
+/* Don't heap allocate this to avoid making grub_loader_set() fallible. */
+static struct grub_simple_loader_hooks simple_loader_hooks;
+
struct grub_preboot
{
grub_err_t (*preboot_func) (int);
@@ -44,6 +54,29 @@ static int grub_loader_loaded;
static struct grub_preboot *preboots_head = 0,
*preboots_tail = 0;
+static grub_err_t
+grub_simple_boot_hook (void *context)
+{
+ struct grub_simple_loader_hooks *hooks;
+
+ hooks = (struct grub_simple_loader_hooks *) context;
+ return hooks->boot ();
+}
+
+static grub_err_t
+grub_simple_unload_hook (void *context)
+{
+ struct grub_simple_loader_hooks *hooks;
+ grub_err_t ret;
+
+ hooks = (struct grub_simple_loader_hooks *) context;
+
+ ret = hooks->unload ();
+ grub_memset (hooks, 0, sizeof (*hooks));
+
+ return ret;
+}
+
int
grub_loader_is_loaded (void)
{
@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot
*hnd)
}
void
-grub_loader_set (grub_err_t (*boot) (void),
- grub_err_t (*unload) (void),
- int flags)
+grub_loader_set_ex (grub_err_t (*boot) (void *context),
+ grub_err_t (*unload) (void *context),
+ void *context,
+ int flags)
{
if (grub_loader_loaded && grub_loader_unload_func)
- grub_loader_unload_func ();
+ grub_loader_unload_func (grub_loader_context);
grub_loader_boot_func = boot;
grub_loader_unload_func = unload;
+ grub_loader_context = context;
grub_loader_flags = flags;
grub_loader_loaded = 1;
}
void
+grub_loader_set (grub_err_t (*boot) (void),
+ grub_err_t (*unload) (void),
+ int flags)
+{
+ grub_loader_set_ex (grub_simple_boot_hook,
+ grub_simple_unload_hook,
+ &simple_loader_hooks,
+ flags);
+
+ simple_loader_hooks.boot = boot;
+ simple_loader_hooks.unload = unload;
+}
+
+void
grub_loader_unset(void)
{
if (grub_loader_loaded && grub_loader_unload_func)
- grub_loader_unload_func ();
+ grub_loader_unload_func (grub_loader_context);
grub_loader_boot_func = 0;
grub_loader_unload_func = 0;
+ grub_loader_context = 0;
grub_loader_loaded = 0;
}
@@ -158,7 +208,7 @@ grub_loader_boot (void)
return err;
}
}
- err = (grub_loader_boot_func) ();
+ err = (grub_loader_boot_func) (grub_loader_context);
for (cur = preboots_tail; cur; cur = cur->prev)
if (! err)
diff --git a/include/grub/loader.h b/include/grub/loader.h
index b20864282..97f231054 100644
--- a/include/grub/loader.h
+++ b/include/grub/loader.h
@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot)
(void),
grub_err_t (*unload) (void),
int flags);
+void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *context),
+ grub_err_t (*unload) (void *context),
+ void *context,
+ int flags);
+
/* Unset current loader, if any. */
void EXPORT_FUNC (grub_loader_unset) (void);
--
2.11.0
- [SECURITY PATCH 00/30] Multiple GRUB2 vulnerabilities - 2022/06/07 round, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 02/30] commands/boot: Add API to pass context to loader,
Daniel Kiper <=
- [SECURITY PATCH 01/30] loader/efi/chainloader: Simplify the loader state, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 04/30] kern/efi/sb: Reject non-kernel files in the shim_lock verifier, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 13/30] video/readers/jpeg: Refuse to handle multiple start of streams, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 11/30] video/readers/jpeg: Abort sooner if a read operation fails, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 16/30] net/ip: Do IP fragment maths safely, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 05/30] kern/file: Do not leak device_name on error in grub_file_open(), Daniel Kiper, 2022/06/07
- [SECURITY PATCH 26/30] fs/f2fs: Do not read past the end of nat bitmap, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 12/30] video/readers/jpeg: Do not reallocate a given huff table, Daniel Kiper, 2022/06/07
- [SECURITY PATCH 03/30] loader/efi/chainloader: Use grub_loader_set_ex(), Daniel Kiper, 2022/06/07
- [SECURITY PATCH 10/30] video/readers/png: Sanity check some huffman codes, Daniel Kiper, 2022/06/07