diff --git a/kernel/Makefile b/kernel/Makefile index 57ccc724..bc29af67 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -14,7 +14,7 @@ CFLAGS := ${CFLAGS} -D_MOON_SUFFIX=-$(shell git rev-parse --short HEAD) endif ifeq ($(MOON_BUILD_DEBUG), 1) -CFLAGS := -ggdb ${CFLAGS} +CFLAGS := -ggdb -fsanitize=undefined ${CFLAGS} endif rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) @@ -45,6 +45,10 @@ $(MOON_OBJ)/%.cpp.o: $(MOON_SRC)/%.cpp @mkdir -p $(@D) $(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $^ +$(MOON_OBJ)/memory/liballoc/liballoc.c.o: $(MOON_SRC)/memory/liballoc/liballoc.c + @mkdir -p $(@D) + $(CC) $(CFLAGS) -fno-sanitize=undefined -o $@ -c $^ + $(MOON_OBJ)/%.c.o: $(MOON_SRC)/%.c @mkdir -p $(@D) $(CC) $(CFLAGS) -o $@ -c $^ diff --git a/kernel/src/cpu/CPU.cpp b/kernel/src/cpu/CPU.cpp index 75c717f5..f686a009 100644 --- a/kernel/src/cpu/CPU.cpp +++ b/kernel/src/cpu/CPU.cpp @@ -76,7 +76,7 @@ bool CPU::has_nx() static bool _has_feature(int feature) { - return (CPU::get_feature_bitmask() & (uint64_t)(1 << feature)) > 0; + return (CPU::get_feature_bitmask() & (uint64_t)(1UL << feature)) > 0; } bool CPU::has_feature(CPU::Features feature) diff --git a/kernel/src/init/InitRD.cpp b/kernel/src/init/InitRD.cpp index afde38a0..ea2bd4ee 100644 --- a/kernel/src/init/InitRD.cpp +++ b/kernel/src/init/InitRD.cpp @@ -56,7 +56,7 @@ InitRD::File InitRD::get_file(TarHeader* header) File result; result.size = 0; memcpy(result.name, header->name, 100); - int multiplier = + long multiplier = 1; // why they decided to store the size as an octal-encoded string instead of an integer is beyond me for (int i = 10; i >= 0; i--) { diff --git a/kernel/src/misc/ubsan.cpp b/kernel/src/misc/ubsan.cpp new file mode 100644 index 00000000..d9394956 --- /dev/null +++ b/kernel/src/misc/ubsan.cpp @@ -0,0 +1,205 @@ +#define MODULE "ubsan" + +#include +#include +#include + +#pragma GCC push_options +#pragma GCC diagnostic ignored "-Wpedantic" + +struct source_location +{ + const char* file; + uint32_t line; + uint32_t column; +}; + +struct type_descriptor +{ + uint16_t kind; + uint16_t info; + char name[]; +}; + +struct type_mismatch_info +{ + struct source_location location; + struct type_descriptor* type; + uintptr_t alignment; + uint8_t type_check_kind; +}; + +struct type_mismatch_info_v1 +{ + struct source_location location; + struct type_descriptor* type; + unsigned char log_alignment; + unsigned char type_check_kind; +}; + +struct overflow_info +{ + struct source_location location; + struct type_descriptor* type; +}; + +struct unreachable_info +{ + struct source_location location; +}; + +struct out_of_bounds_info +{ + struct source_location location; + struct type_descriptor* array_type; + struct type_descriptor* index_type; +}; + +struct invalid_value_info +{ + struct source_location location; + struct type_descriptor* type; +}; + +struct shift_out_of_bounds_info +{ + struct source_location location; + struct type_descriptor* lhs_type; + struct type_descriptor* rhs_type; +}; + +struct pointer_overflow_info +{ + struct source_location location; +}; + +#define is_aligned(value, alignment) !(value & (alignment - 1)) + +const char* Type_Check_Kinds[] = { + "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", +}; + +static void log_location(source_location* location) +{ + kinfoln("at %s:%d:%d", location->file, location->line, location->column); +} + +extern "C" void __ubsan_handle_type_mismatch(type_mismatch_info* type_mismatch, uintptr_t pointer) +{ + source_location* location = &type_mismatch->location; + if (pointer == 0) { kinfoln("Null pointer access"); } + else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment)) + { + // Most useful on architectures with stricter memory alignment requirements, like ARM. + kinfoln("Unaligned memory access"); + } + else + { + kinfoln("Insufficient size"); + kinfoln("%s address %p with insufficient space for object of type %s\n", + Type_Check_Kinds[type_mismatch->type_check_kind], (void*)pointer, type_mismatch->type->name); + } + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_type_mismatch_v1(type_mismatch_info_v1* type_mismatch, unsigned long pointer) +{ + type_mismatch_info info = {type_mismatch->location, type_mismatch->type, 1UL << type_mismatch->log_alignment, + type_mismatch->type_check_kind}; + + __ubsan_handle_type_mismatch(&info, pointer); +} + +extern "C" void __ubsan_handle_add_overflow(overflow_info* overflow_data, uintptr_t, uintptr_t) +{ + source_location* location = &overflow_data->location; + kinfoln("Addition overflow for two values of type %s", overflow_data->type->name); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_sub_overflow(overflow_info* overflow_data, uintptr_t, uintptr_t) +{ + source_location* location = &overflow_data->location; + kinfoln("Substraction overflow for two values of type %s", overflow_data->type->name); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_mul_overflow(overflow_info* overflow_data, uintptr_t, uintptr_t) +{ + source_location* location = &overflow_data->location; + kinfoln("Multiplication overflow for two values of type %s", overflow_data->type->name); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_negate_overflow(overflow_info* overflow_data, uintptr_t) +{ + source_location* location = &overflow_data->location; + kinfoln("Negation overflow for two values of type %s", overflow_data->type->name); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_divrem_overflow(overflow_info* overflow_data, uintptr_t, uintptr_t) +{ + source_location* location = &overflow_data->location; + kinfoln("Division overflow for two values of type %s", overflow_data->type->name); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_builtin_unreachable(unreachable_info* unreachable_data) +{ + source_location* location = &unreachable_data->location; + kinfoln("Reached the unreachable"); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_out_of_bounds(out_of_bounds_info* out_of_bounds_data, uintptr_t index) +{ + source_location* location = &out_of_bounds_data->location; + kinfoln("Out of bounds access at index %ld of array type %s and index type %s", index, + out_of_bounds_data->array_type->name, out_of_bounds_data->index_type->name); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_load_invalid_value(invalid_value_info* invalid_value_data, uintptr_t) +{ + source_location* location = &invalid_value_data->location; + kinfoln("Invalid value load of type %s", invalid_value_data->type->name); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_shift_out_of_bounds(shift_out_of_bounds_info* shift_out_of_bounds_data, uintptr_t, + uintptr_t) +{ + source_location* location = &shift_out_of_bounds_data->location; + kinfoln("Shift out of bounds for type %s", shift_out_of_bounds_data->lhs_type->name); + log_location(location); + panic("Undefined behaviour detected"); +} + +extern "C" void __ubsan_handle_pointer_overflow(pointer_overflow_info* pointer_overflow_data, uintptr_t, uintptr_t) +{ + source_location* location = &pointer_overflow_data->location; + kinfoln("Pointer overflow"); + log_location(location); + panic("Undefined behaviour detected"); +} + +#pragma GCC pop_options \ No newline at end of file