VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46157

CVE-2026-46157

Description

In the Linux kernel, the following vulnerability has been resolved:

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().

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A data race in the Linux kernel's ALSA PCM OSS emulation layer allows concurrent access to a critical bit field, potentially corrupting trigger state.

Vulnerability

In the Linux kernel, the ALSA PCM OSS emulation layer has a data race on the runtime.oss.trigger bit field [1]. This field is accessed concurrently without proper locking, which can corrupt adjacent bit fields because writes to a bit field are not atomic on many architectures. The vulnerability affects all kernel versions that include the OSS PCM emulation code prior to the fix applied in commit 6b01c1bc9a4748ab37548a700a8aaff910e298e6 [1].

Exploitation

An attacker needs to have access to the ALSA OSS PCM emulation interface, which is often exposed to unprivileged users via /dev/snd/* or /dev/audio depending on the system configuration. By triggering concurrent calls to snd_pcm_oss_get_trigger() and snd_pcm_oss_poll() (or other operations that read/write the same bit field), the attacker can cause a race condition that corrupts runtime.oss.trigger and other bit fields in the same word [1]. No authentication is required beyond local user access to the sound device.

Impact

Successful exploitation can lead to corruption of the OSS PCM trigger state, potentially causing the audio subsystem to behave unpredictably. In fuzzing tests, this data race caused severe confusion in the operation of the ALSA PCM OSS emulation [1]. Depending on the corrupted bit pattern, an attacker might be able to trigger denial of service or, in theory, leverage the corrupt state to escalate privileges if the confusion leads to memory corruption or use-after-free. The primary impact is integrity (corrupted state) and availability (audio subsystem hangs or crashes).

Mitigation

The fix is included in Linux kernel commit 6b01c1bc9a4748ab37548a700a8aaff910e298e6 [1], which adds proper locking using the existing params_lock mutex to protect access to runtime.oss.trigger. System administrators should apply this kernel patch or update to a kernel version that includes it. No workaround is available other than restricting local access to OSS PCM devices (e.g., removing unprivileged users from the audio group). No CISA KEV listing has been published for this CVE.

AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

8
49f9d048845b

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

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTakashi IwaiApr 24, 2026Fixed in 6.12.88via kernel-cna
1 file changed · +23 7
  • sound/core/oss/pcm_oss.c+23 7 modified
    diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
    index 9f8dabe2727ceb..daa7cda98ae6f6 100644
    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -2147,10 +2147,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
     
     	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
     	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_OUTPUT;
    -	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_INPUT;
    +	if (psubstream && psubstream->runtime) {
    +		guard(mutex)(&psubstream->runtime->oss.params_lock);
    +		if (psubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_OUTPUT;
    +	}
    +	if (csubstream && csubstream->runtime) {
    +		guard(mutex)(&csubstream->runtime->oss.params_lock);
    +		if (csubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_INPUT;
    +	}
     	return result;
     }
     
    @@ -2824,6 +2830,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
     						runtime->oss.period_frames;
     }
     
    +static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
    +{
    +	bool ret;
    +
    +	guard(mutex)(&runtime->oss.params_lock);
    +	ret = runtime->oss.trigger;
    +	if (ret)
    +		runtime->oss.trigger = 0;
    +	return ret;
    +}
    +
     static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     {
     	struct snd_pcm_oss_file *pcm_oss_file;
    @@ -2856,11 +2873,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     			    snd_pcm_oss_capture_ready(csubstream))
     				mask |= EPOLLIN | EPOLLRDNORM;
     		}
    -		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
    +		if (ostate != SNDRV_PCM_STATE_RUNNING &&
    +		    need_input_retrigger(runtime)) {
     			struct snd_pcm_oss_file ofile;
     			memset(&ofile, 0, sizeof(ofile));
     			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -			runtime->oss.trigger = 0;
     			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
     		}
     	}
    -- 
    cgit 1.3-korg
    
    
    
6b01c1bc9a47

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

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTakashi IwaiApr 24, 2026Fixed in 7.0.7via kernel-cna
1 file changed · +23 7
  • sound/core/oss/pcm_oss.c+23 7 modified
    diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
    index d4fd4dfc7fc312..6af26ec2ecfd59 100644
    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -2149,10 +2149,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
     
     	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
     	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_OUTPUT;
    -	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_INPUT;
    +	if (psubstream && psubstream->runtime) {
    +		guard(mutex)(&psubstream->runtime->oss.params_lock);
    +		if (psubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_OUTPUT;
    +	}
    +	if (csubstream && csubstream->runtime) {
    +		guard(mutex)(&csubstream->runtime->oss.params_lock);
    +		if (csubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_INPUT;
    +	}
     	return result;
     }
     
    @@ -2826,6 +2832,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
     						runtime->oss.period_frames;
     }
     
    +static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
    +{
    +	bool ret;
    +
    +	guard(mutex)(&runtime->oss.params_lock);
    +	ret = runtime->oss.trigger;
    +	if (ret)
    +		runtime->oss.trigger = 0;
    +	return ret;
    +}
    +
     static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     {
     	struct snd_pcm_oss_file *pcm_oss_file;
    @@ -2858,11 +2875,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     			    snd_pcm_oss_capture_ready(csubstream))
     				mask |= EPOLLIN | EPOLLRDNORM;
     		}
    -		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
    +		if (ostate != SNDRV_PCM_STATE_RUNNING &&
    +		    need_input_retrigger(runtime)) {
     			struct snd_pcm_oss_file ofile;
     			memset(&ofile, 0, sizeof(ofile));
     			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -			runtime->oss.trigger = 0;
     			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
     		}
     	}
    -- 
    cgit 1.3-korg
    
    
    
901ac0ff15ed

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

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTakashi IwaiApr 24, 2026Fixed in 7.1-rc2via kernel-cna
1 file changed · +23 7
  • sound/core/oss/pcm_oss.c+23 7 modified
    diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
    index a140a0d9abb808..33fd34f0d615d9 100644
    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -2155,10 +2155,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
     
     	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
     	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_OUTPUT;
    -	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_INPUT;
    +	if (psubstream && psubstream->runtime) {
    +		guard(mutex)(&psubstream->runtime->oss.params_lock);
    +		if (psubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_OUTPUT;
    +	}
    +	if (csubstream && csubstream->runtime) {
    +		guard(mutex)(&csubstream->runtime->oss.params_lock);
    +		if (csubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_INPUT;
    +	}
     	return result;
     }
     
    @@ -2832,6 +2838,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
     						runtime->oss.period_frames;
     }
     
    +static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
    +{
    +	bool ret;
    +
    +	guard(mutex)(&runtime->oss.params_lock);
    +	ret = runtime->oss.trigger;
    +	if (ret)
    +		runtime->oss.trigger = 0;
    +	return ret;
    +}
    +
     static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     {
     	struct snd_pcm_oss_file *pcm_oss_file;
    @@ -2864,11 +2881,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     			    snd_pcm_oss_capture_ready(csubstream))
     				mask |= EPOLLIN | EPOLLRDNORM;
     		}
    -		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
    +		if (ostate != SNDRV_PCM_STATE_RUNNING &&
    +		    need_input_retrigger(runtime)) {
     			struct snd_pcm_oss_file ofile;
     			memset(&ofile, 0, sizeof(ofile));
     			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -			runtime->oss.trigger = 0;
     			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
     		}
     	}
    -- 
    cgit 1.3-korg
    
    
    
ac3e9b55b7da

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

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTakashi IwaiApr 24, 2026Fixed in 6.18.30via kernel-cna
1 file changed · +23 7
  • sound/core/oss/pcm_oss.c+23 7 modified
    diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
    index b12df5b5ddfc17..9b5a3def8d2ce9 100644
    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -2146,10 +2146,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
     
     	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
     	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_OUTPUT;
    -	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_INPUT;
    +	if (psubstream && psubstream->runtime) {
    +		guard(mutex)(&psubstream->runtime->oss.params_lock);
    +		if (psubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_OUTPUT;
    +	}
    +	if (csubstream && csubstream->runtime) {
    +		guard(mutex)(&csubstream->runtime->oss.params_lock);
    +		if (csubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_INPUT;
    +	}
     	return result;
     }
     
    @@ -2823,6 +2829,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
     						runtime->oss.period_frames;
     }
     
    +static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
    +{
    +	bool ret;
    +
    +	guard(mutex)(&runtime->oss.params_lock);
    +	ret = runtime->oss.trigger;
    +	if (ret)
    +		runtime->oss.trigger = 0;
    +	return ret;
    +}
    +
     static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     {
     	struct snd_pcm_oss_file *pcm_oss_file;
    @@ -2855,11 +2872,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     			    snd_pcm_oss_capture_ready(csubstream))
     				mask |= EPOLLIN | EPOLLRDNORM;
     		}
    -		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
    +		if (ostate != SNDRV_PCM_STATE_RUNNING &&
    +		    need_input_retrigger(runtime)) {
     			struct snd_pcm_oss_file ofile;
     			memset(&ofile, 0, sizeof(ofile));
     			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -			runtime->oss.trigger = 0;
     			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
     		}
     	}
    -- 
    cgit 1.3-korg
    
    
    
901ac0ff15ed

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

1 file changed · +23 7
  • sound/core/oss/pcm_oss.c+23 7 modified
    diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
    index a140a0d9abb808..33fd34f0d615d9 100644
    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -2155,10 +2155,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
     
     	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
     	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_OUTPUT;
    -	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_INPUT;
    +	if (psubstream && psubstream->runtime) {
    +		guard(mutex)(&psubstream->runtime->oss.params_lock);
    +		if (psubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_OUTPUT;
    +	}
    +	if (csubstream && csubstream->runtime) {
    +		guard(mutex)(&csubstream->runtime->oss.params_lock);
    +		if (csubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_INPUT;
    +	}
     	return result;
     }
     
    @@ -2832,6 +2838,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
     						runtime->oss.period_frames;
     }
     
    +static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
    +{
    +	bool ret;
    +
    +	guard(mutex)(&runtime->oss.params_lock);
    +	ret = runtime->oss.trigger;
    +	if (ret)
    +		runtime->oss.trigger = 0;
    +	return ret;
    +}
    +
     static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     {
     	struct snd_pcm_oss_file *pcm_oss_file;
    @@ -2864,11 +2881,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     			    snd_pcm_oss_capture_ready(csubstream))
     				mask |= EPOLLIN | EPOLLRDNORM;
     		}
    -		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
    +		if (ostate != SNDRV_PCM_STATE_RUNNING &&
    +		    need_input_retrigger(runtime)) {
     			struct snd_pcm_oss_file ofile;
     			memset(&ofile, 0, sizeof(ofile));
     			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -			runtime->oss.trigger = 0;
     			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
     		}
     	}
    -- 
    cgit 1.3-korg
    
    
    
49f9d048845b

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

1 file changed · +23 7
  • sound/core/oss/pcm_oss.c+23 7 modified
    diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
    index 9f8dabe2727ceb..daa7cda98ae6f6 100644
    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -2147,10 +2147,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
     
     	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
     	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_OUTPUT;
    -	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_INPUT;
    +	if (psubstream && psubstream->runtime) {
    +		guard(mutex)(&psubstream->runtime->oss.params_lock);
    +		if (psubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_OUTPUT;
    +	}
    +	if (csubstream && csubstream->runtime) {
    +		guard(mutex)(&csubstream->runtime->oss.params_lock);
    +		if (csubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_INPUT;
    +	}
     	return result;
     }
     
    @@ -2824,6 +2830,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
     						runtime->oss.period_frames;
     }
     
    +static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
    +{
    +	bool ret;
    +
    +	guard(mutex)(&runtime->oss.params_lock);
    +	ret = runtime->oss.trigger;
    +	if (ret)
    +		runtime->oss.trigger = 0;
    +	return ret;
    +}
    +
     static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     {
     	struct snd_pcm_oss_file *pcm_oss_file;
    @@ -2856,11 +2873,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     			    snd_pcm_oss_capture_ready(csubstream))
     				mask |= EPOLLIN | EPOLLRDNORM;
     		}
    -		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
    +		if (ostate != SNDRV_PCM_STATE_RUNNING &&
    +		    need_input_retrigger(runtime)) {
     			struct snd_pcm_oss_file ofile;
     			memset(&ofile, 0, sizeof(ofile));
     			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -			runtime->oss.trigger = 0;
     			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
     		}
     	}
    -- 
    cgit 1.3-korg
    
    
    
6b01c1bc9a47

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

1 file changed · +23 7
  • sound/core/oss/pcm_oss.c+23 7 modified
    diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
    index d4fd4dfc7fc312..6af26ec2ecfd59 100644
    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -2149,10 +2149,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
     
     	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
     	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_OUTPUT;
    -	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_INPUT;
    +	if (psubstream && psubstream->runtime) {
    +		guard(mutex)(&psubstream->runtime->oss.params_lock);
    +		if (psubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_OUTPUT;
    +	}
    +	if (csubstream && csubstream->runtime) {
    +		guard(mutex)(&csubstream->runtime->oss.params_lock);
    +		if (csubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_INPUT;
    +	}
     	return result;
     }
     
    @@ -2826,6 +2832,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
     						runtime->oss.period_frames;
     }
     
    +static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
    +{
    +	bool ret;
    +
    +	guard(mutex)(&runtime->oss.params_lock);
    +	ret = runtime->oss.trigger;
    +	if (ret)
    +		runtime->oss.trigger = 0;
    +	return ret;
    +}
    +
     static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     {
     	struct snd_pcm_oss_file *pcm_oss_file;
    @@ -2858,11 +2875,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     			    snd_pcm_oss_capture_ready(csubstream))
     				mask |= EPOLLIN | EPOLLRDNORM;
     		}
    -		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
    +		if (ostate != SNDRV_PCM_STATE_RUNNING &&
    +		    need_input_retrigger(runtime)) {
     			struct snd_pcm_oss_file ofile;
     			memset(&ofile, 0, sizeof(ofile));
     			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -			runtime->oss.trigger = 0;
     			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
     		}
     	}
    -- 
    cgit 1.3-korg
    
    
    
ac3e9b55b7da

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

1 file changed · +23 7
  • sound/core/oss/pcm_oss.c+23 7 modified
    diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
    index b12df5b5ddfc17..9b5a3def8d2ce9 100644
    --- a/sound/core/oss/pcm_oss.c
    +++ b/sound/core/oss/pcm_oss.c
    @@ -2146,10 +2146,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
     
     	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
     	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_OUTPUT;
    -	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
    -		result |= PCM_ENABLE_INPUT;
    +	if (psubstream && psubstream->runtime) {
    +		guard(mutex)(&psubstream->runtime->oss.params_lock);
    +		if (psubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_OUTPUT;
    +	}
    +	if (csubstream && csubstream->runtime) {
    +		guard(mutex)(&csubstream->runtime->oss.params_lock);
    +		if (csubstream->runtime->oss.trigger)
    +			result |= PCM_ENABLE_INPUT;
    +	}
     	return result;
     }
     
    @@ -2823,6 +2829,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
     						runtime->oss.period_frames;
     }
     
    +static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
    +{
    +	bool ret;
    +
    +	guard(mutex)(&runtime->oss.params_lock);
    +	ret = runtime->oss.trigger;
    +	if (ret)
    +		runtime->oss.trigger = 0;
    +	return ret;
    +}
    +
     static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     {
     	struct snd_pcm_oss_file *pcm_oss_file;
    @@ -2855,11 +2872,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
     			    snd_pcm_oss_capture_ready(csubstream))
     				mask |= EPOLLIN | EPOLLRDNORM;
     		}
    -		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
    +		if (ostate != SNDRV_PCM_STATE_RUNNING &&
    +		    need_input_retrigger(runtime)) {
     			struct snd_pcm_oss_file ofile;
     			memset(&ofile, 0, sizeof(ofile));
     			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
    -			runtime->oss.trigger = 0;
     			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
     		}
     	}
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing mutex protection on concurrent reads and writes to the bit-field `runtime.oss.trigger` in the ALSA OSS PCM emulation layer, causing data races that can corrupt adjacent bit fields."

Attack vector

An attacker with local access to the ALSA OSS PCM device can trigger a data race by concurrently invoking `snd_pcm_oss_get_trigger()` (via an OSS ioctl) and `snd_pcm_oss_poll()` (via `poll()`/`select()`) on the same PCM substream. Because `runtime.oss.trigger` is a bit field, a concurrent write can corrupt neighboring bit fields in the same word, leading to undefined behavior in the PCM OSS state machine. The vulnerability was discovered through fuzzing [patch_id=2898209].

Affected code

The file `sound/core/oss/pcm_oss.c` contains the vulnerable functions `snd_pcm_oss_get_trigger()` and `snd_pcm_oss_poll()`, both of which accessed `runtime->oss.trigger` without holding the `params_lock` mutex [patch_id=2898209].

What the fix does

The patch wraps all accesses to `runtime.oss.trigger` with the existing `runtime->oss.params_lock` mutex. In `snd_pcm_oss_get_trigger()`, each substream's trigger check is now guarded by `guard(mutex)(&runtime->oss.params_lock)`. In `snd_pcm_oss_poll()`, the read-and-clear of `runtime->oss.trigger` is moved into a new helper `need_input_retrigger()` that holds the same lock, eliminating the unlocked bit-field write that was previously done inline [patch_id=2898209].

Preconditions

  • accessLocal access to an ALSA OSS PCM device (e.g., /dev/dsp)
  • inputAbility to concurrently call ioctl (trigger query) and poll on the same PCM substream

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.