Skip to content

Commit 4a5e37d

Browse files
committed
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: <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, we can return early. The msg->list pointer itself is already verified with K_SYSCALL_MEMORY_WRITE(). Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent 2a92f66 commit 4a5e37d

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

src/ipc/ipc-common.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,15 @@ void z_vrfy_ipc_msg_list_remove(struct ipc_msg *msg)
356356
bool found = false;
357357

358358
K_OOPS(K_SYSCALL_MEMORY_WRITE(msg, sizeof(*msg)));
359+
360+
/*
361+
* special case: empty list was passed. we can't trust where
362+
* list->prev points to, so do not pass to
363+
* z_impl_ipc_msg_list_remove(), but handle here
364+
*/
365+
if (list_is_empty(&msg->list))
366+
return;
367+
359368
list_for_item_safe(mlist, _mlist, &ipc->msg_list) {
360369
if (mlist == &msg->list) {
361370
found = true;

0 commit comments

Comments
 (0)