summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-05-29 16:07:14 -0400
committerJakob Kaivo <jkk@ung.org>2024-05-29 16:07:14 -0400
commit824f22a3684209b1e11c87f20e6ff17beb8e73a3 (patch)
tree591521c80a1cc771da5dc37d5bdfee5b89a3bb73
parentc9ec058657f9f8b3fd39a16f1a9e993b4a1e982e (diff)
finish integrating jkmalloc and read-only variable support
-rw-r--r--src/__readonly.c2
-rw-r--r--src/_forced/mprotect.h5
-rw-r--r--src/signal/sigaction.c15
-rw-r--r--src/signal/signal.c6
-rw-r--r--src/stdlib/__jkmalloc.c81
-rw-r--r--src/stdlib/_jkmalloc.h2
-rw-r--r--src/stdlib/aligned_alloc.c4
-rw-r--r--src/stdlib/calloc.c4
-rw-r--r--src/stdlib/free.c4
-rw-r--r--src/stdlib/malloc.c4
-rw-r--r--src/stdlib/realloc.c4
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.