Takashi Iwai aa1dc7
From 8423f0b6d513b259fdab9c9bf4aaa6188d054c2d Mon Sep 17 00:00:00 2001
Takashi Iwai aa1dc7
From: Takashi Iwai <tiwai@suse.de>
Takashi Iwai aa1dc7
Date: Mon, 5 Sep 2022 08:07:14 +0200
Takashi Iwai aa1dc7
Subject: [PATCH] ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
Takashi Iwai aa1dc7
Git-commit: 8423f0b6d513b259fdab9c9bf4aaa6188d054c2d
Takashi Iwai aa1dc7
Patch-mainline: v6.0-rc5
Takashi Iwai aa1dc7
References: CVE-2022-3303 bsc#1203769
Takashi Iwai aa1dc7
Takashi Iwai aa1dc7
There is a small race window at snd_pcm_oss_sync() that is called from
Takashi Iwai aa1dc7
OSS PCM SNDCTL_DSP_SYNC ioctl; namely the function calls
Takashi Iwai aa1dc7
snd_pcm_oss_make_ready() at first, then takes the params_lock mutex
Takashi Iwai aa1dc7
for the rest.  When the stream is set up again by another thread
Takashi Iwai aa1dc7
between them, it leads to inconsistency, and may result in unexpected
Takashi Iwai aa1dc7
results such as NULL dereference of OSS buffer as a fuzzer spotted
Takashi Iwai aa1dc7
recently.
Takashi Iwai aa1dc7
Takashi Iwai aa1dc7
The fix is simply to cover snd_pcm_oss_make_ready() call into the same
Takashi Iwai aa1dc7
params_lock mutex with snd_pcm_oss_make_ready_locked() variant.
Takashi Iwai aa1dc7
Takashi Iwai aa1dc7
Reported-and-tested-by: butt3rflyh4ck <butterflyhuangxx@gmail.com>
Takashi Iwai aa1dc7
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Takashi Iwai aa1dc7
Cc: <stable@vger.kernel.org>
Takashi Iwai aa1dc7
Link: https://lore.kernel.org/r/CAFcO6XN7JDM4xSXGhtusQfS2mSBcx50VJKwQpCq=WeLt57aaZA@mail.gmail.com
Takashi Iwai aa1dc7
Link: https://lore.kernel.org/r/20220905060714.22549-1-tiwai@suse.de
Takashi Iwai aa1dc7
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai aa1dc7
Takashi Iwai aa1dc7
---
Takashi Iwai aa1dc7
 sound/core/oss/pcm_oss.c |    5 +++--
Takashi Iwai aa1dc7
 1 file changed, 3 insertions(+), 2 deletions(-)
Takashi Iwai aa1dc7
Takashi Iwai aa1dc7
--- a/sound/core/oss/pcm_oss.c
Takashi Iwai aa1dc7
+++ b/sound/core/oss/pcm_oss.c
Takashi Iwai aa1dc7
@@ -1645,13 +1645,14 @@ static int snd_pcm_oss_sync(struct snd_p
Takashi Iwai aa1dc7
 		runtime = substream->runtime;
Takashi Iwai aa1dc7
 		if (atomic_read(&substream->mmap_count))
Takashi Iwai aa1dc7
 			goto __direct;
Takashi Iwai aa1dc7
-		if ((err = snd_pcm_oss_make_ready(substream)) < 0)
Takashi Iwai aa1dc7
-			return err;
Takashi Iwai aa1dc7
 		atomic_inc(&runtime->oss.rw_ref);
Takashi Iwai aa1dc7
 		if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
Takashi Iwai aa1dc7
 			atomic_dec(&runtime->oss.rw_ref);
Takashi Iwai aa1dc7
 			return -ERESTARTSYS;
Takashi Iwai aa1dc7
 		}
Takashi Iwai aa1dc7
+		err = snd_pcm_oss_make_ready_locked(substream);
Takashi Iwai aa1dc7
+		if (err < 0)
Takashi Iwai aa1dc7
+			goto unlock;
Takashi Iwai aa1dc7
 		format = snd_pcm_oss_format_from(runtime->oss.format);
Takashi Iwai aa1dc7
 		width = snd_pcm_format_physical_width(format);
Takashi Iwai aa1dc7
 		if (runtime->oss.buffer_used > 0) {