-
Notifications
You must be signed in to change notification settings - Fork 14.9k
release/21.x: [libc++][hardening] Add an experimental function to log hardening errors (#149452) #150481
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
Conversation
@ldionne What do you think about merging this PR to the release branch? |
@llvm/pr-subscribers-libcxx Author: None (llvmbot) ChangesBackport d750c6d Requested by: @ldionne Full diff: https://github.com/llvm/llvm-project/pull/150481.diff 9 Files Affected:
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 4f2a8dddad92c..85758c671e1e0 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 8f215bbe47928..7bb5d9ac77ea4 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..d1805306f6b6e
--- /dev/null
+++ b/libcxx/include/__log_hardening_failure
@@ -0,0 +1,42 @@
+// -*- 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
+
+// Hardening logging is not available in the C++03 mode; moreover, it is currently only available in the experimental
+// library.
+#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG)
+
+_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.
+[[__gnu__::__cold__]] _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 && !defined(_LIBCPP_CXX03_LANG)
+
+#endif // _LIBCPP___LOG_HARDENING_FAILURE
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 61ba1c381b2b3..53f10ab8a92a5 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..f836c15452249
--- /dev/null
+++ b/libcxx/src/experimental/log_hardening_failure.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+#endif // __BIONIC__
+
+_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);
+
+#if defined(__BIONIC__)
+ // 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
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..dda071b8d0296
--- /dev/null
+++ b/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: c++03
+// UNSUPPORTED: libcpp-has-no-experimental-hardening-observe-semantic
+
+#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.
|
The rationale for cherry-picking this "feature" into the release is that we want to gain experience with this and be able to ship a robust version of this in the next release, non-experimentally. |
…ors (llvm#149452) 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. (cherry picked from commit d750c6d)
@ldionne (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. |
Backport d750c6d
Requested by: @ldionne