DragonFlyBSD Kernel Audit
DF-1337 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -1759,6 +1759,17 @@
 
 	CHN_LOCKASSERT(c);
 
+	/*
+	 * Wait for any in-flight chn_read/chn_write to finish before resizing
+	 * the buffer.  chn_read/chn_write drop the channel lock across uiomove()
+	 * while holding a raw pointer into bs->buf; a concurrent remalloc here
+	 * would free that buffer from under them (use-after-free write/read).
+	 * The SILENCE/SKIP ioctls already wait via this counter (see dsp.c); the
+	 * blocksize/fragment/format-change ioctls must do the same.
+	 */
+	while (c->inprog != 0)
+		cv_wait(&c->cv, c->lock);
+
 	if ((c->flags & (CHN_F_MMAP | CHN_F_TRIGGERED)) ||
 	    !(c->direction == PCMDIR_PLAY || c->direction == PCMDIR_REC))
 		return EINVAL;