Bug 267555 - mmap of dsp device fails if sound buffer is not a multiple of page size
Summary: mmap of dsp device fails if sound buffer is not a multiple of page size
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-11-03 22:01 UTC by Florian Walpen
Modified: 2022-11-12 12:42 UTC (History)
2 users (show)

See Also:


Attachments
Fix the length check for mmap of the dsp sound buffer (1.52 KB, patch)
2022-11-03 22:01 UTC, Florian Walpen
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Florian Walpen 2022-11-03 22:01:27 UTC
Created attachment 237855 [details]
Fix the length check for mmap of the dsp sound buffer

For some sound cards, the system call mmap(2) consistently fails with EINVAL instead of mapping the sound buffer memory into userspace. It took me a while to figure out a pattern until I found the culprit.

What happens:
 1) Application does a ioctl(2) query of the dsp sound buffer size (SNDCTL_DSP_GETISPACE or SNDCTL_DSP_GETOSPACE).
 2) Application requests to mmap(2) the dsp buffer of that size.
 3) The requested memory map length is rounded to page size (vm_mmap() in sys/vm/vm_mmap.c).
 4) The device checks that the requested length does not exceed its buffer size (dsp_mmap_single() in sys/dev/sound/pcm/dsp.c).

Now because of the rounding in 3), 4) will always fail if the buffer size is not a multiple of the page size. This primarily affects dsp devices with a non-power-of-two number of channels, 24bit sample size, or low-latency sound buffers smaller than one page.

I was able to reproduce the problem with multiple sound card setups on both 13.1-RELEASE and 14.0-CURRENT.

Proposed fix (see patch attached):
Let the device check the requested length against the allocation size of the buffer, which is always whole pages. This still prevents mapping pages which do not belong to the dsp buffer allocation, but works fine with the rounding in 3).
Even though the application may now map more than the actual sound buffer (but no more than allocated by the dsp), the additional parts are effectively unused.

This fix was tested with multiple sound card setups on 14.0-CURRENT.
Comment 1 Florian Walpen 2022-11-03 22:06:38 UTC
@HPS: I hope it's ok to invite you here?
Sounds like a topic you'd be interested in.
Comment 2 Hans Petter Selasky freebsd_committer freebsd_triage 2022-11-03 22:14:09 UTC
Looks good. I'll check the patch tomorrow. Do you have a committer?

--HPS
Comment 3 Florian Walpen 2022-11-03 22:19:57 UTC
(In reply to Hans Petter Selasky from comment #2)

Thanks! No committer yet, so you'd be very welcome to do that :-)
Comment 4 commit-hook freebsd_committer freebsd_triage 2022-11-04 18:06:29 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=ad370f7658ba59811d02c04032ac33ef787f752f

commit ad370f7658ba59811d02c04032ac33ef787f752f
Author:     Florian Walpen <dev@submerge.ch>
AuthorDate: 2022-11-04 18:04:26 +0000
Commit:     Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2022-11-04 18:05:34 +0000

    sound(4): Fix memory map of /dev/dsp devices when buffer size is not a multiple of PAGE_SIZE.

    By using sndbuf_getallocsize() instead of sndbuf_getsize() in dsp_mmap_single().

    PR:             267555
    MFC after:      1 week
    Sponsored by:   NVIDIA Networking

 sys/dev/sound/pcm/dsp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Comment 5 Hans Petter Selasky freebsd_committer freebsd_triage 2022-11-04 18:07:08 UTC
Thank you for the patch!

--HPS
Comment 6 commit-hook freebsd_committer freebsd_triage 2022-11-12 12:42:53 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=f0a3d2341d345121c92e01f03d439b054f69793c

commit f0a3d2341d345121c92e01f03d439b054f69793c
Author:     Florian Walpen <dev@submerge.ch>
AuthorDate: 2022-11-04 18:04:26 +0000
Commit:     Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2022-11-12 12:00:01 +0000

    sound(4): Fix memory map of /dev/dsp devices when buffer size is not a multiple of PAGE_SIZE.

    By using sndbuf_getallocsize() instead of sndbuf_getsize() in dsp_mmap_single().

    PR:             267555
    Sponsored by:   NVIDIA Networking

    (cherry picked from commit ad370f7658ba59811d02c04032ac33ef787f752f)

 sys/dev/sound/pcm/dsp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)