Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | /* * Copyright (c) 2018 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <ztest.h> #include <irq_offload.h> #include <misc/stack.h> #define STACKSIZE (256 + CONFIG_TEST_EXTRA_STACKSIZE) #if defined(CONFIG_USERSPACE) && defined(CONFIG_DYNAMIC_OBJECTS) static K_THREAD_STACK_DEFINE(dyn_thread_stack, STACKSIZE); static K_SEM_DEFINE(start_sem, 0, 1); static K_SEM_DEFINE(end_sem, 0, 1); static void dyn_thread_entry(void *p1, void *p2, void *p3) { k_sem_take(&start_sem, K_FOREVER); k_sem_give(&end_sem); } static void prep(void) { k_thread_access_grant(k_current_get(), dyn_thread_stack, &start_sem, &end_sem); } static void create_dynamic_thread(void) { struct k_thread *dyn_thread; k_tid_t tid; dyn_thread = k_object_alloc(K_OBJ_THREAD); zassert_not_null(dyn_thread, "Cannot allocate thread k_object!"); tid = k_thread_create(dyn_thread, dyn_thread_stack, STACKSIZE, dyn_thread_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_USER, 0); k_object_access_grant(&start_sem, tid); k_object_access_grant(&end_sem, tid); k_sem_give(&start_sem); zassert_true(k_sem_take(&end_sem, K_SECONDS(1)) == 0, "k_sem_take(end_sem) failed"); k_thread_abort(tid); k_object_release(dyn_thread); } static void permission_test(void) { struct k_thread *dyn_thread; k_tid_t tid; dyn_thread = k_object_alloc(K_OBJ_THREAD); zassert_not_null(dyn_thread, "Cannot allocate thread k_object!"); tid = k_thread_create(dyn_thread, dyn_thread_stack, STACKSIZE, dyn_thread_entry, NULL, NULL, NULL, K_PRIO_PREEMPT(0), K_USER, 0); k_object_access_grant(&start_sem, tid); /* * Notice dyn_thread will not have permission to access * end_sem, which will cause kernel oops. */ k_sem_give(&start_sem); /* * If dyn_thread has permission to access end_sem, * k_sem_take() would be able to take the semaphore. */ zassert_true(k_sem_take(&end_sem, K_SECONDS(1)) != 0, "Semaphore end_sem has incorrect permission"); k_thread_abort(tid); k_object_release(dyn_thread); } /** * @ingroup kernel_thread_tests * @brief Test object permission on dynamic user thread when index is reused * * @details This creates one dynamic thread with permissions to both * semaphores so there is no fault. Then a new thread is created and will be * re-using the thread index in first pass. Except the second thread does * not have permission to one of the semaphore. If permissions are cleared * correctly when thread is destroyed, the second should raise kernel oops. */ static void test_dyn_thread_perms(void) { permission_test(); TC_PRINT("===== must have access denied on k_sem %p\n", &end_sem); } #else /* (CONFIG_USERSPACE && CONFIG_DYNAMIC_OBJECTS) */ static void prep(void) { } static void create_dynamic_thread(void) { TC_PRINT("Test skipped. Userspace and dynamic objects required.\n"); ztest_test_skip(); } static void test_dyn_thread_perms(void) { TC_PRINT("Test skipped. Userspace and dynamic objects required.\n"); ztest_test_skip(); } #endif /* !(CONFIG_USERSPACE && CONFIG_DYNAMIC_OBJECTS) */ /** * @ingroup kernel_thread_tests * @brief Test creation of dynamic user thread under kernel thread * * @details This is a simple test to create a user thread * dynamically via k_object_alloc() under a kernel thread. */ static void test_kernel_create_dyn_user_thread(void) { create_dynamic_thread(); } /** * @ingroup kernel_thread_tests * @brief Test creation of dynamic user thread under user thread * * @details This is a simple test to create a user thread * dynamically via k_object_alloc() under a user thread. */ static void test_user_create_dyn_user_thread(void) { create_dynamic_thread(); } /* test case main entry */ void test_main(void) { k_thread_system_pool_assign(k_current_get()); prep(); ztest_test_suite(thread_dynamic, ztest_unit_test(test_kernel_create_dyn_user_thread), ztest_user_unit_test(test_user_create_dyn_user_thread), ztest_unit_test(test_dyn_thread_perms) ); ztest_run_test_suite(thread_dynamic); } |