Skip to content
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

Log errno (or fuchsia equivalent) on map failures #95391

Merged
merged 8 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler-rt/lib/gwp_asan/definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
#define GWP_ASAN_TLS_INITIAL_EXEC \
__thread __attribute__((tls_model("initial-exec")))

#define GWP_ASAN_UNLIKELY(X) __builtin_expect(!!(X), 0)
#define GWP_ASAN_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
#define GWP_ASAN_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
#define GWP_ASAN_ALWAYS_INLINE inline __attribute__((always_inline))

#define GWP_ASAN_WEAK __attribute__((weak))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ void *GuardedPoolAllocator::map(size_t Size, const char *Name) const {
assert((Size % State.PageSize) == 0);
zx_handle_t Vmo;
zx_status_t Status = _zx_vmo_create(Size, 0, &Vmo);
check(Status == ZX_OK, "Failed to create Vmo");
checkWithErrorCode(Status == ZX_OK, "Failed to create Vmo", Status);
_zx_object_set_property(Vmo, ZX_PROP_NAME, Name, strlen(Name));
zx_vaddr_t Addr;
Status = _zx_vmar_map(_zx_vmar_root_self(),
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_ALLOW_FAULTS,
0, Vmo, 0, Size, &Addr);
check(Status == ZX_OK, "Vmo mapping failed");
checkWithErrorCode(Status == ZX_OK, "Vmo mapping failed", Status);
_zx_handle_close(Vmo);
return reinterpret_cast<void *>(Addr);
}
Expand All @@ -40,7 +40,7 @@ void GuardedPoolAllocator::unmap(void *Ptr, size_t Size) const {
assert((Size % State.PageSize) == 0);
zx_status_t Status = _zx_vmar_unmap(_zx_vmar_root_self(),
reinterpret_cast<zx_vaddr_t>(Ptr), Size);
check(Status == ZX_OK, "Vmo unmapping failed");
checkWithErrorCode(Status == ZX_OK, "Vmo unmapping failed", Status);
}

void *GuardedPoolAllocator::reserveGuardedPool(size_t Size) {
Expand All @@ -50,7 +50,8 @@ void *GuardedPoolAllocator::reserveGuardedPool(size_t Size) {
_zx_vmar_root_self(),
ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, 0,
Size, &GuardedPagePoolPlatformData.Vmar, &Addr);
check(Status == ZX_OK, "Failed to reserve guarded pool allocator memory");
checkWithErrorCode(Status == ZX_OK,
"Failed to reserve guarded pool allocator memory", Status);
_zx_object_set_property(GuardedPagePoolPlatformData.Vmar, ZX_PROP_NAME,
kGwpAsanGuardPageName, strlen(kGwpAsanGuardPageName));
return reinterpret_cast<void *>(Addr);
Expand All @@ -59,8 +60,10 @@ void *GuardedPoolAllocator::reserveGuardedPool(size_t Size) {
void GuardedPoolAllocator::unreserveGuardedPool() {
const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar;
assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self());
check(_zx_vmar_destroy(Vmar) == ZX_OK, "Failed to destroy a vmar");
check(_zx_handle_close(Vmar) == ZX_OK, "Failed to close a vmar");
zx_status_t Status = _zx_vmar_destroy(Vmar);
checkWithErrorCode(Status == ZX_OK, "Failed to destroy a vmar", Status);
Status = _zx_handle_close(Vmar);
checkWithErrorCode(Status == ZX_OK, "Failed to close a vmar", Status);
GuardedPagePoolPlatformData.Vmar = ZX_HANDLE_INVALID;
}

Expand All @@ -69,7 +72,7 @@ void GuardedPoolAllocator::allocateInGuardedPool(void *Ptr, size_t Size) const {
assert((Size % State.PageSize) == 0);
zx_handle_t Vmo;
zx_status_t Status = _zx_vmo_create(Size, 0, &Vmo);
check(Status == ZX_OK, "Failed to create vmo");
checkWithErrorCode(Status == ZX_OK, "Failed to create vmo", Status);
_zx_object_set_property(Vmo, ZX_PROP_NAME, kGwpAsanAliveSlotName,
strlen(kGwpAsanAliveSlotName));
const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar;
Expand All @@ -81,7 +84,7 @@ void GuardedPoolAllocator::allocateInGuardedPool(void *Ptr, size_t Size) const {
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
ZX_VM_ALLOW_FAULTS | ZX_VM_SPECIFIC,
Offset, Vmo, 0, Size, &P);
check(Status == ZX_OK, "Vmo mapping failed");
checkWithErrorCode(Status == ZX_OK, "Vmo mapping failed", Status);
_zx_handle_close(Vmo);
}

Expand All @@ -93,7 +96,7 @@ void GuardedPoolAllocator::deallocateInGuardedPool(void *Ptr,
assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self());
const zx_status_t Status =
_zx_vmar_unmap(Vmar, reinterpret_cast<zx_vaddr_t>(Ptr), Size);
check(Status == ZX_OK, "Vmar unmapping failed");
checkWithErrorCode(Status == ZX_OK, "Vmar unmapping failed", Status);
}

