diff options
author | Jakob Kaivo <jkk@ung.org> | 2024-05-29 16:07:14 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2024-05-29 16:07:14 -0400 |
commit | 824f22a3684209b1e11c87f20e6ff17beb8e73a3 (patch) | |
tree | 591521c80a1cc771da5dc37d5bdfee5b89a3bb73 /src | |
parent | c9ec058657f9f8b3fd39a16f1a9e993b4a1e982e (diff) |
finish integrating jkmalloc and read-only variable support
Diffstat (limited to 'src')
-rw-r--r-- | src/__readonly.c | 2 | ||||
-rw-r--r-- | src/_forced/mprotect.h | 5 | ||||
-rw-r--r-- | src/signal/sigaction.c | 15 | ||||
-rw-r--r-- | src/signal/signal.c | 6 | ||||
-rw-r--r-- | src/stdlib/__jkmalloc.c | 81 | ||||
-rw-r--r-- | src/stdlib/_jkmalloc.h | 2 | ||||
-rw-r--r-- | src/stdlib/aligned_alloc.c | 4 | ||||
-rw-r--r-- | src/stdlib/calloc.c | 4 | ||||
-rw-r--r-- | src/stdlib/free.c | 4 | ||||
-rw-r--r-- | src/stdlib/malloc.c | 4 | ||||
-rw-r--r-- | src/stdlib/realloc.c | 4 |
11 files changed, 80 insertions, 51 deletions
diff --git a/src/__readonly.c b/src/__readonly.c index f2d33c38..9d0752d2 100644 --- a/src/__readonly.c +++ b/src/__readonly.c @@ -12,7 +12,7 @@ void* __readonly(ro_action_t action, void *ptr) { switch (action) { case RO_ALLOC: - return __jkmalloc(NULL, NULL, 0, NULL, 1, PAGESIZE, 0, ptr); + return __jkmalloc(NULL, 1, PAGESIZE, 0, ptr); case RO_FREE: diff --git a/src/_forced/mprotect.h b/src/_forced/mprotect.h index 5abbe5ed..717778de 100644 --- a/src/_forced/mprotect.h +++ b/src/_forced/mprotect.h @@ -1,9 +1,6 @@ -#ifdef _POSIX_C_SOURCE -#include <sys/mman.h> -#else +//#include <sys/mman.h> #include "_syscall.h" #define mprotect(__ptr, __len, __prot) __syscall(__sys_mprotect, __ptr, __len, __prot) #define PROT_NONE 0x0 #define PROT_READ 0x1 #define PROT_WRITE 0x2 -#endif diff --git a/src/signal/sigaction.c b/src/signal/sigaction.c index 1e9db8cb..d4721538 100644 --- a/src/signal/sigaction.c +++ b/src/signal/sigaction.c @@ -1,4 +1,3 @@ - #include <stddef.h> #include <signal.h> #include "_syscall.h" @@ -29,11 +28,17 @@ int sigaction(int sig, const struct sigaction * restrict act, struct sigaction * } #endif - a.flags = act->sa_flags; + /* SA_RESTORER seems to be required for sigaction to *actually* work on Linux */ + a.flags = act->sa_flags | SA_RESTORER; a.mask = act->sa_mask; - ret = __syscall(scno, sig, &a, &o, sizeof(act->sa_mask), 0, 0); - if (ret != -1 && oact != NULL) { + ret = __syscall(scno, sig, &a, oact ? &o : NULL, /* 8 */ sizeof(act->sa_mask), 0, 0); + if (ret < 0) { + errno = -ret; + return -1; + } + + if (oact != NULL) { oact->sa_handler = o.fn.handler; #ifdef SA_SIGINFO if (o.flags & SA_SIGINFO) { @@ -45,7 +50,7 @@ int sigaction(int sig, const struct sigaction * restrict act, struct sigaction * oact->sa_mask = o.mask; } - return ret; + return 0; } /* diff --git a/src/signal/signal.c b/src/signal/signal.c index f55e2e57..923fdb6d 100644 --- a/src/signal/signal.c +++ b/src/signal/signal.c @@ -5,7 +5,7 @@ /** set a signal handler **/ -#if 0 +#if 1 #include "_forced/sigaction.h" #else @@ -36,11 +36,11 @@ void (*signal(int sig, void (*func)(int)))(int) void (*prev)(int) = ___signal.handlers[sig]; ___signal.handlers[sig] = func; - struct linux_sigaction act = { 0 }; + struct sigaction act = { 0 }; act.sa_handler = __signal_handler; act.sa_flags = SA_RESTART | SA_RESTORER; - int ret = sigaction(sig, &act, NULL, 8); + int ret = sigaction(sig, &act, NULL); if (ret != 0) { errno = -ret; return SIG_ERR; diff --git a/src/stdlib/__jkmalloc.c b/src/stdlib/__jkmalloc.c index c55842ea..e21baffd 100644 --- a/src/stdlib/__jkmalloc.c +++ b/src/stdlib/__jkmalloc.c @@ -6,6 +6,8 @@ #include <stdio.h> #include <string.h> +#include "_safety.h" + #ifdef _XOPEN_SOURCE #include <fcntl.h> #include <sys/mman.h> @@ -23,13 +25,6 @@ #include "_jkmalloc.h" -#if defined __OpenBSD__ || defined __FreeBSD__ || defined __APPLE__ -#define psiginfo(x, y) ((y) ? fprintf(stderr, "%s\n", (char*)(y)) : 0) -#ifndef SA_SIGINFO -#define SA_SIGINFO (0) -#endif -#endif - #define PTR_BITS (CHAR_BIT * sizeof(uintptr_t)) #define JKMALLOC_EXIT_VALUE (127 + SIGSEGV) @@ -39,7 +34,7 @@ #define JK_FREE_MAGIC (0x551a51dc) #define JK_UNDER_MAGIC (0xcb2873ac) #define JK_OVER_MAGIC (0x18a12c17) -#define JK_RONLY_MAGIC (0xdeadb00d) +#define JK_RONLY_MAGIC (0x902faf31) #define jk_pages(bytes) (((bytes + __jk_pagesize - 1) / __jk_pagesize) + 2) #define jk_pageof(addr) ((void*)((uintptr_t)addr - ((uintptr_t)addr % __jk_pagesize))) @@ -66,12 +61,23 @@ static struct jk_bucket *__jk_free_list[JK_FREE_LIST_SIZE]; static size_t __jk_free_buckets = 0; static size_t __jk_pagesize = 0; +static void __jk_undef(void) +{ + static int printed = 0; + if (printed == 0) { + printed = 1; + fprintf(stderr, "Undefined Behavior: "); + } +} + static void __jk_error(const char *s, void *addr, struct jk_source *src) { + __jk_undef(); + if (s && *s) { fputs(s, stderr); if (addr != NULL) { - fprintf(stderr, "%p", addr); + fprintf(stderr, " %p", addr); } fputs("\n", stderr); } @@ -114,7 +120,15 @@ static void *__jk_page_alloc(size_t npages) static void __jk_sigaction(int sig, siginfo_t *si, void *addr) { ___signal.current = 0; + (void)sig; (void)addr; + + __jk_undef(); + + if (!si) { + __jk_error("No signal information provided", NULL, NULL); + } + if (si->si_addr == NULL) { psiginfo(si, "NULL pointer dereference"); __jk_error(NULL, NULL, NULL); @@ -126,6 +140,7 @@ static void __jk_sigaction(int sig, siginfo_t *si, void *addr) __jk_error(NULL, NULL, NULL); } + MAGIC_CHECK: switch (bucket->magic) { case JK_UNDER_MAGIC: if (bucket->size == 0) { @@ -149,24 +164,25 @@ static void __jk_sigaction(int sig, siginfo_t *si, void *addr) psiginfo(si, "Use after free() detected"); break; + case JK_RONLY_MAGIC: + psiginfo(si, "Attempt to modify read-only memory detected"); + break; + default: - psiginfo(si, NULL); + /* try to find the actual error */ + bucket = (void*)((char*)bucket - __jk_pagesize); + if (mprotect(bucket, __jk_pagesize, PROT_READ) != 0) { + psiginfo(si, NULL); + __jk_error(NULL, NULL, NULL); + } + goto MAGIC_CHECK; } struct jk_source src = { .bucket = bucket }; __jk_error(NULL, NULL, &src); } -/* -static void jk_sigsegv(int sig) -{ - ___signal.current = 0; - fprintf(stderr, "JK SIGSEGV!\n"); - __jk_sigaction(sig, NULL, NULL); -} -*/ - -void* __jkmalloc(const char *file, const char *func, uintmax_t line, void *ptr, size_t alignment, size_t size1, size_t size2, const char *user) +void* __jkmalloc(void *ptr, size_t alignment, size_t size1, size_t size2, const char *user) { static int sa_set = 0; if (!sa_set) { @@ -174,9 +190,8 @@ void* __jkmalloc(const char *file, const char *func, uintmax_t line, void *ptr, .sa_flags = SA_SIGINFO, .sa_sigaction = __jk_sigaction, }; - //sigemptyset(&sa.sa_mask); + sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, NULL); - //signal(SIGSEGV, jk_sigsegv); sa_set = 1; } @@ -185,9 +200,9 @@ void* __jkmalloc(const char *file, const char *func, uintmax_t line, void *ptr, } struct jk_source src = { - .file = file, - .func = func, - .line = line, + .file = __checked_call.file, + .func = __checked_call.func, + .line = __checked_call.line, }; /* free() */ @@ -220,16 +235,16 @@ void* __jkmalloc(const char *file, const char *func, uintmax_t line, void *ptr, char *base = (char*)b; mprotect(base, __jk_pagesize * b->pages, PROT_READ | PROT_WRITE); - if (file) { + if (src.file) { size_t len = b->tlen; b->tlen += snprintf(b->trace + len, __jk_pagesize - sizeof(*b) - len, - "%s--- %s() (%s:%ju)", len ? "\n" : "", func, file, line); + "%s--- %s() (%s:%ju)", len ? "\n" : "", src.func, src.file, src.line); } b->magic = JK_FREE_MAGIC; for (size_t i = 1; i < b->pages; i++) { - memmove(base + i * __jk_pagesize, b, __jk_pagesize); + memcpy(base + i * __jk_pagesize, b, __jk_pagesize - 1); } size_t fb = __jk_free_buckets % JK_FREE_LIST_SIZE; @@ -267,7 +282,7 @@ void* __jkmalloc(const char *file, const char *func, uintmax_t line, void *ptr, __jk_error("Attempt to reallocate() incorrect address", ptr, &src); } - void *newptr = __jkmalloc(NULL, NULL, 0, NULL, alignment, size1, size2, user); + void *newptr = __jkmalloc(NULL, alignment, size1, size2, user); if (newptr != NULL) { memmove(newptr, ptr, b->size); free(ptr); @@ -314,13 +329,15 @@ void* __jkmalloc(const char *file, const char *func, uintmax_t line, void *ptr, ptr = (void*)under->start; - if (file) { - under->tlen = snprintf(under->trace, __jk_pagesize - sizeof(*under), "+++ %s() (%s:%ju)", func, file, line); + if (src.file) { + under->tlen = snprintf(under->trace, __jk_pagesize - sizeof(*under), "+++ %s() (%s:%ju)", src.func, src.file, src.line); memcpy(over->trace, under->trace, under->tlen + 1); over->tlen = under->tlen; } else if (user) { + under->magic = JK_RONLY_MAGIC; under->tlen = snprintf(under->trace, __jk_pagesize - sizeof(*under), "Read-only memory for %s", user); memcpy(over->trace, under->trace, under->tlen + 1); + over->magic = JK_RONLY_MAGIC; over->tlen = under->tlen; } else { under->trace[0] = '\0'; @@ -347,7 +364,7 @@ int (jk_memalign)(void **ptr, size_t a, size_t n) return EINVAL; } - if (((*ptr) = __jkmalloc(NULL, NULL, 0, NULL, a, n, 0, NULL)) == NULL) { + if (((*ptr) = __jkmalloc(NULL, a, n, 0, NULL)) == NULL) { return errno; } diff --git a/src/stdlib/_jkmalloc.h b/src/stdlib/_jkmalloc.h index c6088024..cab5cfcb 100644 --- a/src/stdlib/_jkmalloc.h +++ b/src/stdlib/_jkmalloc.h @@ -3,6 +3,6 @@ #include <inttypes.h> -void* __jkmalloc(const char *file, const char *func, uintmax_t line, void *ptr, size_t alignment, size_t size1 , size_t size2, const char *user); +void* __jkmalloc(void *ptr, size_t alignment, size_t size1 , size_t size2, const char *user); #endif diff --git a/src/stdlib/aligned_alloc.c b/src/stdlib/aligned_alloc.c index 6fa28e9f..89126b18 100644 --- a/src/stdlib/aligned_alloc.c +++ b/src/stdlib/aligned_alloc.c @@ -5,9 +5,11 @@ void *aligned_alloc(size_t alignment, size_t size) { SIGNAL_SAFE(0); - return __jkmalloc(NULL, NULL, 0, NULL, alignment, size, 0, NULL); + return __jkmalloc(NULL, alignment, size, 0, NULL); } +CHECK_2(void *, NULL, aligned_alloc, size_t, size_t) + /* STDC(201112) */ diff --git a/src/stdlib/calloc.c b/src/stdlib/calloc.c index f7d24dc0..9efec5b8 100644 --- a/src/stdlib/calloc.c +++ b/src/stdlib/calloc.c @@ -9,9 +9,11 @@ void * calloc(size_t nmemb, size_t size) { SIGNAL_SAFE(0); - return __jkmalloc(NULL, NULL, 0, NULL, 1, nmemb, size, NULL); + return __jkmalloc(NULL, 1, nmemb, size, NULL); } +CHECK_2(void *, NULL, calloc, size_t, size_t) + /*** allocates an array of ARGUMENT(nmemb) elements, each of which are ARGUMENT(size) bytes, and sets all their bits to 0. diff --git a/src/stdlib/free.c b/src/stdlib/free.c index 3662adb3..40ee9671 100644 --- a/src/stdlib/free.c +++ b/src/stdlib/free.c @@ -9,10 +9,12 @@ void free(void * ptr) SIGNAL_SAFE(0); if (ptr) { - __jkmalloc(NULL, NULL, 0, ptr, 0, 0, 0, NULL); + __jkmalloc(ptr, 0, 0, 0, NULL); } } +VCHECK_1(free, void *) + /*** deallocates the memory at ARGUMENT(ptr). Specifying CONSTANT(NULL) causes nothing to happen. diff --git a/src/stdlib/malloc.c b/src/stdlib/malloc.c index ebac8d39..b32f719a 100644 --- a/src/stdlib/malloc.c +++ b/src/stdlib/malloc.c @@ -7,9 +7,11 @@ void * malloc(size_t size) { SIGNAL_SAFE(0); - return __jkmalloc(NULL, NULL, 0, NULL, 1, size, 0, NULL); + return __jkmalloc(NULL, 1, size, 0, NULL); } +CHECK_1(void *, NULL, malloc, size_t) + /*** allocates ARGUMENT(size) bytes of memory. ***/ diff --git a/src/stdlib/realloc.c b/src/stdlib/realloc.c index 35e12d26..9bac9c5d 100644 --- a/src/stdlib/realloc.c +++ b/src/stdlib/realloc.c @@ -8,9 +8,11 @@ void * realloc(void * ptr, size_t size) { SIGNAL_SAFE(0); - return __jkmalloc(NULL, NULL, 0, ptr, 1, size, 0, NULL); + return __jkmalloc(ptr, 1, size, 0, NULL); } +CHECK_2(void *, NULL, realloc, void *, size_t) + /*** changes the amount of memory allocated to ARGUMENT(ptr) to ARGUMENT(size) bytes. |