luna: Add UB sanitizer, for both kernel-space and userspace
This commit is contained in:
parent
96a213ec5c
commit
d82b3f809b
@ -17,6 +17,7 @@ set(FREESTANDING_SOURCES
|
||||
src/DebugLog.cpp
|
||||
src/Heap.cpp
|
||||
src/Spinlock.cpp
|
||||
src/UBSAN.cpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
|
74
luna/include/luna/UBSAN.h
Normal file
74
luna/include/luna/UBSAN.h
Normal file
@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
#include <luna/Types.h>
|
||||
|
||||
namespace UBSAN
|
||||
{
|
||||
struct SourceLocation
|
||||
{
|
||||
const char* file;
|
||||
u32 line;
|
||||
u32 column;
|
||||
};
|
||||
|
||||
struct TypeDescriptor
|
||||
{
|
||||
u16 kind;
|
||||
u16 info;
|
||||
char name[];
|
||||
};
|
||||
|
||||
namespace UBInfo
|
||||
{
|
||||
struct TypeMismatchInfo
|
||||
{
|
||||
SourceLocation location;
|
||||
TypeDescriptor* type;
|
||||
usize alignment;
|
||||
u8 type_check_kind;
|
||||
};
|
||||
|
||||
struct TypeMismatchInfo_v1
|
||||
{
|
||||
SourceLocation location;
|
||||
TypeDescriptor* type;
|
||||
u8 log_alignment;
|
||||
u8 type_check_kind;
|
||||
};
|
||||
|
||||
struct OverflowInfo
|
||||
{
|
||||
SourceLocation location;
|
||||
TypeDescriptor* type;
|
||||
};
|
||||
|
||||
struct UnreachableInfo
|
||||
{
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
struct OutOfBoundsInfo
|
||||
{
|
||||
SourceLocation location;
|
||||
TypeDescriptor* array_type;
|
||||
TypeDescriptor* index_type;
|
||||
};
|
||||
|
||||
struct InvalidValueInfo
|
||||
{
|
||||
SourceLocation location;
|
||||
TypeDescriptor* type;
|
||||
};
|
||||
|
||||
struct ShiftOutOfBoundsInfo
|
||||
{
|
||||
SourceLocation location;
|
||||
TypeDescriptor* lhs_type;
|
||||
TypeDescriptor* rhs_type;
|
||||
};
|
||||
|
||||
struct PointerOverflowInfo
|
||||
{
|
||||
SourceLocation location;
|
||||
};
|
||||
}
|
||||
}
|
121
luna/src/UBSAN.cpp
Normal file
121
luna/src/UBSAN.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
#include <luna/Check.h>
|
||||
#include <luna/DebugLog.h>
|
||||
#include <luna/SourceLocation.h>
|
||||
#include <luna/UBSAN.h>
|
||||
|
||||
using namespace UBSAN::UBInfo;
|
||||
|
||||
[[noreturn]] void ub_panic(SourceLocation caller = SourceLocation::current())
|
||||
{
|
||||
expect_at(false, caller, "Undefined behavior");
|
||||
}
|
||||
|
||||
#define DISPLAY(loc) loc.file, loc.line, loc.column
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void __ubsan_handle_builtin_unreachable(UnreachableInfo* info)
|
||||
{
|
||||
const auto& location = info->location;
|
||||
dbgln("ubsan: __builtin_unreachable reached at %s:%d:%d", DISPLAY(location));
|
||||
ub_panic();
|
||||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow(PointerOverflowInfo* info)
|
||||
{
|
||||
const auto& location = info->location;
|
||||
dbgln("ubsan: pointer overflow occurred at %s:%d:%d", DISPLAY(location));
|
||||
ub_panic();
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsInfo* info)
|
||||
{
|
||||
const auto& location = info->location;
|
||||
dbgln("ubsan: shift out of bounds for type %s at %s:%d:%d", info->lhs_type->name, DISPLAY(location));
|
||||
ub_panic();
|
||||
}
|
||||
|
||||
void __ubsan_handle_load_invalid_value(InvalidValueInfo* info)
|
||||
{
|
||||
const auto& location = info->location;
|
||||
dbgln("ubsan: load invalid value for type %s at %s:%d:%d", info->type->name, DISPLAY(location));
|
||||
ub_panic();
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds(OutOfBoundsInfo* info, usize index)
|
||||
{
|
||||
const auto& location = info->location;
|
||||
dbgln("ubsan: out of bounds array (of type %s) access (index %zu of type %s) at %s:%d:%d",
|
||||
info->array_type->name, index, info->index_type->name, DISPLAY(location));
|
||||
ub_panic();
|
||||
}
|
||||
|
||||
void ubsan_handle_generic_overflow(OverflowInfo* info, const char* overflow_type)
|
||||
{
|
||||
const auto& location = info->location;
|
||||
dbgln("ubsan: %s overflow (value cannot fit into type %s) at %s:%d:%d", overflow_type, info->type->name,
|
||||
DISPLAY(location));
|
||||
ub_panic();
|
||||
}
|
||||
|
||||
#define UBSAN_OVERFLOW_BINARY(operation) \
|
||||
void __ubsan_handle_##operation##_overflow(OverflowInfo* info, usize, usize) \
|
||||
{ \
|
||||
ubsan_handle_generic_overflow(info, #operation); \
|
||||
}
|
||||
|
||||
#define UBSAN_OVERFLOW_UNARY(operation) \
|
||||
void __ubsan_handle_##operation##_overflow(OverflowInfo* info, usize) \
|
||||
{ \
|
||||
ubsan_handle_generic_overflow(info, #operation); \
|
||||
}
|
||||
|
||||
UBSAN_OVERFLOW_BINARY(add);
|
||||
UBSAN_OVERFLOW_BINARY(sub);
|
||||
UBSAN_OVERFLOW_BINARY(mul);
|
||||
UBSAN_OVERFLOW_UNARY(negate);
|
||||
UBSAN_OVERFLOW_BINARY(divrem);
|
||||
|
||||
#define is_aligned(value, alignment) !(value & (alignment - 1))
|
||||
|
||||
const char* g_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",
|
||||
};
|
||||
|
||||
void __ubsan_handle_type_mismatch(TypeMismatchInfo* info, usize pointer)
|
||||
{
|
||||
const auto& location = info->location;
|
||||
|
||||
if (pointer == 0) { dbgln("ubsan: null pointer access at %s:%d:%d", DISPLAY(location)); }
|
||||
else if (info->alignment != 0 && is_aligned(pointer, info->alignment))
|
||||
{
|
||||
dbgln("ubsan: unaligned pointer access (address %p) at %s:%d:%d", (void*)pointer, DISPLAY(location));
|
||||
}
|
||||
else
|
||||
{
|
||||
dbgln("ubsan: %s address %p with insufficient space for object of type %s at %s:%d:%d",
|
||||
g_type_check_kinds[info->type_check_kind], (void*)pointer, info->type->name, DISPLAY(location));
|
||||
}
|
||||
ub_panic();
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(TypeMismatchInfo_v1* v1_info, usize pointer)
|
||||
{
|
||||
TypeMismatchInfo info = {
|
||||
.location = v1_info->location,
|
||||
.type = v1_info->type,
|
||||
.alignment = 1UL << v1_info->log_alignment,
|
||||
.type_check_kind = v1_info->type_check_kind,
|
||||
};
|
||||
__ubsan_handle_type_mismatch(&info, pointer);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user