diff --git a/rust/ares_guard/build.rs b/rust/ares_guard/build.rs index a67919d..8205747 100644 --- a/rust/ares_guard/build.rs +++ b/rust/ares_guard/build.rs @@ -37,17 +37,17 @@ fn main() { .flag("-g3") .flag("-Wall") .flag("-Wextra") - .flag("-Wgnu-pointer-arith") - .flag("-Wpointer-arith") - .flag("-Wpedantic") .flag("-Wformat=2") - .flag("-Wno-unused-parameter") + .flag("-Wmissing-include-dirs") + .flag("-Wnested-externs") + .flag("-Wold-style-definition") + .flag("-Wpedantic") + .flag("-Wredundant-decls") .flag("-Wshadow") .flag("-Wwrite-strings") - .flag("-Wold-style-definition") - .flag("-Wredundant-decls") - .flag("-Wnested-externs") - .flag("-Wmissing-include-dirs") + .flag("-Wno-unused-parameter") + .flag("-Wno-pointer-arith") + .flag("-Wno-strict-prototypes") .try_compile("guard"); if let Err(err) = res { diff --git a/rust/ares_guard/c-src/guard.c b/rust/ares_guard/c-src/guard.c index 508f207..6e77b14 100644 --- a/rust/ares_guard/c-src/guard.c +++ b/rust/ares_guard/c-src/guard.c @@ -7,7 +7,8 @@ #include "guard.h" -#define GD_PAGESZ 16384 +#define GD_PAGEBITS 14ULL +#define GD_PAGESIZE (1ULL << GD_PAGEBITS) /* 16K */ static void *guard_p = NULL; static void *stack_p = NULL; @@ -19,45 +20,60 @@ typedef enum { guard_weird = 2, // strange state guard_spent = 3, // out of memory (bail:meme) guard_erupt = 4, // sigint -} guard_err_t; +} guard_error; volatile sig_atomic_t guard_err = guard_sound; -guard_err_t _focus_guard(void *si_addr) { +// Center the guard page. +guard_error _focus_guard() { // Check for strange situations. - if (stack_p == NULL || alloc_p == NULL || si_addr == NULL) { + if (stack_p == NULL || alloc_p == NULL) { return guard_weird; } - // Re-center the guard page if the fault address falls within it. - if (si_addr >= guard_p && si_addr < guard_p + GD_PAGESZ) { - // Unmark the old guard page. - void *old_guard_pg = guard_p; - if (mprotect(old_guard_pg, GD_PAGESZ, PROT_READ | PROT_WRITE) == -1) { + // Unmark the old guard page. + void *old_guard_p = guard_p; + if (mprotect(old_guard_p, GD_PAGESIZE, PROT_READ | PROT_WRITE) == -1) { + return guard_armor; + } + + // Place the new guard page in the center. + if (stack_p > alloc_p) { + guard_p = stack_p - ((stack_p - alloc_p) / 2); + } + else if (stack_p < alloc_p) { + guard_p = stack_p + ((alloc_p - stack_p) / 2); + } + else { + return guard_weird; + } + guard_p = (void *)((uintptr_t)guard_p & ~(GD_PAGESIZE - 1)); + + // Mark the new guard page. + if (guard_p != old_guard_p) { + if (mprotect(guard_p, GD_PAGESIZE, PROT_NONE) == -1) { return guard_armor; } - - // Place the new guard page in the center. - guard_p = stack_p + ((alloc_p - stack_p) / 2); - // TODO: Ensure the guard_p is page-aligned. - // guard_p = (void *)((uintptr_t)guard_p & ~(GD_PAGESZ - 1)); - if (guard_p != old_guard_pg) { - if (mprotect(guard_p, GD_PAGESZ, PROT_NONE) == -1) { - return guard_armor; - } - } else { - return guard_spent; - } + } else { + return guard_spent; } return guard_sound; } +guard_error _slash_guard(void *si_addr) { + if (si_addr >= guard_p && si_addr < guard_p + GD_PAGESIZE) { + return _focus_guard(); + } + + return guard_weird; +} + void _signal_handler(int sig, siginfo_t *si, void *unused) { switch (sig) { case SIGSEGV: - guard_err = _focus_guard(si->si_addr); + guard_err = _slash_guard(si->si_addr); break; case SIGINT: guard_err = guard_erupt; @@ -67,37 +83,31 @@ void _signal_handler(int sig, siginfo_t *si, void *unused) { } } -guard_err_t _register_handler() { - guard_err_t err = guard_sound; +guard_error _register_handler() { struct sigaction sa; sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = _signal_handler; sa.sa_mask = 0; - if (sigaction(SIGSEGV, &sa, NULL)) { - err = guard_weird; + if (sigaction(SIGSEGV, &sa, NULL) || sigaction(SIGINT, &sa, NULL)) { + return guard_weird; } - return guard_err; + return guard_sound; } void guard(void *(*f)(void *), void *arg, void **stack, void **alloc, void **ret) { - guard_err_t err; stack_p = *stack; alloc_p = *alloc; if (_register_handler() != guard_sound) { - err = guard_weird; + guard_err = guard_weird; goto fail; } - if (guard_p == NULL) { - guard_p = stack_p + ((alloc_p - stack_p) / 2); - if (mprotect(guard_p, GD_PAGESZ, PROT_NONE) == -1) { - err = guard_armor; - goto fail; - } + if (guard_p == NULL && (guard_err = _focus_guard()) != guard_sound) { + goto fail; } *ret = f(arg);