From 559675b90acec03b67ed3f2cece1940f00e44c49 Mon Sep 17 00:00:00 2001 From: seyko Date: Fri, 10 Apr 2015 15:17:22 +0300 Subject: a bounds checking code for the ARCH=x86_64 --- lib/Makefile | 2 +- lib/alloca86_64-bt.S | 60 ++++++++++++++++++++++++++++ lib/bcheck.c | 111 +++++++++++++++++++++++++++------------------------ 3 files changed, 119 insertions(+), 54 deletions(-) create mode 100644 lib/alloca86_64-bt.S (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile index aa3984b..348cb72 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -44,7 +44,7 @@ native : TCC = $(TOP)/tcc$(EXESUF) cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF) I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O) -X86_64_O = libtcc1.o alloca86_64.o +X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O) ARM_O = libtcc1.o armeabi.o alloca-arm.o WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o diff --git a/lib/alloca86_64-bt.S b/lib/alloca86_64-bt.S new file mode 100644 index 0000000..ab8629d --- /dev/null +++ b/lib/alloca86_64-bt.S @@ -0,0 +1,60 @@ +/* ---------------------------------------------- */ +/* alloca86_64.S */ + +.globl __bound_alloca +__bound_alloca: + +#ifdef TCC_TARGET_PE + # bound checking is not implemented + pop %rdx + mov %rcx,%rax + add $15,%rax + and $-16,%rax + jz p3 + +p1: + cmp $4096,%rax + jbe p2 + test %rax,-4096(%rsp) + sub $4096,%rsp + sub $4096,%rax + jmp p1 +p2: + + sub %rax,%rsp + mov %rsp,%rax + add $32,%rax + +p3: + push %rdx + ret +#else + pop %rdx + mov %rdi,%rax + movl %rax,%rsi # size, a second parm to the __bound_new_region + + add $15,%rax + and $-16,%rax + jz p3 + + + sub %rax,%rsp + mov %rsp,%rdi # pointer, a first parm to the __bound_new_region + mov %rsp,%rax + + push %rdx + push %rax + call __bound_new_region + pop %rax + pop %rdx + +p3: + push %rdx + ret +#endif + +/* mark stack as nonexecutable */ +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif +/* ---------------------------------------------- */ diff --git a/lib/bcheck.c b/lib/bcheck.c index 7dcb36e..829e33d 100644 --- a/lib/bcheck.c +++ b/lib/bcheck.c @@ -31,6 +31,12 @@ /* #define BOUND_DEBUG */ +#ifdef BOUND_DEBUG + #define dprintf(a...) fprintf(a) +#else + #define dprintf(a...) +#endif + /* define so that bound array is static (faster, but use memory if bound checking not used) */ /* #define BOUND_STATIC */ @@ -50,12 +56,12 @@ #define BOUND_T1_BITS 13 #define BOUND_T2_BITS 11 -#define BOUND_T3_BITS (32 - BOUND_T1_BITS - BOUND_T2_BITS) +#define BOUND_T3_BITS (sizeof(size_t)*8 - BOUND_T1_BITS - BOUND_T2_BITS) +#define BOUND_E_BITS (sizeof(size_t)) #define BOUND_T1_SIZE (1 << BOUND_T1_BITS) #define BOUND_T2_SIZE (1 << BOUND_T2_BITS) #define BOUND_T3_SIZE (1 << BOUND_T3_BITS) -#define BOUND_E_BITS 4 #define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS) #define BOUND_T23_SIZE (1 << BOUND_T23_BITS) @@ -64,7 +70,7 @@ /* this pointer is generated when bound check is incorrect */ #define INVALID_POINTER ((void *)(-2)) /* size of an empty region */ -#define EMPTY_SIZE 0xffffffff +#define EMPTY_SIZE ((size_t)(-1)) /* size of an invalid region */ #define INVALID_SIZE 0 @@ -168,9 +174,7 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset) __bound_init(); -#if defined(BOUND_DEBUG) - printf("%s %s: 0x%x %d\n", __FILE__, __FUNCTION__, (int)p, offset); -#endif + dprintf(stderr, "%s %s: %p %p\n", __FILE__, __FUNCTION__, p, offset); e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; e = (BoundEntry *)((char *)e + @@ -197,6 +201,8 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ size_t addr = (size_t)p; \ BoundEntry *e; \ \ + dprintf(stderr, "%s %s: %p %p start\n", __FILE__, __FUNCTION__, p, offset); \ + \ __bound_init(); \ e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \ e = (BoundEntry *)((char *)e + \ @@ -212,6 +218,7 @@ void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ fprintf(stderr,"%s %s: %p is outside of the region\n", __FILE__, __FUNCTION__, p + offset); \ return INVALID_POINTER; /* return an invalid pointer */ \ } \ + dprintf(stderr, "%s %s: return p+offset = %p\n", __FILE__, __FUNCTION__, p + offset); \ return p + offset; \ } @@ -232,9 +239,8 @@ BOUND_PTR_INDIR(16) void FASTCALL __bound_local_new(void *p1) { size_t addr, size, fp, *p = p1; -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s start p1=%p *p1=%p\n", __FILE__, __FUNCTION__, p, *p); -#endif + + dprintf(stderr, "%s, %s start p1=%p\n", __FILE__, __FUNCTION__, p); GET_CALLER_FP(fp); for(;;) { addr = p[0]; @@ -245,9 +251,7 @@ void FASTCALL __bound_local_new(void *p1) p += 2; __bound_new_region((void *)addr, size); } -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); -#endif + dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); } /* called when leaving a function to delete all the local regions */ @@ -268,7 +272,7 @@ void FASTCALL __bound_local_delete(void *p1) static BoundEntry *__bound_new_page(void) { BoundEntry *page; - int i; + size_t i; page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE); if (!page) @@ -296,11 +300,11 @@ static void bound_free_entry(BoundEntry *e) libc_free(e); } -static inline BoundEntry *get_page(int index) +static BoundEntry *get_page(size_t index) { BoundEntry *page; page = __bound_t1[index]; - if (page == __bound_empty_t2 || page == __bound_invalid_t2) { + if (!page || page == __bound_empty_t2 || page == __bound_invalid_t2) { /* create a new page if necessary */ page = __bound_new_page(); __bound_t1[index] = page; @@ -325,7 +329,7 @@ static void mark_invalid(size_t addr, size_t size) t2_end = 1 << (BOUND_T1_BITS + BOUND_T2_BITS); #if 0 - printf("mark_invalid: start = %x %x\n", t2_start, t2_end); + dprintf(stderr, "mark_invalid: start = %x %x\n", t2_start, t2_end); #endif /* first we handle full pages */ @@ -364,7 +368,7 @@ static void mark_invalid(size_t addr, size_t size) void __bound_init(void) { - int i; + size_t i; BoundEntry *page; size_t start, size; size_t *p; @@ -375,9 +379,7 @@ void __bound_init(void) inited = 1; -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); -#endif + dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); /* save malloc hooks and install bound check hooks */ install_malloc_hooks(); @@ -445,19 +447,18 @@ void __bound_init(void) __bound_new_region((void *)p[0], p[1]); p += 2; } -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__); -#endif + + dprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__); } void __bound_main_arg(void **p) { void *start = p; while (*p++); -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", + + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", __FILE__, __FUNCTION__, (void *) p - start); -#endif + __bound_new_region(start, (void *) p - start); } @@ -495,10 +496,8 @@ void __bound_new_region(void *p, size_t size) __bound_init(); -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s(%p, %p) start\n", + dprintf(stderr, "%s, %s(%p, %p) start\n", __FILE__, __FUNCTION__, p, size); -#endif start = (size_t)p; end = start + size; @@ -553,9 +552,8 @@ void __bound_new_region(void *p, size_t size) } add_region(e, start, size); } -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); -#endif + + dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); } /* delete a region */ @@ -610,9 +608,7 @@ int __bound_delete_region(void *p) __bound_init(); -#ifdef BOUND_DEBUG - fprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__); -#endif + dprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__); start = (size_t)p; t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); @@ -681,9 +677,7 @@ int __bound_delete_region(void *p) delete_region(e, p, empty_size); } -#ifdef BOUND_DEBUG - fprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__); -#endif + dprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__); return 0; } @@ -771,10 +765,9 @@ void *__bound_malloc(size_t size, const void *caller) if (!ptr) return NULL; -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", __FILE__, __FUNCTION__, ptr, size); -#endif + __bound_new_region(ptr, size); return ptr; } @@ -805,10 +798,9 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) if (!ptr) return NULL; -#ifdef BOUND_DEBUG - fprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", __FILE__, __FUNCTION__, ptr, size); -#endif + __bound_new_region(ptr, size); return ptr; } @@ -861,23 +853,23 @@ void *__bound_calloc(size_t nmemb, size_t size) static void bound_dump(void) { BoundEntry *page, *e; - int i, j; + size_t i, j; - printf("region dump:\n"); + fprintf(stderr, "region dump:\n"); for(i=0;isize != EMPTY_SIZE && e->start != 0) { - printf("%08x:", + fprintf(stderr, "%08x:", (i << (BOUND_T2_BITS + BOUND_T3_BITS)) + (j << BOUND_T3_BITS)); do { - printf(" %08lx:%08lx", e->start, e->start + e->size); + fprintf(stderr, " %08lx:%08lx", e->start, e->start + e->size); e = e->next; } while (e != NULL); - printf("\n"); + fprintf(stderr, "\n"); } } } @@ -891,19 +883,27 @@ static void __bound_check(const void *p, size_t size) { if (size == 0) return; - p = __bound_ptr_add((void *)p, size); + p = __bound_ptr_add((void *)p, size - 1); if (p == INVALID_POINTER) bound_error("invalid pointer"); } void *__bound_memcpy(void *dst, const void *src, size_t size) { + void* p; + + dprintf(stderr, "%s %s: start, dst=%p src=%p size=%p\n", __FILE__, __FUNCTION__, dst, src, size); + __bound_check(dst, size); __bound_check(src, size); /* check also region overlap */ if (src >= dst && src < dst + size) bound_error("overlapping regions in memcpy()"); - return memcpy(dst, src, size); + + p = memcpy(dst, src, size); + + dprintf(stderr, "%s %s: end, p=%p\n", __FILE__, __FUNCTION__, p); + return p; } void *__bound_memmove(void *dst, const void *src, size_t size) @@ -939,7 +939,12 @@ int __bound_strlen(const char *s) char *__bound_strcpy(char *dst, const char *src) { - int len; + size_t len; + void *p; + + dprintf(stderr, "%s %s: strcpy start, dst=%p src=%p\n", __FILE__, __FUNCTION__, dst, src); len = __bound_strlen(src); - return __bound_memcpy(dst, src, len + 1); + p = __bound_memcpy(dst, src, len + 1); + dprintf(stderr, "%s %s: strcpy end, p=%p\n", __FILE__, __FUNCTION__, dst, src, p); + return p; } -- cgit v1.3.1