summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2024-01-30 16:08:14 -0500
committerJakob Kaivo <jkk@ung.org>2024-01-30 16:08:14 -0500
commit0771ff15d44a59f7b1ccc5ddb2129b45ed9c93a1 (patch)
treea49bfb39f7e3fb59844bc489e5cdd99162015c7f
parent237bf6358ed3e39b584b23d6b52e2b91a1d69cfa (diff)
prep for integration
-rw-r--r--src/signal/__sigsegv.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/signal/__sigsegv.c b/src/signal/__sigsegv.c
new file mode 100644
index 00000000..cf03278f
--- /dev/null
+++ b/src/signal/__sigsegv.c
@@ -0,0 +1,142 @@
+#if 0
+#define _DEFAULT_SOURCE "give me anonymous, gnu"
+#define _XOPEN_SOURCE 700
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#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
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define psiginfo(x, y) ((y) ? fprintf(stderr, "%s\n", (char*)(y)) : 0)
+
+#define PTR_BITS (CHAR_BIT * sizeof(uintptr_t))
+
+#define JKMALLOC_EXIT_VALUE (127 + SIGSEGV)
+#define JK_FREE_LIST_SIZE (8)
+
+/* magic numbers derived from CRC-32 of jk_foo_block */
+#define JK_FREE_MAGIC (0x551a51dc)
+#define JK_UNDER_MAGIC (0xcb2873ac)
+#define JK_OVER_MAGIC (0x18a12c17)
+
+#define jk_pages(bytes) (((bytes + jk_pagesize - 1) / jk_pagesize) + 2)
+#define jk_pageof(addr) ((void*)((uintptr_t)addr - ((uintptr_t)addr % jk_pagesize)))
+#define jk_bucketof(addr) ((void*)((uintptr_t)jk_pageof(addr) - jk_pagesize))
+
+struct jk_bucket {
+ uint32_t magic;
+ uintptr_t start;
+ size_t size;
+ size_t align;
+ size_t pages;
+ size_t tlen;
+ char trace[];
+};
+
+struct jk_source {
+ const char *file;
+ const char *func;
+ uintmax_t line;
+ struct jk_bucket *bucket;
+};
+
+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_error(const char *s, void *addr, struct jk_source *src)
+{
+ if (s && *s) {
+ write(STDERR_FILENO, s, strlen(s));
+ if (addr != NULL) {
+ char hex[] = "01234567890abcdef";
+ char ha[sizeof(uintptr_t) * 2 + 5] = ": 0x";
+ uintptr_t a = (uintptr_t)addr;
+ /* FIXME */
+ for (size_t i = 0; i < sizeof(uintptr_t); i++) {
+ ha[4 + 2 * i] = hex[(a >> (PTR_BITS - i)) & 0xf];
+ ha[4 + 2 * i + 1] = hex[(a >> (PTR_BITS - i + 1)) & 0xf];
+ }
+ write(STDERR_FILENO, ha, sizeof(ha));
+ }
+ write(STDERR_FILENO, "\n", 1);
+ }
+
+ if (src && src->bucket && src->bucket->trace[0] != '\0') {
+ write(STDERR_FILENO, src->bucket->trace, src->bucket->tlen);
+ write(STDERR_FILENO, "\n", 1);
+ }
+
+ if (src && src->file) {
+ fprintf(stderr, "!!! %s() (%s:%ju)\n", src->func, src->file, src->line);
+ }
+
+ _Exit(JKMALLOC_EXIT_VALUE);
+}
+
+static void jk_sigaction(int sig, siginfo_t *si, void *addr)
+{
+ (void)sig; (void)addr;
+ if (si->si_addr == NULL) {
+ psiginfo(si, "NULL pointer dereference");
+ jk_error(NULL, NULL, NULL);
+ }
+
+ struct jk_bucket *bucket = jk_pageof(si->si_addr);
+ if (mprotect(bucket, jk_pagesize, PROT_READ) != 0) {
+ psiginfo(si, NULL);
+ jk_error(NULL, NULL, NULL);
+ }
+
+ switch (bucket->magic) {
+ case JK_UNDER_MAGIC:
+ if (bucket->size == 0) {
+ psiginfo(si, "Attempt to use 0-byte allocation");
+ } else {
+ psiginfo(si, "Heap underflow detected");
+ }
+ break;
+
+ case JK_OVER_MAGIC:
+ if (bucket->size == 0) {
+ psiginfo(si, "Attempt to use 0-byte allocation");
+ } else {
+ psiginfo(si, "Heap overflow detected");
+ fprintf(stderr, "Allocation of size %zu at %p, overflow at %p (offset %zu)\n", bucket->size, (void*)bucket->start, si->si_addr, (size_t)((char*)si->si_addr - (char*)bucket->start));
+ fprintf(stderr, "Buffer begins with %4s\n", (char*)bucket->start);
+ }
+ break;
+
+ case JK_FREE_MAGIC:
+ psiginfo(si, "Use after free() detected");
+ break;
+
+ default:
+ psiginfo(si, NULL);
+ }
+
+ struct jk_source src = { .bucket = bucket };
+ jk_error(NULL, NULL, &src);
+}
+
+/*
+STDC(0)
+SIGNAL_SAFE(0)
+*/
+#endif