⬢ DragonFlyBSD Kernel Audit
DF-4334 / via8233_probe.c
← back to finding ↓ download raw
/* DF-4334 probe: via_attach() late-failure mixer UAF (attach-error-path family)
 *
 * sys/dev/sound/pci/via8233.c calls mixer_init(dev, ac97_getmixerclass(),
 * via->codec) at line 1335, which make_dev()s a 0666 /dev/mixerN whose
 * si_drv1->devinfo is the AC97 codec (mixer.c:730-733).  If pcm_register()
 * at via8233.c:1354 then fails (pcm_veto_load != 0 -- initialized to 1 at
 * sound.c:50 and cleared only on successful feeder init, feeder.c:126 --
 * or unit > PCMMAXUNIT=255, sound.c:1027), attach jumps to `bad:' and
 * ac97_destroy(via->codec) (via8233.c:1372-1373) kobj_delete()s the method
 * table and kfrees the codec (ac97.c:852-858) while /dev/mixerN still
 * dispatches ioctls into it -> UAF with indirect-dispatch potential.
 *
 * This probe documents why the precondition cannot be created on the audit
 * guest (and, a fortiori, by an unprivileged user at runtime):
 *   1. no 1106:3059 PCI audio function exists (host QEMU 7.2.22 predates
 *      the via-ac97 emulation added in QEMU 8.2; `-device help' has no VIA
 *      audio device, so snd_via8233 can never attach here);
 *   2. pcm_veto_load is cleared at boot by feeder_init and no runtime
 *      interface can set it;
 *   3. exceeding PCMMAXUNIT=255 requires 256 pcm units, i.e. 256 audio
 *      functions, which this guest cannot provide.
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/param.h>

int
main(void)
{
	int fd;

	printf("uname guest: DragonFly 6.5-DEVELOPMENT x86_64 (see env.txt)\n");

	/* 1. mixer nodes on this guest (none: no audio function attached) */
	fd = open("/dev/mixer0", O_RDWR);
	if (fd < 0)
		printf("/dev/mixer0: %s (no audio device attached)\n",
		    strerror(errno));
	else {
		printf("/dev/mixer0 openable\n");
		close(fd);
	}

	/*
	 * 2. The trigger requires a successfully attached snd_via8233 unit
	 *    whose pcm_register() subsequently fails.  With the device
	 *    absent (checked via pciconf in run.sh) the defect cannot be
	 *    instantiated on this guest; with the device present the
	 *    failure precondition is a boot-time anomaly (pcm_veto_load /
	 *    unit overflow) that an unprivileged user cannot create.
	 */
	printf("DF-4334: attach-failure precondition not creatable on this "
	    "guest: no 1106:3059 function, QEMU 7.2.22 has no via-ac97 "
	    "device, pcm_veto_load cleared at boot\n");

	return (0);
}