size_t GuardedPoolAllocator::getPlatformPageSize() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "gwp_asan/utilities.h"

#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
Expand Down Expand Up @@ -46,23 +47,25 @@ void *GuardedPoolAllocator::map(size_t Size, const char *Name) const {
assert((Size % State.PageSize) == 0);
void *Ptr = mmap(nullptr, Size, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
check(Ptr != MAP_FAILED, "Failed to map guarded pool allocator memory");
checkWithErrorCode(Ptr != MAP_FAILED,
"Failed to map guarded pool allocator memory", errno);
MaybeSetMappingName(Ptr, Size, Name);
return Ptr;
}

void GuardedPoolAllocator::unmap(void *Ptr, size_t Size) const {
assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
assert((Size % State.PageSize) == 0);
check(munmap(Ptr, Size) == 0,
"Failed to unmap guarded pool allocator memory.");
checkWithErrorCode(munmap(Ptr, Size) == 0,
"Failed to unmap guarded pool allocator memory.", errno);
}

void *GuardedPoolAllocator::reserveGuardedPool(size_t Size) {
assert((Size % State.PageSize) == 0);
void *Ptr =
mmap(nullptr, Size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
check(Ptr != MAP_FAILED, "Failed to reserve guarded pool allocator memory");
checkWithErrorCode(Ptr != MAP_FAILED,
"Failed to reserve guarded pool allocator memory", errno);
MaybeSetMappingName(Ptr, Size, kGwpAsanGuardPageName);
return Ptr;
}
Expand All @@ -75,8 +78,9 @@ void GuardedPoolAllocator::unreserveGuardedPool() {
void GuardedPoolAllocator::allocateInGuardedPool(void *Ptr, size_t Size) const {
assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
assert((Size % State.PageSize) == 0);
check(mprotect(Ptr, Size, PROT_READ | PROT_WRITE) == 0,
"Failed to allocate in guarded pool allocator memory");
checkWithErrorCode(mprotect(Ptr, Size, PROT_READ | PROT_WRITE) == 0,
"Failed to allocate in guarded pool allocator memory",
errno);
MaybeSetMappingName(Ptr, Size, kGwpAsanAliveSlotName);
}

Expand All @@ -87,9 +91,10 @@ void GuardedPoolAllocator::deallocateInGuardedPool(void *Ptr,
// mmap() a PROT_NONE page over the address to release it to the system, if
// we used mprotect() here the system would count pages in the quarantine
// against the RSS.
check(mmap(Ptr, Size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1,
0) != MAP_FAILED,
"Failed to deallocate in guarded pool allocator memory");
checkWithErrorCode(
mmap(Ptr, Size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1,
0) != MAP_FAILED,
"Failed to deallocate in guarded pool allocator memory", errno);
MaybeSetMappingName(Ptr, Size, kGwpAsanGuardPageName);
}

Expand Down
13 changes: 13 additions & 0 deletions compiler-rt/lib/gwp_asan/platform_specific/utilities_fuchsia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,25 @@

#include "gwp_asan/utilities.h"

#include <alloca.h>
#include <stdio.h>
#include <string.h>
hctim marked this conversation as resolved.
Show resolved Hide resolved
#include <zircon/sanitizer.h>
hctim marked this conversation as resolved.
Show resolved Hide resolved
#include <zircon/status.h>

namespace gwp_asan {
void die(const char *Message) {
__sanitizer_log_write(Message, strlen(Message));
__builtin_trap();
}

void dieWithErrorCode(const char *Message, int64_t ErrorCode) {
const char *error_str =
_zx_status_get_string(static_cast<zx_status_t>(ErrorCode));
size_t buffer_size = strlen(Message) + 32 + strlen(error_str);
char *buffer = static_cast<char *>(alloca(buffer_size));
snprintf(buffer, buffer_size, "%s (Error Code: %s)", Message, error_str);
__sanitizer_log_write(buffer, strlen(buffer));
__builtin_trap();
}
} // namespace gwp_asan
21 changes: 21 additions & 0 deletions compiler-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
//
//===----------------------------------------------------------------------===//

#include <alloca.h>
#include <features.h> // IWYU pragma: keep (for __BIONIC__ macro)
#include <inttypes.h>
#include <stdint.h>
#include <string.h>

#ifdef __BIONIC__
#include "gwp_asan/definitions.h"
Expand All @@ -27,4 +31,21 @@ void die(const char *Message) {
__builtin_trap();
#endif // __BIONIC__
}

void dieWithErrorCode(const char *Message, int64_t ErrorCode) {
#ifdef __BIONIC__
if (&android_set_abort_message == nullptr)
abort();

size_t buffer_size = strlen(Message) + 48;
char *buffer = static_cast<char *>(alloca(buffer_size));
snprintf(buffer, buffer_size, "%s (Error Code: %" PRId64 ")", Message,
ErrorCode);
android_set_abort_message(buffer);
abort();
#else // __BIONIC__
fprintf(stderr, "%s (Error Code: %" PRId64 ")", Message, ErrorCode);
__builtin_trap();
#endif // __BIONIC__
}
} // namespace gwp_asan
4 changes: 3 additions & 1 deletion compiler-rt/lib/gwp_asan/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ set(GWP_ASAN_UNITTESTS
late_init.cpp
options.cpp
recoverable.cpp
never_allocated.cpp)
never_allocated.cpp
utilities.cpp
)

set(GWP_ASAN_UNIT_TEST_HEADERS
${GWP_ASAN_HEADERS}
Expand Down
24 changes: 24 additions & 0 deletions compiler-rt/lib/gwp_asan/tests/utilities.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===-- utilities.cpp -------------------------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "gwp_asan/utilities.h"
#include "gwp_asan/tests/harness.h"

using gwp_asan::check;
using gwp_asan::checkWithErrorCode;

TEST(UtilitiesDeathTest, CheckPrintsAsExpected) {
EXPECT_DEATH({ check(false, "Hello world"); }, "Hello world");
check(true, "Should not crash");
EXPECT_DEATH(
{ checkWithErrorCode(false, "Hello world", 1337); },
"Hello world \\(Error Code: 1337\\)");
hctim marked this conversation as resolved.
Show resolved Hide resolved
EXPECT_DEATH(
{ checkWithErrorCode(false, "Hello world", -1337); },
"Hello world \\(Error Code: -1337\\)");
}
13 changes: 12 additions & 1 deletion compiler-rt/lib/gwp_asan/utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,28 @@
#include "gwp_asan/definitions.h"

#include <stddef.h>
#include <stdint.h>

namespace gwp_asan {
// Terminates in a platform-specific way with `Message`.
void die(const char *Message);
void dieWithErrorCode(const char *Message, int64_t ErrorCode);

// Checks that `Condition` is true, otherwise dies with `Message`.
GWP_ASAN_ALWAYS_INLINE void check(bool Condition, const char *Message) {
hctim marked this conversation as resolved.
Show resolved Hide resolved
if (Condition)
if (GWP_ASAN_LIKELY(Condition))
return;
die(Message);
}

// Checks that `Condition` is true, otherwise dies with `Message` (including
// errno at the end).
GWP_ASAN_ALWAYS_INLINE void
checkWithErrorCode(bool Condition, const char *Message, int64_t ErrorCode) {
hctim marked this conversation as resolved.
Show resolved Hide resolved
if (GWP_ASAN_LIKELY(Condition))
return;
dieWithErrorCode(Message, ErrorCode);
}
} // namespace gwp_asan

#endif // GWP_ASAN_UTILITIES_H_
Loading