From 8e93815846f83163a554b7d254778287bfdabec4 Mon Sep 17 00:00:00 2001 From: Brian Gianforcaro Date: Sun, 8 Aug 2021 12:40:45 -0700 Subject: [PATCH] Kernel: Fix panic loop when encountering an unknown boot_mode The kernel panic handler now parses the kernels boot_mode to decide how to handle the panic. So the previous logic could end up in an panic loop until we blew out the kernel stack. Instead only validate the kernel's boot mode once per boot, after initializing the kernel command line. --- Kernel/CommandLine.cpp | 9 +++++++-- Kernel/CommandLine.h | 10 ++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Kernel/CommandLine.cpp b/Kernel/CommandLine.cpp index 9353313715..64716fb8bf 100644 --- a/Kernel/CommandLine.cpp +++ b/Kernel/CommandLine.cpp @@ -38,6 +38,8 @@ UNMAP_AFTER_INIT void CommandLine::initialize() VERIFY(!s_the); s_the = new CommandLine(s_cmd_line); dmesgln("Kernel Commandline: {}", kernel_command_line().string()); + // Validate the boot mode the user passed in. + (void)s_the->boot_mode(Validate::Yes); } UNMAP_AFTER_INIT void CommandLine::build_commandline(const String& cmdline_from_bootloader) @@ -191,7 +193,7 @@ UNMAP_AFTER_INIT AHCIResetMode CommandLine::ahci_reset_mode() const PANIC("Unknown AHCIResetMode: {}", ahci_reset_mode); } -BootMode CommandLine::boot_mode() const +BootMode CommandLine::boot_mode(Validate should_validate) const { const auto boot_mode = lookup("boot_mode"sv).value_or("graphical"sv); if (boot_mode == "no-fbdev"sv) { @@ -201,7 +203,10 @@ BootMode CommandLine::boot_mode() const } else if (boot_mode == "graphical"sv) { return BootMode::Graphical; } - PANIC("Unknown BootMode: {}", boot_mode); + + if (should_validate == Validate::Yes) + PANIC("Unknown BootMode: {}", boot_mode); + return BootMode::Unknown; } UNMAP_AFTER_INIT bool CommandLine::is_no_framebuffer_devices_mode() const diff --git a/Kernel/CommandLine.h b/Kernel/CommandLine.h index 20aaa6b9cc..35d70e3db7 100644 --- a/Kernel/CommandLine.h +++ b/Kernel/CommandLine.h @@ -16,7 +16,8 @@ namespace Kernel { enum class BootMode { NoFramebufferDevices, SelfTest, - Graphical + Graphical, + Unknown, }; enum class HPETMode { @@ -48,6 +49,11 @@ public: static void early_initialize(const char* cmd_line); static void initialize(); + enum class Validate { + Yes, + No, + }; + [[nodiscard]] const String& string() const { return m_string; } Optional lookup(const StringView& key) const; [[nodiscard]] bool contains(const StringView& key) const; @@ -62,7 +68,7 @@ public: [[nodiscard]] bool is_no_framebuffer_devices_mode() const; [[nodiscard]] bool is_force_pio() const; [[nodiscard]] AcpiFeatureLevel acpi_feature_level() const; - [[nodiscard]] BootMode boot_mode() const; + [[nodiscard]] BootMode boot_mode(Validate should_validate = Validate::No) const; [[nodiscard]] HPETMode hpet_mode() const; [[nodiscard]] bool disable_physical_storage() const; [[nodiscard]] bool disable_ps2_controller() const;