cmake: Add ENABLE_UBSAN for -fsanitize=undefined

Change-Id: I73db5f904a7d86052aae62e67b01281763c83561
This commit is contained in:
Dominique Martinet
2018-10-10 15:20:08 +09:00
parent 2a63c962fc
commit 2f456b8752
5 changed files with 237 additions and 0 deletions

View File

@ -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("-------------------------------")

View File

@ -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}"

View File

@ -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
View 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);
}

View File

@ -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__*/