summaryrefslogtreecommitdiffstats
path: root/src/boot
diff options
context:
space:
mode:
authorJan Janssen <medhefgo@web.de>2023-03-12 16:51:48 +0100
committerJan Janssen <medhefgo@web.de>2023-03-17 10:39:39 +0100
commit1e7ff4ba8855996c8e077e0546acf9491c97663f (patch)
treec2e50735d33324c8d2ab971f1fad1a49013dc144 /src/boot
parentmeson: Share more C flags (diff)
downloadsystemd-1e7ff4ba8855996c8e077e0546acf9491c97663f.tar.xz
systemd-1e7ff4ba8855996c8e077e0546acf9491c97663f.zip
boot: Add undefined sanitizer support
Sadly, no stack traces, but this is better than nothing.
Diffstat (limited to 'src/boot')
-rw-r--r--src/boot/efi/log.c2
-rw-r--r--src/boot/efi/log.h1
-rw-r--r--src/boot/efi/meson.build18
-rw-r--r--src/boot/efi/ubsan.c46
4 files changed, 62 insertions, 5 deletions
diff --git a/src/boot/efi/log.c b/src/boot/efi/log.c
index 82307516dc..6d0edec2cf 100644
--- a/src/boot/efi/log.c
+++ b/src/boot/efi/log.c
@@ -6,7 +6,7 @@
static unsigned log_count = 0;
-_noreturn_ static void freeze(void) {
+void freeze(void) {
for (;;)
BS->Stall(60 * 1000 * 1000);
}
diff --git a/src/boot/efi/log.h b/src/boot/efi/log.h
index 7b2735d028..973e13c260 100644
--- a/src/boot/efi/log.h
+++ b/src/boot/efi/log.h
@@ -19,6 +19,7 @@ __attribute__((no_stack_protector, noinline)) void __stack_chk_guard_init(void);
# define __stack_chk_guard_init()
#endif
+_noreturn_ void freeze(void);
void log_wait(void);
_gnu_printf_(2, 3) EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...);
#define log_error_status(status, ...) log_internal(status, __VA_ARGS__)
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
index 58bebe446e..e6e7eed3bc 100644
--- a/src/boot/efi/meson.build
+++ b/src/boot/efi/meson.build
@@ -179,17 +179,23 @@ efi_disabled_c_args = cc.get_supported_arguments(
'-fcf-protection=none',
'-fno-asynchronous-unwind-tables',
'-fno-exceptions',
- '-fno-sanitize=all',
'-fno-unwind-tables',
)
-efi_c_args += efi_disabled_c_args
-efi_c_ld_args += efi_disabled_c_args
efi_override_options = [
'b_coverage=false',
'b_pgo=off',
- 'b_sanitize=none',
]
+if get_option('b_sanitize') == 'undefined'
+ efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize-link-runtime')
+else
+ efi_disabled_c_args += cc.get_supported_arguments('-fno-sanitize=all')
+ efi_override_options += 'b_sanitize=none'
+endif
+
+efi_c_args += efi_disabled_c_args
+efi_c_ld_args += efi_disabled_c_args
+
if cc.get_id() == 'clang'
# clang is too picky sometimes.
efi_c_args += '-Wno-unused-command-line-argument'
@@ -252,6 +258,10 @@ stub_sources = files(
'stub.c',
)
+if get_option('b_sanitize') == 'undefined'
+ libefi_sources += files('ubsan.c')
+endif
+
if host_machine.cpu_family() in ['x86', 'x86_64']
stub_sources += files('linux_x86.c')
endif
diff --git a/src/boot/efi/ubsan.c b/src/boot/efi/ubsan.c
new file mode 100644
index 0000000000..951204683e
--- /dev/null
+++ b/src/boot/efi/ubsan.c
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "log.h"
+
+typedef struct {
+ const char *filename;
+ uint32_t line;
+ uint32_t column;
+} SourceLocation;
+
+/* Note that all ubsan handlers have a pointer to a type-specific struct passed as first argument.
+ * Since we do not inspect the extra data in it we can just treat it as a SourceLocation struct
+ * directly to keep things simple. */
+
+#define HANDLER(name, ...) \
+ _used_ _noreturn_ void __ubsan_handle_##name(__VA_ARGS__); \
+ void __ubsan_handle_##name(__VA_ARGS__) { \
+ log_error("systemd-boot: %s in %s@%u:%u", \
+ __func__, \
+ location->filename, \
+ location->line, \
+ location->column); \
+ freeze(); \
+ }
+
+#define UNARY_HANDLER(name) HANDLER(name, SourceLocation *location, uintptr_t v)
+#define BINARY_HANDLER(name) HANDLER(name, SourceLocation *location, uintptr_t v1, uintptr_t v2)
+
+UNARY_HANDLER(load_invalid_value);
+UNARY_HANDLER(negate_overflow);
+UNARY_HANDLER(out_of_bounds);
+UNARY_HANDLER(type_mismatch_v1);
+UNARY_HANDLER(vla_bound_not_positive);
+
+BINARY_HANDLER(add_overflow);
+BINARY_HANDLER(divrem_overflow);
+BINARY_HANDLER(implicit_conversion);
+BINARY_HANDLER(mul_overflow);
+BINARY_HANDLER(pointer_overflow);
+BINARY_HANDLER(shift_out_of_bounds);
+BINARY_HANDLER(sub_overflow);
+
+HANDLER(builtin_unreachable, SourceLocation *location);
+HANDLER(invalid_builtin, SourceLocation *location);
+HANDLER(nonnull_arg, SourceLocation *location);
+HANDLER(nonnull_return_v1, SourceLocation *attr_location, SourceLocation *location);