Skip to content
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
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ See docs/process.md for more on how version tagging works.
includes all downstream patches and many upstream changes.
- libc++ library updated to llvm-13. (#15901)
- libc++-abi library updated to llvm-13. (#15904)
- compiler-rt library updated to llvm-13. (#15906)

3.1.0 - 12/22/2021
------------------
Expand Down
111 changes: 74 additions & 37 deletions system/lib/compiler-rt/include/sanitizer/dfsan_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,15 @@
extern "C" {
#endif

typedef uint16_t dfsan_label;

/// Stores information associated with a specific label identifier. A label
/// may be a base label created using dfsan_create_label, with associated
/// text description and user data, or an automatically created union label,
/// which represents the union of two label identifiers (which may themselves
/// be base or union labels).
struct dfsan_label_info {
// Fields for union labels, set to 0 for base labels.
dfsan_label l1;
dfsan_label l2;

// Fields for base labels.
const char *desc;
void *userdata;
};
typedef uint8_t dfsan_label;
typedef uint32_t dfsan_origin;

/// Signature of the callback argument to dfsan_set_write_callback().
typedef void (*dfsan_write_callback_t)(int fd, const void *buf, size_t count);

/// Computes the union of \c l1 and \c l2, possibly creating a union label in
/// the process.
/// Computes the union of \c l1 and \c l2, resulting in a union label.
dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2);

/// Creates and returns a base label with the given description and user data.
dfsan_label dfsan_create_label(const char *desc, void *userdata);

/// Sets the label for each address in [addr,addr+size) to \c label.
void dfsan_set_label(dfsan_label label, void *addr, size_t size);

Expand All @@ -63,22 +45,18 @@ void dfsan_add_label(dfsan_label label, void *addr, size_t size);
/// value.
dfsan_label dfsan_get_label(long data);

/// Retrieves the immediate origin associated with the given data. The returned
/// origin may point to another origin.
///
/// The type of 'data' is arbitrary.
dfsan_origin dfsan_get_origin(long data);

/// Retrieves the label associated with the data at the given address.
dfsan_label dfsan_read_label(const void *addr, size_t size);

/// Retrieves a pointer to the dfsan_label_info struct for the given label.
const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label);

/// Returns whether the given label label contains the label elem.
int dfsan_has_label(dfsan_label label, dfsan_label elem);

/// If the given label label contains a label with the description desc, returns
/// that label, else returns 0.
dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc);

/// Returns the number of labels allocated.
size_t dfsan_get_label_count(void);

/// Flushes the DFSan shadow, i.e. forgets about all labels currently associated
/// with the application memory. Use this call to start over the taint tracking
/// within the same process.
Expand All @@ -92,12 +70,6 @@ void dfsan_flush(void);
/// callback executes. Pass in NULL to remove any callback.
void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback);

/// Writes the labels currently used by the program to the given file
/// descriptor. The lines of the output have the following format:
///
/// <label> <parent label 1> <parent label 2> <label description if any>
void dfsan_dump_labels(int fd);

/// Interceptor hooks.
/// Whenever a dfsan's custom function is called the corresponding
/// hook is called it non-zero. The hooks should be defined by the user.
Expand All @@ -110,6 +82,71 @@ void dfsan_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2,
void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
size_t n, dfsan_label s1_label,
dfsan_label s2_label, dfsan_label n_label);

/// Prints the origin trace of the label at the address addr to stderr. It also
/// prints description at the beginning of the trace. If origin tracking is not
/// on, or the address is not labeled, it prints nothing.
void dfsan_print_origin_trace(const void *addr, const char *description);

/// Prints the origin trace of the label at the address \p addr to a
/// pre-allocated output buffer. If origin tracking is not on, or the address is
/// not labeled, it prints nothing.
///
/// Typical usage:
/// \code
/// char kDescription[] = "...";
/// char buf[1024];
/// dfsan_sprint_origin_trace(&tainted_var, kDescription, buf, sizeof(buf));
/// \endcode
///
/// Typical usage that handles truncation:
/// \code
/// char buf[1024];
/// int len = dfsan_sprint_origin_trace(&var, nullptr, buf, sizeof(buf));
///
/// if (len < sizeof(buf)) {
/// ProcessOriginTrace(buf);
/// } else {
/// char *tmpbuf = new char[len + 1];
/// dfsan_sprint_origin_trace(&var, nullptr, tmpbuf, len + 1);
/// ProcessOriginTrace(tmpbuf);
/// delete[] tmpbuf;
/// }
/// \endcode
///
/// \param addr The tainted memory address whose origin we are printing.
/// \param description A description printed at the beginning of the trace.
/// \param [out] out_buf The output buffer to write the results to.
/// \param out_buf_size The size of \p out_buf.
///
/// \returns The number of symbols that should have been written to \p out_buf
/// (not including trailing null byte '\0'). Thus, the string is truncated iff
/// return value is not less than \p out_buf_size.
size_t dfsan_sprint_origin_trace(const void *addr, const char *description,
char *out_buf, size_t out_buf_size);

