Skip to content

Instantly share code, notes, and snippets.

@aprell
Created June 12, 2018 13:58
Show Gist options
  • Select an option

  • Save aprell/cbef2a6d32b5662803928a488fb7c261 to your computer and use it in GitHub Desktop.

Select an option

Save aprell/cbef2a6d32b5662803928a488fb7c261 to your computer and use it in GitHub Desktop.
Guard page polling
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
static void *guard_page;
static unsigned int interruptions;
static inline void protect_guard_page(int prot)
{
if (mprotect(guard_page, sizeof(int), prot) == -1) {
perror("mprotect");
exit(EXIT_FAILURE);
}
}
static void handle_signal(int sig, siginfo_t *info, void *ucontext)
{
(void)ucontext; // unused
if (sig == SIGSEGV && info->si_addr == guard_page) {
interruptions++;
// Reset guard page protection
protect_guard_page(PROT_READ | PROT_WRITE);
} else {
// Regular segfault
abort();
}
}
static void init(void)
{
// Allocate guard page
guard_page = mmap(
NULL,
sizeof(int),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1,
0
);
if (guard_page == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
// Invalidate guard page
// protect_guard_page(PROT_NONE);
struct sigaction action = {
.sa_sigaction = handle_signal,
.sa_flags = SA_SIGINFO
};
// Install SIGSEGV handler
if (sigaction(SIGSEGV, &action, NULL) == -1) {
perror("sigaction");
exit(EXIT_FAILURE);
}
}
#define POLL() (*((int *)(guard_page)) = 0)
static void run(void)
{
long s = 0;
int i;
for (i = 0; i < 100; i++, POLL()) {
s += i;
if (i % 2 == 0) {
protect_guard_page(PROT_NONE);
}
}
assert(interruptions == 50);
}
int main(void)
{
init();
run();
return 0;
}
@aprell

aprell commented Jun 12, 2018

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment