From 2ad265cb75abe12ff1daf397f3ec087fbcfce63c Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Tue, 14 May 2024 16:16:10 -0700 Subject: [PATCH] kernel: userspace: manipulate _thread_idx_map on per-byte basis The sys_bitfield_(clear/set)_bit() work on pointer size element. However, _thread_idx_map[] is a byte array. On little endian systems, the bitops should work fine. However, on big endian systems, changing the lower bits may actually be manipulating memory outside the array when CONFIG_MAX_THREAD_BYTES is not multiple of 4. So modify the code to perform bit ops on a per-byte basis. Fixes #72430 Signed-off-by: Daniel Leung --- kernel/userspace.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kernel/userspace.c b/kernel/userspace.c index 6a77532f8ae..664971e2727 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -277,8 +277,10 @@ static bool thread_idx_alloc(uintptr_t *tidx) if (idx != 0) { *tidx = base + (idx - 1); - sys_bitfield_clear_bit((mem_addr_t)_thread_idx_map, - *tidx); + /* Clear the bit. We already know the array index, + * and the bit to be cleared. + */ + _thread_idx_map[i] &= ~(BIT(idx - 1)); /* Clear permission from all objects */ k_object_wordlist_foreach(clear_perms_cb, @@ -308,7 +310,11 @@ static void thread_idx_free(uintptr_t tidx) /* To prevent leaked permission when index is recycled */ k_object_wordlist_foreach(clear_perms_cb, (void *)tidx); - sys_bitfield_set_bit((mem_addr_t)_thread_idx_map, tidx); + /* Figure out which bits to set in _thread_idx_map[] and set it. */ + int base = tidx / NUM_BITS(_thread_idx_map[0]); + int offset = tidx % NUM_BITS(_thread_idx_map[0]); + + _thread_idx_map[base] |= BIT(offset); } static struct k_object *dynamic_object_create(enum k_objects otype, size_t align,