Skip to content

Commit

Permalink
Revert "[DFSan] Remove trampolines to unblock opaque pointers."
Browse files Browse the repository at this point in the history
This reverts commit 84af903.
  • Loading branch information
browneee committed Mar 14, 2022
1 parent 003c0b9 commit edc33fa
Show file tree
Hide file tree
Showing 10 changed files with 310 additions and 132 deletions.
16 changes: 1 addition & 15 deletions compiler-rt/lib/dfsan/dfsan.cpp
Expand Up @@ -937,20 +937,6 @@ void dfsan_clear_thread_local_state() {
}
}

SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_set_arg_tls(uptr offset, dfsan_label label) {
// 2x to match ShadowTLSAlignment.
// ShadowTLSAlignment should probably be changed.
// TODO: Consider reducing ShadowTLSAlignment to 1.
// Aligning to 2 bytes is probably a remnant of fast16 mode.
((dfsan_label *)__dfsan_arg_tls)[offset * 2] = label;
}

SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o) {
__dfsan_arg_origin_tls[offset] = o;
}

extern "C" void dfsan_flush() {
const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
Expand Down Expand Up @@ -1120,7 +1106,7 @@ static void DFsanInit(int argc, char **argv, char **envp) {

dfsan_allocator_init();

DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr);
DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr, nullptr);
SetCurrentThread(main_thread);
main_thread->Init();

Expand Down
6 changes: 0 additions & 6 deletions compiler-rt/lib/dfsan/dfsan.h
Expand Up @@ -36,12 +36,6 @@ void dfsan_clear_arg_tls(uptr offset, uptr size);
// Zero out the TLS storage.
void dfsan_clear_thread_local_state();

// Set DFSan label and origin TLS of argument for a call.
// Note that offset may not correspond with argument number.
// Some arguments (aggregate/array) will use several offsets.
void dfsan_set_arg_tls(uptr offset, dfsan_label label);
void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o);

// Return the origin associated with the first taint byte in the size bytes
// from the address addr.
dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, uptr size);
Expand Down
213 changes: 127 additions & 86 deletions compiler-rt/lib/dfsan/dfsan_custom.cpp
Expand Up @@ -753,6 +753,7 @@ static void *DFsanThreadStartFunc(void *arg) {
}

static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *start_routine_trampoline,
void *start_routine, void *arg,
dfsan_label *ret_label,
bool track_origins = false) {
Expand All @@ -766,7 +767,8 @@ static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));

DFsanThread *t =
DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);
DFsanThread::Create(start_routine_trampoline,
(thread_callback_t)start_routine, arg, track_origins);
ScopedBlockSignals block(&t->starting_sigset_);
int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);

Expand All @@ -777,22 +779,28 @@ static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
}

SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
void *arg, dfsan_label thread_label, dfsan_label attr_label,
dfsan_label start_routine_label, dfsan_label arg_label,
dfsan_label *ret_label) {
return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label);
pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine_trampoline)(void *, void *, dfsan_label,
dfsan_label *),
void *start_routine, void *arg, dfsan_label thread_label,
dfsan_label attr_label, dfsan_label start_routine_label,
dfsan_label arg_label, dfsan_label *ret_label) {
return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline,
start_routine, arg, ret_label);
}

SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
void *arg, dfsan_label thread_label, dfsan_label attr_label,
dfsan_label start_routine_label, dfsan_label arg_label,
dfsan_label *ret_label, dfsan_origin thread_origin,
pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine_trampoline)(void *, void *, dfsan_label,
dfsan_label *, dfsan_origin,
dfsan_origin *),
void *start_routine, void *arg, dfsan_label thread_label,
dfsan_label attr_label, dfsan_label start_routine_label,
dfsan_label arg_label, dfsan_label *ret_label, dfsan_origin thread_origin,
dfsan_origin attr_origin, dfsan_origin start_routine_origin,
dfsan_origin arg_origin, dfsan_origin *ret_origin) {
return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,
true);
return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline,
start_routine, arg, ret_label, true);
}

SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
Expand All @@ -817,7 +825,22 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
}

struct dl_iterate_phdr_info {
int (*callback)(struct dl_phdr_info *info, size_t size, void *data);
int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
size_t size, void *data, dfsan_label info_label,
dfsan_label size_label, dfsan_label data_label,
dfsan_label *ret_label);
void *callback;
void *data;
};

