⬢ DragonFlyBSD Kernel Audit
DF-4710 / ospace.c
← back to finding ↓ download raw
/*
 * ospace.c — kernel-side churn: EQ-enabled multichannel playback on the live
 * guest (/dev/dsp), polling SNDCTL_DSP_GETOSPACE for the rl>bufsize wrap that
 * sndbuf_acquire would exhibit if the FXDIV overshoot return (count+align-1)
 * is accepted with exactly `count` free. Unprivileged (maxx).
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
int main(int argc, char **argv) {
	int ch = argc>1?atoi(argv[1]):6;
	int fd = open("/dev/dsp", O_WRONLY);
	if (fd<0){perror("open");return 1;}
	int v=AFMT_S16_LE; ioctl(fd,SNDCTL_DSP_SETFMT,&v);
	v=ch; ioctl(fd,SNDCTL_DSP_CHANNELS,&v);
	v=48000; ioctl(fd,SNDCTL_DSP_SPEED,&v);
	int frag = (16<<16)|15; ioctl(fd,SNDCTL_DSP_SETFRAGMENT,&frag);
	audio_buf_info bi; memset(&bi,0,sizeof bi);
	ioctl(fd,SNDCTL_DSP_GETOSPACE,&bi);
	printf("ch=%d frags=%d fragstotal=%d fragsize=%d bytes=%d\n",
	    bi.fragments, bi.fragstotal, bi.fragsize, bi.bytes);
	int total = bi.fragstotal*bi.fragsize;
	short *buf = malloc(1<<20);
	for (int i=0;i<(1<<19);i++) buf[i]=(short)(i*2654435761u);
	int weird=0;
	for (int iter=0; iter<400; iter++) {
		write(fd, buf, 32768);
		write(fd, buf, 32768);
		usleep(3000);
		memset(&bi,0,sizeof bi);
		ioctl(fd,SNDCTL_DSP_GETOSPACE,&bi);
		if (bi.fragstotal && (bi.bytes > total || bi.fragments > bi.fragstotal+64 ||
		    (int)bi.bytes < -1000)) {
			printf("ANOMALY iter=%d frags=%d total=%d fragsize=%d bytes=%d (buf=%d)\n",
			    iter, bi.fragments, bi.fragstotal, bi.fragsize, bi.bytes, total);
			if (++weird > 5) break;
		}
	}
	printf("done ch=%d weird=%d errno=%d\n", ch, weird, errno);
	return 0;
}