โฌข DragonFlyBSD Kernel Audit
DF-4552 / mixer_probe.c
โ† back to finding โ†“ download raw
/*
 * DF-4552 probe โ€” snd_vibes attach-failure mixer-UAF family (12th instance).
 *
 * Trigger contract (on hardware with an S3 SonicVibes 5333:ca00 present):
 *   1. Make sv_attach() fail AFTER mixer_init() (vibes.c:789) โ€” e.g. by
 *      withholding the DMAA/DMAC I/O window (the driver's midi/games port
 *      "resource assumptions" hack at vibes.c:815-821 fails when the gap is
 *      >= 0x800 or misaligned), or by forcing pcm_register() to fail.
 *   2. mixer_init() (mixer.c:730) has already published /dev/mixerN with
 *      mode 0666 and si_drv1->devinfo == sc. The fail path (vibes.c:888-901)
 *      releases enh/dmaa/dmac bus resources and destroys the dma tag, but
 *      never calls mixer_uninit().
 *   3. As an unprivileged user, open /dev/mixerN and issue MIXER_WRITE โ€”
 *      sv_mix_set() -> sv_gain() -> sv_indirect_get/set() now perform
 *      bus_space_read/write on I/O ports that rman no longer owns
 *      (numerically-valid cached handles sc->enh_st/enh_sh).
 *
 * On the QEMU audit guest there is no SonicVibes PCI device at all, so step
 * 1 cannot even be entered: this probe reports the device's absence, which
 * is the honest not_reproduced evidence for this pack.
 *
 * Build:  cc -O -o mixer_probe mixer_probe.c
 * Run:    ./mixer_probe [/dev/mixerN]
 */
#include <sys/ioctl.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <sys/soundcard.h>

int
main(int argc, char **argv)
{
	const char *path = (argc > 1) ? argv[1] : "/dev/mixer0";
	int fd, v;

	fd = open(path, O_RDWR);
	if (fd < 0) {
		printf("open(\"%s\", O_RDWR): %s\n", path, strerror(errno));
		return (1);
	}

	v = 75 | (75 << 8);	/* l/r 75% */
	if (ioctl(fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &v) < 0)
		printf("MIXER_WRITE(VOLUME): %s\n", strerror(errno));
	else
		printf("MIXER_WRITE(VOLUME): ok (0x%04x)\n", v);

	v = -1;
	if (ioctl(fd, MIXER_READ(SOUND_MIXER_VOLUME), &v) < 0)
		printf("MIXER_READ(VOLUME): %s\n", strerror(errno));
	else
		printf("MIXER_READ(VOLUME): 0x%04x\n", v);

	close(fd);
	return (0);
}