Compare commits
2 Commits
ffcaac0ca3
...
67f536cf91
Author | SHA1 | Date | |
---|---|---|---|
67f536cf91 | |||
d0efc106b0 |
@ -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 $^
|
||||
|
4
kernel/include/utils/StringParsing.h
Normal file
4
kernel/include/utils/StringParsing.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
long parse_decimal(const char* str);
|
||||
long parse_octal(const char* str);
|
@ -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)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "std/errno.h"
|
||||
#include "std/stdlib.h"
|
||||
#include "std/string.h"
|
||||
#include "utils/StringParsing.h"
|
||||
|
||||
extern BOOTBOOT bootboot;
|
||||
|
||||
@ -54,24 +55,14 @@ uint64_t InitRD::get_file_physical_address(InitRD::File& file)
|
||||
InitRD::File InitRD::get_file(TarHeader* header)
|
||||
{
|
||||
File result;
|
||||
result.size = 0;
|
||||
char null_terminated_size[13];
|
||||
memcpy(null_terminated_size, header->size, 12);
|
||||
null_terminated_size[12] = 0;
|
||||
result.size = parse_octal(null_terminated_size);
|
||||
memcpy(result.name, header->name, 100);
|
||||
int 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--)
|
||||
{
|
||||
result.size += (multiplier * (header->size[i] - 48));
|
||||
multiplier *= 8;
|
||||
}
|
||||
result.addr = (void*)((uint64_t)header + TAR_BLOCKSIZE);
|
||||
result.size_in_blocks = Utilities::get_blocks_from_size(TAR_BLOCKSIZE, result.size);
|
||||
result.mode = 0;
|
||||
multiplier = 1;
|
||||
for (int i = 6; i >= 0; i--)
|
||||
{
|
||||
result.mode += (mode_t)(multiplier * (header->mode[i] - 48));
|
||||
multiplier *= 8;
|
||||
}
|
||||
result.mode = (mode_t)parse_octal(header->mode);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
205
kernel/src/misc/ubsan.cpp
Normal file
205
kernel/src/misc/ubsan.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
#define MODULE "ubsan"
|
||||
|
||||
#include <log/Log.h>
|
||||
#include <panic/Panic.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
49
kernel/src/utils/StringParsing.cpp
Normal file
49
kernel/src/utils/StringParsing.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "utils/StringParsing.h"
|
||||
|
||||
int isdigit(int c)
|
||||
{
|
||||
return c >= '0' && c < ':';
|
||||
}
|
||||
|
||||
int isodigit(int c)
|
||||
{
|
||||
return c >= '0' && c < '8';
|
||||
}
|
||||
|
||||
int isxdigit(int c)
|
||||
{
|
||||
return isdigit(c) || ((unsigned int)c | 32) - 'a' < 6;
|
||||
}
|
||||
|
||||
template <typename T, typename ValidDigitChecker, typename Converter>
|
||||
static T string_to_integer_type(const char* str, int base, ValidDigitChecker checker, Converter converter)
|
||||
{
|
||||
bool neg = false;
|
||||
T val = 0;
|
||||
|
||||
switch (*str)
|
||||
{
|
||||
case '-':
|
||||
neg = true;
|
||||
str++;
|
||||
break;
|
||||
case '+': str++; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
while (checker(*str)) { val = (base * val) + converter(*str++); }
|
||||
|
||||
return (neg ? -val : val);
|
||||
}
|
||||
|
||||
long parse_decimal(const char* str)
|
||||
{
|
||||
return string_to_integer_type<long>(
|
||||
str, 10, [](char c) { return isdigit(c); }, [](char c) { return c - '0'; });
|
||||
}
|
||||
|
||||
long parse_octal(const char* str)
|
||||
{
|
||||
return string_to_integer_type<long>(
|
||||
str, 8, [](char c) { return isodigit(c); }, [](char c) { return c - '0'; });
|
||||
}
|
Loading…
Reference in New Issue
Block a user