2020-10-20 02:54:43 +08:00
|
|
|
//===-- crash_handler.cpp ---------------------------------------*- C++ -*-===//
|
[GWP-ASan] Crash Handler API.
Summary:
Forewarning: This patch looks big in #LOC changed. I promise it's not that bad, it just moves a lot of content from one file to another. I've gone ahead and left inline comments on Phabricator for sections where this has happened.
This patch:
1. Introduces the crash handler API (crash_handler_api.h).
2. Moves information required for out-of-process crash handling into an AllocatorState. This is a trivially-copied POD struct that designed to be recovered from a deceased process, and used by the crash handler to create a GWP-ASan report (along with the other trivially-copied Metadata struct).
3. Implements the crash handler API using the AllocatorState and Metadata.
4. Adds tests for the crash handler.
5. Reimplements the (now optionally linked by the supporting allocator) in-process crash handler (i.e. the segv handler) using the new crash handler API.
6. Minor updates Scudo & Scudo Standalone to fix compatibility.
7. Changed capitalisation of errors (e.g. /s/Use after free/Use After Free).
Reviewers: cryptoad, eugenis, jfb
Reviewed By: eugenis
Subscribers: merge_guards_bot, pcc, jfb, dexonsmith, mgorny, cryptoad, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D73557
2020-02-06 07:39:03 +08:00
|
|
|
//
|
|
|
|
// 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/common.h"
|
|
|
|
#include "gwp_asan/stack_trace_compressor.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
2020-12-11 04:41:56 +08:00
|
|
|
#include <stdint.h>
|
2020-07-28 01:51:53 +08:00
|
|
|
#include <string.h>
|
[GWP-ASan] Crash Handler API.
Summary:
Forewarning: This patch looks big in #LOC changed. I promise it's not that bad, it just moves a lot of content from one file to another. I've gone ahead and left inline comments on Phabricator for sections where this has happened.
This patch:
1. Introduces the crash handler API (crash_handler_api.h).
2. Moves information required for out-of-process crash handling into an AllocatorState. This is a trivially-copied POD struct that designed to be recovered from a deceased process, and used by the crash handler to create a GWP-ASan report (along with the other trivially-copied Metadata struct).
3. Implements the crash handler API using the AllocatorState and Metadata.
4. Adds tests for the crash handler.
5. Reimplements the (now optionally linked by the supporting allocator) in-process crash handler (i.e. the segv handler) using the new crash handler API.
6. Minor updates Scudo & Scudo Standalone to fix compatibility.
7. Changed capitalisation of errors (e.g. /s/Use after free/Use After Free).
Reviewers: cryptoad, eugenis, jfb
Reviewed By: eugenis
Subscribers: merge_guards_bot, pcc, jfb, dexonsmith, mgorny, cryptoad, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D73557
2020-02-06 07:39:03 +08:00
|
|
|
|
|
|
|
using AllocationMetadata = gwp_asan::AllocationMetadata;
|
|
|
|
using Error = gwp_asan::Error;
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool __gwp_asan_error_is_mine(const gwp_asan::AllocatorState *State,
|
|
|
|
uintptr_t ErrorPtr) {
|
|
|
|
assert(State && "State should not be nullptr.");
|
|
|
|
if (State->FailureType != Error::UNKNOWN && State->FailureAddress != 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return ErrorPtr < State->GuardedPagePoolEnd &&
|
|
|
|
State->GuardedPagePool <= ErrorPtr;
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t
|
|
|
|
__gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State) {
|
|
|
|
return State->FailureAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const AllocationMetadata *
|
|
|
|
addrToMetadata(const gwp_asan::AllocatorState *State,
|
|
|
|
const AllocationMetadata *Metadata, uintptr_t Ptr) {
|
|
|
|
// Note - Similar implementation in guarded_pool_allocator.cpp.
|
|
|
|
return &Metadata[State->getNearestSlot(Ptr)];
|
|
|
|
}
|
|
|
|
|
|
|
|
gwp_asan::Error
|
|
|
|
__gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State,
|
|
|
|
const gwp_asan::AllocationMetadata *Metadata,
|
|
|
|
uintptr_t ErrorPtr) {
|
|
|
|
if (!__gwp_asan_error_is_mine(State, ErrorPtr))
|
|
|
|
return Error::UNKNOWN;
|
|
|
|
|
|
|
|
if (State->FailureType != Error::UNKNOWN)
|
|
|
|
return State->FailureType;
|
|
|
|
|
|
|
|
// Let's try and figure out what the source of this error is.
|
|
|
|
if (State->isGuardPage(ErrorPtr)) {
|
|
|
|
size_t Slot = State->getNearestSlot(ErrorPtr);
|
|
|
|
const AllocationMetadata *SlotMeta =
|
|
|
|
addrToMetadata(State, Metadata, State->slotToAddr(Slot));
|
|
|
|
|
|
|
|
// Ensure that this slot was allocated once upon a time.
|
|
|
|
if (!SlotMeta->Addr)
|
|
|
|
return Error::UNKNOWN;
|
|
|
|
|
|
|
|
if (SlotMeta->Addr < ErrorPtr)
|
|
|
|
return Error::BUFFER_OVERFLOW;
|
|
|
|
return Error::BUFFER_UNDERFLOW;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Access wasn't a guard page, check for use-after-free.
|
|
|
|
const AllocationMetadata *SlotMeta =
|
|
|
|
addrToMetadata(State, Metadata, ErrorPtr);
|
|
|
|
if (SlotMeta->IsDeallocated) {
|
|
|
|
return Error::USE_AFTER_FREE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have reached here, the error is still unknown.
|
|
|
|
return Error::UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
const gwp_asan::AllocationMetadata *
|
|
|
|
__gwp_asan_get_metadata(const gwp_asan::AllocatorState *State,
|
|
|
|
const gwp_asan::AllocationMetadata *Metadata,
|
|
|
|
uintptr_t ErrorPtr) {
|
|
|
|
if (!__gwp_asan_error_is_mine(State, ErrorPtr))
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (ErrorPtr >= State->GuardedPagePoolEnd ||
|
|
|
|
State->GuardedPagePool > ErrorPtr)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
const AllocationMetadata *Meta = addrToMetadata(State, Metadata, ErrorPtr);
|
|
|
|
if (Meta->Addr == 0)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return Meta;
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t __gwp_asan_get_allocation_address(
|
|
|
|
const gwp_asan::AllocationMetadata *AllocationMeta) {
|
|
|
|
return AllocationMeta->Addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t __gwp_asan_get_allocation_size(
|
|
|
|
const gwp_asan::AllocationMetadata *AllocationMeta) {
|
|
|
|
return AllocationMeta->Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t __gwp_asan_get_allocation_thread_id(
|
|
|
|
const gwp_asan::AllocationMetadata *AllocationMeta) {
|
|
|
|
return AllocationMeta->AllocationTrace.ThreadID;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t __gwp_asan_get_allocation_trace(
|
|
|
|
const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
|
|
|
|
size_t BufferLen) {
|
2020-07-28 01:51:53 +08:00
|
|
|
uintptr_t UncompressedBuffer[AllocationMetadata::kMaxTraceLengthToCollect];
|
|
|
|
size_t UnpackedLength = gwp_asan::compression::unpack(
|
[GWP-ASan] Crash Handler API.
Summary:
Forewarning: This patch looks big in #LOC changed. I promise it's not that bad, it just moves a lot of content from one file to another. I've gone ahead and left inline comments on Phabricator for sections where this has happened.
This patch:
1. Introduces the crash handler API (crash_handler_api.h).
2. Moves information required for out-of-process crash handling into an AllocatorState. This is a trivially-copied POD struct that designed to be recovered from a deceased process, and used by the crash handler to create a GWP-ASan report (along with the other trivially-copied Metadata struct).
3. Implements the crash handler API using the AllocatorState and Metadata.
4. Adds tests for the crash handler.
5. Reimplements the (now optionally linked by the supporting allocator) in-process crash handler (i.e. the segv handler) using the new crash handler API.
6. Minor updates Scudo & Scudo Standalone to fix compatibility.
7. Changed capitalisation of errors (e.g. /s/Use after free/Use After Free).
Reviewers: cryptoad, eugenis, jfb
Reviewed By: eugenis
Subscribers: merge_guards_bot, pcc, jfb, dexonsmith, mgorny, cryptoad, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D73557
2020-02-06 07:39:03 +08:00
|
|
|
AllocationMeta->AllocationTrace.CompressedTrace,
|
2020-07-28 01:51:53 +08:00
|
|
|
AllocationMeta->AllocationTrace.TraceSize, UncompressedBuffer,
|
|
|
|
AllocationMetadata::kMaxTraceLengthToCollect);
|
|
|
|
if (UnpackedLength < BufferLen)
|
|
|
|
BufferLen = UnpackedLength;
|
|
|
|
memcpy(Buffer, UncompressedBuffer, BufferLen * sizeof(*Buffer));
|
|
|
|
return UnpackedLength;
|
[GWP-ASan] Crash Handler API.
Summary:
Forewarning: This patch looks big in #LOC changed. I promise it's not that bad, it just moves a lot of content from one file to another. I've gone ahead and left inline comments on Phabricator for sections where this has happened.
This patch:
1. Introduces the crash handler API (crash_handler_api.h).
2. Moves information required for out-of-process crash handling into an AllocatorState. This is a trivially-copied POD struct that designed to be recovered from a deceased process, and used by the crash handler to create a GWP-ASan report (along with the other trivially-copied Metadata struct).
3. Implements the crash handler API using the AllocatorState and Metadata.
4. Adds tests for the crash handler.
5. Reimplements the (now optionally linked by the supporting allocator) in-process crash handler (i.e. the segv handler) using the new crash handler API.
6. Minor updates Scudo & Scudo Standalone to fix compatibility.
7. Changed capitalisation of errors (e.g. /s/Use after free/Use After Free).
Reviewers: cryptoad, eugenis, jfb
Reviewed By: eugenis
Subscribers: merge_guards_bot, pcc, jfb, dexonsmith, mgorny, cryptoad, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D73557
2020-02-06 07:39:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool __gwp_asan_is_deallocated(
|
|
|
|
const gwp_asan::AllocationMetadata *AllocationMeta) {
|
|
|
|
return AllocationMeta->IsDeallocated;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t __gwp_asan_get_deallocation_thread_id(
|
|
|
|
const gwp_asan::AllocationMetadata *AllocationMeta) {
|
|
|
|
return AllocationMeta->DeallocationTrace.ThreadID;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t __gwp_asan_get_deallocation_trace(
|
|
|
|
const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
|
|
|
|
size_t BufferLen) {
|
2020-07-28 01:51:53 +08:00
|
|
|
uintptr_t UncompressedBuffer[AllocationMetadata::kMaxTraceLengthToCollect];
|
|
|
|
size_t UnpackedLength = gwp_asan::compression::unpack(
|
[GWP-ASan] Crash Handler API.
Summary:
Forewarning: This patch looks big in #LOC changed. I promise it's not that bad, it just moves a lot of content from one file to another. I've gone ahead and left inline comments on Phabricator for sections where this has happened.
This patch:
1. Introduces the crash handler API (crash_handler_api.h).
2. Moves information required for out-of-process crash handling into an AllocatorState. This is a trivially-copied POD struct that designed to be recovered from a deceased process, and used by the crash handler to create a GWP-ASan report (along with the other trivially-copied Metadata struct).
3. Implements the crash handler API using the AllocatorState and Metadata.
4. Adds tests for the crash handler.
5. Reimplements the (now optionally linked by the supporting allocator) in-process crash handler (i.e. the segv handler) using the new crash handler API.
6. Minor updates Scudo & Scudo Standalone to fix compatibility.
7. Changed capitalisation of errors (e.g. /s/Use after free/Use After Free).
Reviewers: cryptoad, eugenis, jfb
Reviewed By: eugenis
Subscribers: merge_guards_bot, pcc, jfb, dexonsmith, mgorny, cryptoad, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D73557
2020-02-06 07:39:03 +08:00
|
|
|
AllocationMeta->DeallocationTrace.CompressedTrace,
|
2020-07-28 01:51:53 +08:00
|
|
|
AllocationMeta->DeallocationTrace.TraceSize, UncompressedBuffer,
|
|
|
|
AllocationMetadata::kMaxTraceLengthToCollect);
|
|
|
|
if (UnpackedLength < BufferLen)
|
|
|
|
BufferLen = UnpackedLength;
|
|
|
|
memcpy(Buffer, UncompressedBuffer, BufferLen * sizeof(*Buffer));
|
|
|
|
return UnpackedLength;
|
[GWP-ASan] Crash Handler API.
Summary:
Forewarning: This patch looks big in #LOC changed. I promise it's not that bad, it just moves a lot of content from one file to another. I've gone ahead and left inline comments on Phabricator for sections where this has happened.
This patch:
1. Introduces the crash handler API (crash_handler_api.h).
2. Moves information required for out-of-process crash handling into an AllocatorState. This is a trivially-copied POD struct that designed to be recovered from a deceased process, and used by the crash handler to create a GWP-ASan report (along with the other trivially-copied Metadata struct).
3. Implements the crash handler API using the AllocatorState and Metadata.
4. Adds tests for the crash handler.
5. Reimplements the (now optionally linked by the supporting allocator) in-process crash handler (i.e. the segv handler) using the new crash handler API.
6. Minor updates Scudo & Scudo Standalone to fix compatibility.
7. Changed capitalisation of errors (e.g. /s/Use after free/Use After Free).
Reviewers: cryptoad, eugenis, jfb
Reviewed By: eugenis
Subscribers: merge_guards_bot, pcc, jfb, dexonsmith, mgorny, cryptoad, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D73557
2020-02-06 07:39:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
} // extern "C"
|
|
|
|
#endif
|