diff --git a/arch/info.c b/arch/info.c index 74d2010..0a39e98 100644 --- a/arch/info.c +++ b/arch/info.c @@ -1,5 +1,7 @@ #include +static unsigned char cmdline_terminated(const char *s); + unsigned char kernelmq_info_validate_and_copy( struct KernelMQ_Info *const dest, const struct KernelMQ_Info *const src @@ -8,7 +10,156 @@ unsigned char kernelmq_info_validate_and_copy( return 0; } + if (!cmdline_terminated(src->cmdline)) { + return 0; + } + + if (src->modules_count > KERNELMQ_INFO_MODULES_MAX) { + return 0; + } + + if (src->areas_count > KERNELMQ_INFO_AREAS_MAX) { + return 0; + } + + // TODO: architecture-dependent + if (src->mem_lower_base != KERNELMQ_INFO_MEM_LOWER_BASE) { + return 0; + } + + // TODO: architecture-dependent + if (src->mem_upper_base != KERNELMQ_INFO_MEM_UPPER_BASE) { + return 0; + } + + // TODO: architecture-dependent + if (src->mem_lower_size == 0) { + return 0; + } + + // TODO: architecture-dependent + if (src->mem_upper_size == 0) { + return 0; + } + + // TODO: architecture-dependent + if (src->mem_lower_size > KERNELMQ_INFO_MEM_LOWER_SIZE_MAX) { + return 0; + } + + if (src->mem_lower_base + src->mem_lower_size != src->mem_lower_limit + 1) { + return 0; + } + + if (src->mem_upper_base + src->mem_upper_size != src->mem_upper_limit + 1) { + return 0; + } + + if (src->kernel_size == 0) { + return 0; + } + + if (src->kernel_offset == 0) { + return 0; + } + + if (src->kernel_phys_base + src->kernel_size != src->kernel_phys_limit + 1) { + return 0; + } + + if (src->kernel_virt_base + src->kernel_size != src->kernel_virt_limit + 1) { + return 0; + } + + if (src->kernel_virt_base - src->kernel_phys_base != src->kernel_offset) { + return 0; + } + + unsigned long modules_total_size = 0; + + for (unsigned int i = 0; i < src->modules_count; ++i) { + const struct KernelMQ_Info_Module *const module = &src->modules[i]; + + modules_total_size += module->size; + + if (module->size == 0) { + return 0; + } + + if (module->base + module->size != module->limit + 1) { + return 0; + } + + if (!cmdline_terminated(module->cmdline)) { + return 0; + } + } + + if (src->modules_total_size != modules_total_size) { + return 0; + } + + if (src->kernel_and_modules_total_size != src->kernel_size + src->modules_total_size) { + return 0; + } + + unsigned long long last = 0; + + for (unsigned int i = 0; i < src->areas_count; ++i) { + const struct KernelMQ_Info_Area *const area = &src->areas[i]; + if (last > area->base) { + return 0; + } + + if (area->size == 0) { + return 0; + } + + if (area->base + area->size != area->limit + 1) { + return 0; + } + + last = area->limit + 1; + + if (!area->is_available) { + if (src->kernel_phys_base >= area->base && + src->kernel_phys_base <= area->limit) { + return 0; + } + + if (src->kernel_phys_limit >= area->base && + src->kernel_phys_limit <= area->limit) { + return 0; + } + + for (unsigned int j = 0; j < src->modules_count; ++j) { + const struct KernelMQ_Info_Module *const module = &src->modules[j]; + + if (module->base >= area->base && + module->base <= area->limit) { + return 0; + } + + if (module->limit >= area->base && + module->limit <= area->limit) { + return 0; + } + } + } + } + *dest = *src; return 1; } + +unsigned char cmdline_terminated(const char *const s) +{ + for (unsigned int i = 0; i < KERNELMQ_INFO_CMDLINE_SIZE_MAX; ++i) { + if (s[i] == 0) { + return 1; + } + } + + return 0; +} diff --git a/arch/init.c b/arch/init.c index 1a76f53..4c5735d 100644 --- a/arch/init.c +++ b/arch/init.c @@ -32,5 +32,7 @@ const struct KernelMQ_Info *init(unsigned long multiboot_magic, unsigned long mu kinfo.kernel_phys_limit = kinfo.kernel_phys_base + kinfo.kernel_size - 1; kinfo.kernel_virt_limit = kinfo.kernel_virt_base + kinfo.kernel_size - 1; + kinfo.kernel_and_modules_total_size = kinfo.kernel_size + kinfo.modules_total_size; + return &kinfo; } diff --git a/arch/multiboot.c b/arch/multiboot.c index c8ec022..e62582e 100644 --- a/arch/multiboot.c +++ b/arch/multiboot.c @@ -149,6 +149,8 @@ unsigned char print_multiboot_tag_module(struct KernelMQ_Info *kinfo, const stru ++kinfo->modules_count; + kinfo->modules_total_size += module->size; + return 1; } diff --git a/include/kernelmq/info.h b/include/kernelmq/info.h index 4d1983e..58c2850 100644 --- a/include/kernelmq/info.h +++ b/include/kernelmq/info.h @@ -10,9 +10,12 @@ extern "C" { #define KERNELMQ_INFO_MODULES_MAX 20 #define KERNELMQ_INFO_AREAS_MAX 20 +// TODO: architecture-dependent #define KERNELMQ_INFO_MEM_LOWER_BASE ((unsigned long)0) +// TODO: architecture-dependent #define KERNELMQ_INFO_MEM_UPPER_BASE ((unsigned long)(1 * 1024 * 1024 * 1024)) // 1 MB +// TODO: architecture-dependent #define KERNELMQ_INFO_MEM_LOWER_SIZE_MAX ((unsigned long)(640 * 1024)) // 640 KB struct KernelMQ_Info_Module {