Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ALSA: pcm: oss: Fix data race at accessing runtime.oss.trigger

Currently the runtime.oss.trigger field may be accessed concurrently
without protection, which may lead to the data race. And, in this
case, it may lead to more severe problem because it's a bit field; as
writing the data, it may overwrite other bit fields as well, which
confuses the operation completely, as spotted by fuzzing.

Fix it by covering runtime.oss.trigger bit fled also with the existing
params_lock mutex in both snd_pcm_oss_get_trigger() and
snd_pcm_oss_poll().

Reported-and-tested-by: Jaeyoung Chung <jjy600901@snu.ac.kr>
Closes: https://lore.kernel.org/20260423145330.210035-1-jjy600901@snu.ac.kr
Cc: <stable@vger.kernel.org>
Link: https://patch.msgid.link/20260424112205.123703-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+23 -6
+23 -6
sound/core/oss/pcm_oss.c
··· 2155 2155 2156 2156 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2157 2157 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2158 - if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger) 2159 - result |= PCM_ENABLE_OUTPUT; 2160 - if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger) 2161 - result |= PCM_ENABLE_INPUT; 2158 + if (psubstream && psubstream->runtime) { 2159 + guard(mutex)(&psubstream->runtime->oss.params_lock); 2160 + if (psubstream->runtime->oss.trigger) 2161 + result |= PCM_ENABLE_OUTPUT; 2162 + } 2163 + if (csubstream && csubstream->runtime) { 2164 + guard(mutex)(&csubstream->runtime->oss.params_lock); 2165 + if (csubstream->runtime->oss.trigger) 2166 + result |= PCM_ENABLE_INPUT; 2167 + } 2162 2168 return result; 2163 2169 } 2164 2170 ··· 2838 2832 runtime->oss.period_frames; 2839 2833 } 2840 2834 2835 + static bool need_input_retrigger(struct snd_pcm_runtime *runtime) 2836 + { 2837 + bool ret; 2838 + 2839 + guard(mutex)(&runtime->oss.params_lock); 2840 + ret = runtime->oss.trigger; 2841 + if (ret) 2842 + runtime->oss.trigger = 0; 2843 + return ret; 2844 + } 2845 + 2841 2846 static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) 2842 2847 { 2843 2848 struct snd_pcm_oss_file *pcm_oss_file; ··· 2881 2864 snd_pcm_oss_capture_ready(csubstream)) 2882 2865 mask |= EPOLLIN | EPOLLRDNORM; 2883 2866 } 2884 - if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) { 2867 + if (ostate != SNDRV_PCM_STATE_RUNNING && 2868 + need_input_retrigger(runtime)) { 2885 2869 struct snd_pcm_oss_file ofile; 2886 2870 memset(&ofile, 0, sizeof(ofile)); 2887 2871 ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2888 - runtime->oss.trigger = 0; 2889 2872 snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT); 2890 2873 } 2891 2874 }