sound/core/oss/pcm_oss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
During a process exit, do_exit() calls exit_mm() before exit_files(),
so current->mm is already NULL when __fput() triggers
snd_pcm_oss_release() -> snd_pcm_oss_sync(). The latter calls
snd_pcm_lib_write() with a NULL buffer to fill the remaining ALSA
period with silence. snd_pcm_lib_write() passes in_kernel=false to
__snd_pcm_lib_xfer(), causing do_transfer() to call
import_ubuf(ITER_SOURCE, NULL, ...) which invokes access_ok(NULL, ...).
On RISC-V, untagged_addr() in access_ok() dereferences
current->mm->context.pmlen, crashing with a NULL pointer dereference.
Fix by using snd_pcm_kernel_write() and snd_pcm_kernel_writev() instead,
which pass in_kernel=true and use iov_iter_kvec() to bypass user-space
address validation entirely. Since the buffer is NULL and the transfer
function fill_silence() ignores the iterator and writes directly to the
DMA buffer, this is safe.
Fixes: 13f72c8c28fc ("ALSA: pcm: Kill set_fs() in PCM OSS layer")
Signed-off-by: Jiakai Xu <xujiakai24@mails.ucas.ac.cn>
---
sound/core/oss/pcm_oss.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 33fd34f0d615..4f81002e4b96 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1710,9 +1710,9 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
if (size > 0) {
size = runtime->period_size - size;
if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
- snd_pcm_lib_write(substream, NULL, size);
+ snd_pcm_kernel_write(substream, NULL, size);
else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
- snd_pcm_lib_writev(substream, NULL, size);
+ snd_pcm_kernel_writev(substream, NULL, size);
}
unlock:
mutex_unlock(&runtime->oss.params_lock);
--
2.34.1
On Fri, 15 May 2026 07:15:16 +0200,
Jiakai Xu wrote:
>
> During a process exit, do_exit() calls exit_mm() before exit_files(),
> so current->mm is already NULL when __fput() triggers
> snd_pcm_oss_release() -> snd_pcm_oss_sync(). The latter calls
> snd_pcm_lib_write() with a NULL buffer to fill the remaining ALSA
> period with silence. snd_pcm_lib_write() passes in_kernel=false to
> __snd_pcm_lib_xfer(), causing do_transfer() to call
> import_ubuf(ITER_SOURCE, NULL, ...) which invokes access_ok(NULL, ...).
> On RISC-V, untagged_addr() in access_ok() dereferences
> current->mm->context.pmlen, crashing with a NULL pointer dereference.
>
> Fix by using snd_pcm_kernel_write() and snd_pcm_kernel_writev() instead,
> which pass in_kernel=true and use iov_iter_kvec() to bypass user-space
> address validation entirely. Since the buffer is NULL and the transfer
> function fill_silence() ignores the iterator and writes directly to the
> DMA buffer, this is safe.
>
> Fixes: 13f72c8c28fc ("ALSA: pcm: Kill set_fs() in PCM OSS layer")
> Signed-off-by: Jiakai Xu <xujiakai24@mails.ucas.ac.cn>
Thanks for the patch. I believe the problem is rather in
do_transfer() setting up a bogus iter for silencing unnecessarily.
So it's a bug introduced in the commit cf393babb37a ("ALSA: pcm: Add
copy ops with iov_iter").
Could you verify whether the change below works instead?
noninterleaved_copy() has already the handling of NULL data.
Takashi
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2138,6 +2138,9 @@ static int interleaved_copy(struct snd_pcm_substream *substream,
off = frames_to_bytes(runtime, off);
frames = frames_to_bytes(runtime, frames);
+ if (!data)
+ return fill_silence(substream, 0, hwoff, NULL, frames);
+
return do_transfer(substream, 0, hwoff, data + off, frames, transfer,
in_kernel);
}
Thank you for your review, Takashi.
> Thanks for the patch. I believe the problem is rather in
> do_transfer() setting up a bogus iter for silencing unnecessarily.
> So it's a bug introduced in the commit cf393babb37a ("ALSA: pcm: Add
> copy ops with iov_iter").
I agree with your analysis. The root cause is indeed in
interleaved_copy() — it should not pass a NULL data pointer to
do_transfer(), which then unnecessarily constructs an iov_iter.
> Could you verify whether the change below works instead?
> noninterleaved_copy() has already the handling of NULL data.
Unfortunately, this crash was discovered through fuzzing, and
the fuzzer did not generate a reproducer. As a result, I am unable to
test the fix directly. However, the fix looks correct to me.
Best regards,
Jiakai
On Sun, 17 May 2026 15:36:08 +0200,
Jiakai Xu wrote:
>
> Thank you for your review, Takashi.
>
> > Thanks for the patch. I believe the problem is rather in
> > do_transfer() setting up a bogus iter for silencing unnecessarily.
> > So it's a bug introduced in the commit cf393babb37a ("ALSA: pcm: Add
> > copy ops with iov_iter").
>
> I agree with your analysis. The root cause is indeed in
> interleaved_copy() ― it should not pass a NULL data pointer to
> do_transfer(), which then unnecessarily constructs an iov_iter.
>
> > Could you verify whether the change below works instead?
> > noninterleaved_copy() has already the handling of NULL data.
>
> Unfortunately, this crash was discovered through fuzzing, and
> the fuzzer did not generate a reproducer. As a result, I am unable to
> test the fix directly. However, the fix looks correct to me.
OK, no problem. Then I'm going to submit a proper patch later.
Thanks for your checking!
Takashi
© 2016 - 2026 Red Hat, Inc.