mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-29 00:32:29 +00:00
Have ASAN errors show origin of memory
This commit is contained in:
parent
e20fcf02c1
commit
46a3b88594
6 changed files with 256 additions and 4 deletions
53
examples/auto-memory-safety-crash.c
Normal file
53
examples/auto-memory-safety-crash.c
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#if 0
|
||||||
|
/*─────────────────────────────────────────────────────────────────╗
|
||||||
|
│ To the extent possible under law, Justine Tunney has waived │
|
||||||
|
│ all copyright and related or neighboring rights to this file, │
|
||||||
|
│ as it is written in the following disclaimers: │
|
||||||
|
│ • http://unlicense.org/ │
|
||||||
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||||
|
╚─────────────────────────────────────────────────────────────────*/
|
||||||
|
#endif
|
||||||
|
#include "libc/bits/bits.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ASAN static memory safety crash example.
|
||||||
|
*
|
||||||
|
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash.com
|
||||||
|
* o/dbg/examples/auto-memory-safety-crash.com
|
||||||
|
*
|
||||||
|
* You should see:
|
||||||
|
*
|
||||||
|
* global redzone 1-byte store at 0x42700d shadow 0x8007ce01
|
||||||
|
* ./o/dbg/examples/auto-memory-safety-crash.com
|
||||||
|
* x
|
||||||
|
* ........................................GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
|
||||||
|
* |0 |0 |0 |0 |5 |-18 |-18 |-18 |-18
|
||||||
|
* f.☼▼ä f.☼▼ä f☼▼D hello
|
||||||
|
* 000000400000-000000427000 .text
|
||||||
|
* 000000427000-000000429000 .data ←address
|
||||||
|
* 00007fff0000-00008000ffff
|
||||||
|
* 000080070000-00008008ffff ←shadow
|
||||||
|
* 0e007fff0000-0e008000ffff
|
||||||
|
* 100047d20000-100047d3ffff
|
||||||
|
* 6ffffffe0000-6fffffffffff
|
||||||
|
* the memory in question belongs to the symbols
|
||||||
|
* buffer [0x427000,0x42700c] size 13
|
||||||
|
* the crash was caused by
|
||||||
|
* 0x00000000004046f3: __die at libc/log/die.c:40
|
||||||
|
* 0x0000000000404aed: __asan_report_store at libc/intrin/asan.c:1183
|
||||||
|
* 0x0000000000402552: main at examples/auto-memory-safety-crash.c:27
|
||||||
|
* 0x000000000040268d: cosmo at libc/runtime/cosmo.S:64
|
||||||
|
* 0x00000000004021ae: _start at libc/crt/crt.S:77
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
char buffer[13] = "hello";
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
|
||||||
|
int i = 13;
|
||||||
|
asm("" : "+r"(i)); /* prevent compiler being smart */
|
||||||
|
buffer[i] = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
65
examples/auto-memory-safety-crash2.c
Normal file
65
examples/auto-memory-safety-crash2.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#if 0
|
||||||
|
/*─────────────────────────────────────────────────────────────────╗
|
||||||
|
│ To the extent possible under law, Justine Tunney has waived │
|
||||||
|
│ all copyright and related or neighboring rights to this file, │
|
||||||
|
│ as it is written in the following disclaimers: │
|
||||||
|
│ • http://unlicense.org/ │
|
||||||
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||||
|
╚─────────────────────────────────────────────────────────────────*/
|
||||||
|
#endif
|
||||||
|
#include "libc/bits/bits.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ASAN heap memory safety crash example.
|
||||||
|
*
|
||||||
|
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash2.com
|
||||||
|
* o/dbg/examples/auto-memory-safety-crash2.com
|
||||||
|
*
|
||||||
|
* You should see:
|
||||||
|
*
|
||||||
|
* heap overrun 1-byte store at 0x10008004002d shadow 0x20090000005
|
||||||
|
* ./o/dbg/examples/auto-memory-safety-crash2.com
|
||||||
|
* x
|
||||||
|
* OOOOOOOOOOOUUUUUUUUUUUUUUUU.............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
|
||||||
|
* |-7 |-6 |-6 |0 |5 |-7 |-7 |-7 |-7
|
||||||
|
* »!@ ÿ▄:Y╩≥= S hello ∙∙∙∙∙∙∙ ♪ GT◘&@ á+@ »!@
|
||||||
|
* 000000400000-00000042b000 .text
|
||||||
|
* 00000042b000-00000042d000 .data
|
||||||
|
* 00007fff0000-00008000ffff
|
||||||
|
* 000080070000-00008008ffff
|
||||||
|
* 02008fff0000-02009000ffff ←shadow
|
||||||
|
* 0e007fff0000-0e008000ffff
|
||||||
|
* 10003ab90000-10003abaffff
|
||||||
|
* 100080000000-10008000ffff ←address
|
||||||
|
* 6ffffffe0000-6fffffffffff
|
||||||
|
*
|
||||||
|
* the memory was allocated by
|
||||||
|
* 0x100080040020 64 bytes [dlmalloc]
|
||||||
|
* 0x100080040030 13 bytes [actual]
|
||||||
|
* 402608 main
|
||||||
|
* 402ba0 cosmo
|
||||||
|
* 4021af _start
|
||||||
|
*
|
||||||
|
* the crash was caused by
|
||||||
|
* 0x0000000000404793: __die at libc/log/die.c:40
|
||||||
|
* 0x0000000000404f56: __asan_report_store at libc/intrin/asan.c:1183
|
||||||
|
* 0x0000000000402579: main at examples/auto-memory-safety-crash2.c:30
|
||||||
|
* 0x000000000040270f: cosmo at libc/runtime/cosmo.S:64
|
||||||
|
* 0x00000000004021ae: _start at libc/crt/crt.S:77
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
char *buffer;
|
||||||
|
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
|
||||||
|
buffer = malloc(13);
|
||||||
|
strcpy(buffer, "hello");
|
||||||
|
int i = 13;
|
||||||
|
asm("" : "+r"(i)); /* prevent compiler being smart */
|
||||||
|
buffer[i] = 1;
|
||||||
|
asm("" : "+r"(buffer)); /* prevent compiler being smart */
|
||||||
|
return 0;
|
||||||
|
}
|
32
examples/auto-memory-safety-crash3.c
Normal file
32
examples/auto-memory-safety-crash3.c
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#if 0
|
||||||
|
/*─────────────────────────────────────────────────────────────────╗
|
||||||
|
│ To the extent possible under law, Justine Tunney has waived │
|
||||||
|
│ all copyright and related or neighboring rights to this file, │
|
||||||
|
│ as it is written in the following disclaimers: │
|
||||||
|
│ • http://unlicense.org/ │
|
||||||
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||||
|
╚─────────────────────────────────────────────────────────────────*/
|
||||||
|
#endif
|
||||||
|
#include "libc/bits/bits.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ASAN use-after-free memory safety crash example.
|
||||||
|
*
|
||||||
|
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash3.com
|
||||||
|
* o/dbg/examples/auto-memory-safety-crash3.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
char *buffer;
|
||||||
|
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
|
||||||
|
buffer = malloc(13);
|
||||||
|
strcpy(buffer, "hello");
|
||||||
|
free(buffer);
|
||||||
|
asm("" : "+r"(buffer)); /* prevent compiler being smart */
|
||||||
|
buffer[0] = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -83,6 +83,8 @@ STATIC_YOINK("_init_asan");
|
||||||
* movq (%addr),%dst
|
* movq (%addr),%dst
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define ASAN_MORGUE_SIZE 128
|
||||||
|
|
||||||
#define HOOK(HOOK, IMPL) \
|
#define HOOK(HOOK, IMPL) \
|
||||||
do { \
|
do { \
|
||||||
if (weaken(HOOK)) { \
|
if (weaken(HOOK)) { \
|
||||||
|
@ -137,7 +139,7 @@ struct AsanGlobal {
|
||||||
|
|
||||||
struct AsanMorgue {
|
struct AsanMorgue {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
void *p[32];
|
void *p[ASAN_MORGUE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
bool __asan_noreentry;
|
bool __asan_noreentry;
|
||||||
|
@ -618,6 +620,102 @@ static char *__asan_format_section(char *p, const void *p1, const void *p2,
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
||||||
|
unsigned l, m, r, n, k;
|
||||||
|
struct SymbolTable *st;
|
||||||
|
kprintf("%nthe memory belongs to image symbols%n");
|
||||||
|
if (weaken(GetSymbolTable)) {
|
||||||
|
if ((st = weaken(GetSymbolTable)())) {
|
||||||
|
l = 0;
|
||||||
|
r = n = st->count;
|
||||||
|
k = a - st->addr_base;
|
||||||
|
while (l < r) {
|
||||||
|
m = (l + r) >> 1;
|
||||||
|
if (st->symbols[m].y < k) {
|
||||||
|
l = m + 1;
|
||||||
|
} else {
|
||||||
|
r = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; l < n; ++l) {
|
||||||
|
if ((st->symbols[l].x <= k && k <= st->symbols[l].y) ||
|
||||||
|
(st->symbols[l].x <= k + z && k + z <= st->symbols[l].y) ||
|
||||||
|
(k < st->symbols[l].x && st->symbols[l].y < k + z)) {
|
||||||
|
kprintf("\t%s [%#x,%#x] size %'d%n", st->name_base + st->names[l],
|
||||||
|
st->addr_base + st->symbols[l].x,
|
||||||
|
st->addr_base + st->symbols[l].y,
|
||||||
|
st->symbols[l].y - st->symbols[l].x + 1);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG%n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kprintf("\tunknown please STATIC_YOINK(\"GetSymbolTable\");%n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ReportOriginHeap {
|
||||||
|
const unsigned char *a;
|
||||||
|
int z;
|
||||||
|
};
|
||||||
|
|
||||||
|
static noasan void OnMemory(void *x, void *y, size_t n, void *a) {
|
||||||
|
const unsigned char *p = x;
|
||||||
|
struct ReportOriginHeap *t = a;
|
||||||
|
if ((p <= t->a && t->a < p + n) ||
|
||||||
|
(p <= t->a + t->z && t->a + t->z < p + n) ||
|
||||||
|
(t->a < p && p + n <= t->a + t->z)) {
|
||||||
|
kprintf("%p %,lu bytes [dlmalloc]", x, n);
|
||||||
|
__asan_print_trace(x);
|
||||||
|
kprintf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __asan_report_memory_origin_heap(const unsigned char *a, int z) {
|
||||||
|
struct ReportOriginHeap t;
|
||||||
|
kprintf("%nthe memory was allocated by%n");
|
||||||
|
if (weaken(malloc_inspect_all)) {
|
||||||
|
t.a = a;
|
||||||
|
t.z = z;
|
||||||
|
weaken(malloc_inspect_all)(OnMemory, &t);
|
||||||
|
} else {
|
||||||
|
kprintf("\tunknown please STATIC_YOINK(\"malloc_inspect_all\");%n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __asan_report_memory_origin(const unsigned char *addr, int size,
|
||||||
|
signed char kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case kAsanStackOverrun:
|
||||||
|
case kAsanGlobalOverrun:
|
||||||
|
case kAsanAllocaOverrun:
|
||||||
|
case kAsanHeapOverrun:
|
||||||
|
addr -= 1;
|
||||||
|
size += 1;
|
||||||
|
break;
|
||||||
|
case kAsanHeapUnderrun:
|
||||||
|
case kAsanStackUnderrun:
|
||||||
|
case kAsanAllocaUnderrun:
|
||||||
|
case kAsanGlobalUnderrun:
|
||||||
|
size += 1;
|
||||||
|
break;
|
||||||
|
case kAsanGlobalRedzone:
|
||||||
|
addr -= 1;
|
||||||
|
size += 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (_base <= addr && addr < _end) {
|
||||||
|
__asan_report_memory_origin_image((intptr_t)addr, size);
|
||||||
|
} else if (IsAutoFrame((intptr_t)addr >> 16)) {
|
||||||
|
__asan_report_memory_origin_heap(addr, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nodiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
nodiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
||||||
const char *message,
|
const char *message,
|
||||||
signed char kind) {
|
signed char kind) {
|
||||||
|
@ -705,6 +803,8 @@ nodiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
kprintf("%s", __fatalbuf);
|
kprintf("%s", __fatalbuf);
|
||||||
|
__asan_report_memory_origin(addr, size, kind);
|
||||||
|
kprintf("%nthe crash was caused by%n");
|
||||||
return __asan_die();
|
return __asan_die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,7 +1005,7 @@ int __asan_print_trace(void *p) {
|
||||||
kprintf(" bad cookie");
|
kprintf(" bad cookie");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
kprintf(" %'zu used", n);
|
kprintf("%n%p %,lu bytes [asan]", (char *)p + 16, n);
|
||||||
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16)) {
|
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16)) {
|
||||||
kprintf(" (shadow not mapped?!)");
|
kprintf(" (shadow not mapped?!)");
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/sysv/consts/ss.h"
|
#include "libc/sysv/consts/ss.h"
|
||||||
|
|
||||||
STATIC_YOINK("__die");
|
STATIC_YOINK("__die"); /* for backtracing */
|
||||||
|
STATIC_YOINK("malloc_inspect_all"); /* for asan memory origin */
|
||||||
|
STATIC_YOINK("__get_symbol_by_addr"); /* for asan memory origin */
|
||||||
|
|
||||||
extern const unsigned char __oncrash_thunks[8][11];
|
extern const unsigned char __oncrash_thunks[8][11];
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ static noasan void OnMemory(void *x, void *y, size_t n, void *a) {
|
||||||
static int i;
|
static int i;
|
||||||
if (n) {
|
if (n) {
|
||||||
if (++i < 20) {
|
if (++i < 20) {
|
||||||
kprintf("%p %,d bytes", x, n);
|
kprintf("%p %,lu bytes [dlmalloc]", x, n);
|
||||||
if (IsAsan()) {
|
if (IsAsan()) {
|
||||||
__asan_print_trace(x);
|
__asan_print_trace(x);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue