[build] Support AddressSanitizer userland build with USE_ASAN=true
ASan builds by default go in build-$PROJECT-asan/. The buildall and run-magenta scripts do ASan builds with the -A switch. Code that is incompatible with sanitizer builds adds $(NO_SANITIZERS) to MODULE_COMPILEFLAGS. Everything else in userland gets built with ASan. Using USE_ASAN=true requires a Clang toolchain with the ASan runtime shared library, which will not land for a while yet. MG-71 # Enabled all-or-nothing USE_ASAN build switch for Magenta standalone. Change-Id: Ifc0628934c19affcb909b20f3cfdcc86ee54c2f9
Esse commit está contido em:
commit de
CQ bot account: commit-bot@chromium.org
pai
29127ca3b4
commit
e379d8860e
+44
-3
@@ -24,7 +24,8 @@ ENABLE_BUILD_LISTFILES := $(call TOBOOL,$(ENABLE_BUILD_LISTFILES))
|
||||
ENABLE_BUILD_SYSROOT := $(call TOBOOL,$(ENABLE_BUILD_SYSROOT))
|
||||
ENABLE_NEW_FB := true
|
||||
ENABLE_ACPI_BUS ?= false
|
||||
USE_CLANG ?= false
|
||||
USE_ASAN ?= false
|
||||
USE_CLANG ?= $(USE_ASAN)
|
||||
USE_LLD ?= $(USE_CLANG)
|
||||
ifeq ($(call TOBOOL,$(USE_LLD)),true)
|
||||
USE_GOLD := false
|
||||
@@ -39,7 +40,6 @@ LKNAME ?= magenta
|
||||
CLANG_TARGET_FUCHSIA ?= false
|
||||
USE_LINKER_GC ?= true
|
||||
|
||||
|
||||
# If no build directory suffix has been explicitly supplied by the environment,
|
||||
# generate a default based on build options. Start with no suffix, then add
|
||||
# "-clang" if we are building with clang, and "-release" if we are building with
|
||||
@@ -47,7 +47,9 @@ USE_LINKER_GC ?= true
|
||||
ifeq ($(origin BUILDDIR_SUFFIX),undefined)
|
||||
BUILDDIR_SUFFIX :=
|
||||
|
||||
ifeq ($(call TOBOOL,$(USE_CLANG)),true)
|
||||
ifeq ($(call TOBOOL,$(USE_ASAN)),true)
|
||||
BUILDDIR_SUFFIX := $(BUILDDIR_SUFFIX)-asan
|
||||
else ifeq ($(call TOBOOL,$(USE_CLANG)),true)
|
||||
BUILDDIR_SUFFIX := $(BUILDDIR_SUFFIX)-clang
|
||||
endif
|
||||
|
||||
@@ -187,9 +189,11 @@ endif
|
||||
ifeq ($(call TOBOOL,$(USE_CLANG)),true)
|
||||
SAFESTACK := -fsanitize=safe-stack -fstack-protector-strong
|
||||
NO_SAFESTACK := -fno-sanitize=safe-stack -fno-stack-protector
|
||||
NO_SANITIZERS := -fno-sanitize=all -fno-stack-protector
|
||||
else
|
||||
SAFESTACK :=
|
||||
NO_SAFESTACK :=
|
||||
NO_SANITIZERS :=
|
||||
endif
|
||||
|
||||
USER_COMPILEFLAGS += $(SAFESTACK)
|
||||
@@ -205,6 +209,11 @@ USERLIB_SO_LDFLAGS := $(USER_LDFLAGS) -z defs
|
||||
# absolute pathname as is used for this on other systems.
|
||||
USER_SHARED_INTERP := ld.so.1
|
||||
|
||||
# Programs built with ASan use the ASan-supporting dynamic linker.
|
||||
ifeq ($(call TOBOOL,$(USE_ASAN)),true)
|
||||
USER_SHARED_INTERP := asan/$(USER_SHARED_INTERP)
|
||||
endif
|
||||
|
||||
# Additional flags for building dynamically-linked executables.
|
||||
USERAPP_LDFLAGS := \
|
||||
$(USER_LDFLAGS) -pie -dynamic-linker $(USER_SHARED_INTERP)
|
||||
@@ -381,6 +390,38 @@ ifeq ($(call TOBOOL,$(USE_CLANG)),true)
|
||||
GLOBAL_COMPILEFLAGS += --target=$(CLANG_ARCH)-fuchsia
|
||||
endif
|
||||
|
||||
ifeq ($(call TOBOOL,$(USE_ASAN)),true)
|
||||
ifeq ($(call TOBOOL,$(USE_CLANG)),false)
|
||||
$(error USE_ASAN requires USE_CLANG)
|
||||
endif
|
||||
|
||||
# Compile all of userland with ASan. ASan makes safe-stack superfluous
|
||||
# and ASan reporting doesn't really grok safe-stack, so disable it.
|
||||
# Individual modules can append $(NO_SANITIZERS) to counteract this.
|
||||
USER_COMPILEFLAGS += -fsanitize=address -fno-sanitize=safe-stack
|
||||
|
||||
# Ask the Clang driver where the library with SONAME $1 is found at link time.
|
||||
find-clang-solib = \
|
||||
$(shell $(CLANG_TOOLCHAIN_PREFIX)clang $(GLOBAL_COMPILEFLAGS) \
|
||||
-print-file-name=$1)
|
||||
|
||||
# Every userland executable and shared library compiled with ASan
|
||||
# needs to link with $(ASAN_SOLIB). module-user{app,lib}.mk adds it
|
||||
# to MODULE_EXTRA_OBJS so the linking target will depend on it.
|
||||
ASAN_SONAME := libclang_rt.asan-$(CLANG_ARCH).so
|
||||
# TODO(TO-376): It shouldn't need the lib/fuchsia/ prefix here, but it does.
|
||||
ASAN_SOLIB := $(call find-clang-solib,lib/fuchsia/$(ASAN_SONAME))
|
||||
USER_MANIFEST_LINES += lib/$(ASAN_SONAME)=$(ASAN_SOLIB)
|
||||
|
||||
# The ASan runtime DSO depends on more DSOs from the toolchain. We don't
|
||||
# link against those, so we don't need any build-time dependencies on them.
|
||||
# But we need them alongside the ASan runtime DSO in the bootfs.
|
||||
ASAN_RUNTIME_SONAMES := libc++abi.so.1 libunwind.so.1
|
||||
USER_MANIFEST_LINES += \
|
||||
$(foreach soname,$(ASAN_RUNTIME_SONAMES),\
|
||||
lib/$(soname)=$(call find-clang-solib,$(soname)))
|
||||
endif
|
||||
|
||||
# recursively include any modules in the MODULE variable, leaving a trail of included
|
||||
# modules in the ALLMODULES list
|
||||
include make/recurse.mk
|
||||
|
||||
@@ -34,6 +34,11 @@ MODULE_SOLIBS := $(foreach lib,$(MODULE_LIBS),$(call TOBUILDDIR,$(lib))/lib$(not
|
||||
# Include this in every link.
|
||||
MODULE_EXTRA_OBJS += scripts/dso_handle.ld
|
||||
|
||||
# Link the ASan runtime into everything compiled with ASan.
|
||||
ifeq (,$(filter -fno-sanitize=all,$(MODULE_COMPILEFLAGS)))
|
||||
MODULE_EXTRA_OBJS += $(ASAN_SOLIB)
|
||||
endif
|
||||
|
||||
$(MODULE_USERAPP_OBJECT): _OBJS := $(USER_CRT1_OBJ) $(MODULE_OBJS) $(MODULE_EXTRA_OBJS)
|
||||
$(MODULE_USERAPP_OBJECT): _LIBS := $(MODULE_ALIBS) $(MODULE_SOLIBS)
|
||||
$(MODULE_USERAPP_OBJECT): _LDFLAGS := $(MODULE_LDFLAGS) $(USERAPP_LDFLAGS)
|
||||
|
||||
@@ -37,6 +37,11 @@ MODULE_SOLIBS := $(foreach lib,$(MODULE_LIBS),$(call TOBUILDDIR,$(lib))/lib$(not
|
||||
# Include this in every link.
|
||||
MODULE_EXTRA_OBJS += scripts/dso_handle.ld
|
||||
|
||||
# Link the ASan runtime into everything compiled with ASan.
|
||||
ifeq (,$(filter -fno-sanitize=all,$(MODULE_COMPILEFLAGS)))
|
||||
MODULE_EXTRA_OBJS += $(ASAN_SOLIB)
|
||||
endif
|
||||
|
||||
$(MODULE_LIBNAME).so: _OBJS := $(MODULE_OBJS) $(MODULE_EXTRA_OBJS)
|
||||
$(MODULE_LIBNAME).so: _LIBS := $(MODULE_ALIBS) $(MODULE_SOLIBS)
|
||||
$(MODULE_LIBNAME).so: _SONAME := lib$(MODULE_SO_NAME).so
|
||||
@@ -110,7 +115,12 @@ GENERATED += \
|
||||
endif
|
||||
|
||||
ifeq ($(MODULE_SO_INSTALL_NAME),)
|
||||
MODULE_SO_INSTALL_NAME := lib/lib$(MODULE_SO_NAME).so
|
||||
MODULE_SO_INSTALL_NAME := lib$(MODULE_SO_NAME).so
|
||||
# At runtime, ASan-supporting libraries are found in lib/asan/ first.
|
||||
ifeq ($(call TOBOOL,$(USE_ASAN)),true)
|
||||
MODULE_SO_INSTALL_NAME := asan/$(MODULE_SO_INSTALL_NAME)
|
||||
endif
|
||||
MODULE_SO_INSTALL_NAME := lib/$(MODULE_SO_INSTALL_NAME)
|
||||
endif
|
||||
ifneq ($(MODULE_SO_INSTALL_NAME),-)
|
||||
USER_MANIFEST_LINES += $(MODULE_SO_INSTALL_NAME)=$(MODULE_LIBNAME).so.strip
|
||||
|
||||
+16
-1
@@ -14,6 +14,7 @@ function HELP {
|
||||
echo "-m : Build magenta targets only"
|
||||
echo "-r : Also build release mode builds"
|
||||
echo "-c : Also build with clang"
|
||||
echo "-A : Also build with ASan"
|
||||
echo "-q : Build quietly"
|
||||
echo "-h for help"
|
||||
exit 1
|
||||
@@ -22,12 +23,14 @@ function HELP {
|
||||
FAIL_FAST=0
|
||||
DO_RELEASE=0
|
||||
DO_CLANG=0
|
||||
DO_ASAN=0
|
||||
MAGENTA_ONLY=0
|
||||
MAKE_ARGS=
|
||||
QUIET=0
|
||||
|
||||
while getopts a:fhmrcq FLAG; do
|
||||
while getopts Aa:fhmrcq FLAG; do
|
||||
case $FLAG in
|
||||
A) DO_ASAN=1;;
|
||||
a) MAKE_ARGS="${MAKE_ARGS} ${OPTARG}";;
|
||||
f) FAIL_FAST=1;;
|
||||
h) HELP;;
|
||||
@@ -77,6 +80,18 @@ for p in $PROJECTS; do
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DO_ASAN" -eq 1 ]; then
|
||||
echo building $p with ASan
|
||||
nice $DIR/make-parallel $p ${MAKE_ARGS} USE_ASAN=true
|
||||
STATUS=$?
|
||||
if [ "$STATUS" -ne 0 ]; then
|
||||
FAILED="$FAILED $p-asan"
|
||||
if [ "$FAIL_FAST" -eq 1 ]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DO_RELEASE" -eq 1 ]; then
|
||||
echo building $p with release
|
||||
nice $DIR/make-release $p ${MAKE_ARGS}
|
||||
|
||||
@@ -12,6 +12,7 @@ function HELP {
|
||||
echo "-b : build first"
|
||||
echo "-c <text> : add item to kernel commandline"
|
||||
echo "-C : use Clang build"
|
||||
echo "-A : use ASan build"
|
||||
echo "-d : run with emulated disk"
|
||||
echo "-D <disk file|device>: specify disk file or device path on host, default is blk.bin"
|
||||
echo "--disktype[=<type>] : should be one of (ahci, virtio, nvme), default is ahci"
|
||||
@@ -40,6 +41,7 @@ function HELP {
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
ARCH=
|
||||
ASAN=0
|
||||
AUDIO=
|
||||
AUDIO_WAVFILE="/tmp/qemu.wav"
|
||||
BUILD=0
|
||||
@@ -68,8 +70,9 @@ else
|
||||
IFNAME="qemu"
|
||||
fi
|
||||
|
||||
while getopts "a:bc:CdD:gI:km:nNo:q:rs:u:Vx:h-:" FLAG; do
|
||||
while getopts "Aa:bc:CdD:gI:km:nNo:q:rs:u:Vx:h-:" FLAG; do
|
||||
case $FLAG in
|
||||
A) ASAN=1;;
|
||||
a) ARCH=$OPTARG;;
|
||||
b) BUILD=1;;
|
||||
c) CMDLINE+="$OPTARG ";;
|
||||
@@ -126,7 +129,10 @@ fi
|
||||
BUILDDIR_SUFFIX=
|
||||
BUILD_ARGS=
|
||||
|
||||
if (( $CLANG )); then
|
||||
if (( $ASAN )); then
|
||||
BUILDDIR_SUFFIX+=-asan
|
||||
BUILD_ARGS=USE_ASAN=true
|
||||
elif (( $CLANG )); then
|
||||
BUILDDIR_SUFFIX+=-clang
|
||||
BUILD_ARGS+=USE_CLANG=true
|
||||
fi
|
||||
|
||||
@@ -38,7 +38,7 @@ MODULE_COMPILEFLAGS += -Ithird_party/ulib/musl/src/internal
|
||||
MODULE_COMPILEFLAGS += -fvisibility=hidden
|
||||
|
||||
# We don't have normal setup, so safe-stack is a non-starter.
|
||||
MODULE_COMPILEFLAGS += $(NO_SAFESTACK)
|
||||
MODULE_COMPILEFLAGS += $(NO_SAFESTACK) $(NO_SANITIZERS)
|
||||
|
||||
# system/ulib/runtime is compiled without safe-stack. We can't use any other
|
||||
# static libs, because they might be built with safe-stack or other
|
||||
|
||||
@@ -9,7 +9,7 @@ MODULE := $(LOCAL_DIR)
|
||||
MODULE_TYPE := userlib
|
||||
|
||||
# This library should not depend on libc.
|
||||
MODULE_COMPILEFLAGS := -ffreestanding $(NO_SAFESTACK)
|
||||
MODULE_COMPILEFLAGS := -ffreestanding $(NO_SAFESTACK) $(NO_SANITIZERS)
|
||||
|
||||
MODULE_HEADER_DEPS := kernel/lib/vdso
|
||||
|
||||
|
||||
@@ -59,7 +59,11 @@ static mx_status_t write_ctx_message(
|
||||
// This function is the entire program that the child process will execute. It
|
||||
// gets directly mapped into the child process via mx_vmo_write() so it must not
|
||||
// reference any addressable entity outside it.
|
||||
__NO_SAFESTACK static void minipr_thread_loop(mx_handle_t channel, uintptr_t fnptr) {
|
||||
__NO_SAFESTACK
|
||||
#ifdef __clang__
|
||||
__attribute__((no_sanitize("all")))
|
||||
#endif
|
||||
static void minipr_thread_loop(mx_handle_t channel, uintptr_t fnptr) {
|
||||
if (fnptr == 0) {
|
||||
// In this mode we don't have a VDSO so we don't care what the handle is
|
||||
// and therefore we busy-loop. Unless external steps are taken this will
|
||||
|
||||
@@ -22,6 +22,6 @@ MODULE_HEADER_DEPS += \
|
||||
system/ulib/c
|
||||
|
||||
# This code is used in early startup, where safe-stack setup is not ready yet.
|
||||
MODULE_COMPILEFLAGS += $(NO_SAFESTACK)
|
||||
MODULE_COMPILEFLAGS += $(NO_SAFESTACK) $(NO_SANITIZERS)
|
||||
|
||||
include make/module.mk
|
||||
|
||||
@@ -11,7 +11,7 @@ MODULE_TYPE := userlib
|
||||
# This whole module is a hack to deal with these functions needing to be compiled with
|
||||
# -fno-stack-protector
|
||||
MODULE_SRCS += $(LOCAL_DIR)/threads.c
|
||||
MODULE_COMPILEFLAGS += $(NO_SAFESTACK)
|
||||
MODULE_COMPILEFLAGS += $(NO_SAFESTACK) $(NO_SANITIZERS)
|
||||
|
||||
MODULE_NAME := threads-test-threads
|
||||
|
||||
|
||||
@@ -102,7 +102,12 @@ bool thread_injection_test(void) {
|
||||
}
|
||||
|
||||
BEGIN_TEST_CASE(thread_injection_tests)
|
||||
// This test is incompatible with ASan, because both the original
|
||||
// dynamic linker and the injected one would try to set up shadow
|
||||
// memory in the same place.
|
||||
#if !__has_feature(address_sanitizer)
|
||||
RUN_TEST(thread_injection_test)
|
||||
#endif
|
||||
END_TEST_CASE(thread_injection_tests)
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário