DragonFlyBSD Kernel Audit
DF-2675 / pml4dump.c
← back to finding ↓ download raw
/* DF-2675: dump present PML4 entries (phys + PT count) of the running kernel */
#include <sys/types.h>
#include <err.h>
#include <fcntl.h>
#include <kvm.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define PMASK 0x000FFFFFFFFFF000ULL

int
main(void)
{
	kvm_t *kd;
	struct nlist nl[] = { { "_KPML4phys" }, { NULL } };
	uint64_t KPML4, pml4[512], pud[512], pd[512];
	int memfd, p4, p3, p2, ptes;

	kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "pml4dump");
	if (!kd) return 1;
	if (kvm_nlist(kd, nl) != 0 || nl[0].n_value == 0)
		errx(1, "nlist");
	if (kvm_read(kd, nl[0].n_value, &KPML4, 8) != 8)
		errx(1, "read");
	kvm_close(kd);
	memfd = open("/dev/mem", O_RDONLY);
	if (memfd < 0) err(1, "/dev/mem");
	if (pread(memfd, pml4, 4096, (off_t)KPML4) != 4096) errx(1, "pml4 read");
	printf("KPML4phys = %jx\n", (uintmax_t)KPML4);
	for (p4 = 0; p4 < 512; ++p4) {
		if (!(pml4[p4] & 1)) continue;
		ptes = 0;
		if (pread(memfd, pud, 4096, (off_t)(pml4[p4] & PMASK)) != 4096) continue;
		for (p3 = 0; p3 < 512; ++p3) {
			if (!(pud[p3] & 1)) continue;
			if (pud[p3] & 0x80) { ptes += 262144; continue; }
			if (pread(memfd, pd, 4096, (off_t)(pud[p3] & PMASK)) != 4096) continue;
			for (p2 = 0; p2 < 512; ++p2) {
				if (!(pd[p2] & 1)) continue;
				if (pd[p2] & 0x80) { ptes += 512; continue; }
				ptes += 1;
			}
		}
		printf("PML4[%3d] phys=%012jx PTs(+large)=%d KVA=%016llx..%016llx\n",
		       p4, (uintmax_t)(pml4[p4] & PMASK), ptes,
		       (unsigned long long)((uint64_t)p4 << 39),
		       (unsigned long long)(((uint64_t)p4 + 1) << 39) - 1);
	}
	return 0;
}