DF-4115 / frag_start.c
/* * 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; } |