[DFSan] Add functions to print origin trace from origin id instead of address.

dfsan_print_origin_id_trace
dfsan_sprint_origin_id_trace

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D116184
This commit is contained in:
Andrew Browne 2021-12-22 12:35:42 -08:00
parent 9b39737129
commit ed6c757d5c
4 changed files with 156 additions and 14 deletions

View File

@ -87,6 +87,9 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
/// 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);
/// As above, but use an origin id from dfsan_get_origin() instead of address.
/// Does not include header line with taint label and address information.
void dfsan_print_origin_id_trace(dfsan_origin origin);
/// 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
@ -124,6 +127,10 @@ void dfsan_print_origin_trace(const void *addr, const char *description);
/// 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);
/// As above, but use an origin id from dfsan_get_origin() instead of address.
/// Does not include header line with taint label and address information.
size_t dfsan_sprint_origin_id_trace(dfsan_origin origin, char *out_buf,
size_t out_buf_size);
/// Prints the stack trace leading to this call to a pre-allocated output
/// buffer.

View File

@ -630,22 +630,16 @@ void PrintInvalidOriginWarning(dfsan_label label, const void *address) {
d.Warning(), label, address, d.Default());
}
bool PrintOriginTraceToStr(const void *addr, const char *description,
InternalScopedString *out) {
CHECK(out);
CHECK(dfsan_get_track_origins());
void PrintInvalidOriginIdWarning(dfsan_origin origin) {
Decorator d;
Printf(
" %sOrigin Id %d has invalid origin tracking. This can "
"be a DFSan bug.%s\n",
d.Warning(), origin, d.Default());
}
const dfsan_label label = *__dfsan::shadow_for(addr);
CHECK(label);
const dfsan_origin origin = *__dfsan::origin_for(addr);
out->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n",
d.Origin(), label, addr, description ? description : "",
d.Default());
Origin o = Origin::FromRawId(origin);
bool PrintOriginTraceFramesToStr(Origin o, InternalScopedString *out) {
Decorator d;
bool found = false;
while (o.isChainedOrigin()) {
@ -668,6 +662,25 @@ bool PrintOriginTraceToStr(const void *addr, const char *description,
return found;
}
bool PrintOriginTraceToStr(const void *addr, const char *description,
InternalScopedString *out) {
CHECK(out);
CHECK(dfsan_get_track_origins());
Decorator d;
const dfsan_label label = *__dfsan::shadow_for(addr);
CHECK(label);
const dfsan_origin origin = *__dfsan::origin_for(addr);
out->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n",
d.Origin(), label, addr, description ? description : "",
d.Default());
Origin o = Origin::FromRawId(origin);
return PrintOriginTraceFramesToStr(o, out);
}
} // namespace
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_trace(
@ -725,6 +738,50 @@ dfsan_sprint_origin_trace(const void *addr, const char *description,
return trace.length();
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_id_trace(
dfsan_origin origin) {
if (!dfsan_get_track_origins()) {
PrintNoOriginTrackingWarning();
return;
}
Origin o = Origin::FromRawId(origin);
InternalScopedString trace;
bool success = PrintOriginTraceFramesToStr(o, &trace);
if (trace.length())
Printf("%s", trace.data());
if (!success)
PrintInvalidOriginIdWarning(origin);
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr dfsan_sprint_origin_id_trace(
dfsan_origin origin, char *out_buf, uptr out_buf_size) {
CHECK(out_buf);
if (!dfsan_get_track_origins()) {
PrintNoOriginTrackingWarning();
return 0;
}
Origin o = Origin::FromRawId(origin);
InternalScopedString trace;
bool success = PrintOriginTraceFramesToStr(o, &trace);
if (!success) {
PrintInvalidOriginIdWarning(origin);
return 0;
}
if (out_buf_size) {
internal_strncpy(out_buf, trace.data(), out_buf_size - 1);
out_buf[out_buf_size - 1] = '\0';
}
return trace.length();
}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
dfsan_get_init_origin(const void *addr) {
if (!dfsan_get_track_origins())

View File

@ -30,8 +30,12 @@ fun:dfsan_flush=uninstrumented
fun:dfsan_flush=discard
fun:dfsan_print_origin_trace=uninstrumented
fun:dfsan_print_origin_trace=discard
fun:dfsan_print_origin_id_trace=uninstrumented
fun:dfsan_print_origin_id_trace=discard
fun:dfsan_sprint_origin_trace=uninstrumented
fun:dfsan_sprint_origin_trace=discard
fun:dfsan_sprint_origin_id_trace=uninstrumented
fun:dfsan_sprint_origin_id_trace=discard
fun:dfsan_sprint_stack_trace=uninstrumented
fun:dfsan_sprint_stack_trace=discard
fun:dfsan_get_origin=uninstrumented

View File

@ -0,0 +1,74 @@
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-instrument-with-call-threshold=0 %s -o %t && \
// RUN: %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
//
// REQUIRES: x86_64-target-arch
#include <sanitizer/dfsan_interface.h>
#include <stdio.h>
#include <string.h>
__attribute__((noinline)) int foo(int a, int b) { return a + b; }
__attribute__((noinline)) void bar(int depth, void *addr, int size) {
if (depth) {
bar(depth - 1, addr, size);
} else {
dfsan_set_label(1, addr, size);
}
}
__attribute__((noinline)) void baz(int depth, void *addr, int size) {
bar(depth, addr, size);
}
int main(int argc, char *argv[]) {
int a = 10;
int b = 20;
baz(8, &a, sizeof(a));
int c = foo(a, b);
dfsan_origin c_o = dfsan_get_origin(c);
dfsan_print_origin_id_trace(c_o);
// CHECK: Origin value: {{.*}}, Taint value was created at
// CHECK: #0 {{.*}} in bar.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-16]]
// CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in bar.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-19]]
// CHECK: #9 {{.*}} in baz.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-13]]
char buf[3000];
size_t length = dfsan_sprint_origin_id_trace(c_o, buf, sizeof(buf));
printf("==OUTPUT==\n\n%s==EOS==\n", buf);
// CHECK: ==OUTPUT==
// CHECK: Origin value: {{.*}}, Taint value was created at
// CHECK: #0 {{.*}} in bar.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-26]]
// CHECK-COUNT-8: #{{[0-9]+}} {{.*}} in bar.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-29]]
// CHECK: #9 {{.*}} in baz.dfsan {{.*}}origin_id_stack_trace.c:[[@LINE-23]]
// CHECK: ==EOS==
char tinybuf[20];
size_t same_length =
dfsan_sprint_origin_id_trace(c_o, tinybuf, sizeof(tinybuf));
printf("==TRUNCATED OUTPUT==\n\n%s==EOS==\n", tinybuf);
// CHECK: ==TRUNCATED OUTPUT==
// CHECK: Origin value: 0x1==EOS==
printf("Returned length: %zu\n", length);
printf("Actual length: %zu\n", strlen(buf));
printf("Returned length with truncation: %zu\n", same_length);
// CHECK: Returned length: [[#LEN:]]
// CHECK: Actual length: [[#LEN]]
// CHECK: Returned length with truncation: [[#LEN]]
buf[0] = '\0';
length = dfsan_sprint_origin_id_trace(c_o, buf, 0);
printf("Output=\"%s\"\n", buf);
printf("Returned length: %zu\n", length);
// CHECK: Output=""
// CHECK: Returned length: [[#LEN]]
}