From 6245a3d19f4744abfd377989d432330659737a6a Mon Sep 17 00:00:00 2001 From: Matheus Date: Tue, 31 Dec 2024 11:20:27 -0300 Subject: [PATCH] kernel: add ubsan bindings, fix some UB reported by it --- kernel-src/arch/x86-64/acpi.c | 6 +- kernel-src/arch/x86-64/apic.c | 80 ++++----- kernel-src/include/kernel/topology.h | 2 +- kernel-src/include/string.h | 2 +- kernel-src/io/pci.c | 14 +- kernel-src/io/pseudodevices.c | 2 +- kernel-src/lib/string.c | 2 +- kernel-src/lib/ubsan.c | 252 +++++++++++++++++++++++++++ kernel-src/mm/alloc.c | 2 +- kernel-src/sys/cmdline.c | 68 ++++---- kernel-src/sys/signal.c | 8 +- 11 files changed, 348 insertions(+), 90 deletions(-) create mode 100644 kernel-src/lib/ubsan.c diff --git a/kernel-src/arch/x86-64/acpi.c b/kernel-src/arch/x86-64/acpi.c index 61212526..990051f2 100644 --- a/kernel-src/arch/x86-64/acpi.c +++ b/kernel-src/arch/x86-64/acpi.c @@ -4,12 +4,12 @@ #include -static volatile struct limine_rsdp_request rsdpreq = { +static volatile struct limine_rsdp_request rsdp_request = { .id = LIMINE_RSDP_REQUEST, .revision = 0 }; -uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *outrsdp) { - *outrsdp = (uintptr_t)FROM_HHDM(rsdpreq.response->address); +uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *rsdp_out) { + *rsdp_out = (uintptr_t)FROM_HHDM(rsdp_request.response->address); return UACPI_STATUS_OK; } diff --git a/kernel-src/arch/x86-64/apic.c b/kernel-src/arch/x86-64/apic.c index 8069b86b..5651a604 100644 --- a/kernel-src/arch/x86-64/apic.c +++ b/kernel-src/arch/x86-64/apic.c @@ -12,7 +12,7 @@ #include #define IOAPIC_REG_ID 0 -#define IOAPIC_REG_ENTRYCOUNT 1 +#define IOAPIC_REG_ENTRY_COUNT 1 #define IOAPIC_REG_PRIORITY 2 #define IOAPIC_REG_ENTRY 0x10 @@ -28,7 +28,7 @@ #define APIC_LVT_LINT0 0x350 #define APIC_LVT_LINT1 0x360 #define APIC_LVT_ERROR 0x370 -#define APIC_TIMER_INITIALCOUNT 0x380 +#define APIC_TIMER_INITIAL_COUNT 0x380 #define APIC_TIMER_COUNT 0x390 #define APIC_TIMER_DIVIDE 0x3E0 @@ -39,22 +39,22 @@ typedef struct { void *addr; int base; int top; -} ioapicdesc_t; +} ioapic_desc_t; -static ioapicdesc_t *ioapics; +static ioapic_desc_t *ioapics; static struct acpi_madt *madt; -static struct acpi_entry_hdr *liststart; -static struct acpi_entry_hdr *listend; -static void *lapicaddr; +static struct acpi_entry_hdr *list_start; +static struct acpi_entry_hdr *list_end; +static void *lapic_address; -static size_t overridecount; -static size_t iocount; -static size_t lapiccount; -static size_t lapicnmicount; +static size_t override_count; +static size_t io_count; +static size_t lapic_count; +static size_t lapic_nmi_count; -static ioapicdesc_t *ioapicfromgsi(int gsi) { - for (int i = 0; i < iocount; ++i) { +static ioapic_desc_t *ioapicfromgsi(int gsi) { + for (int i = 0; i < io_count; ++i) { if (ioapics[i].base <= gsi && ioapics[i].top > gsi) return &ioapics[i]; } @@ -67,9 +67,9 @@ static inline struct acpi_entry_hdr *getnext(struct acpi_entry_hdr *header) { } static inline void *getentry(int type, int n) { - struct acpi_entry_hdr *entry = liststart; + struct acpi_entry_hdr *entry = list_start; - while (entry < listend) { + while (entry < list_end) { if (entry->type == type) { if (n-- == 0) return entry; @@ -81,10 +81,10 @@ static inline void *getentry(int type, int n) { } static int getcount(int type) { - struct acpi_entry_hdr *entry = liststart; + struct acpi_entry_hdr *entry = list_start; int count = 0; - while (entry < listend) { + while (entry < list_end) { if (entry->type == type) ++count; entry = getnext(entry); @@ -94,12 +94,12 @@ static int getcount(int type) { } static inline void writelapic(int reg, uint32_t v) { - volatile uint32_t *ptr = (void *)((uintptr_t)lapicaddr + reg); + volatile uint32_t *ptr = (void *)((uintptr_t)lapic_address + reg); *ptr = v; } static inline uint32_t readlapic(int reg) { - volatile uint32_t *ptr = (void *)((uintptr_t)lapicaddr + reg); + volatile uint32_t *ptr = (void *)((uintptr_t)lapic_address + reg); return *ptr; } @@ -131,7 +131,7 @@ void arch_ioapic_setirq(uint8_t irq, uint8_t vector, uint8_t proc, bool masked) // default settings for ISA irqs uint8_t polarity = 1; // active high uint8_t trigger = 0; // edge triggered - for (uintmax_t i = 0; i < overridecount; ++i) { + for (uintmax_t i = 0; i < override_count; ++i) { struct acpi_madt_interrupt_source_override *override = getentry(ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE, i); if (override->source != irq) continue; @@ -142,7 +142,7 @@ void arch_ioapic_setirq(uint8_t irq, uint8_t vector, uint8_t proc, bool masked) break; } - ioapicdesc_t* ioapic = ioapicfromgsi(irq); + ioapic_desc_t* ioapic = ioapicfromgsi(irq); __assert(ioapic); irq = irq - ioapic->base; writeiored(ioapic->addr, irq, vector, 0, 0, polarity, trigger, masked ? 1 : 0, proc); @@ -170,7 +170,7 @@ void arch_apic_initap() { // get the acpi id for the local nmi sources - for (size_t i = 0; i < lapiccount; ++i) { + for (size_t i = 0; i < lapic_count; ++i) { struct acpi_madt_lapic *current = getentry(ACPI_MADT_ENTRY_TYPE_LAPIC, i); if (current_cpu()->id == current->id) { current_cpu()->acpiid = current->uid; @@ -181,7 +181,7 @@ void arch_apic_initap() { isr_t *nmiisr = interrupt_allocate(nmi, NULL, IPL_MAX); // MAX IPL because NMI __assert(nmiisr); - for (size_t i = 0; i < lapicnmicount; ++i) { + for (size_t i = 0; i < lapic_nmi_count; ++i) { struct acpi_madt_lapic_nmi* current = getentry(ACPI_MADT_ENTRY_TYPE_LAPIC_NMI, i); if (current->uid == current_cpu()->acpiid || current->uid == 0xff) writelapic(APIC_LVT_LINT0 + 0x10 * current->lint, (nmiisr->id & 0xff) | LVT_DELIVERY_NMI | (current->flags << 12)); @@ -194,16 +194,16 @@ void arch_apic_eoi() { static time_t stoptimer(timer_t *) { time_t remaining = readlapic(APIC_TIMER_COUNT); - time_t initial = readlapic(APIC_TIMER_INITIALCOUNT); + time_t initial = readlapic(APIC_TIMER_INITIAL_COUNT); - writelapic(APIC_TIMER_INITIALCOUNT, 0); + writelapic(APIC_TIMER_INITIAL_COUNT, 0); return initial - remaining; } static time_t time_passed(timer_t *) { time_t remaining = readlapic(APIC_TIMER_COUNT); - time_t initial = readlapic(APIC_TIMER_INITIALCOUNT); + time_t initial = readlapic(APIC_TIMER_INITIAL_COUNT); return initial - remaining; } @@ -213,7 +213,7 @@ static void timerisr(isr_t *isr, context_t *context) { } static void armtimer(timer_t *, time_t ticks) { - writelapic(APIC_TIMER_INITIALCOUNT, ticks); + writelapic(APIC_TIMER_INITIAL_COUNT, ticks); } void arch_apic_timerinit() { @@ -223,13 +223,13 @@ void arch_apic_timerinit() { writelapic(APIC_TIMER_DIVIDE, 11); - writelapic(APIC_TIMER_INITIALCOUNT, 0xffffffff); + writelapic(APIC_TIMER_INITIAL_COUNT, 0xffffffff); timekeeper_wait_us(50000); time_t ticksperus = (0xffffffff - readlapic(APIC_TIMER_COUNT)) / 50000; - writelapic(APIC_TIMER_INITIALCOUNT, 0); + writelapic(APIC_TIMER_INITIAL_COUNT, 0); printf("cpu%lu: local apic timer calibrated at %lu ticks per us. ISR vector %lu\n", current_cpu()->id, ticksperus, vec); @@ -252,13 +252,13 @@ void arch_apic_init() { __assert(ret == UACPI_STATUS_OK); madt = tbl.ptr; - liststart = (void *)((uintptr_t)madt + sizeof(struct acpi_madt)); - listend = (void *)((uintptr_t)madt + madt->hdr.length); + list_start = (void *)((uintptr_t)madt + sizeof(struct acpi_madt)); + list_end = (void *)((uintptr_t)madt + madt->hdr.length); - overridecount = getcount(ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE); - iocount = getcount(ACPI_MADT_ENTRY_TYPE_IOAPIC); - lapiccount = getcount(ACPI_MADT_ENTRY_TYPE_LAPIC); - lapicnmicount = getcount(ACPI_MADT_ENTRY_TYPE_LAPIC_NMI); + override_count = getcount(ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE); + io_count = getcount(ACPI_MADT_ENTRY_TYPE_IOAPIC); + lapic_count = getcount(ACPI_MADT_ENTRY_TYPE_LAPIC); + lapic_nmi_count = getcount(ACPI_MADT_ENTRY_TYPE_LAPIC_NMI); // map LAPIC to virtual memory @@ -269,22 +269,22 @@ void arch_apic_init() { if (lapic64) printf("\e[94mUsing 64 bit override for the local APIC address\n\e[0m"); - lapicaddr = vmm_map(NULL, PAGE_SIZE, VMM_FLAGS_PHYSICAL, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, paddr); - __assert(lapicaddr); + lapic_address = vmm_map(NULL, PAGE_SIZE, VMM_FLAGS_PHYSICAL, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, paddr); + __assert(lapic_address); // map I/O apics to memory - ioapics = alloc(sizeof(ioapicdesc_t) * iocount); + ioapics = alloc(sizeof(ioapic_desc_t) * io_count); __assert(ioapics); - for (int i = 0; i < iocount; ++i) { + for (int i = 0; i < io_count; ++i) { struct acpi_madt_ioapic *entry = getentry(ACPI_MADT_ENTRY_TYPE_IOAPIC, i); __assert((entry->address % PAGE_SIZE) == 0); ioapics[i].addr = vmm_map(NULL, PAGE_SIZE, VMM_FLAGS_PHYSICAL, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, (void *)(uint64_t)entry->address); __assert(ioapics[i].addr); ioapics[i].base = entry->gsi_base; - ioapics[i].top = ioapics[i].base + ((readioapic(ioapics[i].addr, IOAPIC_REG_ENTRYCOUNT) >> 16) & 0xff) + 1; + ioapics[i].top = ioapics[i].base + ((readioapic(ioapics[i].addr, IOAPIC_REG_ENTRY_COUNT) >> 16) & 0xff) + 1; printf("ioapic%lu: addr %p base %lu top %lu\n", i, entry->address, entry->gsi_base, ioapics[i].top); for (int j = ioapics[i].base; j < ioapics[i].top; ++j) writeiored(ioapics[i].addr, j - ioapics[i].base, 0xfe, 0, 0, 0, 0, 1, 0); diff --git a/kernel-src/include/kernel/topology.h b/kernel-src/include/kernel/topology.h index 2e026723..5dbe1ef7 100644 --- a/kernel-src/include/kernel/topology.h +++ b/kernel-src/include/kernel/topology.h @@ -1,7 +1,7 @@ #ifndef _TOPOLOGY_H #define _TOPOLOGY_H -#define TOPOLOGY_MAKE_ID(depth, id) ((depth << 16) | id) +#define TOPOLOGY_MAKE_ID(depth, id) (((depth & 0xfffflu) << 16) | id) #include diff --git a/kernel-src/include/string.h b/kernel-src/include/string.h index e133ef9c..0a73b0f9 100644 --- a/kernel-src/include/string.h +++ b/kernel-src/include/string.h @@ -7,7 +7,7 @@ size_t strlen(const char *str); char *strcpy(char *dest, const char *src); char *strcat(char *dest, const char *str); void *memcpy(void *dest, const void *src, size_t size); -void *memset(void *dest, unsigned long what, size_t size); +void *memset(void *dest, int what, size_t size); int strcmp(const char *a, const char *b); int strncmp(const char *a, const char *b, size_t c); int memcmp(const void *a, const void *b, size_t s); diff --git a/kernel-src/io/pci.c b/kernel-src/io/pci.c index cfa7d248..50a3869e 100644 --- a/kernel-src/io/pci.c +++ b/kernel-src/io/pci.c @@ -12,6 +12,11 @@ uint16_t pci_read16(int bus, int device, int function, uint32_t offset) { return (pci_archread32(bus, device, function, offset) >> ((offset & 0b11) * 8)) & 0xffff; } +uint32_t pci_read32(int bus, int device, int function, uint32_t offset) { + return pci_archread32(bus, device, function, offset); +} + + void pci_write8(int bus, int device, int function, uint32_t offset, uint8_t v) { uint32_t old = pci_archread32(bus, device, function, offset); int bitoffset = 8 * (offset & 0b11); @@ -23,19 +28,16 @@ void pci_write8(int bus, int device, int function, uint32_t offset, uint8_t v) { void pci_write16(int bus, int device, int function, uint32_t offset, uint16_t v) { uint32_t old = pci_archread32(bus, device, function, offset); int bitoffset = 8 * (offset & 0b11); - old &= ~(0xffff << bitoffset); - old |= v << bitoffset; + old &= ~(0xfffflu << bitoffset); + old |= (uint32_t)v << bitoffset; pci_archwrite32(bus, device, function, offset, old); } -uint32_t pci_read32(int bus, int device, int function, uint32_t offset) { - return pci_archread32(bus, device, function, offset); -} - void pci_write32(int bus, int device, int function, uint32_t offset, uint32_t value) { pci_archwrite32(bus, device, function, offset, value); } + int pci_getcapoffset(pcienum_t *e, int cap, int n) { if ((PCI_READ16(e, PCI_CONFIG_STATUS) & PCI_STATUS_HASCAP) == 0) return 0; diff --git a/kernel-src/io/pseudodevices.c b/kernel-src/io/pseudodevices.c index 0c16415d..382ce858 100644 --- a/kernel-src/io/pseudodevices.c +++ b/kernel-src/io/pseudodevices.c @@ -30,7 +30,7 @@ static int maxseek(int minor, size_t *max) { static long current = 0xdeadbeefbadc0ffe; -static uint8_t getrand8() { +__attribute__((no_sanitize("undefined"))) static uint8_t getrand8() { current += timekeeper_timefromboot().ns * timekeeper_timefromboot().s - timekeeper_time().ns * timekeeper_time().s + timekeeper_time().s; return current & 0xff; } diff --git a/kernel-src/lib/string.c b/kernel-src/lib/string.c index 531bd8e1..cab63683 100644 --- a/kernel-src/lib/string.c +++ b/kernel-src/lib/string.c @@ -16,7 +16,7 @@ void *memcpy(void *d, const void *s, size_t c) { return d; } -void *memset(void *ptr, unsigned long value, size_t num) { +void *memset(void *ptr, int value, size_t num) { #ifdef __x86_64__ asm volatile ("rep stosb" : : "D"(ptr), "a"(value), "c"(num) : "memory"); #else diff --git a/kernel-src/lib/ubsan.c b/kernel-src/lib/ubsan.c new file mode 100644 index 00000000..cdfe11bc --- /dev/null +++ b/kernel-src/lib/ubsan.c @@ -0,0 +1,252 @@ +#include +#include + +/* +typedefs and some other bits taken from https://git.thenest.dev/wux/elysium-os/-/blob/5.0/kernel/src/ubsan.c + +BSD 3-Clause License + +Copyright (c) 2024, ImWuX + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +typedef struct { + const char *filename; + uint32_t line; + uint32_t column; +} source_location_t; + +typedef struct { + uint16_t kind; + uint16_t info; + char name[]; +} type_descriptor_t; + +typedef struct { + source_location_t location; +} data_only_location_t; + +typedef struct { + source_location_t location; + type_descriptor_t *type; +} data_location_type_t; + +typedef struct { + source_location_t location; + type_descriptor_t *type; +} data_load_invalid_value_t; + +typedef struct { + source_location_t location; + source_location_t attr_location; + int arg_index; +} data_nonnull_arg_t; + +typedef struct { + source_location_t location; + type_descriptor_t *lhs_type; + type_descriptor_t *rhs_type; +} data_shift_out_of_bounds_t; + +typedef struct { + source_location_t location; + type_descriptor_t *array_type; + type_descriptor_t *index_type; +} data_out_of_bounds_t; + +typedef struct { + source_location_t location; + type_descriptor_t *type; + uint8_t alignment; + uint8_t type_check_kind; +} data_type_mismatch_t; + +typedef struct { + source_location_t location; + source_location_t assumption_location; + type_descriptor_t *type; +} data_alignment_assumption_t; + +typedef struct { + source_location_t location; + type_descriptor_t *from_type; + type_descriptor_t *to_type; + uint8_t kind; +} data_implicit_conversion_t; + +typedef struct { + source_location_t location; + uint8_t kind; +} data_invalid_builtin_t; + +const char *kind_to_type(uint16_t kind) { + const char* type; + switch (kind) { + case 0: type = "integer"; break; + case 1: type = "float"; break; + default: type = "unknown"; break; + } + return type; +} + +unsigned int info_to_bits(uint16_t info) { + return 1 << (info >> 1); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_load_invalid_value(data_load_invalid_value_t *data, uintptr_t value) { + printf("\e[93mubsan: load_invalid_value @ %s:%u:%u {value: %#lx}\e[0m\n", data->location.filename, data->location.line, data->location.column, value); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_nonnull_arg(data_nonnull_arg_t *data) { + printf("\e[93mubsan: handle_nonnull_arg @ %s:%u:%u {arg_index: %i}\e[0m\n", data->location.filename, data->location.line, data->location.column, data->arg_index); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_nullability_arg(data_nonnull_arg_t *data) { + printf("\e[93mubsan: nullability_arg @ %s:%u:%u {arg_index: %i}\e[0m\n", data->location.filename, data->location.line, data->location.column, data->arg_index); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_nonnull_return_v1(data_only_location_t *data [[maybe_unused]], source_location_t *location) { + printf("\e[93mubsan: nonnull_return @ %s:%u:%u\e[0m\n", location->filename, location->line, location->column); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_nullability_return_v1(data_only_location_t *data [[maybe_unused]], source_location_t *location) { + printf("\e[93mubsan: nullability_return @ %s:%u:%u\e[0m\n", location->filename, location->line, location->column); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_vla_bound_not_positive(data_location_type_t *data, uintptr_t bound) { + printf("\e[93mubsan: vla_bound_not_positive @ %s:%u:%u {bound: %#lx, type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, bound, info_to_bits(data->type->info), kind_to_type(data->type->kind), data->type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_add_overflow(data_location_type_t *data, uintptr_t lhs, uintptr_t rhs) { + printf("\e[93mubsan: add_overflow @ %s:%u:%u {lhs: %#lx, rhs: %#lx, type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, lhs, rhs, info_to_bits(data->type->info), kind_to_type(data->type->kind), data->type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_sub_overflow(data_location_type_t *data, uintptr_t lhs, uintptr_t rhs) { + printf("\e[93mubsan: sub_overflow @ %s:%u:%u {lhs: %#lx, rhs: %#lx, type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, lhs, rhs, info_to_bits(data->type->info), kind_to_type(data->type->kind), data->type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_mul_overflow(data_location_type_t *data, uintptr_t lhs, uintptr_t rhs) { + printf("\e[93mubsan: mul_overflow @ %s:%u:%u {lhs: %#lx, rhs: %#lx, type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, lhs, rhs, info_to_bits(data->type->info), kind_to_type(data->type->kind), data->type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_divrem_overflow(data_location_type_t *data, uintptr_t lhs, uintptr_t rhs) { + printf("\e[93mubsan: divrem_overflow @ %s:%u:%u {lhs: %#lx, rhs: %#lx, type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, lhs, rhs, info_to_bits(data->type->info), kind_to_type(data->type->kind), data->type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_negate_overflow(data_location_type_t *data, uintptr_t old) { + printf("\e[93mubsan: negate_overflow @ %s:%u:%u {old: %#lx, type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, old, info_to_bits(data->type->info), kind_to_type(data->type->kind), data->type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_shift_out_of_bounds(data_shift_out_of_bounds_t *data, uintptr_t lhs, uintptr_t rhs) { + printf("\e[93mubsan: shift_out_of_bounds @ %s:%u:%u {lhs: %#lx, rhs: %#lx, rhs_type: %u-bit %s %s, lhs_type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, lhs, rhs, + info_to_bits(data->rhs_type->info), kind_to_type(data->rhs_type->kind), data->rhs_type->name, + info_to_bits(data->lhs_type->info), kind_to_type(data->lhs_type->kind), data->lhs_type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_out_of_bounds(data_out_of_bounds_t *data, uint64_t index) { + printf("\e[93mubsan: out_of_bounds @ %s:%u:%u {index: %#lx, array_type: %u-bit %s %s, index_type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, index, + info_to_bits(data->array_type->info), kind_to_type(data->array_type->kind), data->array_type->name, + info_to_bits(data->index_type->info), kind_to_type(data->index_type->kind), data->index_type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_type_mismatch_v1(data_type_mismatch_t *data, void *pointer) { + static const char *kind_strs[] = { + "load of", + "store to", + "reference binding to", + "member access within", + "member call on", + "constructor call on", + "downcast of", + "downcast of", + "upcast of", + "cast to virtual base of", + "nonnull binding to", + "dynamic operation on" + }; + + if(pointer == NULL) { + printf("\e[93mubsan: type_mismatch @ %s:%u:%u (%s NULL pointer of type %s)\e[0m\n", + data->location.filename, data->location.line, data->location.column, kind_strs[data->type_check_kind], data->type->name + ); + } else if((1 << data->alignment) - 1) { + printf("\e[93mubsan: type_mismatch @ %s:%u:%u (%s misaligned address %#lx of type %s)\e[0m\n", + data->location.filename, data->location.line, data->location.column, kind_strs[data->type_check_kind], (uintptr_t) pointer, data->type->name + ); + } else { + printf("\e[93mubsan: type_mismatch @ %s:%u:%u (%s address %#lx, not enough spce for type %s)\e[0m\n", + data->location.filename, data->location.line, data->location.column, kind_strs[data->type_check_kind], (uintptr_t) pointer, data->type->name + ); + } +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_alignment_assumption(data_alignment_assumption_t *data, void *, void *, void *) { + printf("\e[93mubsan: alignment_assumption @ %s:%u:%u\e[0m\n", data->location.filename, data->location.line, data->location.column); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_implicit_conversion(data_implicit_conversion_t *data, void *, void *) { + printf("\e[93mubsan: implicit_conversion @ %s:%u:%u {from_type: %u-bit %s %s, to_type: %u-bit %s %s}\e[0m\n", + data->location.filename, data->location.line, data->location.column, + info_to_bits(data->from_type->info), kind_to_type(data->from_type->kind), data->from_type->name, + info_to_bits(data->to_type->info), kind_to_type(data->to_type->kind), data->to_type->name + ); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_invalid_builtin(data_invalid_builtin_t *data) { + printf("\e[93mubsan: invalid_builtin @ %s:%u:%u\e[0m\n", data->location.filename, data->location.line, data->location.column); +} + +__attribute__((no_sanitize("undefined"))) void __ubsan_handle_pointer_overflow(data_only_location_t *data, void *, void *) { + printf("\e[93mubsan: pointer_overflow @ %s:%u:%u\e[0m\n", data->location.filename, data->location.line, data->location.column); +} + +__attribute__((no_sanitize("undefined"))) __attribute__((noreturn)) void __ubsan_handle_builtin_unreachable(data_only_location_t *data) { + printf("\e[93mubsan: builtin_unreachable @ %s:%u:%u\e[0m\n", data->location.filename, data->location.line, data->location.column); + __assert(!"ubsan error"); +} + +__attribute__((no_sanitize("undefined"))) __attribute__((noreturn)) void __ubsan_handle_missing_return(data_only_location_t *data) { + printf("\e[93mubsan: missing_return @ %s:%u:%u\e[0m\n", data->location.filename, data->location.line, data->location.column); + __assert(!"ubsan error"); +} diff --git a/kernel-src/mm/alloc.c b/kernel-src/mm/alloc.c index 97754cb9..611eafb3 100644 --- a/kernel-src/mm/alloc.c +++ b/kernel-src/mm/alloc.c @@ -35,7 +35,7 @@ static void dtor(scache_t *cache, void *obj) { } static scache_t *getcachefromsize(size_t size) { - if (size == 0) + if (size <= 1) return caches[0]; size_t i = 64 - __builtin_clzll(size - 1); diff --git a/kernel-src/sys/cmdline.c b/kernel-src/sys/cmdline.c index 0901a443..9fbf4276 100644 --- a/kernel-src/sys/cmdline.c +++ b/kernel-src/sys/cmdline.c @@ -4,48 +4,48 @@ #include #include -static volatile struct limine_kernel_file_request kfreq = { +static volatile struct limine_kernel_file_request kernel_file_request = { .id = LIMINE_KERNEL_FILE_REQUEST, .revision = 0 }; -static hashtable_t pairtable; +static hashtable_t pair_table; char *cmdline_get(char *key) { void *v; - return hashtable_get(&pairtable, &v, key, strlen(key)) == 0 ? v : NULL; + return hashtable_get(&pair_table, &v, key, strlen(key)) == 0 ? v : NULL; } void cmdline_parse() { - __assert(hashtable_init(&pairtable, 16) == 0); - __assert(kfreq.response); - struct limine_file *kernelfile = kfreq.response->kernel_file; - __assert(kernelfile); - char *cmdline = kernelfile->cmdline; + __assert(hashtable_init(&pair_table, 16) == 0); + __assert(kernel_file_request.response); + struct limine_file *kernel_file = kernel_file_request.response->kernel_file; + __assert(kernel_file); + char *cmdline = kernel_file->cmdline; __assert(cmdline); - size_t bufferlen = strlen(cmdline) + 1; - char buffer[bufferlen]; - memset(buffer, 0, bufferlen); - char *cmdp = cmdline; - char *buffp = buffer; + size_t buffer_len = strlen(cmdline) + 1; + char buffer[buffer_len]; + memset(buffer, 0, buffer_len); + char *cmdline_ptr = cmdline; + char *buffer_ptr = buffer; - bool doconvert = true; + bool do_convert = true; - while (*cmdp) { - char cmdchar = *cmdp++; - if (cmdchar == ' ' && doconvert) - *buffp++ = '\0'; - else if (cmdchar == '"') { - doconvert = !doconvert; - --bufferlen; + while (*cmdline_ptr) { + char cmd_char = *cmdline_ptr++; + if (cmd_char == ' ' && do_convert) + *buffer_ptr++ = '\0'; + else if (cmd_char == '"') { + do_convert = !do_convert; + --buffer_len; } else - *buffp++ = cmdchar; + *buffer_ptr++ = cmd_char; } - buffer[bufferlen] = '\0'; + buffer[buffer_len - 1] = '\0'; int i = 0; - while (i < bufferlen) { + while (i < buffer_len) { char *iterator = &buffer[i]; bool pair = false; while (*iterator) { @@ -56,22 +56,22 @@ void cmdline_parse() { ++iterator; } - size_t keylen = strlen(&buffer[i]); + size_t key_len = strlen(&buffer[i]); if (pair) { - char *valuep = &buffer[i + keylen + 1]; - size_t valuelen = strlen(valuep); + char *value_ptr = &buffer[i + key_len + 1]; + size_t value_len = strlen(value_ptr); - char *value = alloc(valuelen) + 1; + char *value = alloc(value_len) + 1; __assert(value); - strcpy(value, valuep); - __assert(hashtable_set(&pairtable, value, &buffer[i], keylen, true) == 0); - i += valuelen + 1; + strcpy(value, value_ptr); + __assert(hashtable_set(&pair_table, value, &buffer[i], key_len, true) == 0); + i += value_len + 1; } else { - char *value = alloc(keylen + 1); + char *value = alloc(key_len + 1); __assert(value); strcpy(value, &buffer[i]); - __assert(hashtable_set(&pairtable, value, &buffer[i], keylen, true) == 0); + __assert(hashtable_set(&pair_table, value, &buffer[i], key_len, true) == 0); } - i += keylen + 1; + i += key_len + 1; } } diff --git a/kernel-src/sys/signal.c b/kernel-src/sys/signal.c index 2b9c0ac4..63636096 100644 --- a/kernel-src/sys/signal.c +++ b/kernel-src/sys/signal.c @@ -422,6 +422,11 @@ void signal_signalproc(struct proc_t *proc, int signal) { } } +__attribute__((no_sanitize("undefined"))) static inline void set_siginfo_ucontext(context_t *context, void *stack) { + CTX_ARG1(context) = (uint64_t)&((sigframe_t *)stack)->siginfo; + CTX_ARG2(context) = (uint64_t)ARCH_SIGFRAME_GET_UCONTEXT_POINTER((sigframe_t *)stack); +} + // returns true if should retry check bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uint64_t syscallret, uint64_t syscallerrno, bool *need_context_switch) { bool retry = false; @@ -593,8 +598,7 @@ bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uin CTX_IP(context) = (uint64_t)action->address; CTX_SP(context) = (uint64_t)stack; CTX_ARG0(context) = signal; - CTX_ARG1(context) = (uint64_t)&((sigframe_t *)stack)->siginfo; - CTX_ARG2(context) = (uint64_t)ARCH_SIGFRAME_GET_UCONTEXT_POINTER((sigframe_t *)stack); + set_siginfo_ucontext(context, stack); // reset handler if asked for if (action->flags & SA_RESETHAND)