Repository navigation
userspace: restrict SOF syscalls to the threads that need them - #11408
Conversation
|
Sample test case run on Intel PTL: |
There was a problem hiding this comment.
🟡 Changes recommended
Critical registration and caller-check defects can break normal IPC, DP notifications, and module cleanup, while a user-writable thread handle can grant LL syscall privileges to an unintended thread.
5 open issues
Allow validated module end-of-stream notifications · New Allow DP-thread module cleanup to free IPC messages · New Register IPC threads with SOF_SYSUSER_IPC during initialization · New Preserve DP-thread error notification path · New Keep LL thread handle trusted during secondary-core registration · New
What changed in this PR
This PR narrows SOF’s userspace syscall access by distinguishing infrastructure threads from module threads, reducing the exposed kernel interface.
Changes:
- Adds a default-enabled caller check backed by a kernel-only thread registry.
- Applies role restrictions to syscall validators and registers LL scheduler threads.
- Adds standalone security tests, adapts existing DMA tests, and documents allowed callers.
| File | Description |
|---|---|
zephyr/test/userspace/test_syscall_caller.c |
Adds caller-role and invalid-argument tests. |
zephyr/test/userspace/test_intel_ssp_dai.c |
Registers the test thread with the IPC role. |
zephyr/test/userspace/test_intel_hda_dma.c |
Registers the test thread with the IPC role. |
zephyr/test/CMakeLists.txt |
Enables the new standalone test suite. |
zephyr/syscall/vregion.c |
Restricts virtual-region syscalls to infrastructure threads. |
zephyr/syscall/sof_dma.c |
Restricts DMA syscalls to infrastructure threads. |
zephyr/syscall/dai.c |
Restricts DAI device lookup. |
zephyr/syscall/caller.c |
Implements the kernel-only caller registry. |
zephyr/syscall/alloc.c |
Restricts heap allocation and freeing. |
zephyr/Kconfig |
Adds the default-enabled caller-check option. |
zephyr/CMakeLists.txt |
Conditionally builds the caller registry. |
src/schedule/zephyr_ll.c |
Restricts LL task semaphore management. |
src/schedule/zephyr_dp_schedule.c |
Limits scheduler ticks to LL threads. |
src/schedule/zephyr_dp_schedule_application.c |
Restricts DP task cleanup. |
src/schedule/zephyr_domain.c |
Registers and unregisters LL threads. |
src/library_manager/lib_manager.c |
Uses the registry to authorize module unloading. |
src/ipc/ipc4/notification.c |
Restricts resource notifications. |
src/ipc/ipc4/handler-kernel.c |
Adds role checks to IPC handlers. |
src/ipc/ipc-common.c |
Restricts message sending and queue removal. |
src/include/sof/userspace/syscall_caller.h |
Defines roles, registration APIs, and check macros. |
src/include/sof/userspace/README.md |
Documents caller permissions and validator requirements. |
src/debug/debug_stream/debug_stream_slot.c |
Restricts debug record submission. |
src/audio/kpb.c |
Restricts KPB notifier initialization. |
Review effort: Balanced
PR 11408: test resultsRun date: 2026-11-09 12:50 UTC Tested commit: 289207f2bd23ada01fecf6c885dcec18c13014ba |
5baf828 to
c171548
Compare
|
V2 pushed:
|
Zephyr lets any user thread invoke any system call. SOF user threads have different trust levels: the LL scheduler and IPC user threads are SOF infrastructure, while DP threads run module code that can come from a third party. Add a registry in kernel-only memory that records the LL and IPC user thread of each core, and sof_syscall_caller_allowed() for validators to check the calling thread against a set of roles. Register the threads where they are created, before they start, and clear the LL entry before the thread object is freed. The registry is enabled with the new SOF_USERSPACE_SYSCALL_CALLER_CHECK option, default y with SOF_USERSPACE_LL. No validator uses it yet. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Use the caller registry in the validators of SOF system calls, so DP module threads can only reach the syscalls needed to implement the module interface, including sending notifications: - any user thread: cpu_get_id, the mod_* module syscalls, ipc_msg_send, ipc_msg_list_remove and send_resource_notif - IPC user thread only: ipc_compound_pre_start, ipc_compound_post_start, ipc_wait_for_compound_msg, lib_manager_free_module - LL user thread only: scheduler_dp_ll_tick - LL or IPC user thread: all other SOF syscalls DP modules send notifications with mod_ipc_msg_init() and ipc_msg_send(), free them with mod_ipc_msg_free() from their .free() callback, and dp_task_run() reports processing errors with send_resource_notif(), so these stay open to all user threads. lib_manager_free_module() previously identified the IPC thread through ipc_user->thread[], which user threads can write. It now uses the registry, keeping the old check only if the option is disabled. The HDA DMA and SSP DAI userspace tests call DMA syscalls from their own user thread, so register that thread for the duration of the test. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Default-on authorization changes across IPC, scheduling, and DMA require human runtime validation on supported userspace targets to confirm multicore thread lifecycles and module processing and cleanup remain functional.
1 open issue
4 resolved since last review
Review effort: Balanced
Add the missing kpb_notifier_init and mod_data_blob_set entries to the syscall map, document which threads may call which syscalls, and extend the rules for adding syscalls with the caller check, single fetch of user data and not following user-writable pointers in the kernel. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add standalone boot tests that check the caller restriction, rejection of a forged vregion handle, and the DMA channel range and transfer direction checks. Cases that need features the target lacks are skipped. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
c171548 to
289207f
Compare
|
V3 pushed:
|
|
User-space tools fail is unrelated and is fixed by #11418 |
There was a problem hiding this comment.
🔵 Needs a closer look
Default-on authorization restrictions span IPC, LL and DP contexts across cores, requiring target-side validation of legitimate callbacks, thread lifecycles and normal audio workloads before approval.
No open issues 🎉
1 resolved since last review
Review effort: Balanced

A set of PRs to add infra to limit syscalls to a subset of threads. This allows to limit attack surface of syscalls. This doesn't remove need to secure the syscalls LL/IPC threads use, but limits the exposure significantly without any functional impact and makes the user-kernel separation more easy to verify and understand.
A standalone test case is added to test the constraints.