diff --git a/Makefile b/Makefile index 7e20f9c..aa7b486 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ OBJFILES := $(patsubst $(SRC)/%.c, $(BUILDDIR)/%.o, $(SOURCES)) CC := x86_64-elf-gcc CC_FLAGS=-Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fstack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel -CC_PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable +CC_PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable -fsanitize=undefined LD := x86_64-elf-ld diff --git a/include/security/ubsan.h b/include/security/ubsan.h new file mode 100644 index 0000000..a7abc4a --- /dev/null +++ b/include/security/ubsan.h @@ -0,0 +1,59 @@ +/* + * @author xamidev + * @brief Undefined behavior sanitization hooks + * @license GPL-3.0-only + */ + +#ifndef UBSAN_H +#define UBSAN_H + +#include + +struct ubsan_source_location +{ + const char* filename; + uint32_t line; + uint32_t column; +}; + +struct ubsan_type_descriptor +{ + uint16_t type_kind; + uint16_t type_info; + char type_name[]; +}; + +struct ubsan_type_mismatch_v1_data +{ + struct ubsan_source_location location; + struct ubsan_type_descriptor* type; + unsigned char log_alignment; + unsigned char type_check_kind; +}; + +struct ubsan_pointer_overflow_data +{ + struct ubsan_source_location location; +}; + +struct ubsan_shift_out_of_bounds_data +{ + struct ubsan_source_location location; + struct ubsan_type_descriptor* lhs_type; + struct ubsan_type_descriptor* rhs_type; +}; + +struct ubsan_invalid_value_data +{ + struct ubsan_source_location location; + struct ubsan_type_descriptor* type; +}; + +struct ubsan_out_of_bounds_data +{ + struct ubsan_source_location location; + struct ubsan_type_descriptor* array_type; + struct ubsan_type_descriptor* index_type; +}; + +#endif \ No newline at end of file diff --git a/src/kmain.c b/src/kmain.c index 0323562..2a75272 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -85,15 +85,6 @@ void thing_main(void* arg) extern uintptr_t kheap_start; -/* Stack Smashing Protection */ - -uint64_t __stack_chk_guard = STACK_CHK_GUARD; - -void __stack_chk_fail(void) -{ - panic(NULL, "SSP: Stask Smashing Detected!!! (very spicy)"); -} - /* * kmain - Kernel entry point * diff --git a/src/security/ssp.c b/src/security/ssp.c new file mode 100644 index 0000000..654df7a --- /dev/null +++ b/src/security/ssp.c @@ -0,0 +1,17 @@ +/* + * @author xamidev + * @brief Stack Smashing Protection feature + * @license GPL-3.0-only + */ + +#include +#include +#include +#include + +uint64_t __stack_chk_guard = STACK_CHK_GUARD; + +void __stack_chk_fail(void) +{ + panic(NULL, "SSP: Stask Smashing Detected!!! (very spicy)"); +} \ No newline at end of file diff --git a/src/security/ubsan.c b/src/security/ubsan.c new file mode 100644 index 0000000..cf0b6e4 --- /dev/null +++ b/src/security/ubsan.c @@ -0,0 +1,160 @@ +/* + * @author xamidev + * @brief Undefined behavior sanitization hooks + * @license GPL-3.0-only + */ + +#include +#include +#include +#include + +/* + * Hooks were inspired from the Sortix implementation: + * https://gitlab.com/sortix/sortix/-/blob/main/libc/ubsan/ubsan.c + * + * Not all hooks are implemented here. + */ + +extern struct init_status init; + +/* + * __ubsan_handle_type_mismatch_v1 - Hook for UBSan + * @data_raw: pointer to error data + * @pointer_raw: faulty pointer + * + * This function is executed when the UBSan library detects + * following undefined behavior: type mismatch, null pointer + * access, and unaligned access. It halts the system and + * gives the location of the code that triggered it. + */ +void __ubsan_handle_type_mismatch_v1(void* data_raw, void* pointer_raw) +{ + struct ubsan_type_mismatch_v1_data* data = (struct ubsan_type_mismatch_v1_data*) data_raw; + uintptr_t pointer = (uintptr_t)pointer_raw; + uintptr_t alignment = (uintptr_t)1UL << data->log_alignment; + const char* violation = "type mismatch"; + if ( !pointer ) { + violation = "null pointer access"; + } + else if ( alignment && (pointer & (alignment - 1)) ) { + violation = "unaligned access"; + } + + struct ubsan_source_location* loc = &data->location; + + DEBUG("\x1b[38;5;231mUBSan: %s (ptr=%p) at %s:%u:%u\x1b[0m", violation, pointer, loc->filename, loc->line, loc->column); + + if (init.all) { + printf("\x1b[38;5;231mUBSan: %s (ptr=%p) at %s:%u:%u\x1b[0m\r\n", violation, pointer, loc->filename, loc->line, loc->column); + } + + panic(NULL, "Undefined Behavior Sanitization error"); +} + +/* + * __ubsan_handle_pointer_overflow - Hook for UBSan + * @data_raw: pointer to error data + * @base_raw: base pointer + * @result_raw: pointer after faulty operation + * + * This function is executed when the UBSan library detects + * following undefined behavior: pointer overflow. + * It halts the system and gives the location of the code + * that triggered it. + */ +void __ubsan_handle_pointer_overflow(void* data_raw, void* base_raw, void* result_raw) +{ + struct ubsan_pointer_overflow_data* data = (struct ubsan_pointer_overflow_data*) data_raw; + uintptr_t base = (uintptr_t)base_raw; + uintptr_t result = (uintptr_t)result_raw; + + struct ubsan_source_location* loc = &data->location; + + DEBUG("\x1b[38;5;231mUBSan: pointer overflow (base=%p, result=%p) at %s:%u:%u\x1b[0m", base, result, loc->filename, loc->line, loc->column); + + if (init.all) { + printf("\x1b[38;5;231mUBSan: pointer overflow (base=%p, result=%p) at %s:%u:%u\x1b[0m", base, result, loc->filename, loc->line, loc->column); + } + + panic(NULL, "Undefined Behavior Sanitization error: pointer overflow"); +} + +/* + * __ubsan_handle_shift_out_of_bounds - Hook for UBSan + * @data_raw: pointer to error data + * @lhs_raw: left hand side (value being shifted) + * @rhs_raw: right hand side (shift amount) + * + * This function is executed when the UBSan library detects + * following undefined behavior: shift out of bounds. + * It halts the system and gives the location of the code + * that triggered it. + */ +void __ubsan_handle_shift_out_of_bounds(void* data_raw, void* lhs_raw, void* rhs_raw) +{ + struct ubsan_shift_out_of_bounds_data* data = (struct ubsan_shift_out_of_bounds_data*) data_raw; + uintptr_t lhs = (uintptr_t) lhs_raw; + uintptr_t rhs = (uintptr_t) rhs_raw; + + struct ubsan_source_location* loc = &data->location; + + DEBUG("\x1b[38;5;231mUBSan: shift out of bounds (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); + + if (init.all) { + printf("\x1b[38;5;231mUBSan: shift out of bounds (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); + } + + panic(NULL, "Undefined Behavior Sanitization error: shift out of bounds"); +} + +/* + * __ubsan_handle_load_invalid_value - Hook for UBSan + * @data_raw: pointer to error data + * @value_raw: value loaded + * + * This function is executed when the UBSan library detects + * following undefined behavior: invalid value load. + * It halts the system and gives the location of the code + * that triggered it. + */ +void __ubsan_handle_load_invalid_value(void* data_raw, void* value_raw) +{ + struct ubsan_invalid_value_data* data = (struct ubsan_invalid_value_data*) data_raw; + uintptr_t value = (uintptr_t) value_raw; + + struct ubsan_source_location* loc = &data->location; + + DEBUG("\x1b[38;5;231mUBSan: invalid value load (value=%p) at %s:%u:%u\x1b[0m", value, loc->filename, loc->line, loc->column); + + if (init.all) { + printf("\x1b[38;5;231mUBSan: invalid value load (value=%p) at %s:%u:%u\x1b[0m", value, loc->filename, loc->line, loc->column); + } + + panic(NULL, "Undefined Behavior Sanitization error: invalid value load"); +} + +/* + * __ubsan_handle_out_of_bounds - Hook for UBSan + * @data_raw: pointer to error data + * @index_raw: out-of-bounds index in array + * + * This function is executed when the UBSan library detects + * following undefined behavior: access out of bounds. + * It halts the system and gives the location of the code + * that triggered it. + */ +void __ubsan_handle_out_of_bounds(void* data_raw, void* index_raw) +{ + struct ubsan_out_of_bounds_data* data = (struct ubsan_out_of_bounds_data*) data_raw; + uintptr_t index = (uintptr_t) index_raw; + struct ubsan_source_location* loc = &data->location; + + DEBUG("\x1b[38;5;231mUBSan: out of bounds (index=%p) at %s:%u:%u\x1b[0m", index, loc->filename, loc->line, loc->column); + + if (init.all) { + printf("\x1b[38;5;231mUBSan: out of bounds (index=%p) at %s:%u:%u\x1b[0m", index, loc->filename, loc->line, loc->column); + } + + panic(NULL, "Undefined Behavior Sanitization error: out of bounds"); +}