Skip to content

ipc: userspace: don't fault when removing an already-sent IPC message - #11157

Open
kv2019i wants to merge 1 commit into
thesofproject:mainfrom
kv2019i:202609-fix-ipc-send-vrfy
Open

ipc: userspace: don't fault when removing an already-sent IPC message#11157
kv2019i wants to merge 1 commit into
thesofproject:mainfrom
kv2019i:202609-fix-ipc-send-vrfy

Conversation

@kv2019i

@kv2019i kv2019i commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

z_vrfy_ipc_msg_list_remove() rejected any message that was not currently on ipc->msg_list by failing K_SYSCALL_VERIFY(found), which turns into a kernel oops. But ipc_msg_list_remove() is called from ipc_msg_free() / mod_ipc_msg_free() to drop a message that may or may not still be queued. The common case at stream stop / pipeline delete is freeing a message that has already been sent and dequeued: its list node is self-linked (empty), so it is not "found" and the verifier oopses the LL user thread with:

os.z_vrfy_ipc_msg_list_remove: syscall z_vrfy_ipc_msg_list_remove
... failed check: found
os.z_fatal_error: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0

Relax the checks to avoid this scenario. If the msg->list is empty, it is safe to call z_impl_ipc_msg_list_remove(). The msg->list pointer itself is already verified with K_SYSCALL_MEMORY_WRITE().

z_vrfy_ipc_msg_list_remove() rejected any message that was not currently
on ipc->msg_list by failing K_SYSCALL_VERIFY(found), which turns into a
kernel oops. But ipc_msg_list_remove() is called from ipc_msg_free() /
mod_ipc_msg_free() to drop a message that may or may not still be
queued. The common case at stream stop / pipeline delete is freeing a
message that has already been sent and dequeued: its list node is
self-linked (empty), so it is not "found" and the verifier oopses the LL
user thread with:

  <err> os.z_vrfy_ipc_msg_list_remove: syscall z_vrfy_ipc_msg_list_remove
  ... failed check: found
  <err> os.z_fatal_error: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0

Relax the checks to avoid this scenario. If the msg->list is empty, it
is safe to call z_impl_ipc_msg_list_remove(). The msg->list pointer
itself is already verified with K_SYSCALL_MEMORY_WRITE().

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Copilot AI lite review requested due to automatic review settings September 2, 2026 11:31
@kv2019i
kv2019i requested review from jsarha and lyakh September 2, 2026 11:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new verifier condition allows a userspace caller to bypass safety checks with a partially self-linked node (next==self, prev!=self), enabling unsafe list_item_del() writes through an attacker-controlled prev pointer.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR adjusts the Zephyr userspace syscall verifier for ipc_msg_list_remove() to avoid a kernel oops when freeing an IPC message that has already been dequeued (i.e., its list node is self-linked/empty), which commonly occurs during stream stop / pipeline delete paths.

Changes:

  • Relax z_vrfy_ipc_msg_list_remove() verification to allow removing an already-dequeued (empty) message list node without faulting.
  • Add an explanatory comment documenting why empty/self-linked nodes are safe to remove and what scenario triggered the oops.
File summaries
File Description
src/ipc/ipc-common.c Updates the userspace syscall verifier logic for IPC message list removal to avoid faulting on already-sent/dequeued messages.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/ipc/ipc-common.c
* non-empty node that is not on ipc->msg_list, i.e. one whose list
* pointers would make list_item_del() corrupt unrelated memory.
*/
K_OOPS(K_SYSCALL_VERIFY(found || list_is_empty(&msg->list)));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, now that I think about it, Copilot actually has a point here, but I would not fix it the way Copilot suggests, but I would simply add:

if (list_is_empty(&msg->list))
	return;

after the search loop, and have the original K_OOPS(K_SYSCALL_VERIFY(found)); after that.

@intel-sofci

Copy link
Copy Markdown

PR 11157: test results

Run date: 2026-09-02 12:38 UTC

Tested commit: 86bd9113201649ac3eb459254ed7994d0e5945df

mtl pass rate lnl pass rate ptl pass rate wcl pass rate nvl pass rate

@jsarha jsarha left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good. I was a bit worried about the earlier check, but since I did not hit it in my tests, I assumed its Ok.

Comment thread src/ipc/ipc-common.c
* non-empty node that is not on ipc->msg_list, i.e. one whose list
* pointers would make list_item_del() corrupt unrelated memory.
*/
K_OOPS(K_SYSCALL_VERIFY(found || list_is_empty(&msg->list)));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, now that I think about it, Copilot actually has a point here, but I would not fix it the way Copilot suggests, but I would simply add:

if (list_is_empty(&msg->list))
	return;

after the search loop, and have the original K_OOPS(K_SYSCALL_VERIFY(found)); after that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants