cmake: Add ENABLE_UBSAN for -fsanitize=undefined
Change-Id: I73db5f904a7d86052aae62e67b01281763c83561
This commit is contained in:
@ -59,6 +59,7 @@ option(ENABLE_RUSAGE "Enable rusage support" ON)
|
||||
option(ENABLE_MCOVERLAYFS "Enable overlay filesystem" OFF)
|
||||
option(ENABLE_QLMPI "Enable qlmpi programs" OFF)
|
||||
option(ENABLE_UTI "Enable uti support" OFF)
|
||||
option(ENABLE_UBSAN "Enable undefined behaviour sanitizer on mckernel size" OFF)
|
||||
|
||||
find_library(LIBRT rt)
|
||||
find_library(LIBNUMA numa)
|
||||
@ -187,4 +188,5 @@ message("ENABLE_MCOVERLAYFS: ${ENABLE_MCOVERLAYFS}")
|
||||
message("ENABLE_QLMPI: ${ENABLE_QLMPI}")
|
||||
message("ENABLE_UTI: ${ENABLE_UTI}")
|
||||
message("ENABLE_WERROR: ${ENABLE_WERROR}")
|
||||
message("ENABLE_UBSAN: ${ENABLE_UBSAN}")
|
||||
message("-------------------------------")
|
||||
|
||||
@ -24,6 +24,9 @@
|
||||
/* whether UTI is enabled */
|
||||
#cmakedefine ENABLE_UTI 1
|
||||
|
||||
/* whether undefined behaviour sanitizer is enabled */
|
||||
#cmakedefine ENABLE_UBSAN 1
|
||||
|
||||
/* Path of bind-mount source directory */
|
||||
#cmakedefine ROOTFSDIR "${ROOTFSDIR}"
|
||||
|
||||
|
||||
@ -45,6 +45,11 @@ set(MCKERNEL_SRCS
|
||||
${IHK_FULL_SOURCE_DIR}/cokernel/smp/${ARCH}/setup.c
|
||||
)
|
||||
|
||||
if (ENABLE_UBSAN)
|
||||
add_compile_options(-fsanitize=undefined)
|
||||
list(APPEND MCKERNEL_SRCS ubsan.c)
|
||||
endif(ENABLE_UBSAN)
|
||||
|
||||
if (BUILD_TARGET STREQUAL "smp-x86")
|
||||
list(APPEND MCKERNEL_SRCS
|
||||
${PROJECT_SOURCE_DIR}/arch/${ARCH}/kernel/context.S
|
||||
|
||||
226
kernel/ubsan.c
Normal file
226
kernel/ubsan.c
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* UBSAN handlers
|
||||
* Types shamelessly copied over from linux
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <lwk/stddef.h>
|
||||
#include <kmsg.h>
|
||||
#include <kmalloc.h>
|
||||
|
||||
enum {
|
||||
type_kind_int = 0,
|
||||
type_kind_float = 1,
|
||||
type_unknown = 0xffff
|
||||
};
|
||||
|
||||
struct type_descriptor {
|
||||
short type_kind;
|
||||
short type_info;
|
||||
char type_name[1];
|
||||
};
|
||||
|
||||
struct source_location {
|
||||
const char *file_name;
|
||||
union {
|
||||
unsigned long reported;
|
||||
struct {
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct type_mismatch_data_v1 {
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
unsigned char log_alignment;
|
||||
unsigned char type_check_kind;
|
||||
};
|
||||
|
||||
struct type_mismatch_data {
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
unsigned long alignment;
|
||||
unsigned char type_check_kind;
|
||||
};
|
||||
|
||||
struct overflow_data {
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct nonnull_arg_data {
|
||||
struct source_location location;
|
||||
struct source_location attr_location;
|
||||
int arg_index;
|
||||
};
|
||||
|
||||
struct vla_bound_data {
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct out_of_bounds_data {
|
||||
struct source_location location;
|
||||
struct type_descriptor *array_type;
|
||||
struct type_descriptor *index_type;
|
||||
};
|
||||
|
||||
struct shift_out_of_bounds_data {
|
||||
struct source_location location;
|
||||
struct type_descriptor *lhs_type;
|
||||
struct type_descriptor *rhs_type;
|
||||
};
|
||||
|
||||
struct unreachable_data {
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct invalid_value_data {
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct pointer_overflow_data {
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
|
||||
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"
|
||||
};
|
||||
|
||||
#define REPORTED_BIT 31
|
||||
|
||||
#define COLUMN_MASK (~(1U << REPORTED_BIT))
|
||||
#define LINE_MASK (~0U)
|
||||
|
||||
#define VALUE_LENGTH 40
|
||||
|
||||
|
||||
|
||||
void ubsan_prologue(struct source_location *loc)
|
||||
{
|
||||
kprintf("UBSAN: Undefined behaviour in %s:%d:%d\n", loc->file_name,
|
||||
loc->line & LINE_MASK, loc->column & COLUMN_MASK);
|
||||
}
|
||||
|
||||
|
||||
void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
|
||||
unsigned long ptr)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
if (!ptr) {
|
||||
kprintf("%s: null pointer deref\n", __func__);
|
||||
} else if (data->alignment && !IS_ALIGNED(ptr, data->alignment)) {
|
||||
kprintf("%s: pointer %#16lx of type %s is not aligned at %#lx\n",
|
||||
__func__, ptr, data->type->type_name, data->alignment);
|
||||
} else {
|
||||
kprintf("%s: %s address %#16lx with insufficient space for an object of type %s\n",
|
||||
__func__, type_check_kinds[data->type_check_kind], ptr,
|
||||
data->type->type_name);
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data_v1,
|
||||
unsigned long ptr)
|
||||
{
|
||||
struct type_mismatch_data data = {
|
||||
.location = data_v1->location,
|
||||
.type = data_v1->type,
|
||||
.alignment = 1UL << data_v1->log_alignment,
|
||||
.type_check_kind = data_v1->type_check_kind,
|
||||
};
|
||||
__ubsan_handle_type_mismatch(&data, ptr);
|
||||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow(struct pointer_overflow_data *data,
|
||||
unsigned long base, unsigned long result)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: pointer overflow from %lx to %lx\n",
|
||||
__func__, base, result);
|
||||
}
|
||||
|
||||
void __ubsan_handle_add_overflow(struct overflow_data *data,
|
||||
unsigned long lhs,
|
||||
unsigned long rhs)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx %lx\n", __func__, lhs, rhs);
|
||||
|
||||
}
|
||||
void __ubsan_handle_sub_overflow(struct overflow_data *data,
|
||||
unsigned long lhs,
|
||||
unsigned long rhs)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx %lx\n", __func__, lhs, rhs);
|
||||
}
|
||||
|
||||
void __ubsan_handle_mul_overflow(struct overflow_data *data,
|
||||
unsigned long lhs,
|
||||
unsigned long rhs)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx %lx\n", __func__, lhs, rhs);
|
||||
}
|
||||
|
||||
void __ubsan_handle_negate_overflow(struct overflow_data *data,
|
||||
unsigned long old_val)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx\n", __func__, old_val);
|
||||
}
|
||||
|
||||
void __ubsan_handle_divrem_overflow(struct overflow_data *data,
|
||||
unsigned long lhs,
|
||||
unsigned long rhs)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx %lx\n", __func__, lhs, rhs);
|
||||
}
|
||||
|
||||
void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
|
||||
unsigned long bound)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx\n", __func__, bound);
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
|
||||
unsigned long index)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx\n", __func__, index);
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
|
||||
unsigned long lhs, unsigned long rhs)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx %lx\n", __func__, lhs, rhs);
|
||||
}
|
||||
|
||||
void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s\n", __func__);
|
||||
panic(__func__);
|
||||
}
|
||||
|
||||
void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
|
||||
unsigned long val)
|
||||
{
|
||||
ubsan_prologue(&data->location);
|
||||
kprintf("%s: %lx\n", __func__, val);
|
||||
}
|
||||
|
||||
@ -51,6 +51,7 @@ static inline unsigned long hweight_long(unsigned long w)
|
||||
#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask))
|
||||
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
|
||||
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
|
||||
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
|
||||
|
||||
#endif /*__ASSEMBLY__*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user