From a341ce5570c8bc5296515f9976bee669d46083fb Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Thu, 27 Mar 2025 19:57:24 -0400 Subject: [PATCH] Add a build flavor to opt-out of BTCFI on OpenBSD. To work-around #80059, we need to stop return address signing and opt-out of BTCFI enforcement via enabling a platform linker option. We don't want to completely undo the BTCFI work in the rare case that we later figure out how to properly address the above issue, or allow users who might want to benefit from BTCFI enforcement and won't use Concurrency. To do this, condition the existing BTCFI flag enforcement into a configuration option that defaults to off for now. Because the new swift-driver needs to "know" whether the frontend is configured to opt-out or not, and since the new driver communicates with the frontend via the target info JSON to begin with, we add a field that emits the build flavor to signal the right behavior. --- CMakeLists.txt | 11 +++++++++++ include/swift/Basic/Platform.h | 4 ++++ lib/Basic/Platform.cpp | 4 ++++ lib/Basic/TargetInfo.cpp | 10 ++++++++++ lib/Driver/ToolChains.cpp | 2 ++ lib/Driver/UnixToolChains.cpp | 9 +++++++++ utils/build-script-impl | 13 ++++++++++++- 7 files changed, 52 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dcda42946cad..e95b84a3ff5c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -575,6 +575,17 @@ set(SWIFT_DARWIN_XCRUN_TOOLCHAIN "XcodeDefault" CACHE STRING set(SWIFT_DARWIN_STDLIB_INSTALL_NAME_DIR "/usr/lib/swift" CACHE STRING "The directory of the install_name for standard library dylibs") +# +# User-configurable OpenBSD-specific options. +# + +option(SWIFT_OPENBSD_BTCFI + "Emit branch target identification instructions and sign return addresses when available" + FALSE) +if(SWIFT_OPENBSD_BTCFI) + add_definitions("-DSWIFT_OPENBSD_BTCFI") +endif() + # We don't want to use the same install_name_dir as the standard library which # will be installed in /usr/lib/swift. These private libraries should continue # to use @rpath for now. diff --git a/include/swift/Basic/Platform.h b/include/swift/Basic/Platform.h index 2a1b984087e70..94515f6dbd890 100644 --- a/include/swift/Basic/Platform.h +++ b/include/swift/Basic/Platform.h @@ -71,6 +71,10 @@ namespace swift { /// (eg. in /usr/lib/swift). bool tripleRequiresRPathForSwiftLibrariesInOS(const llvm::Triple &triple); + /// Returns true if the given triple represents a version of OpenBSD + /// that enforces BTCFI by default. + bool tripleBTCFIByDefaultInOpenBSD(const llvm::Triple &triple); + /// Returns the platform name for a given target triple. /// /// For example, the iOS simulator has the name "iphonesimulator", while real diff --git a/lib/Basic/Platform.cpp b/lib/Basic/Platform.cpp index 7778a3784472e..4b6b827ef6594 100644 --- a/lib/Basic/Platform.cpp +++ b/lib/Basic/Platform.cpp @@ -140,6 +140,10 @@ bool swift::tripleRequiresRPathForSwiftLibrariesInOS( return false; } +bool swift::tripleBTCFIByDefaultInOpenBSD(const llvm::Triple &triple) { + return triple.isOSOpenBSD() && triple.getArch() == llvm::Triple::aarch64; +} + DarwinPlatformKind swift::getDarwinPlatformKind(const llvm::Triple &triple) { if (triple.isiOS()) { if (triple.isTvOS()) { diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index 40ad9f26ff9ec..53f3a219d7205 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -171,6 +171,16 @@ void printTripleInfo(const CompilerInvocation &invocation, out << " \"compatibilityLibraries\": [ ],\n"; } + if (tripleBTCFIByDefaultInOpenBSD(triple)) { +#if SWIFT_OPENBSD_BTCFI + out << " \"openbsdBTCFIEnabled\": true,\n"; +#else + out << " \"openbsdBTCFIEnabled\": false,\n"; +#endif + } else { + out << " \"openbsdBTCFIEnabled\": false,\n"; + } + out << " \"librariesRequireRPath\": " << (tripleRequiresRPathForSwiftLibrariesInOS(triple) ? "true" : "false") << "\n"; diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 6a7ae73498e00..739e26953bb8d 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -205,12 +205,14 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, } if (Triple.isOSOpenBSD() && Triple.getArch() == llvm::Triple::aarch64) { +#ifdef SWIFT_OPENBSD_BTCFI arguments.push_back("-Xcc"); arguments.push_back("-Xclang=-mbranch-target-enforce"); arguments.push_back("-Xcc"); arguments.push_back("-Xclang=-msign-return-address=non-leaf"); arguments.push_back("-Xcc"); arguments.push_back("-Xclang=-msign-return-address-key=a_key"); +#endif } if (inputArgs.getLastArg(options::OPT_experimental_serialize_debug_info)) { diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index e016d041199d6..a8a934da16d2e 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -211,6 +211,15 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, #endif } + if (tripleBTCFIByDefaultInOpenBSD(getTriple())) { +#ifndef SWIFT_OPENBSD_BTCFI + Arguments.push_back("-Xlinker"); + Arguments.push_back("-z"); + Arguments.push_back("-Xlinker"); + Arguments.push_back("nobtcfi"); +#endif + } + // Configure the toolchain. if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); diff --git a/utils/build-script-impl b/utils/build-script-impl index ab0c488a861d5..b19e6a3fdbf09 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -124,6 +124,9 @@ KNOWN_SETTINGS=( darwin-toolchain-require-use-os-runtime "0" "When setting up a plist for a toolchain, require the users of the toolchain to link against the OS instead of the packaged toolchain runtime. 0 for false, 1 for true" darwin-xcrun-toolchain "default" "the name of the toolchain to use on Darwin" + ## OpenBSD options + openbsd-btcfi "" "enables BTCFI when possible. May cause stability problems." + ## Runtime options min-runtime-version "" "Used to specify the minimum host runtime version when building the compiler on non-Darwin platforms" @@ -877,6 +880,12 @@ function set_build_options_for_host() { swift_cmake_options+=( -DCOVERAGE_DB="${COVERAGE_DB}" ) + + if [[ "${OPENBSD_BTCFI}" ]]; then + swift_cmake_options+=( + -DSWIFT_OPENBSD_BTCFI:BOOL=TRUE + ) + fi } function configure_default_options() { @@ -1383,7 +1392,9 @@ function swift_c_flags() { echo -n " -D_GNU_SOURCE -DHAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME" ;; openbsd-aarch64) - echo -n " -Xclang=-msign-return-address=non-leaf -Xclang=-msign-return-address-key=a_key -Xclang=-mbranch-target-enforce" + if [[ "${OPENBSD_BTCFI}" ]]; then + echo -n " -Xclang=-msign-return-address=non-leaf -Xclang=-msign-return-address-key=a_key -Xclang=-mbranch-target-enforce" + fi ;; esac }