From 9fbbd8b954f7d456e5967f4836011c4574143e6f Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Fri, 28 May 2021 14:44:13 -0700 Subject: [PATCH] [kernel] Update kernel binary's header structure The kernel's file header has not been verified for a long time. This change returns file verification to the bootloader to make sure the ELF loaded in position 0 is actually the kernel. --- src/boot/loader.cpp | 24 ++++++++++++++++++++++++ src/boot/loader.h | 8 ++++++++ src/boot/main.cpp | 11 +++++++---- src/include/kernel_args.h | 29 +++++++++++++++++++++++++---- src/kernel/boot.s | 20 +++++++++++--------- src/kernel/main.cpp | 3 +++ 6 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index 9a9c850..bba452e 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -113,5 +113,29 @@ load_program( program.entrypoint = header->entrypoint; } +void +verify_kernel_header( + init::program &program, + uefi::boot_services *bs) +{ + status_line status(L"Verifying kernel header"); + + const init::header *header = + reinterpret_cast(program.sections[0].phys_addr); + + if (header->magic != init::header_magic) + error::raise(uefi::status::load_error, L"Bad kernel magic number"); + + if (header->length < sizeof(init::header)) + error::raise(uefi::status::load_error, L"Bad kernel header length"); + + if (header->version < init::min_header_version) + error::raise(uefi::status::unsupported, L"Kernel header version not supported"); + + console::print(L" Loaded kernel vserion: %d.%d.%d %lx\r\n", + header->version_major, header->version_minor, header->version_patch, + header->version_gitsha); +} + } // namespace loader } // namespace boot diff --git a/src/boot/loader.h b/src/boot/loader.h index 1695bdd..323d390 100644 --- a/src/boot/loader.h +++ b/src/boot/loader.h @@ -38,5 +38,13 @@ load_program( buffer data, uefi::boot_services *bs); +/// Verify that a loaded ELF has the j6 kernel header +/// \arg program The program to check for a header +/// \arg bs Boot services +void +verify_kernel_header( + kernel::init::program &program, + uefi::boot_services *bs); + } // namespace loader } // namespace boot diff --git a/src/boot/main.cpp b/src/boot/main.cpp index 17e0688..735a493 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -134,8 +134,8 @@ uefi_preboot(uefi::handle image, uefi::system_table *st) init::args *args = allocate_args_structure(bs, max_modules, max_programs); - args->magic = init::magic; - args->version = init::version; + args->magic = init::args_magic; + args->version = init::args_version; args->runtime_services = rs; args->acpi_table = hw::find_acpi_table(st); paging::allocate_tables(args, bs); @@ -154,6 +154,9 @@ uefi_preboot(uefi::handle image, uefi::system_table *st) loader::load_program(program, desc.name, buf, bs); } + // First program *must* be the kernel + loader::verify_kernel_header(args->programs[0], bs); + return args; } @@ -196,8 +199,8 @@ efi_main(uefi::handle image, uefi::system_table *st) memory::fix_frame_blocks(args); - kernel::entrypoint kentry = - reinterpret_cast(kernel.entrypoint); + init::entrypoint kentry = + reinterpret_cast(kernel.entrypoint); status.next(); hw::setup_control_regs(); diff --git a/src/include/kernel_args.h b/src/include/kernel_args.h index dc750e7..9fcb7e6 100644 --- a/src/include/kernel_args.h +++ b/src/include/kernel_args.h @@ -7,8 +7,12 @@ namespace kernel { namespace init { -constexpr uint32_t magic = 0x600dda7a; -constexpr uint16_t version = 1; +constexpr uint32_t args_magic = 'j6ia'; // "jsix init args" +constexpr uint16_t args_version = 1; + +constexpr uint64_t header_magic = 0x4c454e52454b366aull; // 'j6KERNEL' +constexpr uint16_t header_version = 2; +constexpr uint16_t min_header_version = 2; enum class mod_type : uint32_t { symbol_table @@ -92,7 +96,8 @@ enum class boot_flags : uint16_t { debug = 0x0001 }; -struct args { +struct args +{ uint32_t magic; uint16_t version; boot_flags flags; @@ -122,8 +127,24 @@ struct args { } __attribute__((aligned(alignof(max_align_t)))); -} // namespace init +struct header +{ + uint64_t magic; + + uint16_t length; + uint16_t version; + + uint16_t version_major; + uint16_t version_minor; + uint16_t version_patch; + uint16_t reserved; + + uint32_t version_gitsha; + + uint64_t flags; +}; using entrypoint = __attribute__((sysv_abi)) void (*)(init::args *); +} // namespace init } // namespace kernel diff --git a/src/kernel/boot.s b/src/kernel/boot.s index 6efcd7e..51093f5 100644 --- a/src/kernel/boot.s +++ b/src/kernel/boot.s @@ -1,16 +1,18 @@ -MAGIC equ 0x600db007 ; jsix OS header magic number +MAGIC equ 'j6KERNEL' ; jsix kernel header magic number section .header -align 4 -global _header -_header: - dd MAGIC ; Kernel header magic - dw 1 ; Header version 1 - dw 16 ; Kernel header length - db VERSION_MAJOR ; Kernel version - db VERSION_MINOR +align 8 +global _kernel_header +_kernel_header: + dq MAGIC ; Kernel header magic + dw 32 ; Kernel header length + dw 2 ; Header version 2 + dw VERSION_MAJOR ; Kernel version + dw VERSION_MINOR dw VERSION_PATCH + dw 0 ; reserved dd VERSION_GITSHA + dq 0 ; Flags section .text align 16 diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 2577d90..ff64ee2 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -92,6 +92,9 @@ kernel_main(init::args *args) cpu_validate(); + kassert(args->magic == init::args_magic, + "Bad kernel args magic number"); + log::debug(logs::boot, "jsix init args are at: %016lx", args); log::debug(logs::boot, " Memory map is at: %016lx", args->mem_map); log::debug(logs::boot, "ACPI root table is at: %016lx", args->acpi_table);