DF-2675 / p16watch.c
/* * DF-2675 p16watch: for every OVR buffer (xio_npages > kvasize/4096), * print kva, npages, loff, and the first 16 bytes of the page currently * mapped at kva+MAXBSIZE (the overflow page) -- lets the orchestrator * detect when a neighbor replaced the mapping (content becomes canary). */ #include <sys/types.h> #include <err.h> #include <fcntl.h> #include <kvm.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define PMASK 0x000FFFFFFFFFF000ULL #define MAXBSIZE_ 65536 static int memfd; static uint64_t KPML4; static int rdphys(uint64_t pa, void *buf, size_t len) { return (pread(memfd, buf, len, (off_t)pa) == (ssize_t)len); } static uint64_t pteof(uint64_t va) { uint64_t pml4[512], pud[512], pd[512], pt[512]; int i4, i3, i2; i4 = (int)((va >> 39) & 511); i3 = (int)((va >> 30) & 511); i2 = (int)((va >> 21) & 511); if (!rdphys(KPML4, pml4, 4096) || !(pml4[i4] & 1)) return 0; if (!rdphys(pml4[i4] & PMASK, pud, 4096) || !(pud[i3] & 1)) return 0; if (pud[i3] & 0x80) return 0; if (!rdphys(pud[i3] & PMASK, pd, 4096) || !(pd[i2] & 1)) return 0; if (pd[i2] & 0x80) return 0; if (!rdphys(pd[i2] & PMASK, pt, 4096)) return 0; return pt[(va >> 12) & 511]; } int main(void) { kvm_t *kd; struct nlist nl[] = { { "_buf" }, { "_KPML4phys" }, { NULL } }; unsigned char *arr; long nbuf = 12634, szbuf = 1352, n; uint64_t bufva; kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "p16watch"); if (!kd) return 1; if (kvm_nlist(kd, nl) != 0) errx(1, "nlist"); if (kvm_read(kd, nl[1].n_value, &KPML4, 8) != 8) errx(1, "kpml4"); if (kvm_read(kd, nl[0].n_value, &bufva, 8) != 8) errx(1, "bufptr"); arr = malloc(nbuf * szbuf); if (!arr) err(1, "malloc"); if (kvm_read(kd, bufva, arr, nbuf * szbuf) != nbuf * szbuf) errx(1, "arr"); kvm_close(kd); memfd = open("/dev/mem", O_RDONLY); if (memfd < 0) err(1, "/dev/mem"); for (n = 0; n < nbuf; n++) { uint64_t kv, loff, p16; int np, ks; unsigned char rec[1352], data[16]; memcpy(rec, arr + n * szbuf, szbuf); memcpy(&kv, rec + 1024, 8); if (kv == 0) continue; memcpy(&np, rec + 1056, 4); memcpy(&ks, rec + 1032, 4); if (ks == 0) continue; if (np <= ks / 4096) continue; memcpy(&loff, rec + 176, 8); p16 = pteof(kv + MAXBSIZE_) & PMASK; memset(data, 0, 16); if (p16) rdphys(p16, data, 16); printf("OVR n=%ld kva=%#llx np=%d loff=%#llx p16=%#llx c=%02x%02x%02x%02x %c%c%c%c%c%c%c%c\n", n, (unsigned long long)kv, np, (unsigned long long)loff, (unsigned long long)p16, data[0], data[1], data[2], data[3], (data[0] > 32 && data[0] < 127) ? data[0] : '.', (data[1] > 32 && data[1] < 127) ? data[1] : '.', (data[2] > 32 && data[2] < 127) ? data[2] : '.', (data[3] > 32 && data[3] < 127) ? data[3] : '.', (data[4] > 32 && data[4] < 127) ? data[4] : '.', (data[5] > 32 && data[5] < 127) ? data[5] : '.', (data[6] > 32 && data[6] < 127) ? data[6] : '.', (data[7] > 32 && data[7] < 127) ? data[7] : '.'); } return 0; } |