#include <pthread/private.h>
#if !TARGET_OS_DRIVERKIT
#include <dlfcn.h>
+#include <os/variant_private.h>
#endif
#include <fcntl.h>
#include <errno.h>
void libSystem_atfork_parent(void);
void libSystem_atfork_child(void);
-#if CURRENT_VARIANT_asan
+#if SUPPORT_ASAN
const char *__asan_default_options(void);
#endif
#endif
};
- static const struct _malloc_functions malloc_funcs = {
- .version = 1,
-#if !TARGET_OS_DRIVERKIT
- .dlopen = dlopen,
- .dlsym = dlsym,
-#endif
- };
-
_libSystem_ktrace0(ARIADNE_LIFECYCLE_libsystem_init | DBG_FUNC_START);
__libkernel_init(&libkernel_funcs, envp, apple, vars);
_libxpc_initializer();
_libSystem_ktrace_init_func(LIBXPC);
-#if CURRENT_VARIANT_asan
+#if SUPPORT_ASAN
setenv("DT_BYPASS_LEAKS_CHECK", "1", 1);
#endif
#endif // !TARGET_OS_DRIVERKIT
_libSystem_ktrace_init_func(DARWIN);
#endif // !TARGET_OS_DRIVERKIT
- __stack_logging_early_finished(&malloc_funcs);
+ const struct _malloc_late_init mli = {
+ .version = 1,
+#if !TARGET_OS_DRIVERKIT
+ .dlopen = dlopen,
+ .dlsym = dlsym,
+ // this must come after _libxpc_initializer()
+ .internal_diagnostics = os_variant_has_internal_diagnostics("com.apple.libsystem"),
+#endif
+ };
+
+ __malloc_late_init(&mli);
#if !TARGET_OS_IPHONE
/* <rdar://problem/22139800> - Preserve the old behavior of apple[] for
_pthread_atfork_child_handlers();
}
-#if CURRENT_VARIANT_asan
-#define DEFAULT_ASAN_OPTIONS "color=never" \
- ":handle_segv=0:handle_sigbus=0:handle_sigill=0:handle_sigfpe=0" \
- ":external_symbolizer_path=" \
- ":log_path=stderr:log_exe_name=0" \
- ":halt_on_error=0" \
- ":print_module_map=2" \
- ":start_deactivated=1" \
- ":detect_odr_violation=0"
+#if SUPPORT_ASAN
+
+// Prevents use of coloring terminal signals in report. These
+// hinder readability when writing to files or the system log.
+#define ASAN_OPT_NO_COLOR "color=never"
+
+// Disables ASan's signal handlers. It's better to let the system catch
+// these kinds of crashes.
+#define ASAN_OPT_NO_SIGNAL_HANDLERS ":handle_segv=0:handle_sigbus=0:handle_sigill=0:handle_sigfpe=0"
+
+// Disables using the out-of-process symbolizer (atos) but still allows
+// in-process symbolization via `dladdr()`. This gives useful function names
+// (unless they are redacted) which can be helpful in the event we can't
+// symbolize offline. Out-of-process symbolization isn't useful because
+// the dSYMs are usually not present on the device.
+#define ASAN_OPT_NO_OOP_SYMBOLIZER ":external_symbolizer_path="
+
+// Don't try to log to a file. It's difficult to find a location for the file
+// that is writable so just write to stderr.
+#define ASAN_OPT_FILE_LOG ":log_path=stderr:log_exe_name=0"
+
+// Print the module map when finding an issue. This is necessary for offline
+// symbolication.
+#define ASAN_OPT_MODULE_MAP ":print_module_map=2"
+
+// Disable ODR violation checking.
+// <rdar://problem/71021707> Investigate enabling ODR checking for ASan in BATS and in the `_asan` variant
+#define ASAN_OPT_NO_ODR_VIOLATION ":detect_odr_violation=0"
+
+// Start ASan in deactivated mode. This reduces memory overhead until
+// instrumented code is loaded. This prevents catching bugs if no instrumented
+// code is loaded.
+#define ASAN_OPT_START_DEACTIVATED ":start_deactivated=1"
+
+// Do not crash when an error is found. This always works for errors caught via
+// ASan's interceptors. This won't work for errors caught in ASan
+// instrumentation unless the code is compiled with
+// `-fsanitize-recover=address`. If this option is being used then the ASan
+// reports can only be found by looking at the system log.
+#define ASAN_OPT_NO_HALT_ON_ERROR ":halt_on_error=0"
+
+// Crash when an error is found.
+#define ASAN_OPT_HALT_ON_ERROR ":halt_on_error=1"
+
+// ASan options common to all supported variants
+#define COMMON_ASAN_OPTIONS \
+ ASAN_OPT_NO_COLOR \
+ ASAN_OPT_NO_SIGNAL_HANDLERS \
+ ASAN_OPT_NO_OOP_SYMBOLIZER \
+ ASAN_OPT_FILE_LOG \
+ ASAN_OPT_MODULE_MAP \
+ ASAN_OPT_NO_ODR_VIOLATION
+
+#if defined(CURRENT_VARIANT_normal) || defined(CURRENT_VARIANT_debug) || defined (CURRENT_VARIANT_no_asan)
+
+// In the normal variant ASan will be running in all userspace processes ("whole userspace ASan").
+// This mode exists to support "ASan in BATS".
+//
+// Supporting ASan in the debug variant preserves existing behavior.
+//
+// The no_asan variant does not load the ASan runtime. However, the runtime
+// might still be loaded if a program or its dependencies are instrumented.
+// There is nothing we can do to prevent this so we should set the appropriate
+// ASan options (same as normal variant) if it does happen. We try to do this
+// here but this currently doesn't work due to rdar://problem/72212914.
+//
+// These variants use the following extra options:
+//
+// ASAN_OPT_NO_HALT_ON_ERROR - Try to avoid crash loops and increase the
+// chances of booting successfully.
+// ASAN_OPT_START_DEACTIVATED - Try to reduce memory overhead.
+
+# define DEFAULT_ASAN_OPTIONS \
+ COMMON_ASAN_OPTIONS \
+ ASAN_OPT_START_DEACTIVATED \
+ ASAN_OPT_NO_HALT_ON_ERROR
+
+#elif defined(CURRENT_VARIANT_asan)
+
+// The `_asan` variant is used to support running proceses with
+// `DYLD_IMAGE_SUFFIX=_asan`. This mode is typically used to target select parts of the OS.
+//
+// It uses the following extra options:
+//
+// ASAN_OPT_HALT_ON_ERROR - Crashing is better than just writing the error to the system log
+// if the system can handle this. This workflow is
+// more tolerant (e.g. `launchctl debug`) to crashing
+// than the "whole userspace ASan" workflow.
+
+# define DEFAULT_ASAN_OPTIONS \
+ COMMON_ASAN_OPTIONS \
+ ASAN_OPT_HALT_ON_ERROR
+
+#else
+# error Supporting ASan is not supported in the current variant
+#endif
+
char dynamic_asan_opts[1024] = {0};
const char *__asan_default_options(void) {
- char executable_path[4096] = {0};
- uint32_t size = sizeof(executable_path);
- const char *process_name = "";
- if (_NSGetExecutablePath(executable_path, &size) == 0) {
- process_name = strrchr(executable_path, '/') + 1;
- }
-
int fd = open("/System/Library/Preferences/com.apple.asan.options", O_RDONLY);
if (fd != -1) {
ssize_t remaining_size = sizeof(dynamic_asan_opts) - 1;
return DEFAULT_ASAN_OPTIONS;
}
+
+#undef ASAN_OPT_NO_COLOR
+#undef ASAN_OPT_NO_SIGNAL_HANDLERS
+#undef ASAN_OPT_NO_OOP_SYMBOLIZER
+#undef ASAN_OPT_FILE_LOG
+#undef ASAN_OPT_MODULE_MAP
+#undef ASAN_OPT_NO_ODR_VIOLATION
+#undef ASAN_OPT_START_DEACTIVATED
+#undef ASAN_OPT_NO_HALT_ON_ERROR
+#undef ASAN_OPT_HALT_ON_ERROR
+
+#undef COMMON_ASAN_OPTIONS
+#undef DEFAULT_ASAN_OPTIONS
+
#endif
/*