From 59487c2de7bca7528dcf18a649021730daf4a153 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 21 Oct 2026 16:17:08 +0300 Subject: [PATCH] schedule: zephyr_ll_user: return heap address instead of user copy zephyr_ll_user_heap() returned zephyr_ll_heap, a pointer stored in user-writable memory (APP_SYSUSER_DATA). Kernel code reaching it through sof_sys_user_heap_get(), for example dma_init() under the sof_dma_get() system call or the data blob allocations under mod_data_blob_handler_new(), would then run the heap code in supervisor mode on whatever k_heap a user thread had pointed it at. The heap object's address is a link-time constant, so return it directly. User threads can still call the function, as taking the address reads no kernel memory, and the heap system call validators already compare the pointer with this address. The user-writable copy is no longer needed and is removed. zephyr_ll_user_resources_init() runs before platform_init(), so no caller relies on the old NULL return before initialization. Signed-off-by: Kai Vehmanen --- src/include/sof/userspace/README.md | 9 +++++---- src/schedule/zephyr_ll_user.c | 22 +++++++++------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/include/sof/userspace/README.md b/src/include/sof/userspace/README.md index 0ce4abf7d7cc..e8d1ae4babfa 100644 --- a/src/include/sof/userspace/README.md +++ b/src/include/sof/userspace/README.md @@ -147,10 +147,11 @@ ordinary variables in non-userspace builds. marker at its declaration site.* Conversely, marked data is **user-writable**, so kernel code must never trust it — re-validate on every use. DP modules running under `SOF_USERSPACE_APPLICATION` access data through their per-module memory domain set up by the -proxy or DP thread infrastructure, not through `APP_TASK_*` / `APP_SYSUSER_*` markers. See the warning in -[`schedule/zephyr_ll_user.c`](../../../schedule/zephyr_ll_user.c) around `zephyr_ll_heap`, and -`zephyr_ll_user_heap_verify()` which exists precisely because the user-visible heap pointer -cannot be trusted. +proxy or DP thread infrastructure, not through `APP_TASK_*` / `APP_SYSUSER_*` markers. See +[`schedule/zephyr_ll_user.c`](../../../schedule/zephyr_ll_user.c): `zephyr_ll_user_heap()` +returns the address of the kernel-only heap object rather than a pointer stored in +user-writable memory, and `zephyr_ll_user_heap_verify()` checks the heap pointer that user +threads pass to the heap system calls. ## Kconfig hierarchy diff --git a/src/schedule/zephyr_ll_user.c b/src/schedule/zephyr_ll_user.c index bad2f6c9cbb6..1aa56c44e461 100644 --- a/src/schedule/zephyr_ll_user.c +++ b/src/schedule/zephyr_ll_user.c @@ -26,14 +26,6 @@ struct zephyr_ll_mem_resources { static struct zephyr_ll_mem_resources ll_mem_resources; -/** - * Heap allocator for LL scheduler memory (user accessible pointer) - * - * Note: this is also user-writable, so kernel must not rely on this to - * be correct and must always validate it separately. - */ -APP_SYSUSER_DATA static struct k_heap *zephyr_ll_heap; - static struct k_heap *ll_heap_alloc(void) { const size_t alloc_size = CONFIG_SOF_ZEPHYR_SYS_USER_HEAP_SIZE; @@ -98,9 +90,6 @@ void zephyr_ll_user_resources_init(void) ll_heap_init(); - /* store a user-accessible pointer */ - zephyr_ll_heap = &ll_mem_resources.heap; - /* attach common partition to LL domain */ user_memory_attach_common_partition(zephyr_ll_mem_domain()); @@ -124,13 +113,20 @@ bool zephyr_ll_user_heap_verify(struct k_heap *heap) /** * Returns heap object to use in user-space LL code. * - * Can be called from user-space. + * Can be called from both kernel and user-space. The heap object itself is + * kernel-only, but its address is a link-time constant, so returning it + * does not read any memory. User threads only pass it to the + * sof_heap_alloc()/sof_heap_free() system calls, whose validators check it + * with zephyr_ll_user_heap_verify(). + * + * Do not cache the pointer in user-writable memory for kernel use: kernel + * code must call this function, so it never trusts a stored copy. * * @return heap pointer that can be passed to sof_heap_alloc() */ struct k_heap *zephyr_ll_user_heap(void) { - return zephyr_ll_heap; + return &ll_mem_resources.heap; } /**