/// Prints the stack trace leading to this call to a pre-allocated output
/// buffer.
///
/// For usage examples, see dfsan_sprint_origin_trace.
///
/// \param [out] out_buf The output buffer to write the results to.
/// \param out_buf_size The size of \p out_buf.
///
/// \returns The number of symbols that should have been written to \p out_buf
/// (not including trailing null byte '\0'). Thus, the string is truncated iff
/// return value is not less than \p out_buf_size.
size_t dfsan_sprint_stack_trace(char *out_buf, size_t out_buf_size);

/// Retrieves the very first origin associated with the data at the given
/// address.
dfsan_origin dfsan_get_init_origin(const void *addr);

/// Returns the value of -dfsan-track-origins.
/// * 0: do not track origins.
/// * 1: track origins at memory store operations.
/// * 2: track origins at memory load and store operations.
int dfsan_get_track_origins(void);
#ifdef __cplusplus
} // extern "C"

Expand Down
17 changes: 16 additions & 1 deletion system/lib/compiler-rt/include/sanitizer/tsan_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ static const unsigned __tsan_mutex_recursive_lock = 1 << 6;
// the corresponding __tsan_mutex_post_lock annotation.
static const unsigned __tsan_mutex_recursive_unlock = 1 << 7;

// Convenient composed constants.
static const unsigned __tsan_mutex_try_read_lock =
__tsan_mutex_read_lock | __tsan_mutex_try_lock;
static const unsigned __tsan_mutex_try_read_lock_failed =
__tsan_mutex_try_read_lock | __tsan_mutex_try_lock_failed;

// Annotate creation of a mutex.
// Supported flags: mutex creation flags.
void __tsan_mutex_create(void *addr, unsigned flags);
Expand Down Expand Up @@ -141,7 +147,7 @@ void __tsan_external_write(void *addr, void *caller_pc, void *tag);
// and freed by __tsan_destroy_fiber.
// - TSAN context of current fiber or thread can be obtained
// by calling __tsan_get_current_fiber.
// - __tsan_switch_to_fiber should be called immediatly before switch
// - __tsan_switch_to_fiber should be called immediately before switch
// to fiber, such as call of swapcontext.
// - Fiber name can be set by __tsan_set_fiber_name.
void *__tsan_get_current_fiber(void);
Expand All @@ -154,6 +160,15 @@ void __tsan_set_fiber_name(void *fiber, const char *name);
// Do not establish a happens-before relation between fibers
static const unsigned __tsan_switch_to_fiber_no_sync = 1 << 0;

// User-provided callback invoked on TSan initialization.
void __tsan_on_initialize();

// User-provided callback invoked on TSan shutdown.
// `failed` - Nonzero if TSan did detect issues, zero otherwise.
// Return `0` if TSan should exit as if no issues were detected. Return nonzero
// if TSan should exit as if issues were detected.
int __tsan_on_finalize(int failed);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
14 changes: 6 additions & 8 deletions system/lib/compiler-rt/lib/asan/asan_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ struct Allocator {
return false;
if (m->Beg() != addr) return false;
AsanThread *t = GetCurrentThread();
m->SetAllocContext(t ? t->tid() : 0, StackDepotPut(*stack));
m->SetAllocContext(t ? t->tid() : kMainTid, StackDepotPut(*stack));
return true;
}

