[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.
This commit is contained in:
Justin C. Miller
2021-05-28 14:44:13 -07:00
parent 910fde3b2c
commit 9fbbd8b954
6 changed files with 78 additions and 17 deletions

View File

@@ -113,5 +113,29 @@ load_program(
program.entrypoint = header->entrypoint; 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<const init::header *>(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 loader
} // namespace boot } // namespace boot

View File

@@ -38,5 +38,13 @@ load_program(
buffer data, buffer data,
uefi::boot_services *bs); 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 loader
} // namespace boot } // namespace boot

View File

@@ -134,8 +134,8 @@ uefi_preboot(uefi::handle image, uefi::system_table *st)
init::args *args = init::args *args =
allocate_args_structure(bs, max_modules, max_programs); allocate_args_structure(bs, max_modules, max_programs);
args->magic = init::magic; args->magic = init::args_magic;
args->version = init::version; args->version = init::args_version;
args->runtime_services = rs; args->runtime_services = rs;
args->acpi_table = hw::find_acpi_table(st); args->acpi_table = hw::find_acpi_table(st);
paging::allocate_tables(args, bs); 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); loader::load_program(program, desc.name, buf, bs);
} }
// First program *must* be the kernel
loader::verify_kernel_header(args->programs[0], bs);
return args; return args;
} }
@@ -196,8 +199,8 @@ efi_main(uefi::handle image, uefi::system_table *st)
memory::fix_frame_blocks(args); memory::fix_frame_blocks(args);
kernel::entrypoint kentry = init::entrypoint kentry =
reinterpret_cast<kernel::entrypoint>(kernel.entrypoint); reinterpret_cast<init::entrypoint>(kernel.entrypoint);
status.next(); status.next();
hw::setup_control_regs(); hw::setup_control_regs();

View File

@@ -7,8 +7,12 @@
namespace kernel { namespace kernel {
namespace init { namespace init {
constexpr uint32_t magic = 0x600dda7a; constexpr uint32_t args_magic = 'j6ia'; // "jsix init args"
constexpr uint16_t version = 1; 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 { enum class mod_type : uint32_t {
symbol_table symbol_table
@@ -92,7 +96,8 @@ enum class boot_flags : uint16_t {
debug = 0x0001 debug = 0x0001
}; };
struct args { struct args
{
uint32_t magic; uint32_t magic;
uint16_t version; uint16_t version;
boot_flags flags; boot_flags flags;
@@ -122,8 +127,24 @@ struct args {
} }
__attribute__((aligned(alignof(max_align_t)))); __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 *); using entrypoint = __attribute__((sysv_abi)) void (*)(init::args *);
} // namespace init
} // namespace kernel } // namespace kernel

View File

@@ -1,16 +1,18 @@
MAGIC equ 0x600db007 ; jsix OS header magic number MAGIC equ 'j6KERNEL' ; jsix kernel header magic number
section .header section .header
align 4 align 8
global _header global _kernel_header
_header: _kernel_header:
dd MAGIC ; Kernel header magic dq MAGIC ; Kernel header magic
dw 1 ; Header version 1 dw 32 ; Kernel header length
dw 16 ; Kernel header length dw 2 ; Header version 2
db VERSION_MAJOR ; Kernel version dw VERSION_MAJOR ; Kernel version
db VERSION_MINOR dw VERSION_MINOR
dw VERSION_PATCH dw VERSION_PATCH
dw 0 ; reserved
dd VERSION_GITSHA dd VERSION_GITSHA
dq 0 ; Flags
section .text section .text
align 16 align 16

View File

@@ -92,6 +92,9 @@ kernel_main(init::args *args)
cpu_validate(); 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, "jsix init args are at: %016lx", args);
log::debug(logs::boot, " Memory map is at: %016lx", args->mem_map); 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); log::debug(logs::boot, "ACPI root table is at: %016lx", args->acpi_table);