⬢ DragonFlyBSD Kernel Audit
DF-5016 / offmod2.c
← back to finding ↓ download raw
/*
 * offmod2 v2 -- DF-5015 in-kernel evidence probe (crash-safe).
 * sysctl hw.df5015: live syscons history state of the ACTIVE scp +
 * count of Z-cells (0x075a) in the page BEFORE the history buffer.
 */
#include <sys/param.h>
#include <sys/stdint.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
#include <sys/bus.h>
#include <sys/consio.h>
#include <sys/fbio.h>
#include <vm/pmap.h>
#include <dev/misc/syscons/syscons.h>

static char report[4096];

static int
df5015_state(SYSCTL_HANDLER_ARGS)
{
	devclass_t dc;
	device_t dev;
	sc_softc_t *sc;
	scr_stat *scp;
	sc_vtb_t *vtb;
	int n = 0;

	dc = devclass_find("sc");
	if (dc == NULL) {
		n = ksnprintf(report, sizeof(report), "no sc devclass");
		goto out;
	}
	dev = devclass_get_device(dc, 0);
	if (dev == NULL) {
		n = ksnprintf(report, sizeof(report), "no sc0 device");
		goto out;
	}
	sc = device_get_softc(dev);
	if (sc == NULL || sc->cur_scp == NULL) {
		n = ksnprintf(report, sizeof(report), "no softc/cur_scp");
		goto out;
	}
	scp = sc->cur_scp;
	if (scp->history == NULL) {
		ksnprintf(report, sizeof(report),
		    "scp=%p history=NULL xsize=%d ysize=%d",
		    scp, scp->xsize, scp->ysize);
		goto out;
	}
	vtb = scp->history;
	n = ksnprintf(report, sizeof(report),
	    "scp=%p vtb=%p cols=%d rows=%d size=%d buf=%p tail=%d "
	    "xsize=%d ysize=%d", scp, vtb, vtb->vtb_cols, vtb->vtb_rows,
	    vtb->vtb_size, vtb->vtb_buffer, vtb->vtb_tail, scp->xsize,
	    scp->ysize);
	if (vtb->vtb_buffer != NULL) {
		uint16_t *prev = (uint16_t *)((char *)vtb->vtb_buffer - 4096);
		vm_paddr_t pa = pmap_kextract((vm_offset_t)prev);
		int zprev = -1, zin = -1, i;

		if (pa != 0 && pmap_kextract((vm_offset_t)(prev + 2047)) != 0) {
			zprev = 0;
			for (i = 0; i < 2048; i++)
				if (prev[i] == 0x075a)
					zprev++;
		}
		if (vtb->vtb_size > 0 && vtb->vtb_size <= 65536) {
			zin = 0;
			for (i = 0; i < vtb->vtb_size; i++)
				if (vtb->vtb_buffer[i] == 0x075a)
					zin++;
		}
		if (n < (int)sizeof(report) - 1)
			ksnprintf(report + n, sizeof(report) - n,
			    " prevphys=%#llx zprev=%d zin=%d",
			    (unsigned long long)pa, zprev, zin);
	}
out:
	return SYSCTL_OUT(req, report, strlen(report) + 1);
}

SYSCTL_PROC(_hw, OID_AUTO, df5015, CTLTYPE_STRING | CTLFLAG_RD,
    0, 0, df5015_state, "A", "DF-5015 syscons history probe");

static int
offmod2_load(module_t mod, int what, void *arg)
{
	switch (what) {
	case MOD_LOAD:
		kprintf("DF5015OFF2 loaded\n");
		return 0;
	case MOD_UNLOAD:
		return 0;
	default:
		return 0;
	}
}

static moduledata_t offmod2_mod = { "offmod2", offmod2_load, NULL };
DECLARE_MODULE(offmod2, offmod2_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);