diff options
| -rw-r--r-- | Makefile | 15 | ||||
| -rw-r--r-- | arch/riscv64/config.h | 8 | ||||
| -rw-r--r-- | common/pmem.c | 2 | ||||
| -rw-r--r-- | include/apos/bits.h | 6 | ||||
| -rw-r--r-- | include/apos/mem.h | 4 | ||||
| -rw-r--r-- | include/apos/unaligned.h | 67 | ||||
| -rw-r--r-- | include/libfdt.h | 5 | ||||
| -rw-r--r-- | lib/ubsan.c | 159 | ||||
| -rwxr-xr-x | scripts/gen-deps | 25 |
9 files changed, 268 insertions, 23 deletions
@@ -1,11 +1,11 @@ -DO != echo > deps.mk +DO != echo -n > deps.mk # this could be done better DEBUGFLAGS != [ $(RELEASE) ] \ && echo "-flto -O2 -DNDEBUG" \ || echo "-O0 -ggdb3 -DDEBUG" -CFLAGS = -ffreestanding -nostdlib -std=c17 -Wall -Wextra +CFLAGS = -ffreestanding -nostdlib -std=c17 -Wall -Wextra -Wvla DEPFLAGS = -MT $@ -MMD -MP -MF $@.d LINTFLAGS = -fsyntax-only PREPROCESS = -E @@ -56,10 +56,13 @@ KERN_INFO = sed "s/<KERNEL_SIZE>/$$($(KERN_SIZE))/" KERNEL_LINK := arch/$(ARCH)/conf/kernel-link INIT_LINK := arch/$(ARCH)/conf/init-link -KERNEL_OBJECTS != ./scripts/gen-deps --compile "$(KERNEL_SOURCES)" -INIT_OBJECTS != ./scripts/gen-deps --compile "$(INIT_SOURCES)" -KERNEL_LD != ./scripts/gen-deps --link "$(KERNEL_LINK).S" -INIT_LD != ./scripts/gen-deps --link "$(INIT_LINK).S" +KERN_FLAGS != [ $(UBSAN) ] && echo -fsanitize=undefined +INIT_FLAGS := + +KERNEL_OBJECTS != ./scripts/gen-deps --kernel --compile "$(KERNEL_SOURCES)" +INIT_OBJECTS != ./scripts/gen-deps --init --compile "$(INIT_SOURCES)" +KERNEL_LD != ./scripts/gen-deps --kernel --link "$(KERNEL_LINK).S" +INIT_LD != ./scripts/gen-deps --init --link "$(INIT_LINK).S" include deps.mk diff --git a/arch/riscv64/config.h b/arch/riscv64/config.h index 707c0b9..957f848 100644 --- a/arch/riscv64/config.h +++ b/arch/riscv64/config.h @@ -17,12 +17,12 @@ #define VM_DMAP (0xffffffc000000000) /* testing for now */ #define VM_KERN (VM_DMAP + SZ_256K) #define TMP_PTE (-SZ_2G) -#define ROOT_PTE (0) +#define ROOT_PTE (0UL) #define ROOT_REGION (SZ_4K) -#define IO_PAGE 511 -#define KSTART_PAGE 256 -#define CSTACK_PAGE 255 +#define IO_PAGE 511UL +#define KSTART_PAGE 256UL +#define CSTACK_PAGE 255UL /* assume Sv39, probably wouldn't be too difficult to use runtime parameters * instead. First 4K is reserved for NULL, but I suppose it could be mapped diff --git a/common/pmem.c b/common/pmem.c index 6ef89bc..e3e5e5c 100644 --- a/common/pmem.c +++ b/common/pmem.c @@ -236,6 +236,7 @@ static pm_t __populate_order(mm_node_t **op, pm_t cont, enum mm_order src, o->entries = num; o->full = (mm_info_t *)move_forward(cont, state_elems(num)); + cont = align_up(cont, sizeof(void *)); o->next = (mm_node_t **)move_forward(cont, next_elems(num)); memset(o->full, 0, state_elems(num)); memset(o->next, 0, next_elems(num)); @@ -260,6 +261,7 @@ static pm_t __probe_order(pm_t cont, enum mm_order src, enum mm_order dst, cont += sizeof(struct mm_branch_t); cont += state_elems(num); + cont = align_up(cont, sizeof(void *)); cont += next_elems(num); for (size_t i = 0; i < num; ++i) diff --git a/include/apos/bits.h b/include/apos/bits.h index cc3cd00..699cba4 100644 --- a/include/apos/bits.h +++ b/include/apos/bits.h @@ -8,9 +8,9 @@ #define __set_bit(x, y) ((x) |= (y)) #define __clear_bit(x, y) ((x) &= ~(y)) -#define __is_nset(x, y) (__is_set((x), 1 << (y))) -#define __set_nbit(x, y) (__set_bit((x), 1 << (y))) -#define __clear_nbit(x, y) (__clear_bit((x), 1 << (y))) +#define __is_nset(x, y) (__is_set((x), 1UL << (y))) +#define __set_nbit(x, y) (__set_bit((x), 1UL << (y))) +#define __clear_nbit(x, y) (__clear_bit((x), 1UL << (y))) uint16_t __bswap16(uint16_t u); uint32_t __bswap32(uint32_t u); diff --git a/include/apos/mem.h b/include/apos/mem.h index 7c0fde1..be44104 100644 --- a/include/apos/mem.h +++ b/include/apos/mem.h @@ -30,8 +30,8 @@ #define __o_container(idx) ((idx) / MM_OINFO_WIDTH) #define __o_bit(idx) ((idx) & (MM_OINFO_WIDTH - 1)) -#define __va(x) (((char *)(x)) + VM_DMAP - RAM_BASE) -#define __pa(x) (((char *)(x)) + RAM_BASE - VM_DMAP) +#define __va(x) (void *)(((uintptr_t)(x)) + VM_DMAP - RAM_BASE) +#define __pa(x) (void *)(((uintptr_t)(x)) - VM_DMAP + RAM_BASE) #define __page(x) ((x) / BASE_PAGE_SIZE) #define __addr(x) ((x)*BASE_PAGE_SIZE) #define __pages(x) \ diff --git a/include/apos/unaligned.h b/include/apos/unaligned.h new file mode 100644 index 0000000..1dbd253 --- /dev/null +++ b/include/apos/unaligned.h @@ -0,0 +1,67 @@ +#ifndef APOS_UNALIGNED_H +#define APOS_UNALIGNED_H + +#include <apos/types.h> +#include <apos/attrs.h> + +#define get_unaligned(ptr) \ + _Generic(*(ptr), uint8_t \ + : __get_unaligned_uint8_t, uint16_t \ + : __get_unaligned_uint16_t, uint32_t \ + : __get_unaligned_uint32_t, uint64_t \ + : __get_unaligned_uint64_t, int8_t \ + : __get_unaligned_int8_t, int16_t \ + : __get_unaligned_int16_t, int32_t \ + : __get_unaligned_int32_t, int64_t \ + : __get_unaligned_int64_t)((void *)ptr) + +#define put_unaligned(val, ptr) \ + _Generic(*(ptr), uint8_t \ + : __put_unaligned_uint8_t, uint16_t \ + : __put_unaligned_uint16_t, uint32_t \ + : __put_unaligned_uint32_t, uint64_t \ + : __put_unaligned_uint64_t, int8_t \ + : __put_unaligned_int8_t, int16_t \ + : __put_unaligned_int16_t, int32_t \ + : __put_unaligned_int32_t, int64_t \ + : __put_unaligned_int64_t)(val, (void *)ptr) + +#define DEFINE_GET(type) \ + static inline type __get_unaligned_##type(void *ptr) \ + { \ + const struct __packed { \ + type x; \ + } *__pptr = ptr; \ + return __pptr->x; \ + } + +DEFINE_GET(uint8_t); +DEFINE_GET(uint16_t); +DEFINE_GET(uint32_t); +DEFINE_GET(uint64_t); +DEFINE_GET(int8_t); +DEFINE_GET(int16_t); +DEFINE_GET(int32_t); +DEFINE_GET(int64_t); + +#undef DEFINE_GET + +#define DEFINE_PUT(type) \ + static inline void __put_unaligned_##type(type val, void *ptr) \ + { \ + struct __packed { \ + type x; \ + } *__pptr = ptr; \ + __pptr->x = val; \ + } + +DEFINE_PUT(uint8_t); +DEFINE_PUT(uint16_t); +DEFINE_PUT(uint32_t); +DEFINE_PUT(uint64_t); +DEFINE_PUT(int8_t); +DEFINE_PUT(int16_t); +DEFINE_PUT(int32_t); +DEFINE_PUT(int64_t); + +#endif /* APOS_UNALIGNED_H */ diff --git a/include/libfdt.h b/include/libfdt.h index b59d6e4..ffe979d 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -1,6 +1,7 @@ #ifndef APOS_LIBFDT_H #define APOS_LIBFDT_H #include "../dtc/libfdt/libfdt.h" +#include <apos/unaligned.h> #include <apos/types.h> /* apos additions, implementation can be found in common/fdt.c */ @@ -20,7 +21,7 @@ void __dbg_fdt(const void *fdt, int node_offset, int depth); #endif #define fdt_load_int_ptr(c, p) \ - ((c) == 2 ? fdt64_to_cpu(*(fdt64_t *)(p)) : \ - fdt32_to_cpu(*(fdt32_t *)(p))) + ((c) == 2 ? fdt64_to_cpu(get_unaligned((uint64_t *)p)) : \ + fdt32_to_cpu(get_unaligned((uint32_t *)p))) #endif diff --git a/lib/ubsan.c b/lib/ubsan.c new file mode 100644 index 0000000..0a05e2e --- /dev/null +++ b/lib/ubsan.c @@ -0,0 +1,159 @@ +#include <apos/types.h> +#include <apos/debug.h> + +/* mostly lifted from https://github.com/Abb1x/tinyubsan/blob/master/src/tinyubsan.c */ + +struct tu_source_location { + const char *file; + uint32_t line; + uint32_t column; +}; + +struct tu_type_descriptor { + uint16_t kind; + uint16_t info; + char name[]; +}; + +struct tu_overflow_data { + struct tu_source_location location; + struct tu_type_descriptor *type; +}; + +struct tu_shift_out_of_bounds_data { + struct tu_source_location location; + struct tu_type_descriptor *left_type; + struct tu_type_descriptor *right_type; +}; + +struct tu_invalid_value_data { + struct tu_source_location location; + struct tu_type_descriptor *type; +}; + +struct tu_array_out_of_bounds_data { + struct tu_source_location location; + struct tu_type_descriptor *array_type; + struct tu_type_descriptor *index_type; +}; + +struct tu_type_mismatch_v1_data { + struct tu_source_location location; + struct tu_type_descriptor *type; + unsigned char log_alignment; + unsigned char type_check_kind; +}; + +struct tu_negative_vla_data { + struct tu_source_location location; + struct tu_type_descriptor *type; +}; + +struct tu_nonnull_return_data { + struct tu_source_location location; +}; + +struct tu_nonnull_arg_data { + struct tu_source_location location; +}; + +struct tu_unreachable_data { + struct tu_source_location location; +}; + +struct tu_invalid_builtin_data { + struct tu_source_location location; + unsigned char kind; +}; + +static void tu_print_location(const char *message, + struct tu_source_location loc) +{ + bug("ubsan: %s at file %s, line %d, column %d\n", message, loc.file, + loc.line, loc.column); +} + +void __ubsan_handle_add_overflow(struct tu_overflow_data *data) +{ + tu_print_location("addition overflow", data->location); +} + +void __ubsan_handle_sub_overflow(struct tu_overflow_data *data) +{ + tu_print_location("subtraction overflow", data->location); +} + +void __ubsan_handle_mul_overflow(struct tu_overflow_data *data) +{ + tu_print_location("multiplication overflow", data->location); +} + +void __ubsan_handle_divrem_overflow(struct tu_overflow_data *data) +{ + tu_print_location("division overflow", data->location); +} + +void __ubsan_handle_negate_overflow(struct tu_overflow_data *data) +{ + tu_print_location("negation overflow", data->location); +} + +void __ubsan_handle_pointer_overflow(struct tu_overflow_data *data) +{ + tu_print_location("pointer overflow", data->location); +} + +void __ubsan_handle_shift_out_of_bounds(struct tu_shift_out_of_bounds_data *data) +{ + tu_print_location("shift out of bounds", data->location); +} + +void __ubsan_handle_load_invalid_value(struct tu_invalid_value_data *data) +{ + tu_print_location("invalid load value", data->location); +} + +void __ubsan_handle_out_of_bounds(struct tu_array_out_of_bounds_data *data) +{ + tu_print_location("array out of bounds", data->location); +} + +void __ubsan_handle_type_mismatch_v1(struct tu_type_mismatch_v1_data *data, + uintptr_t ptr) +{ + if (!ptr) { + tu_print_location("use of NULL pointer", data->location); + } + + else if (ptr & ((1 << data->log_alignment) - 1)) { + tu_print_location("use of misaligned pointer", data->location); + } else { + tu_print_location("no space for object", data->location); + } +} + +void __ubsan_handle_vla_bound_not_positive(struct tu_negative_vla_data *data) +{ + tu_print_location("variable-length argument is negative", + data->location); +} + +void __ubsan_handle_nonnull_return(struct tu_nonnull_return_data *data) +{ + tu_print_location("non-null return is null", data->location); +} + +void __ubsan_handle_nonnull_arg(struct tu_nonnull_arg_data *data) +{ + tu_print_location("non-null argument is null", data->location); +} + +void __ubsan_handle_builtin_unreachable(struct tu_unreachable_data *data) +{ + tu_print_location("unreachable code reached", data->location); +} + +void __ubsan_handle_invalid_builtin(struct tu_invalid_builtin_data *data) +{ + tu_print_location("invalid builtin", data->location); +} diff --git a/scripts/gen-deps b/scripts/gen-deps index 7c847fb..dc1bd94 100755 --- a/scripts/gen-deps +++ b/scripts/gen-deps @@ -12,19 +12,32 @@ gencommon () { genlink () { gencommon ".ld" - echo " \$(GENLINK) $< | \$(STRIPLINK) | \$(KERN_INFO) > \$@"\ - >> deps.mk; + if [ ${kern} ]; then + echo " \$(GENLINK) $< | \$(STRIPLINK) > \$@" >> deps.mk + else + echo " \$(GENLINK) $< | \$(STRIPLINK) | \$(KERN_INFO) > \$@" >> deps.mk; + fi } genrule () { gencommon "${1}" - echo " \$(COMPILE) -c \$< -o \$@" >> deps.mk + echo " \$(COMPILE) ${flags} -c \$< -o \$@" >> deps.mk echo "${lint}: ${s}" >> deps.mk - echo " \$(LINT) -c \$< -o /dev/null" >> deps.mk + echo " \$(LINT) ${flags} -c \$< -o /dev/null" >> deps.mk } case "${1}" in + --kernel) + kern=1 + flags='$(KERN_FLAGS)' + ;; + --init) + flags='$(INIT_FLAGS)' + ;; +esac + +case "${2}" in --compile) suffix=.o func=genrule @@ -35,9 +48,9 @@ case "${1}" in esac # create all subdirectories -mkdir -p $(echo "${2}" | xargs dirname | uniq | sed 's|^|build/|g') +mkdir -p $(echo "${3}" | xargs dirname | uniq | sed 's|^|build/|g') -for s in ${2} +for s in ${3} do ${func} ${suffix} echo ${obj} |
