DragonFlyBSD Kernel Audit
DF-2675 / findfield.c
← back to finding ↓ download raw
/*
 * DF-2675 findfield: snapshot the buf array, run `ls /mnt/D13`, snapshot
 * again; for every changed record dump the 4-byte fields that changed
 * (old -> new).  Lets us identify b_loffset (0xD1800), b_bufsize (65536),
 * xio_npages (17), b_vp, b_flags offsets by value.
 */
#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>

int
main(int argc, char **argv)
{
	kvm_t *kd;
	struct nlist nl[] = { { "_buf" }, { NULL } };
	unsigned char *a, *b;
	long nbuf = 12634, szbuf = 1352, n;
	uint64_t bufva;

	kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "findfield");
	if (!kd) return 1;
	if (kvm_nlist(kd, nl) != 0) errx(1, "nlist");
	if (kvm_read(kd, nl[0].n_value, &bufva, 8) != 8) errx(1, "ptr");
	a = malloc(nbuf * szbuf);
	b = malloc(nbuf * szbuf);
	if (!a || !b) err(1, "malloc");
	if (kvm_read(kd, bufva, a, nbuf * szbuf) != nbuf * szbuf) errx(1, "snapA");
	kvm_close(kd);

	if (system(argc > 1 ? argv[1] : "ls /mnt/D13 > /dev/null") != 0)
		errx(1, "cmd failed");

	kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "findfield2");
	if (kvm_read(kd, bufva, b, nbuf * szbuf) != nbuf * szbuf) errx(1, "snapB");
	kvm_close(kd);

	for (n = 0; n < nbuf; n++) {
		int off, changed = 0;
		for (off = 0; off < szbuf; off += 4)
			if (memcmp(a + n*szbuf + off, b + n*szbuf + off, 4)) { changed++; }
		if (!changed) continue;
		printf("=== record %ld changed (%d ints)\n", n, changed);
		for (off = 0; off < szbuf; off += 4) {
			uint32_t va_, vb_;
			if (!memcmp(a + n*szbuf + off, b + n*szbuf + off, 4)) continue;
			memcpy(&va_, a + n*szbuf + off, 4);
			memcpy(&vb_, b + n*szbuf + off, 4);
			printf("  off %4d: %#010x -> %#010x\n", off, va_, vb_);
		}
	}
	return 0;
}