| #define _GNU_SOURCE |
| #include <stdio.h> |
| #include <string.h> |
| #include <sys/mman.h> |
| #include <unistd.h> |
| #include <setjmp.h> |
| #include <signal.h> |
| #include <err.h> |
| |
| static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), |
| int flags) |
| { |
| struct sigaction sa; |
| memset(&sa, 0, sizeof(sa)); |
| sa.sa_sigaction = handler; |
| sa.sa_flags = SA_SIGINFO | flags; |
| sigemptyset(&sa.sa_mask); |
| if (sigaction(sig, &sa, 0)) |
| err(1, "sigaction"); |
| } |
| |
| static jmp_buf fail_jmp; |
| |
| static void handler(int sig, siginfo_t *si, void *ctx_void) |
| { |
| siglongjmp(fail_jmp, 1); |
| } |
| |
| static void dump_page(int n, const void *base) |
| { |
| unsigned char data[4096]; |
| |
| sethandler(SIGBUS, handler, 0); |
| |
| if (sigsetjmp(fail_jmp, 1)) { |
| fprintf(stderr, "Cannot read vvar page %d\n", n); |
| memset(data, 0xff, sizeof(data)); |
| } else { |
| memcpy(data, base, sizeof(data)); |
| } |
| |
| write(1, data, 4096); |
| } |
| |
| int main() |
| { |
| FILE *maps; |
| void *vvar_begin, *vvar_end; |
| int found_vvar = 0; |
| int npages; |
| |
| maps = fopen("/proc/self/maps", "r"); |
| char buf[1024]; |
| while (fgets(buf, 1024, maps)) { |
| if (strstr(buf, "[vvar]")) { |
| found_vvar = 1; |
| break; |
| } |
| } |
| fclose(maps); |
| |
| if (!found_vvar) { |
| fprintf(stderr, "Could not find vvar mapping\n"); |
| return 1; |
| } |
| |
| sscanf(buf, "%p-%p", &vvar_begin, &vvar_end); |
| npages = ((char *)vvar_end - (char *)vvar_begin) / 4096;; |
| |
| fprintf(stderr, "vvar mapping is %d pages (0x%lx - 0x%lx)\n", |
| npages, (unsigned long)vvar_begin, (unsigned long)vvar_end); |
| |
| for (int i = 0; i < npages; i++) |
| dump_page(i, (char *)vvar_begin + i * 4096); |
| |
| mprotect(vvar_begin, vvar_end - vvar_begin, PROT_READ | PROT_WRITE); |
| |
| return 0; |
| } |