mirror of
https://github.com/urbit/ares.git
synced 2024-11-26 09:57:56 +03:00
guard: partially address @ashelkovnykov's comments
This commit is contained in:
parent
b1e3b788b1
commit
d13fe50c72
@ -34,7 +34,7 @@ static GD_state gd = {
|
||||
.prev_sigbus_sa = { .sa_sigaction = NULL, .sa_flags = 0 },
|
||||
};
|
||||
|
||||
static guard_result
|
||||
static guard_err
|
||||
_protect_page(void *address, int prot)
|
||||
{
|
||||
if (mprotect(address, GD_PAGE_SIZE, prot)) {
|
||||
@ -43,18 +43,18 @@ _protect_page(void *address, int prot)
|
||||
return guard_mprotect | errno;
|
||||
}
|
||||
|
||||
return guard_success;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Center the guard page.
|
||||
static guard_result
|
||||
static guard_err
|
||||
_focus_guard()
|
||||
{
|
||||
uintptr_t stack_p = *gd.stack_pp;
|
||||
uintptr_t alloc_p = *gd.alloc_pp;
|
||||
uintptr_t old_guard_p = gd.guard_p;
|
||||
uintptr_t new_guard_p;
|
||||
guard_result err = guard_success;
|
||||
guard_err err = 0;
|
||||
|
||||
if (stack_p == 0 || alloc_p == 0) {
|
||||
fprintf(stderr, "guard: focus: stack or alloc pointer is null\r\n");
|
||||
@ -86,14 +86,14 @@ _focus_guard()
|
||||
}
|
||||
}
|
||||
|
||||
return guard_success;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_signal_handler(int sig, siginfo_t *si, void *unused)
|
||||
{
|
||||
uintptr_t sig_addr;
|
||||
guard_result err = guard_success;
|
||||
guard_err err = 0;
|
||||
|
||||
assert(gd.guard_p);
|
||||
|
||||
@ -138,7 +138,7 @@ _signal_handler(int sig, siginfo_t *si, void *unused)
|
||||
}
|
||||
|
||||
// Registers the same handler function for SIGSEGV and SIGBUS.
|
||||
static guard_result
|
||||
static guard_err
|
||||
_register_handlers()
|
||||
{
|
||||
struct sigaction sa;
|
||||
@ -157,10 +157,10 @@ _register_handlers()
|
||||
return guard_sigaction | errno;
|
||||
}
|
||||
|
||||
return guard_success;
|
||||
return 0;
|
||||
}
|
||||
|
||||
guard_result
|
||||
guard_err
|
||||
guard(
|
||||
void *(*f)(void *),
|
||||
void *closure,
|
||||
@ -169,8 +169,8 @@ guard(
|
||||
void **ret
|
||||
) {
|
||||
GD_buflistnode *new_buffer;
|
||||
guard_result err = guard_success;
|
||||
guard_result td_err = guard_success;
|
||||
guard_err err = 0;
|
||||
guard_err td_err = 0;
|
||||
|
||||
if (gd.guard_p == 0) {
|
||||
assert(gd.buffer_list == NULL);
|
||||
|
@ -10,7 +10,7 @@
|
||||
typedef struct GD_buflistnode GD_buflistnode;
|
||||
struct GD_buflistnode {
|
||||
jmp_buf buffer;
|
||||
struct GD_buflistnode *next;
|
||||
GD_buflistnode *next;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -19,21 +19,20 @@ struct GD_buflistnode {
|
||||
* The flags are bitwise added to the errno of their respective errors.
|
||||
*/
|
||||
typedef enum {
|
||||
guard_success = 0, // successful return
|
||||
guard_null = 1, // null stack or alloc pointer
|
||||
guard_signal = 2, // invalid signal
|
||||
guard_oom = 3, // out of memory
|
||||
guard_malloc = 0x10000000, // malloc error flag
|
||||
guard_mprotect = 0x20000000, // mprotect error flag
|
||||
guard_sigaction = 0x40000000, // sigaction error flag
|
||||
} guard_result;
|
||||
} guard_err;
|
||||
|
||||
/**
|
||||
* @brief Executes the given callback function `f` within the memory arena
|
||||
* between the stack and allocation pointers pointed to by `s_pp` and `a_pp`,
|
||||
* with guard page protection. If `f`'s execution succeeds, its result is
|
||||
* written to the return pointer `*ret`. If `f`'s execution triggers an
|
||||
* out of memory error or any other `guard_result`, the `guard_result` is
|
||||
* out of memory error or any other `guard_err`, the `guard_err` is
|
||||
* returned and `*ret` is left empty. In either case, cleanup is performed
|
||||
* before returning.
|
||||
*
|
||||
@ -49,14 +48,14 @@ typedef enum {
|
||||
* - The caller is responsible for managing any external state the callback
|
||||
* function may mutate.
|
||||
* - The callback function may be interrupted in the case of memory exhaustion
|
||||
* or other `guard_result` error (failure to `mprotect`, `malloc`, etc.).
|
||||
* or other `guard_err` error (failure to `mprotect`, `malloc`, etc.).
|
||||
* - `SIGSEGV` signals are expected to be raised only on guard page accesses.
|
||||
*
|
||||
* Invariants:
|
||||
* - A single guard page is installed and maintained in the approximate center
|
||||
* until `crate::guard::call_with_guard` returns.
|
||||
* - A return value is only written to `*ret` on successful callback execution.
|
||||
* - A `guard_result` is returned, excepting panics or negative assertions.
|
||||
* - A `guard_err` is returned, excepting panics or negative assertions.
|
||||
*
|
||||
* Enhancements:
|
||||
* - Use only a single, static jump buffer variable instead of a linked list.
|
||||
@ -70,9 +69,9 @@ typedef enum {
|
||||
* @param a_pp A pointer to the allocation pointer location.
|
||||
* @param ret A pointer to a location where the callback's result can be stored.
|
||||
*
|
||||
* @return A `guard_result` return code.
|
||||
* @return A `guard_err` error code.
|
||||
*/
|
||||
guard_result
|
||||
guard_err
|
||||
guard(
|
||||
void *(*f)(void *),
|
||||
void *closure,
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
|
||||
pub const GUARD_SUCCESS: u32 = guard_result_guard_success;
|
||||
pub const GUARD_NULL: u32 = guard_result_guard_null;
|
||||
pub const GUARD_SIGNAL: u32 = guard_result_guard_signal;
|
||||
pub const GUARD_OOM: u32 = guard_result_guard_oom;
|
||||
|
Loading…
Reference in New Issue
Block a user