[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [UNIKRAFT PATCH 1/1] Add Undefined Behavior Sanitizer Library
This patch adds an internal library that implements the functions needed by UBSAN. The flag can either be enabled globally by enabling the LIBUBSAN_GLOBAL config option or manually by adding the -fsanitize=undefined flag. UBSAN can catch runtime bugs such as dereferencing NULL or non-canonical addresses, certain undefined overflow errors, shifting or multiplying data which is out of bounds, and other errors. For example, ubsan will catch the following addition overflow: int k = 0x7fffffff; k += 127; Signed-off-by: Vlad-Andrei Badoiu <vlad_andrei.badoiu@xxxxxx> --- lib/Makefile.uk | 1 + lib/ubsan/Config.uk | 14 ++ lib/ubsan/Makefile.uk | 5 + lib/ubsan/exportsyms.uk | 19 +++ lib/ubsan/ubsan.c | 321 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 360 insertions(+) create mode 100644 lib/ubsan/Config.uk create mode 100644 lib/ubsan/Makefile.uk create mode 100644 lib/ubsan/exportsyms.uk create mode 100644 lib/ubsan/ubsan.c diff --git a/lib/Makefile.uk b/lib/Makefile.uk index 07e8a29..e9fc205 100644 --- a/lib/Makefile.uk +++ b/lib/Makefile.uk @@ -37,3 +37,4 @@ $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/ukmmap)) $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/ukblkdev)) $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/posix-process)) $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/uksp)) +$(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/ubsan)) diff --git a/lib/ubsan/Config.uk b/lib/ubsan/Config.uk new file mode 100644 index 0000000..92239a0 --- /dev/null +++ b/lib/ubsan/Config.uk @@ -0,0 +1,14 @@ +menuconfig LIBUBSAN + bool "ubsan: Undefined Behavior Sanitization" + default n + +if LIBUBSAN + +config LIBUBSAN_GLOBAL + bool "Global undefined sanitization" + default n + help +| | Enable undefined behavior sanitization globally. + +endif + diff --git a/lib/ubsan/Makefile.uk b/lib/ubsan/Makefile.uk new file mode 100644 index 0000000..ffbb2e9 --- /dev/null +++ b/lib/ubsan/Makefile.uk @@ -0,0 +1,5 @@ +$(eval $(call addlib_s,libubsan,$(CONFIG_LIBUBSAN))) + +COMPFLAGS-$(CONFIG_LIBUBSAN_GLOBAL) += -fsanitize=undefined + +LIBUBSAN_SRCS-y += $(LIBUBSAN_BASE)/ubsan.c diff --git a/lib/ubsan/exportsyms.uk b/lib/ubsan/exportsyms.uk new file mode 100644 index 0000000..50f6165 --- /dev/null +++ b/lib/ubsan/exportsyms.uk @@ -0,0 +1,19 @@ +__ubsan_handle_type_mismatch +__ubsan_handle_type_mismatch_v1 +__ubsan_handle_mul_overflow +__ubsan_handle_sub_overflow +__ubsan_handle_pointer_overflow +__ubsan_handle_add_overflow +__ubsan_handle_negate_overflow +__ubsan_handle_out_of_bounds +__ubsan_handle_shift_out_of_bounds +__ubsan_handle_nonnull_arg +__ubsan_handle_divrem_overflow +__ubsan_handle_vla_bound_not_positive +__ubsan_handle_load_invalid_value +__ubsan_handle_cfi_bad_icall +__ubsan_handle_nonnull_return +__ubsan_handle_function_type_mismatch +__ubsan_handle_float_cast_overflow +__ubsan_handle_builtin_unreachable +__ubsan_handle_missing_return diff --git a/lib/ubsan/ubsan.c b/lib/ubsan/ubsan.c new file mode 100644 index 0000000..fa8feac --- /dev/null +++ b/lib/ubsan/ubsan.c @@ -0,0 +1,321 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Vlad-Andrei Badoiu <vlad_andrei.badoiu@xxxxxx> + * + * Copyright (c) 2020, University Politehnica of Bucharest. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <stdint.h> +#include <uk/assert.h> + +struct source_location { + const char *filename; + uint32_t line; + uint32_t column; +}; + +struct type_descriptor { + uint16_t kind; + uint16_t info; + char name[]; +}; + +struct out_of_bounds_info { + struct source_location location; + struct type_descriptor left_type; + struct type_descriptor right_type; +}; + +struct type_mismatch_info { + struct source_location location; + struct type_descriptor *type; + uintptr_t alignment; + uint8_t type_check_kind; +}; + +static const struct source_location unknown_location = { + + "<unknown file>", + 0, + 0, +}; + +typedef uintptr_t ubsan_value_handle_t; + +static void ubsan_log_location(const struct source_location *location, + const char *violation) __noreturn; + +static void ubsan_log_location(const struct source_location *location, + const char *violation) +{ + if (!location || !location->filename) + location = &unknown_location; + + UK_CRASH("Undefined behavior at %s:%d:%d:%s", + location->filename, location->line, + location->column, violation); +} + +void __ubsan_handle_type_mismatch(void *data_raw, + void *pointer_raw) +{ + struct type_mismatch_info *data = + (struct type_mismatch_info *) data_raw; + ubsan_value_handle_t pointer = (ubsan_value_handle_t) pointer_raw; + const char *violation = "type mismatch"; + + if (!pointer) + violation = "null pointer access"; + else if (data->alignment && (pointer & (data->alignment - 1))) + violation = "unaligned access"; + + ubsan_log_location(&data->location, violation); +} + +void __ubsan_handle_type_mismatch_v1(void *data_raw, + void *pointer_raw) +{ + __ubsan_handle_type_mismatch(data_raw, pointer_raw); +} + +struct ubsan_overflow_data { + struct source_location location; + struct type_descriptor *type; +}; + +void __ubsan_handle_mul_overflow(void *data_raw, + void *lhs_raw __unused, + void *rhs_raw __unused) +{ + struct ubsan_overflow_data *data = + (struct ubsan_overflow_data *) data_raw; + + ubsan_log_location(&data->location, "multiplication overflow"); +} + +void __ubsan_handle_pointer_overflow(void *data_raw, + void *base __unused, + void *result __unused) +{ + struct ubsan_overflow_data *data = + (struct ubsan_overflow_data *) data_raw; + + ubsan_log_location(&data->location, "pointer overflow"); +} + +void __ubsan_handle_sub_overflow(void *data_raw, + void *lhs_raw __unused, + void *rhs_raw __unused) +{ + struct ubsan_overflow_data *data = + (struct ubsan_overflow_data *) data_raw; + + ubsan_log_location(&data->location, "subtraction overflow"); +} + +void __ubsan_handle_add_overflow(void *data_raw, + void *lhs_raw __unused, + void *rhs_raw __unused) +{ + struct ubsan_overflow_data *data = + (struct ubsan_overflow_data *) data_raw; + + ubsan_log_location(&data->location, "addition overflow"); +} + +void __ubsan_handle_negate_overflow(void *data_raw, + void *old_value_raw __unused) +{ + struct ubsan_overflow_data *data = + (struct ubsan_overflow_data *) data_raw; + + ubsan_log_location(&data->location, "negation overflow"); +} + +void __ubsan_handle_divrem_overflow(void *data_raw, + void *lhs_raw __unused, + void *rhs_raw __unused) +{ + struct ubsan_overflow_data *data = + (struct ubsan_overflow_data *) data_raw; + + ubsan_log_location(&data->location, "division remainder overflow"); +} + + +struct ubsan_out_of_bounds_data { + struct source_location location; + struct type_descriptor *array_type; + struct type_descriptor *index_type; +}; + +void __ubsan_handle_out_of_bounds(void *data_raw, + void *index_raw __unused) +{ + struct ubsan_out_of_bounds_data *data = + (struct ubsan_out_of_bounds_data *) data_raw; + + ubsan_log_location(&data->location, "out of bounds"); +} + +struct ubsan_shift_out_of_bounds_data { + struct source_location location; + struct type_descriptor *lhs_type; + struct type_descriptor *rhs_type; +}; + +void __ubsan_handle_shift_out_of_bounds(void *data_raw, + void *lhs_raw __unused, + void *rhs_raw __unused) +{ + struct ubsan_shift_out_of_bounds_data *data = + (struct ubsan_shift_out_of_bounds_data *) data_raw; + + ubsan_log_location(&data->location, "shift out of bounds"); +} + +struct ubsan_nonnull_arg_data { + struct source_location location; + struct source_location attr_location; +}; + +void __ubsan_handle_nonnull_arg(void *data_raw) +{ + struct ubsan_nonnull_arg_data *data = + (struct ubsan_nonnull_arg_data *) data_raw; + + ubsan_log_location(&data->location, "null argument"); +} + +struct ubsan_vla_bound_data { + struct source_location location; + struct type_descriptor *type; +}; + +void __ubsan_handle_vla_bound_not_positive(void *data_raw, + void *bound_raw __unused) +{ + struct ubsan_vla_bound_data *data = + (struct ubsan_vla_bound_data *) data_raw; + + ubsan_log_location(&data->location, "negative variable array length"); +} + +struct ubsan_invalid_value_data { + struct source_location location; + struct type_descriptor *type; +}; + +void __ubsan_handle_load_invalid_value(void *data_raw, + void *value_raw __unused) +{ + struct ubsan_invalid_value_data *data = + (struct ubsan_invalid_value_data *) data_raw; + + ubsan_log_location(&data->location, "invalid value load"); +} + +struct ubsan_cfi_bad_icall_data { + struct source_location location; + struct type_descriptor *type; +}; + +void __ubsan_handle_cfi_bad_icall(void *data_raw, + void *value_raw __unused) +{ + struct ubsan_cfi_bad_icall_data *data = + (struct ubsan_cfi_bad_icall_data *) data_raw; + + ubsan_log_location(&data->location, + "control flow integrity check failure during indirect call"); +} + +struct ubsan_nonnull_return_data { + struct source_location location; + struct source_location attr_location; +}; + +void __ubsan_handle_nonnull_return(void *data_raw) +{ + struct ubsan_nonnull_return_data *data = + (struct ubsan_nonnull_return_data *) data_raw; + + ubsan_log_location(&data->location, "null return"); +} + +struct ubsan_function_type_mismatch_data { + struct source_location location; + struct type_descriptor *type; +}; + +void __ubsan_handle_function_type_mismatch(void *data_raw, + void *value_raw __unused) +{ + struct ubsan_function_type_mismatch_data *data = + (struct ubsan_function_type_mismatch_data *) data_raw; + + ubsan_log_location(&data->location, "function type mismatch"); +} + +struct ubsan_float_cast_overflow_data { + struct source_location location; + struct type_descriptor *from_type; + struct type_descriptor *to_type; +}; + +void __ubsan_handle_float_cast_overflow(void *data_raw, + void *from_raw __unused) +{ + struct ubsan_float_cast_overflow_data *data = + (struct ubsan_float_cast_overflow_data *) data_raw; + + ubsan_log_location(&data->location, "float cast overflow"); +} + +struct ubsan_unreachable_data { + struct source_location location; +}; + +void __ubsan_handle_builtin_unreachable(void *data_raw) +{ + struct ubsan_unreachable_data *data = + (struct ubsan_unreachable_data *) data_raw; + + ubsan_log_location(&data->location, "reached unreachable"); +} + +void __ubsan_handle_missing_return(void *data_raw) __noreturn; + +void __ubsan_handle_missing_return(void *data_raw) +{ + struct ubsan_unreachable_data *data = + (struct ubsan_unreachable_data *) data_raw; + + ubsan_log_location(&data->location, "missing return"); +} -- 2.27.0
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |