Get address sanitizer mostly working

This commit is contained in:
Justine Tunney 2020-09-03 05:44:37 -07:00
parent 1f1f3cd477
commit 7327c345f9
149 changed files with 3777 additions and 3457 deletions

View file

@ -1,99 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
struct SourceLocation {
const char *filename;
int line;
int column;
};
struct AccessInfo {
const uint8_t *addr;
const uint8_t *first_bad_addr;
size_t size;
bool iswrite;
unsigned long ip;
};
struct Global {
const uint8_t *addr;
size_t size;
size_t size_with_redzone;
const void *name;
const void *module_name;
unsigned long has_cxx_init;
struct kasan_source_location *location;
char *odr_indicator;
};
privileged void __asan_init(void) {
}
privileged void __asan_version_mismatch_check_v8(void) {
}
privileged void __asan_register_globals(struct Global globals[], int n) {
}
privileged void __asan_unregister_globals(struct Global globals[], int n) {
}
privileged void __asan_report_load_n(uint8_t *p, int n) {
}
privileged void __asan_report_store_n(uint8_t *p, int n) {
__asan_report_load_n(p, n);
}
privileged void __asan_loadN(uintptr_t ptr, size_t size) {
}
privileged void __asan_storeN(uintptr_t ptr, size_t size) {
}
privileged uintptr_t __asan_stack_malloc(size_t size, int classid) {
return 0;
}
privileged void __asan_stack_free(uintptr_t ptr, size_t size, int classid) {
}
privileged void __asan_handle_no_return(void) {
DebugBreak();
}
privileged void __asan_alloca_poison(uintptr_t addr, uintptr_t size) {
}
privileged void __asan_allocas_unpoison(uintptr_t top, uintptr_t bottom) {
}
privileged void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr,
void **beg, void **end) {
return NULL;
}
privileged void *__asan_get_current_fake_stack(void) {
return NULL;
}

View file

@ -40,6 +40,10 @@ _construct:
je 2f
push %rax
push %rcx
mov %r12,%rdi
mov %r13,%rsi
mov %r14,%rdx
mov %r15,%rcx
call *(%rax)
pop %rcx
pop %rax

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
@ -17,22 +17,39 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
#include "libc/calls/internal.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.h"
#define BYTES 64
static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
unsigned prot, unsigned flags,
int fd, int64_t off) {
struct DirectMap res;
if ((res.maphandle = CreateFileMappingNuma(
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
&kNtIsInheritable, prot2nt(prot, flags), size >> 32, size, NULL,
kNtNumaNoPreferredNode))) {
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, fprot2nt(prot, flags),
off >> 32, off, size, addr,
kNtNumaNoPreferredNode))) {
CloseHandle(res.maphandle);
res.maphandle = kNtInvalidHandleValue;
res.addr = (void *)(intptr_t)winerr();
}
} else {
res.maphandle = kNtInvalidHandleValue;
res.addr = (void *)(intptr_t)winerr();
}
return res;
}
/ RII constant holding 'C:/WINDOWS' directory.
/
/ @note guarantees trailing slash if non-empty
.initbss 300,_init_kNtWindowsDirectory
kNtWindowsDirectory:
.zero BYTES
.endobj kNtWindowsDirectory,globl
.previous
.init.start 300,_init_kNtWindowsDirectory
pushpop BYTES,%rdx
mov __imp_GetWindowsDirectoryA(%rip),%rax
call __getntsyspath
.init.end 300,_init_kNtWindowsDirectory
struct DirectMap DirectMap(void *addr, size_t size, unsigned prot,
unsigned flags, int fd, int64_t off) {
if (!IsWindows()) {
return (struct DirectMap){mmap$sysv(addr, size, prot, flags, fd, off),
kNtInvalidHandleValue};
} else {
return DirectMapNt(addr, size, prot, flags, fd, off);
}
}