Expand Down Expand Up @@ -570,7 +570,7 @@ struct Allocator {
m->SetUsedSize(size);
m->user_requested_alignment_log = user_requested_alignment_log;

m->SetAllocContext(t ? t->tid() : 0, StackDepotPut(*stack));
m->SetAllocContext(t ? t->tid() : kMainTid, StackDepotPut(*stack));

uptr size_rounded_down_to_granularity =
RoundDownTo(size, SHADOW_GRANULARITY);
Expand Down Expand Up @@ -852,12 +852,12 @@ struct Allocator {
quarantine.PrintStats();
}

void ForceLock() {
void ForceLock() ACQUIRE(fallback_mutex) {
allocator.ForceLock();
fallback_mutex.Lock();
}

void ForceUnlock() {
void ForceUnlock() RELEASE(fallback_mutex) {
fallback_mutex.Unlock();
allocator.ForceUnlock();
}
Expand Down Expand Up @@ -1081,11 +1081,9 @@ uptr asan_mz_size(const void *ptr) {
return instance.AllocationSize(reinterpret_cast<uptr>(ptr));
}

void asan_mz_force_lock() {
instance.ForceLock();
}
void asan_mz_force_lock() NO_THREAD_SAFETY_ANALYSIS { instance.ForceLock(); }

void asan_mz_force_unlock() {
void asan_mz_force_unlock() NO_THREAD_SAFETY_ANALYSIS {
instance.ForceUnlock();
}

Expand Down
19 changes: 12 additions & 7 deletions system/lib/compiler-rt/lib/asan/asan_descriptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ void DescribeThread(AsanThreadContext *context) {
CHECK(context);
asanThreadRegistry().CheckLocked();
// No need to announce the main thread.
if (context->tid == 0 || context->announced) {
if (context->tid == kMainTid || context->announced) {
return;
}
context->announced = true;
InternalScopedString str(1024);
InternalScopedString str;
str.append("Thread %s", AsanThreadIdAndName(context).c_str());
if (context->parent_tid == kInvalidTid) {
str.append(" created by unknown thread\n");
Expand Down Expand Up @@ -77,7 +77,6 @@ static bool GetShadowKind(uptr addr, ShadowKind *shadow_kind) {
} else if (AddrIsInLowShadow(addr)) {
*shadow_kind = kShadowKindLow;
} else {
CHECK(0 && "Address is not in memory and not in shadow?");
return false;
}
return true;
Expand Down Expand Up @@ -126,7 +125,7 @@ static void GetAccessToHeapChunkInformation(ChunkAccess *descr,

static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) {
Decorator d;
InternalScopedString str(4096);
InternalScopedString str;
str.append("%s", d.Location());
switch (descr.access_type) {
case kAccessTypeLeft:
Expand Down Expand Up @@ -243,7 +242,7 @@ static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr,
else if (addr >= prev_var_end && addr - prev_var_end >= var.beg - addr_end)
pos_descr = "underflows";
}
InternalScopedString str(1024);
InternalScopedString str;
str.append(" [%zd, %zd)", var.beg, var_end);
// Render variable name.
str.append(" '");
Expand Down Expand Up @@ -276,7 +275,7 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
// Global descriptions
static void DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
const __asan_global &g) {
InternalScopedString str(4096);
InternalScopedString str;
Decorator d;
str.append("%s", d.Location());
if (addr < g.beg) {
Expand Down Expand Up @@ -464,7 +463,13 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size,
return;
}
data.kind = kAddressKindWild;
addr = 0;
data.wild.addr = addr;
data.wild.access_size = access_size;
}

void WildAddressDescription::Print() const {
Printf("Address %p is a wild pointer inside of access range of size %p.\n",
addr, access_size);
}

void PrintAddressDescription(uptr addr, uptr access_size,
Expand Down
13 changes: 10 additions & 3 deletions system/lib/compiler-rt/lib/asan/asan_descriptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ struct StackAddressDescription {
bool GetStackAddressInformation(uptr addr, uptr access_size,
StackAddressDescription *descr);

struct WildAddressDescription {
uptr addr;
uptr access_size;

void Print() const;
};

struct GlobalAddressDescription {
uptr addr;
// Assume address is close to at most four globals.
Expand Down Expand Up @@ -193,7 +200,7 @@ class AddressDescription {
HeapAddressDescription heap;
StackAddressDescription stack;
GlobalAddressDescription global;
uptr addr;
WildAddressDescription wild;
};
};

Expand All @@ -211,7 +218,7 @@ class AddressDescription {
uptr Address() const {
switch (data.kind) {
case kAddressKindWild:
return data.addr;
return data.wild.addr;
case kAddressKindShadow:
return data.shadow.addr;
case kAddressKindHeap:
Expand All @@ -226,7 +233,7 @@ class AddressDescription {
void Print(const char *bug_descr = nullptr) const {
switch (data.kind) {
case kAddressKindWild:
Printf("Address %p is a wild pointer.\n", data.addr);
data.wild.Print();
return;
case kAddressKindShadow:
return data.shadow.Print();
Expand Down
8 changes: 4 additions & 4 deletions system/lib/compiler-rt/lib/asan/asan_errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ void ErrorODRViolation::Print() {
Report("ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(),
global1.beg);
Printf("%s", d.Default());
InternalScopedString g1_loc(256), g2_loc(256);
InternalScopedString g1_loc;
InternalScopedString g2_loc;
PrintGlobalLocation(&g1_loc, global1);
PrintGlobalLocation(&g2_loc, global2);
Printf(" [1] size=%zd '%s' %s\n", global1.size,
Expand All @@ -360,7 +361,7 @@ void ErrorODRViolation::Print() {
Report(
"HINT: if you don't care about these errors you may set "
"ASAN_OPTIONS=detect_odr_violation=0\n");
InternalScopedString error_msg(256);
InternalScopedString error_msg;
error_msg.append("%s: global '%s' at %s", scariness.GetDescription(),
MaybeDemangleGlobalName(global1.name), g1_loc.data());
ReportErrorSummary(error_msg.data());
Expand Down Expand Up @@ -543,7 +544,6 @@ static void PrintLegend(InternalScopedString *str) {
PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
PrintShadowByte(str, " Left alloca redzone: ", kAsanAllocaLeftMagic);
PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic);
PrintShadowByte(str, " Shadow gap: ", kAsanShadowGap);
}

static void PrintShadowBytes(InternalScopedString *str, const char *before,
Expand All @@ -565,7 +565,7 @@ static void PrintShadowMemoryForAddress(uptr addr) {
uptr shadow_addr = MemToShadow(addr);
const uptr n_bytes_per_row = 16;
uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
InternalScopedString str(4096 * 8);
InternalScopedString str;
str.append("Shadow bytes around the buggy address:\n");
for (int i = -5; i <= 5; i++) {
uptr row_shadow_addr = aligned_shadow + i * n_bytes_per_row;
Expand Down
Loading