From 01dbbb270519cd31207ac47ff497cbe854cd9940 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 2 Sep 2026 14:11:41 +0300 Subject: [PATCH] ipc: userspace: don't fault when removing an already-sent IPC message 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, we can return early. The msg->list pointer itself is already verified with K_SYSCALL_MEMORY_WRITE(). Signed-off-by: Kai Vehmanen --- src/ipc/ipc-common.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ipc/ipc-common.c b/src/ipc/ipc-common.c index b3dea0ce0021..ad5ee92a4d2a 100644 --- a/src/ipc/ipc-common.c +++ b/src/ipc/ipc-common.c @@ -356,6 +356,15 @@ void z_vrfy_ipc_msg_list_remove(struct ipc_msg *msg) bool found = false; K_OOPS(K_SYSCALL_MEMORY_WRITE(msg, sizeof(*msg))); + + /* + * special case: empty list was passed. we can't trust where + * list->prev points to, so do not pass to + * z_impl_ipc_msg_list_remove(), but handle here + */ + if (list_is_empty(&msg->list)) + return; + list_for_item_safe(mlist, _mlist, &ipc->msg_list) { if (mlist == &msg->list) { found = true;