โฌข DragonFlyBSD Kernel Audit
DF-4115 / frag_start.c
โ† back to finding โ†“ download raw
/*
 * DF-4115/4116 โ€” focused: extreme SETFRAGMENT + ACTUAL STREAM START.
 * For each hostile fragment setting, configure and then WRITE so the
 * stream is really started (hdaa_channel_start -> hdac_stream_start,
 * the BDL walk). Watch the serial console b[..] lines (hw sndbuf) at
 * hw.snd.verbose=4: the hw blkcnt must never exceed HDA_BDL_MAX=256.
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>

static const int frags[] = {
	0x7fff0000, 0x00010000, 0x00020001, 0xffff001f, 0x8000001e,
	0x00000000, 0x7fffffff, 0xffffffff, 0x01000100, 0x00ff0004,
	0x20000003,	/* 8192 frags of 8 bytes โ€” the exact observed 8192 shape */
};

int main(void)
{
	setvbuf(stdout, NULL, _IONBF, 0);
	char junk[8192];
	memset(junk, 0x41, sizeof(junk));
	int bad = 0;
	for (size_t i = 0; i < sizeof(frags)/sizeof(frags[0]); i++) {
		int fd = open("/dev/dsp0", O_WRONLY);
		if (fd < 0) {
			printf("[-] open: %s\n", strerror(errno));
			return 2;
		}
		int fmt = AFMT_S16_LE, ch = 2, sp = 48000, arg = frags[i];
		audio_buf_info oi;
		(void)ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
		(void)ioctl(fd, SNDCTL_DSP_CHANNELS, &ch);
		(void)ioctl(fd, SNDCTL_DSP_SPEED, &sp);
		(void)ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg);
		memset(&oi, 0, sizeof(oi));
		(void)ioctl(fd, SNDCTL_DSP_GETOSPACE, &oi);
		/* START the stream: this is the BDL-walk trigger */
		ssize_t n = write(fd, junk, sizeof(junk));
		usleep(20000);
		(void)ioctl(fd, SNDCTL_DSP_RESET, NULL);
		close(fd);
		printf("[%02zu] frag=%#010x -> soft %d/%d/%d wrote=%zd\n",
		    i, frags[i], oi.fragsize, oi.fragstotal, oi.bytes, n);
		if (oi.fragstotal > 256)
			printf("     (soft blkcnt>%d โ€” hw path must clamp)\n", 256);
		bad++;
	}
	printf("[+] frag+start battery done, %d configs, guest alive\n",
	    (int)(sizeof(frags)/sizeof(frags[0])));
	return 0;
}