diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -47,6 +47,8 @@ mark_as_advanced(COMPILER_RT_BUILD_XRAY_NO_PREINIT) option(COMPILER_RT_BUILD_ORC "Build ORC runtime" ON) mark_as_advanced(COMPILER_RT_BUILD_ORC) +option(COMPILER_RT_BUILD_GWP_ASAN "Build GWP-ASan, and link it into SCUDO" ON) +mark_as_advanced(COMPILER_RT_BUILD_GWP_ASAN) set(COMPILER_RT_ASAN_SHADOW_SCALE "" CACHE STRING "Override the shadow scale to be used in ASan runtime") diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake new file mode 100644 --- /dev/null +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -0,0 +1,75 @@ +set(ARM64 aarch64) +set(ARM32 arm armhf) +set(HEXAGON hexagon) +set(X86 i386) +set(X86_64 x86_64) +set(MIPS32 mips mipsel) +set(MIPS64 mips64 mips64el) +set(PPC32 powerpc) +set(PPC64 powerpc64 powerpc64le) +set(RISCV32 riscv32) +set(RISCV64 riscv64) +set(S390X s390x) +set(SPARC sparc) +set(SPARCV9 sparcv9) +set(WASM32 wasm32) +set(WASM64 wasm64) +set(VE ve) + +if(APPLE) + set(ARM64 arm64) + set(ARM32 armv7 armv7s armv7k) + set(X86_64 x86_64 x86_64h) +endif() + +set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64} + ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) +set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} + ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) +set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV32} ${RISCV64} ${VE}) +set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) + +if(ANDROID) + set(OS_NAME "Android") +else() + set(OS_NAME "${CMAKE_SYSTEM_NAME}") +endif() + +if(OS_NAME MATCHES "Linux") + set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${S390X}) +elseif (OS_NAME MATCHES "Windows") + set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64}) +elseif(OS_NAME MATCHES "Android") + set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) +else() + set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64}) +endif() + +set(ALL_GWP_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) +if(APPLE) + set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64}) +else() + set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64} ${S390X} ${RISCV64}) +endif() +set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) +set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64}) +set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) +set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} + ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) +set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) +set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} + ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) +set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}) +set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64}) +set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64}) +set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64}) +if(APPLE) +set(ALL_XRAY_SUPPORTED_ARCH ${X86_64}) +else() +set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le) +endif() +set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64}) + +if (UNIX) +set(ALL_ORC_SUPPORTED_ARCH ${X86_64}) +endif() diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -271,81 +271,7 @@ set(${is_valid_out} ${is_valid} PARENT_SCOPE) endfunction() -set(ARM64 aarch64) -set(ARM32 arm armhf) -set(HEXAGON hexagon) -set(X86 i386) -set(X86_64 x86_64) -set(MIPS32 mips mipsel) -set(MIPS64 mips64 mips64el) -set(PPC32 powerpc) -set(PPC64 powerpc64 powerpc64le) -set(RISCV32 riscv32) -set(RISCV64 riscv64) -set(S390X s390x) -set(SPARC sparc) -set(SPARCV9 sparcv9) -set(WASM32 wasm32) -set(WASM64 wasm64) -set(VE ve) - -if(APPLE) - set(ARM64 arm64) - set(ARM32 armv7 armv7s armv7k) - set(X86_64 x86_64 x86_64h) -endif() - -set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64} - ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} - ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV32} ${RISCV64} ${VE}) -set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) - -if(ANDROID) - set(OS_NAME "Android") -else() - set(OS_NAME "${CMAKE_SYSTEM_NAME}") -endif() - -if(OS_NAME MATCHES "Linux") - set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${S390X}) -elseif (OS_NAME MATCHES "Windows") - set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64}) -elseif(OS_NAME MATCHES "Android") - set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) -else() - set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64}) -endif() - -set(ALL_GWP_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) -if(APPLE) - set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64}) -else() - set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64} ${S390X} ${RISCV64}) -endif() -set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) -set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64}) -set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) -set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} - ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) -set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} - ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}) -set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64}) -set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64}) -set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64}) -if(APPLE) -set(ALL_XRAY_SUPPORTED_ARCH ${X86_64}) -else() -set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le) -endif() -set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64}) - -if (UNIX) -set(ALL_ORC_SUPPORTED_ARCH ${X86_64}) -endif() +include(AllSupportedArchDefs) if(APPLE) include(CompilerRTDarwinUtils) @@ -812,7 +738,7 @@ # calling malloc on first use. # TODO(hctim): Enable this on Android again. Looks like it's causing a SIGSEGV # for Scudo and GWP-ASan, further testing needed. -if (COMPILER_RT_HAS_SANITIZER_COMMON AND GWP_ASAN_SUPPORTED_ARCH AND +if (GWP_ASAN_SUPPORTED_ARCH AND COMPILER_RT_BUILD_GWP_ASAN AND OS_NAME MATCHES "Linux") set(COMPILER_RT_HAS_GWP_ASAN TRUE) else() diff --git a/compiler-rt/lib/gwp_asan/CMakeLists.txt b/compiler-rt/lib/gwp_asan/CMakeLists.txt --- a/compiler-rt/lib/gwp_asan/CMakeLists.txt +++ b/compiler-rt/lib/gwp_asan/CMakeLists.txt @@ -33,9 +33,10 @@ # Ensure that GWP-ASan meets the delegated requirements of some supporting # allocators. Some supporting allocators (e.g. scudo standalone) cannot use any # parts of the C++ standard library. -set(GWP_ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS} -fno-rtti -fno-exceptions +set(GWP_ASAN_CFLAGS -fno-rtti -fno-exceptions -nostdinc++ -pthread -fno-omit-frame-pointer) append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC GWP_ASAN_CFLAGS) +append_list_if(COMPILER_RT_HAS_SANITIZER_COMMON, ${SANITIZER_COMMON_CFLAGS} GWP_ASAN_CFLAGS) # Remove -stdlib= which is unused when passing -nostdinc++. string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) diff --git a/libc/lib/CMakeLists.txt b/libc/lib/CMakeLists.txt --- a/libc/lib/CMakeLists.txt +++ b/libc/lib/CMakeLists.txt @@ -1,9 +1,24 @@ set(SCUDO_DEPS "") if(LLVM_LIBC_INCLUDE_SCUDO) + include(../../compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake) + if(NOT (LIBC_TARGET_ARCHITECTURE IN_LIST ALL_SCUDO_STANDALONE_SUPPORTED_ARCH)) + message(FATAL_ERROR "Architecture ${LIBC_TARGET_ARCHITECTURE} is not supported by SCUDO. +Either disable LLVM_LIBC_INCLUDE_SCUDO or change your target architecture.") + endif() list(APPEND SCUDO_DEPS RTScudoStandalone.${LIBC_TARGET_ARCHITECTURE} RTScudoStandaloneCWrappers.${LIBC_TARGET_ARCHITECTURE}) + if((LIBC_TARGET_ARCHITECTURE IN_LIST ALL_GWP_ASAN_SUPPORTED_ARCH) AND COMPILER_RT_BUILD_GWP_ASAN) + list(APPEND SCUDO_DEPS RTGwpAsan.${LIBC_TARGET_ARCHITECTURE} + RTGwpAsanBacktraceLibc.${LIBC_TARGET_ARCHITECTURE} + RTGwpAsanSegvHandler.${LIBC_TARGET_ARCHITECTURE}) + elseif(COMPILER_RT_BUILD_GWP_ASAN) + message(WARNING "Architecture ${LIBC_TARGET_ARCHITECTURE} is not supported by GWP-ASan. Skipping.") + endif() endif() +message(STATUS "SCUDO_DEPS=${SCUDO_DEPS}") + + add_entrypoint_library( llvmlibc DEPENDS diff --git a/libc/test/CMakeLists.txt b/libc/test/CMakeLists.txt --- a/libc/test/CMakeLists.txt +++ b/libc/test/CMakeLists.txt @@ -18,4 +18,5 @@ endif() add_subdirectory(config) +add_subdirectory(integration) add_subdirectory(loader) diff --git a/libc/test/integration/CMakeLists.txt b/libc/test/integration/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/test/integration/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(scudo) diff --git a/libc/test/integration/scudo/CMakeLists.txt b/libc/test/integration/scudo/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/test/integration/scudo/CMakeLists.txt @@ -0,0 +1,39 @@ +if(NOT LLVM_LIBC_INCLUDE_SCUDO) + return() +endif() + +add_executable( + libc-scudo-integration-test + integration_test.cpp +) + +target_link_options( + libc-scudo-integration-test + PRIVATE + # TODO: Uncomment "-nolibc" once llvm-libc is complete enough. + # "-nolibc" + -pthreads +) + +target_link_libraries(libc-scudo-integration-test + PRIVATE + llvmlibc +) + +add_executable( + libc-gwp-asan-uaf-should-crash + gwp_asan_should_crash.cpp +) + +target_link_options( + libc-gwp-asan-uaf-should-crash + PRIVATE + # TODO: Uncomment "-nolibc" once llvm-libc is complete enough. + # "-nolibc" + -pthreads +) + +target_link_libraries(libc-gwp-asan-uaf-should-crash + PRIVATE + llvmlibc +) diff --git a/libc/test/integration/scudo/gwp_asan_should_crash.cpp b/libc/test/integration/scudo/gwp_asan_should_crash.cpp new file mode 100644 --- /dev/null +++ b/libc/test/integration/scudo/gwp_asan_should_crash.cpp @@ -0,0 +1,25 @@ +//===-- libc gwp asan crash test ------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +int main() { + char retval = 0; + for (unsigned i = 0; i < 0x10000; ++i) { + char *Ptr = reinterpret_cast(malloc(10)); + + for (unsigned i = 0; i < 10; ++i) { + *(Ptr + i) = 0x0; + } + + free(Ptr); + volatile char x = *Ptr; + retval = retval + x; + } + return retval; +} diff --git a/libc/test/integration/scudo/integration_test.cpp b/libc/test/integration/scudo/integration_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/integration/scudo/integration_test.cpp @@ -0,0 +1,41 @@ +//===-- Integration Test for Scudo ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +static const size_t ALLOC_SIZE = 128; + +int main() { + void *P = malloc(ALLOC_SIZE); + if (P == nullptr) { + return 1; + } + + free(P); + + P = calloc(4, ALLOC_SIZE); + if (P == nullptr) { + return 2; + } + + P = realloc(P, ALLOC_SIZE * 8); + if (P == nullptr) { + return 3; + } + + free(P); + + P = aligned_alloc(64, ALLOC_SIZE); + if (P == nullptr) { + return 4; + } + + free(P); + + return 0; +}