15
libc/runtime/directmap.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_DIRECTMAP_H_
#define COSMOPOLITAN_LIBC_RUNTIME_DIRECTMAP_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct DirectMap {
void *addr;
int64_t maphandle;
};
struct DirectMap DirectMap(void *, size_t, unsigned, unsigned, int, int64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_DIRECTMAP_H_ */

View file

@ -17,7 +17,6 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/pushpop.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/limits.h"
@ -51,8 +50,14 @@ int mapfileread(const char *filename, struct MappedFile *mf) {
int unmapfile(struct MappedFile *mf) {
int rc;
rc = 0;
rc |= munmap_s(&mf->addr, mf->size);
rc |= close_s(&mf->fd);
pushmov(&mf->size, 0);
if (mf->addr != MAP_FAILED) {
rc |= munmap(mf->addr, mf->size);
mf->addr = MAP_FAILED;
}
if (mf->fd != -1) {
rc |= close(mf->fd);
mf->fd = -1;
}
mf->size = 0;
return rc;
}

View file

@ -25,6 +25,7 @@
#include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"

View file

@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_GC_H_
#define COSMOPOLITAN_LIBC_RUNTIME_GC_H_
#include "libc/calls/calls.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/runtime/runtime.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -13,8 +14,6 @@ COSMOPOLITAN_C_START_
* using very few lines of code.
*/
struct StackFrame;
/**
* Releases resource when function returns.
*

View file

@ -19,10 +19,8 @@
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/bits/weaken.h"
#include "libc/conv/conv.h"
#include "libc/conv/sizemultiply.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
@ -70,8 +68,9 @@ bool grow(void *pp, size_t *capacity, size_t itemsize, size_t extra) {
p1 = isheap(*p) ? *p : NULL;
p2 = NULL;
n1 = *capacity;
n2 = (*p ? n1 + (n1 >> 1) : max(4, INITIAL_CAPACITY / itemsize)) + extra;
if (sizemultiply(&t1, n1, itemsize) && sizemultiply(&t2, n2, itemsize)) {
n2 = (*p ? n1 + (n1 >> 1) : MAX(4, INITIAL_CAPACITY / itemsize)) + extra;
if (!__builtin_mul_overflow(n1, itemsize, &t1) &&
!__builtin_mul_overflow(n2, itemsize, &t2)) {
if (weaken(realloc) && (p2 = weaken(realloc)(p1, ROUNDUP(t2, 32)))) {
if (!p1 && *p) memcpy(p2, *p, t1);
memset((char *)p2 + t1, 0, t2 - t1);

View file

@ -14,6 +14,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
hidden extern bool _mmap_asan_mode;
hidden extern char **g_freebsdhint;
hidden extern unsigned g_runstate;
hidden extern void *g_stacktop;

View file

@ -1,13 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
#include "libc/nexgen32e/vendor.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define kMappingsSize 0x0000100000000000 /* 16TB */
#define kMappingsStart (IsGenuineCosmo() ? 0x300000000000 : 0x200000000000)
#define kFixedMappingsStart 0x0000100000000000
#define kFixedMappingsSize kMappingsSize
#define kAutomapStart 0x0000100000000000
#define kAutomapSize 0x0000100000000000
#define kFixedmapStart 0x0000200000000000
struct MemoryIntervals {
int i;
@ -27,6 +25,7 @@ int TrackMemoryInterval(struct MemoryIntervals *, int, int, long);
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
void (*)(struct MemoryIntervals *, int, int));
void ReleaseMemoryNt(struct MemoryIntervals *, int, int);
int UntrackMemoryIntervals(void *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -18,13 +18,14 @@
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/log/asan.h"
#include "libc/macros.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/rand/rand.h"
#include "libc/runtime/directmap.h"
#include "libc/runtime/memtrack.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
@ -32,79 +33,14 @@
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
#define IP(X) (intptr_t)(X)
#define VIP(X) (void *)IP(X)
#define COORD(a) (int)(IP(a) >> 16)
#define ADDR(c) (void *)(IP(c) << 16)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#define LAST_COORD(a, n) (COORD(a) + (ROUNDUP(n, FRAMESIZE) >> 16) - 1)
struct DirectMap {
void *addr;
int64_t maphandle;
};
#define IP(X) (intptr_t)(X)
#define VIP(X) (void *)IP(X)
#define ADDR(c) (void *)(IP(c) << 16)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
struct MemoryIntervals _mmi;
static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
unsigned prot, unsigned flags,
int fd, int64_t off) {
struct DirectMap res; /* NT IS TORTURE */
if ((res.maphandle = CreateFileMappingNuma(
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
&kNtIsInheritable, prot2nt(prot, flags), size >> 32, size, NULL,
kNtNumaNoPreferredNode))) {
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, fprot2nt(prot, flags),
off >> 32, off, size, addr,
kNtNumaNoPreferredNode))) {
CloseHandle(res.maphandle);
res.maphandle = kNtInvalidHandleValue;
res.addr = VIP(winerr());
}
} else {
res.maphandle = kNtInvalidHandleValue;
res.addr = VIP(winerr());
}
return res;
}
static struct DirectMap DirectMap(void *addr, size_t size, unsigned prot,
unsigned flags, int fd, int64_t off) {
if (!IsWindows()) {
return (struct DirectMap){mmap$sysv(addr, size, prot, flags, fd, off),
kNtInvalidHandleValue};
} else {
return DirectMapNt(addr, size, prot, flags, fd, off);
}
}
static int UntrackMemoryIntervals(void *addr, size_t size) {
return ReleaseMemoryIntervals(&_mmi, COORD(addr), LAST_COORD(addr, size),
ReleaseMemoryNt);
}
/**
* Releases memory pages.
*
* @param addr is a pointer within any memory mapped region the process
* has permission to control, such as address ranges returned by
* mmap(), the program image itself, etc.
* @param size is the amount of memory to unmap, which needn't be a
* multiple of FRAMESIZE, and may be a subset of that which was
* mapped previously, and may punch holes in existing mappings,
* but your mileage may vary on windows
* @return 0 on success, or -1 w/ errno
*/
int munmap(void *addr, size_t size) {
int rc;
if (!ALIGNED(addr) || !CANONICAL(addr) || !size) return einval();
size = ROUNDUP(size, FRAMESIZE);
if (UntrackMemoryIntervals(addr, size) == -1) return -1;
if (IsWindows()) return 0;
return munmap$sysv(addr, size);
}
/**
* Beseeches system for page-table entries.
*
@ -120,8 +56,7 @@ int munmap(void *addr, size_t size) {
* @return virtual base address of new mapping, or MAP_FAILED w/ errno
*/
void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
int i;
long gap;
int i, x, n, a, b;
struct DirectMap dm;
if (!size) return VIP(einval());
if (!ALIGNED(off)) return VIP(einval());
@ -134,24 +69,18 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
if (UntrackMemoryIntervals(addr, size) == -1) {
return MAP_FAILED;
}
} else if (_mmi.i) {
if (0 && IsModeDbg()) {
addr = VIP(rand64() & 0x00007ffffffff000);
} else {
for (i = _mmi.i - 1; i > 0; --i) {
gap = _mmi.p[i].x - _mmi.p[i - 1].y - 1;
assert(gap > 0);
if (gap >= (ROUNDUP(size, FRAMESIZE) >> 16)) {
addr = ADDR(_mmi.p[i - 1].y + 1);
break;
}
}
if (!addr) {
addr = ADDR(_mmi.p[_mmi.i - 1].y + 1);
}
}
} else {
addr = VIP(kMappingsStart);
x = kAutomapStart >> 16;
n = ROUNDUP(size, FRAMESIZE) >> 16;
for (i = 0; i < _mmi.i; ++i) {
if (_mmi.p[i].y < x) continue;
if (_mmi.p[i].x > x + n - 1) break;
x = _mmi.p[i].y + 1;
}
if (x + n - 1 >= ((kAutomapStart + kAutomapSize) >> 16)) {
return (void *)(intptr_t)enomem();
}
addr = (void *)(intptr_t)((int64_t)x << 16);
}
assert((flags & MAP_FIXED) ||
(!isheap(addr) && !isheap((char *)addr + size - 1)));
@ -159,9 +88,13 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
if (dm.addr == MAP_FAILED || dm.addr != addr) {
return MAP_FAILED;
}
if (TrackMemoryInterval(&_mmi, COORD(dm.addr), LAST_COORD(dm.addr, size),
dm.maphandle) == -1) {
_Exit(1);
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
if (TrackMemoryInterval(&_mmi, a, b, dm.maphandle) == -1) {
abort();
}
if (weaken(__asan_map_shadow)) {
weaken(__asan_map_shadow)(dm.addr, size);
}
return dm.addr;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
@ -17,22 +17,34 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/macros.h"
.source __FILE__
#include "libc/runtime/memtrack.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
#define BYTES 64
#define IP(X) (intptr_t)(X)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
/ RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
/
/ @note guarantees trailing slash if non-empty
.initbss 300,_init_kNtSystemDirectory
kNtSystemDirectory:
.zero BYTES
.endobj kNtSystemDirectory,globl
.previous
.init.start 300,_init_kNtSystemDirectory
pushpop BYTES,%rdx
mov __imp_GetSystemDirectoryA(%rip),%rax
call __getntsyspath
.init.end 300,_init_kNtSystemDirectory
/**
* Releases memory pages.
*
* @param addr is a pointer within any memory mapped region the process
* has permission to control, such as address ranges returned by
* mmap(), the program image itself, etc.
* @param size is the amount of memory to unmap, which needn't be a
* multiple of FRAMESIZE, and may be a subset of that which was
* mapped previously, and may punch holes in existing mappings,
* but your mileage may vary on windows
* @return 0 on success, or -1 w/ errno
*/
int munmap(void *addr, size_t size) {
int rc;
if (!ALIGNED(addr) || !CANONICAL(addr) || !size) return einval();
size = ROUNDUP(size, FRAMESIZE);
if (UntrackMemoryIntervals(addr, size) == -1) return -1;
if (IsWindows()) return 0;
return munmap$sysv(addr, size);
}

View file

@ -23,6 +23,7 @@
#include "libc/limits.h"
#include "libc/macros.h"
#include "libc/runtime/ring.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"

View file

@ -17,8 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/runtime/ring.h"
#include "libc/runtime/runtime.h"
/**
* Frees ring buffer.

View file

@ -6,13 +6,6 @@ COSMOPOLITAN_C_START_
cosmopolitan § runtime
*/
struct SymbolTable;
struct StackFrame {
struct StackFrame *next;
intptr_t addr;
};
typedef long jmp_buf[8] aligned(CACHELINE);
extern int g_argc; /* CRT */
@ -71,8 +64,12 @@ void loadxmm(void *);
void peekall(void);
int issetugid(void);
void weakfree(void *) libcesque;
void __hook(void (*)(void), struct SymbolTable *);
bool isheap(void *);
void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t);
void *mremap(void *, uint64_t, uint64_t, int32_t, void *);
int munmap(void *, uint64_t);
int mprotect(void *, uint64_t, int) privileged;
int msync(void *, size_t, int);
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § runtime » optimizations

View file

@ -60,13 +60,8 @@ $(LIBC_RUNTIME_A).pkg: \
$(LIBC_RUNTIME_A_OBJS) \
$(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/runtime/asan.greg.o \
o/$(MODE)/libc/runtime/shadowargs.o \
o/$(MODE)/libc/runtime/hook.greg.o \
o/$(MODE)/libc/runtime/ftrace.greg.o \
o/$(MODE)/libc/runtime/__stack_chk_fail.o \
o/$(MODE)/libc/runtime/__stack_chk_guard.o: \
OVERRIDE_COPTS += \
$(LIBC_RUNTIME_A_OBJS): \
OVERRIDE_CFLAGS += \
$(NO_MAGIC)
# @see ape/ape.s for tuning parameters that make this safe

View file

@ -53,6 +53,7 @@ struct SymbolTable *opensymboltable(const char *) nodiscard;
int closesymboltable(struct SymbolTable **);
const struct Symbol *bisectsymbol(struct SymbolTable *, intptr_t, int64_t *);
const char *getsymbolname(struct SymbolTable *, const struct Symbol *);
void __hook(void (*)(void), struct SymbolTable *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -17,21 +17,12 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/pushpop.h"
#include "libc/calls/calls.h"
#include "libc/runtime/runtime.h"
#include "libc/macros.h"
#include "libc/runtime/memtrack.h"
/**
* Closes memory mapping.
*
* The caller's address holder is set to MAP_FAILED (-1) which is a
* no-op for subsequent invocations.
*
* @return 0 on success, or -1 w/ errno
*/
int munmap_s(void *addrp, uint64_t size) {
void **addrpp = (void **)addrp;
void *addr = (void *)pushpop(-1L);
return munmap(lockxchg(addrpp, &addr), size);
int UntrackMemoryIntervals(void *addr, size_t size) {
int a, b;
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
return ReleaseMemoryIntervals(&_mmi, a, b, ReleaseMemoryNt);
}