struct dl_iterate_phdr_origin_info {
int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
size_t size, void *data, dfsan_label info_label,
dfsan_label size_label, dfsan_label data_label,
dfsan_label *ret_label, dfsan_origin info_origin,
dfsan_origin size_origin, dfsan_origin data_origin,
dfsan_origin *ret_origin);
void *callback;
void *data;
};

Expand All @@ -829,28 +852,53 @@ int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
dfsan_set_label(
0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
dfsan_label ret_label;
return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
0, &ret_label);
}

dfsan_clear_thread_local_state();
return dipi->callback(info, size, dipi->data);
int dl_iterate_phdr_origin_cb(struct dl_phdr_info *info, size_t size,
void *data) {
dl_iterate_phdr_origin_info *dipi = (dl_iterate_phdr_origin_info *)data;
dfsan_set_label(0, *info);
dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
strlen(info->dlpi_name) + 1);
dfsan_set_label(
0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
dfsan_label ret_label;
dfsan_origin ret_origin;
return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
0, &ret_label, 0, 0, 0, &ret_origin);
}

SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
void *data, dfsan_label callback_label, dfsan_label data_label,
dfsan_label *ret_label) {
dl_iterate_phdr_info dipi = {callback, data};
int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
size_t size, void *data, dfsan_label info_label,
dfsan_label size_label, dfsan_label data_label,
dfsan_label *ret_label),
void *callback, void *data, dfsan_label callback_label,
dfsan_label data_label, dfsan_label *ret_label) {
dl_iterate_phdr_info dipi = { callback_trampoline, callback, data };
*ret_label = 0;
return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
}

SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
void *data, dfsan_label callback_label, dfsan_label data_label,
dfsan_label *ret_label, dfsan_origin callback_origin,
dfsan_origin data_origin, dfsan_origin *ret_origin) {
dl_iterate_phdr_info dipi = {callback, data};
int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
size_t size, void *data, dfsan_label info_label,
dfsan_label size_label, dfsan_label data_label,
dfsan_label *ret_label, dfsan_origin info_origin,
dfsan_origin size_origin,
dfsan_origin data_origin,
dfsan_origin *ret_origin),
void *callback, void *data, dfsan_label callback_label,
dfsan_label data_label, dfsan_label *ret_label,
dfsan_origin callback_origin, dfsan_origin data_origin,
dfsan_origin *ret_origin) {
dl_iterate_phdr_origin_info dipi = {callback_trampoline, callback, data};
*ret_label = 0;
return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
return dl_iterate_phdr(dl_iterate_phdr_origin_cb, &dipi);
}

// This function is only available for glibc 2.27 or newer. Mark it weak so
Expand Down Expand Up @@ -1581,7 +1629,10 @@ static void SignalHandler(int signo) {
SignalHandlerScope signal_handler_scope;
ScopedClearThreadLocalState scoped_clear_tls;

// Clear shadows for all inputs provided by system.
// Clear shadows for all inputs provided by system. This is why DFSan
// instrumentation generates a trampoline function to each function pointer,
// and uses the trampoline to clear shadows. However sigaction does not use
// a function pointer directly, so we have to do this manually.
dfsan_clear_arg_tls(0, sizeof(dfsan_label));

typedef void (*signal_cb)(int x);
Expand Down Expand Up @@ -1682,18 +1733,22 @@ static sighandler_t dfsan_signal(int signum, sighandler_t handler,
}

SANITIZER_INTERFACE_ATTRIBUTE
sighandler_t __dfsw_signal(int signum, sighandler_t handler,
dfsan_label signum_label, dfsan_label handler_label,
dfsan_label *ret_label) {
sighandler_t __dfsw_signal(int signum,
void *(*handler_trampoline)(void *, int, dfsan_label,
dfsan_label *),
sighandler_t handler, dfsan_label signum_label,
dfsan_label handler_label, dfsan_label *ret_label) {
return dfsan_signal(signum, handler, ret_label);
}

SANITIZER_INTERFACE_ATTRIBUTE
sighandler_t __dfso_signal(int signum, sighandler_t handler,
dfsan_label signum_label, dfsan_label handler_label,
dfsan_label *ret_label, dfsan_origin signum_origin,
dfsan_origin handler_origin,
dfsan_origin *ret_origin) {
sighandler_t __dfso_signal(
int signum,
void *(*handler_trampoline)(void *, int, dfsan_label, dfsan_label *,
dfsan_origin, dfsan_origin *),
sighandler_t handler, dfsan_label signum_label, dfsan_label handler_label,
dfsan_label *ret_label, dfsan_origin signum_origin,
dfsan_origin handler_origin, dfsan_origin *ret_origin) {
return dfsan_signal(signum, handler, ret_label);
}

Expand Down Expand Up @@ -2033,72 +2088,58 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
addrlen_label, ret_label);
}

// Type of the function passed to dfsan_set_write_callback.
typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);
// Type of the trampoline function passed to the custom version of
// dfsan_set_write_callback.
typedef void (*write_trampoline_t)(
void *callback,
int fd, const void *buf, ssize_t count,
dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label);

typedef void (*write_origin_trampoline_t)(
void *callback, int fd, const void *buf, ssize_t count,
dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin);

// Calls to dfsan_set_write_callback() set the values in this struct.
// Calls to the custom version of write() read (and invoke) them.
static struct {
write_dfsan_callback_t write_callback = nullptr;
write_trampoline_t write_callback_trampoline = nullptr;
void *write_callback = nullptr;
} write_callback_info;

SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(
write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
static struct {
write_origin_trampoline_t write_callback_trampoline = nullptr;
void *write_callback = nullptr;
} write_origin_callback_info;

SANITIZER_INTERFACE_ATTRIBUTE void
__dfsw_dfsan_set_write_callback(
write_trampoline_t write_callback_trampoline,
void *write_callback,
dfsan_label write_callback_label,
dfsan_label *ret_label) {
write_callback_info.write_callback_trampoline = write_callback_trampoline;
write_callback_info.write_callback = write_callback;
}

SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(
write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
dfsan_label *ret_label, dfsan_origin write_callback_origin,
dfsan_origin *ret_origin) {
write_callback_info.write_callback = write_callback;
}

static inline void setup_tls_args_for_write_callback(
dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin,
dfsan_origin count_origin) {
// The callback code will expect argument shadow labels in the args TLS,
// and origin labels in the origin args TLS.
// Previously this was done by a trampoline, but we want to remove this:
// https://github.com/llvm/llvm-project/issues/54172
//
// Instead, this code is manually setting up the args TLS data.
//
// The offsets used need to correspond with the instrumentation code,
// see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
// DFSanFunction::getShadowForTLSArgument.
// https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684
// https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125
//
// Here the arguments are all primitives, but it can be more complex
// to compute offsets for array/aggregate type arguments.
//
// TODO(browneee): Consider a builtin to improve maintainabliity.
// With a builtin, we would provide the argument labels via builtin,
// and the builtin would reuse parts of the instrumentation code to ensure
// that this code and the instrumentation can never be out of sync.
// Note: Currently DFSan instrumentation does not run on this code, so
// the builtin may need to be handled outside DFSan instrumentation.
dfsan_set_arg_tls(0, fd_label);
dfsan_set_arg_tls(1, buf_label);
dfsan_set_arg_tls(2, count_label);
if (origins) {
dfsan_set_arg_origin_tls(0, fd_origin);
dfsan_set_arg_origin_tls(1, buf_origin);
dfsan_set_arg_origin_tls(2, count_origin);
}
write_origin_trampoline_t write_callback_trampoline, void *write_callback,
dfsan_label write_callback_label, dfsan_label *ret_label,
dfsan_origin write_callback_origin, dfsan_origin *ret_origin) {
write_origin_callback_info.write_callback_trampoline =
write_callback_trampoline;
write_origin_callback_info.write_callback = write_callback;
}

SANITIZER_INTERFACE_ATTRIBUTE int
__dfsw_write(int fd, const void *buf, size_t count,
dfsan_label fd_label, dfsan_label buf_label,
dfsan_label count_label, dfsan_label *ret_label) {
if (write_callback_info.write_callback) {
setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,
0, 0, 0);
write_callback_info.write_callback(fd, buf, count);
write_callback_info.write_callback_trampoline(
write_callback_info.write_callback,
fd, buf, count,
fd_label, buf_label, count_label);
}

*ret_label = 0;
Expand All @@ -2110,10 +2151,10 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
dfsan_origin *ret_origin) {
if (write_callback_info.write_callback) {
setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true,
fd_origin, buf_origin, count_origin);
write_callback_info.write_callback(fd, buf, count);
if (write_origin_callback_info.write_callback) {
write_origin_callback_info.write_callback_trampoline(
write_origin_callback_info.write_callback, fd, buf, count, fd_label,
buf_label, count_label, fd_origin, buf_origin, count_origin);
}

*ret_label = 0;
Expand Down

0 comments on commit edc33fa

Please sign in to comment.