Skip to content

Commit 1fcfec3

Browse files
committed
[libc++][hardening] Introduce a dylib function to log hardening errors.
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.
1 parent a0fcb50 commit 1fcfec3

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ set(files
535535
__locale_dir/time.h
536536
__locale_dir/wbuffer_convert.h
537537
__locale_dir/wstring_convert.h
538+
__log_hardening_failure
538539
__math/abs.h
539540
__math/copysign.h
540541
__math/error_functions.h

libcxx/include/__configuration/availability.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@
304304
#define _LIBCPP_AVAILABILITY_HAS_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15
305305
#define _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE
306306

307+
// This controls whether the library provides a function to log hardening failures without terminating the program (for
308+
// the `observe` assertion semantic).
309+
#define _LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21
310+
#define _LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE
311+
307312
// This controls the availability of the C++17 std::pmr library,
308313
// which is implemented in large part in the built library.
309314
//
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___LOG_HARDENING_FAILURE
11+
#define _LIBCPP___LOG_HARDENING_FAILURE
12+
13+
#include <__config>
14+
15+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16+
# pragma GCC system_header
17+
#endif
18+
19+
_LIBCPP_BEGIN_NAMESPACE_STD
20+
21+
// This function should never be called directly from the code -- it should only be called through the
22+
// `_LIBCPP_LOG_HARDENING_FAILURE` macro.
23+
_LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_OVERRIDABLE_FUNC_VIS void
24+
__libcpp_log_hardening_failure(const char* message) _NOEXCEPT;
25+
26+
// _LIBCPP_LOG_HARDENING_FAILURE(message)
27+
//
28+
// This macro is used to log a hardening failure without terminating the program (as is the case if the `observe`
29+
// assertion semantic is used). Where possible, it logs in a way that indicates a fatal error (which might include
30+
// capturing the stack trace).
31+
#if !defined(_LIBCPP_LOG_HARDENING_FAILURE)
32+
33+
# if !_LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE
34+
// The decltype is there to suppress -Wunused warnings in this configuration.
35+
void __use(const char*);
36+
# define _LIBCPP_LOG_HARDENING_FAILURE(message) (decltype(::std::__use(message))())
37+
# else
38+
# define _LIBCPP_LOG_HARDENING_FAILURE(message) ::std::__libcpp_log_hardening_failure(message)
39+
# endif
40+
41+
#endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE)
42+
43+
_LIBCPP_END_NAMESPACE_STD
44+
45+
#endif // _LIBCPP___LOG_HARDENING_FAILURE

libcxx/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ set(LIBCXX_SOURCES
3030
include/ryu/ryu.h
3131
include/to_chars_floating_point.h
3232
include/from_chars_floating_point.h
33+
log_hardening_failure.cpp
3334
memory.cpp
3435
memory_resource.cpp
3536
new_handler.cpp

libcxx/src/log_hardening_failure.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <__config>
10+
#include <__log_hardening_failure>
11+
#include <cstdio>
12+
13+
#ifdef __BIONIC__
14+
# include <syslog.h>
15+
extern "C" void android_set_abort_message(const char* msg);
16+
#endif // __BIONIC__
17+
18+
#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
19+
# include <os/reason_private.h>
20+
#endif
21+
22+
_LIBCPP_BEGIN_NAMESPACE_STD
23+
24+
_LIBCPP_WEAK void __libcpp_log_hardening_failure(const char* message) noexcept {
25+
// On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
26+
#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
27+
os_fault_with_payload(
28+
/*reason_namespace=*/OS_REASON_SECURITY,
29+
/*reason_code=*/0,
30+
/*payload=*/nullptr,
31+
/*payload_size=*/0,
32+
/*reason_string=*/message,
33+
/*reason_flags=*/0);
34+
35+
#elif defined(__BIONIC__)
36+
// Show error in tombstone.
37+
android_set_abort_message(message);
38+
39+
// Show error in logcat.
40+
openlog("libc++", 0, 0);
41+
syslog(LOG_CRIT, "%s", message);
42+
closelog();
43+
44+
#else
45+
fprintf(stderr, "%s", message);
46+
#endif
47+
}
48+
49+
_LIBCPP_END_NAMESPACE_STD

0 commit comments

Comments
 (0)