-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[libc++][hardening] Add an experimental function to log hardening errors #149452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++][hardening] Add an experimental function to log hardening errors #149452
Conversation
48c191d
to
74fc2ec
Compare
libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp
Outdated
Show resolved
Hide resolved
74fc2ec
to
13e14f1
Compare
@llvm/pr-subscribers-libcxx Author: Konstantin Varlamov (var-const) ChangesUnlike Full diff: https://github.com/llvm/llvm-project/pull/149452.diff 9 Files Affected:
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 25b567df2dd33..4a6a61b640a48 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -535,6 +535,7 @@ set(files
__locale_dir/time.h
__locale_dir/wbuffer_convert.h
__locale_dir/wstring_convert.h
+ __log_hardening_failure
__math/abs.h
__math/copysign.h
__math/error_functions.h
diff --git a/libcxx/include/__config b/libcxx/include/__config
index ee06abfba7a08..c867b4bcc0f1f 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -207,6 +207,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
+# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
# if defined(__MVS__)
# include <features.h> // for __NATIVE_ASCII_F
diff --git a/libcxx/include/__log_hardening_failure b/libcxx/include/__log_hardening_failure
new file mode 100644
index 0000000000000..76da1153d78b2
--- /dev/null
+++ b/libcxx/include/__log_hardening_failure
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___LOG_HARDENING_FAILURE
+#define _LIBCPP___LOG_HARDENING_FAILURE
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// This function should never be called directly from the code -- it should only be called through the
+// `_LIBCPP_LOG_HARDENING_FAILURE` macro.
+_LIBCPP_EXPORTED_FROM_ABI void __log_hardening_failure(const char* __message) _NOEXCEPT;
+
+// _LIBCPP_LOG_HARDENING_FAILURE(message)
+//
+// This macro is used to log an error without terminating the program (as is the case for hardening failures if the
+// `observe` assertion semantic is used).
+
+# if !defined(_LIBCPP_LOG_HARDENING_FAILURE)
+# define _LIBCPP_LOG_HARDENING_FAILURE(__message) ::std::__log_hardening_failure(__message)
+# endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE)
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC
+
+#endif // _LIBCPP___LOG_HARDENING_FAILURE
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 78607f2c1301d..9ee964c0069f4 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2353,6 +2353,9 @@ module std [system] {
header "__std_mbstate_t.h"
export *
}
+ module log_hardening_failure {
+ header "__log_hardening_failure"
+ }
module verbose_abort {
header "__verbose_abort"
}
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 97fe57a5f24f8..f59fe0e08fccb 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -309,6 +309,7 @@ add_custom_target(cxx DEPENDS ${LIBCXX_BUILD_TARGETS})
# Build the experimental static library
set(LIBCXX_EXPERIMENTAL_SOURCES
experimental/keep.cpp
+ experimental/log_hardening_failure.cpp
)
if (LIBCXX_PSTL_BACKEND STREQUAL "libdispatch")
diff --git a/libcxx/src/experimental/log_hardening_failure.cpp b/libcxx/src/experimental/log_hardening_failure.cpp
new file mode 100644
index 0000000000000..274175c1acaa8
--- /dev/null
+++ b/libcxx/src/experimental/log_hardening_failure.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <__config>
+#include <__log_hardening_failure>
+#include <cstdio>
+
+#ifdef __BIONIC__
+# include <syslog.h>
+extern "C" void android_set_abort_message(const char* msg);
+#endif // __BIONIC__
+
+#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
+# include <TargetConditionals.h>
+# include <os/reason_private.h>
+#endif
+
+#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+void __log_hardening_failure(const char* message) noexcept {
+ // Always log the message to `stderr` in case the platform-specific system calls fail.
+ std::fputs(message, stderr);
+
+ // On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
+# if defined(__APPLE__) && __has_include(<os/reason_private.h>) && !TARGET_OS_SIMULATOR
+ os_fault_with_payload(
+ /*reason_namespace=*/OS_REASON_SECURITY,
+ /*reason_code=*/0,
+ /*payload=*/nullptr,
+ /*payload_size=*/0,
+ /*reason_string=*/message,
+ /*reason_flags=*/0);
+
+# elif defined(__BIONIC__)
+ // Show error in tombstone.
+ android_set_abort_message(message);
+
+ // Show error in logcat. The latter two arguments are ignored on Android.
+ openlog("libc++", 0, 0);
+ syslog(LOG_CRIT, "%s", message);
+ closelog();
+# endif
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC
diff --git a/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp b/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp
new file mode 100644
index 0000000000000..d13b1a0a9c13a
--- /dev/null
+++ b/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Basic smoke test for `__log_hardening_failure`.
+//
+// UNSUPPORTED: libcpp-has-no-experimental-hardening-observe-semantic
+// XFAIL: availability-log_hardening_failure-missing
+// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME
+
+#include <__log_hardening_failure>
+
+#include "test_macros.h"
+
+ASSERT_NOEXCEPT(std::__log_hardening_failure(""));
+
+int main(int, char**) {
+ std::__log_hardening_failure("Some message");
+ // It's difficult to properly test platform-specific logging behavior of the function; just make sure it exists and
+ // can be called at runtime.
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp
index 3cf497da233fb..3d97446ffe826 100644
--- a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp
+++ b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp
@@ -29,3 +29,7 @@
#if !_LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM
# error "-fexperimental-library should enable the syncstream header"
#endif
+
+#if !_LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC
+# error "-fexperimental-library should allow using the Hardening observe semantic"
+#endif
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index adfb2a9f69508..93cf29bcdff0d 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -361,6 +361,7 @@ def getSuitableClangTidy(cfg):
AddFeature("libcpp-has-no-incomplete-pstl"),
AddFeature("libcpp-has-no-experimental-tzdb"),
AddFeature("libcpp-has-no-experimental-syncstream"),
+ AddFeature("libcpp-has-no-experimental-hardening-observe-semantic"),
],
),
# TODO: This can be improved once we use a version of GoogleBenchmark that supports the dry-run mode.
|
Unlike `verbose_abort`, this function merely logs the error but does not terminate execution. It is intended to make it possible to implement the `observe` semantic for Hardening.
13e14f1
to
afc0146
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
Merging now (bypassing check) since the only change was |
/cherry-pick d750c6d |
/pull-request #150481 |
Hi, after this change got landed, we are seeing a build failure on baremetal armv6m-none-eabi target, error message:
Build task: https://ci.chromium.org/ui/p/fuchsia/builders/toolchain.ci/clang-linux-x64/b8708441153070837249/overview |
@zeroomega Does this failure happen on Fuchsia? IIUC, Fuchsia doesn't support many filesystem-related functions (and I don't think we officially support Fuchsia). The build error is complaining that An easy fix for the build error would be to simply avoid referencing Cc @ldionne |
This is a quick fix for a build error on Fuchsia where many C standard library filesystem-related functions are not available; it effectively makes the hardening log function a no-op on Fuchsia. Links: * llvm#149452 (comment) * https://ci.chromium.org/ui/p/fuchsia/builders/toolchain.ci/clang-linux-x64/b8708441153070837249/overview
It failed when building llvm baremetal target runtimes. Those are for microcontrollers like STM32 or Raspberry Pi Picos. Unrelated to Fuchsia. We encountered this issue because we build those runtimes when we build the LLVM toolchain. I am not very familiar with libcxx but simple mitigation would be just avoiding building this file when the target triple is a baremetal target like armv6m-none-eabi, riscv32-unknown-elf. |
Libc++ cannot properly build in an environment that doesn't provide a reasonably complete C library, not without a lot of workarounds. I need to understand how this issue is currently mitigated in other places where it should show up, such as for |
I dig into how we build the baremetal targets and found out the mitigation in
|
I landed the workaround 38f6364 . It should address the failure on our side. Ideally, LLVM libc should provide those functions for the baremetal targets, even if they don't work. But that is a different discussion. |
@zeroomega Thank you for investigating and landing the fix! Very happy the breakage got fixed quickly. |
Unlike
verbose_abort
, this function merely logs the error but does notterminate execution. It is intended to make it possible to implement the
observe
semantic for Hardening.