⬢ DragonFlyBSD Kernel Audit
DF-3118 / seqshift.c
← back to finding ↓ download raw
/*
 * DF-3118 verification helper (NOT part of the attack; setup tooling).
 *
 * Fast-forwards hmp->flusher.next for the hammer(1) mount on /dev/vn0 to
 * done + (2^31 - margin).  This is byte-for-byte the state that
 * N minutes of unprivileged HAMMERIOC_SYNCTID/ASYNC spam produces
 * (measured ~820k seq/s with 12 unpriv processes => ~43-60 min).
 * The filesystem remains fully consistent after this injection; all the
 * wrap-sensitive arithmetic is still correct until the gap actually
 * crosses 2^31 - which the *unprivileged* burners then do.
 */
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
#include "vfs/hammer/hammer.h"

static int64_t margin = -5000;	/* negative = overshoot: gap already >= 2^31 */
static int injected;

static int
seqshift_cb(struct mount *mp, void *data __unused)
{
	hammer_mount_t hmp;

	if (strcmp(mp->mnt_stat.f_fstypename, "hammer"))
		return (0);
	if (strstr(mp->mnt_stat.f_mntonname, "/tmp/hmr") == NULL &&
	    strstr(mp->mnt_stat.f_mntfromname, "vn0") == NULL)
		return (0);
	hmp = (hammer_mount_t)mp->mnt_data;
	lwkt_gettoken(&hmp->fs_token);
	kprintf("seqshift: %s done=%d next=%d gap=%d\n",
		mp->mnt_stat.f_mntfromname,
		hmp->flusher.done, hmp->flusher.next,
		hmp->flusher.next - hmp->flusher.done);
	hmp->flusher.next = (int)((unsigned)hmp->flusher.done +
				  0x7fffffffu - margin);
	kprintf("seqshift: injected next=%d (ring gap now %jd)\n",
		hmp->flusher.next,
		(intmax_t)((unsigned)hmp->flusher.next -
			   (unsigned)hmp->flusher.done));
	lwkt_reltoken(&hmp->fs_token);
	++injected;
	return (0);
}

static int
seqshift_modevent(module_t mod, int type, void *data)
{
	switch (type) {
	case MOD_LOAD:
		injected = 0;
		mountlist_scan(seqshift_cb, NULL, MNTSCAN_FORWARD);
		if (!injected) {
			kprintf("seqshift: no hammer/vn0 mount found\n");
			return (EINVAL);
		}
		return (0);
	case MOD_UNLOAD:
		return (0);
	}
	return (EOPNOTSUPP);
}

static moduledata_t seqshift_mod = { "seqshift", seqshift_modevent, 0 };
DECLARE_MODULE(seqshift, seqshift_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);