⬢ DragonFlyBSD Kernel Audit
DF-3248 / bufdump.c
← back to finding ↓ download raw
/*
 * DF-3248 bufdump KLD — walks the kernel buffer-cache queues (bufpcpu[],
 * exported by kern/vfs_bio.c) and prints every buffer whose data contains
 * the HPFS dirblk magic (0x77E40AAE) with d_freeoff 2048, i.e. our cached
 * dirblk chunks, together with the exact kernel-virtual b_data addresses.
 * This measures the chunk layout the de_reclen hop must hit.
 */
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/malloc.h>
#include <sys/spinlock2.h>
#include <vm/vm_page.h>

#define	BQUEUE_NONE	0
#define	BQUEUE_LOCKED	1
#define	BQUEUE_CLEAN	2
#define	BQUEUE_DIRTY	3
#define	BQUEUE_DIRTY_HW	4
#define	BQUEUE_EMPTY	5
#define	BUFFER_QUEUES	6

struct bqueues;
TAILQ_HEAD(bqueues, buf);

struct bufpcpu {
	struct spinlock spin;
	struct bqueues bufqueues[BUFFER_QUEUES];
} __cachealign;

extern struct bufpcpu bufpcpu[MAXCPU];

static void
dumpq(int cpu, int q)
{
	struct buf *bp;

	spin_lock(&bufpcpu[cpu].spin);
	TAILQ_FOREACH(bp, &bufpcpu[cpu].bufqueues[q], b_freelist) {
		if (bp->b_data == NULL || bp->b_bcount < 32)
			continue;
		/* our crafted dirblks: magic 0x77E40AAE + freeoff 2048 */
		if (*(uint32_t *)(bp->b_data) == 0x77E40AAE &&
		    *(uint32_t *)(bp->b_data + 4) == 2048) {
			uint32_t self;
			memcpy(&self, bp->b_data + 16, 4);
			kprintf("DF3248 lsn 0x%04x b_data %p bcount %d q%d\n",
			    self, bp->b_data, bp->b_bcount, q);
		}
	}
	spin_unlock(&bufpcpu[cpu].spin);
}

static int
df3248_handler(module_t mod, int what, void *arg)
{
	int cpu, q;

	switch (what) {
	case MOD_LOAD:
		kprintf("DF3248 bufdump start\n");
		for (cpu = 0; cpu < ncpus; cpu++)
			for (q = BQUEUE_LOCKED; q <= BQUEUE_DIRTY_HW; q++)
				dumpq(cpu, q);
		kprintf("DF3248 bufdump done\n");
		return (0);
	}
	return (0);
}

static moduledata_t df3248_mod = {
	"df3248mod",
	df3248_handler,
	NULL
};

DECLARE_MODULE(df3248mod, df3248_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
MODULE_VERSION(df3248mod, 1);