/* * @author xamidev * @brief Undefined behavior sanitization hooks * @license GPL-3.0-only */ #include #include #include #include /* * Hooks were inspired from the Sortix implementation: * https://gitlab.com/sortix/sortix/-/blob/main/libc/ubsan/ubsan.c * * Not all hooks are implemented here. */ extern struct init_status init; /* * __ubsan_handle_type_mismatch_v1 - Hook for UBSan * @data_raw: pointer to error data * @pointer_raw: faulty pointer * * This function is executed when the UBSan library detects * following undefined behavior: type mismatch, null pointer * access, and unaligned access. It halts the system and * gives the location of the code that triggered it. */ void __ubsan_handle_type_mismatch_v1(void* data_raw, void* pointer_raw) { struct ubsan_type_mismatch_v1_data* data = (struct ubsan_type_mismatch_v1_data*) data_raw; uintptr_t pointer = (uintptr_t)pointer_raw; uintptr_t alignment = (uintptr_t)1UL << data->log_alignment; const char* violation = "type mismatch"; if ( !pointer ) { violation = "null pointer access"; } else if ( alignment && (pointer & (alignment - 1)) ) { violation = "unaligned access"; } struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: %s (ptr=%p) at %s:%u:%u\x1b[0m", violation, pointer, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: %s (ptr=%p) at %s:%u:%u\x1b[0m\r\n", violation, pointer, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error"); } /* * __ubsan_handle_pointer_overflow - Hook for UBSan * @data_raw: pointer to error data * @base_raw: base pointer * @result_raw: pointer after faulty operation * * This function is executed when the UBSan library detects * following undefined behavior: pointer overflow. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_pointer_overflow(void* data_raw, void* base_raw, void* result_raw) { struct ubsan_pointer_overflow_data* data = (struct ubsan_pointer_overflow_data*) data_raw; uintptr_t base = (uintptr_t)base_raw; uintptr_t result = (uintptr_t)result_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: pointer overflow (base=%p, result=%p) at %s:%u:%u\x1b[0m", base, result, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: pointer overflow (base=%p, result=%p) at %s:%u:%u\x1b[0m", base, result, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: pointer overflow"); } /* * __ubsan_handle_shift_out_of_bounds - Hook for UBSan * @data_raw: pointer to error data * @lhs_raw: left hand side (value being shifted) * @rhs_raw: right hand side (shift amount) * * This function is executed when the UBSan library detects * following undefined behavior: shift out of bounds. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_shift_out_of_bounds(void* data_raw, void* lhs_raw, void* rhs_raw) { struct ubsan_shift_out_of_bounds_data* data = (struct ubsan_shift_out_of_bounds_data*) data_raw; uintptr_t lhs = (uintptr_t) lhs_raw; uintptr_t rhs = (uintptr_t) rhs_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: shift out of bounds (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: shift out of bounds (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: shift out of bounds"); } /* * __ubsan_handle_load_invalid_value - Hook for UBSan * @data_raw: pointer to error data * @value_raw: value loaded * * This function is executed when the UBSan library detects * following undefined behavior: invalid value load. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_load_invalid_value(void* data_raw, void* value_raw) { struct ubsan_invalid_value_data* data = (struct ubsan_invalid_value_data*) data_raw; uintptr_t value = (uintptr_t) value_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: invalid value load (value=%p) at %s:%u:%u\x1b[0m", value, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: invalid value load (value=%p) at %s:%u:%u\x1b[0m", value, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: invalid value load"); } /* * __ubsan_handle_out_of_bounds - Hook for UBSan * @data_raw: pointer to error data * @index_raw: out-of-bounds index in array * * This function is executed when the UBSan library detects * following undefined behavior: access out of bounds. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_out_of_bounds(void* data_raw, void* index_raw) { struct ubsan_out_of_bounds_data* data = (struct ubsan_out_of_bounds_data*) data_raw; uintptr_t index = (uintptr_t) index_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: out of bounds (index=%p) at %s:%u:%u\x1b[0m", index, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: out of bounds (index=%p) at %s:%u:%u\x1b[0m", index, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: out of bounds"); } /* * __ubsan_handle_divrem_overflow - Hook for UBSan * @data_raw: pointer to error data * @lhs_raw: left hand side operator * @rhs_raw: right hand side operator * * This function is executed when the UBSan library detects * following undefined behavior: division remainder overflow. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_divrem_overflow(void* data_raw, void* lhs_raw, void* rhs_raw) { struct ubsan_overflow_data* data = (struct ubsan_overflow_data*) data_raw; uintptr_t lhs = (uintptr_t) lhs_raw; uintptr_t rhs = (uintptr_t) rhs_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: division remainder overflow (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: division remainder overflow (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: division remainder overflow"); } /* * __ubsan_handle_sub_overflow - Hook for UBSan * @data_raw: pointer to error data * @lhs_raw: left hand side operator * @rhs_raw: right hand side operator * * This function is executed when the UBSan library detects * following undefined behavior: subtraction overflow. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_sub_overflow(void* data_raw, void* lhs_raw, void* rhs_raw) { struct ubsan_overflow_data* data = (struct ubsan_overflow_data*) data_raw; uintptr_t lhs = (uintptr_t) lhs_raw; uintptr_t rhs = (uintptr_t) rhs_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: subtraction overflow (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: subtraction overflow (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: subtraction overflow"); } /* * __ubsan_handle_add_overflow - Hook for UBSan * @data_raw: pointer to error data * @lhs_raw: left hand side operator * @rhs_raw: right hand side operator * * This function is executed when the UBSan library detects * following undefined behavior: addition overflow. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_add_overflow(void* data_raw, void* lhs_raw, void* rhs_raw) { struct ubsan_overflow_data* data = (struct ubsan_overflow_data*) data_raw; uintptr_t lhs = (uintptr_t) lhs_raw; uintptr_t rhs = (uintptr_t) rhs_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: addition overflow (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: addition overflow (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: addition overflow"); } /* * __ubsan_handle_mul_overflow - Hook for UBSan * @data_raw: pointer to error data * @lhs_raw: left hand side operator * @rhs_raw: right hand side operator * * This function is executed when the UBSan library detects * following undefined behavior: multiplication overflow. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_mul_overflow(void* data_raw, void* lhs_raw, void* rhs_raw) { struct ubsan_overflow_data* data = (struct ubsan_overflow_data*) data_raw; uintptr_t lhs = (uintptr_t) lhs_raw; uintptr_t rhs = (uintptr_t) rhs_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: multiplication overflow (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: multiplication overflow (lhs=%p, rhs=%p) at %s:%u:%u\x1b[0m", lhs, rhs, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: multiplication overflow"); } /* * __ubsan_handle_negate_overflow - Hook for UBSan * @data_raw: pointer to error data * @old_value_raw: value before overflow * * This function is executed when the UBSan library detects * following undefined behavior: negation overflow. * It halts the system and gives the location of the code * that triggered it. */ void __ubsan_handle_negate_overflow(void* data_raw, void* old_value_raw) { struct ubsan_overflow_data* data = (struct ubsan_overflow_data*) data_raw; uintptr_t old_value = (uintptr_t) old_value_raw; struct ubsan_source_location* loc = &data->location; DEBUG("\x1b[38;5;231mUBSan: negation overflow (old_value=%p) at %s:%u:%u\x1b[0m", old_value, loc->filename, loc->line, loc->column); if (init.all) { printf("\x1b[38;5;231mUBSan: negation overflow (old_value=%p) at %s:%u:%u\x1b[0m", old_value, loc->filename, loc->line, loc->column); } panic(NULL, "Undefined Behavior Sanitization error: negation overflow"); }