1 /*
2  * Copyright (c) 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_INCLUDE_SYS_KOBJECT_H
7 #define ZEPHYR_INCLUDE_SYS_KOBJECT_H
8 
9 #include <stdint.h>
10 #include <stddef.h>
11 
12 #include <zephyr/sys/iterable_sections.h>
13 #include <zephyr/sys/internal/kobject_internal.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 struct k_thread;
20 struct k_mutex;
21 struct z_futex_data;
22 
23 /**
24  * @brief Kernel Object Types
25  *
26  * This enumeration needs to be kept in sync with the lists of kernel objects
27  * and subsystems in scripts/build/gen_kobject_list.py, as well as the otype_to_str()
28  * function in kernel/userspace.c
29  */
30 enum k_objects {
31 	K_OBJ_ANY,
32 
33 	/** @cond
34 	 *  Doxygen should ignore this build-time generated include file
35 	 *  when generating API documentation.  Enumeration values are
36 	 *  generated during build by gen_kobject_list.py.  It includes
37 	 *  basic kernel objects (e.g.  pipes and mutexes) and driver types.
38 	 */
39 #include <kobj-types-enum.h>
40 	/** @endcond
41 	 */
42 
43 	K_OBJ_LAST
44 };
45 /**
46  * @defgroup usermode_apis User Mode APIs
47  * @ingroup kernel_apis
48  * @{
49  */
50 
51 #ifdef CONFIG_USERSPACE
52 
53 /**
54  * @brief Grant a static thread access to a list of kernel objects
55  *
56  * For threads declared with K_THREAD_DEFINE(), grant the thread access to
57  * a set of kernel objects. These objects do not need to be in an initialized
58  * state. The permissions will be granted when the threads are initialized
59  * in the early boot sequence.
60  *
61  * All arguments beyond the first must be pointers to kernel objects.
62  *
63  * @param name_ Name of the thread, as passed to K_THREAD_DEFINE()
64  */
65 #define K_THREAD_ACCESS_GRANT(name_, ...) \
66 	static void * const _CONCAT(_object_list_, name_)[] = \
67 		{ __VA_ARGS__, NULL }; \
68 	static const STRUCT_SECTION_ITERABLE(k_object_assignment, \
69 					_CONCAT(_object_access_, name_)) = \
70 			{ (&_k_thread_obj_ ## name_), \
71 			  (_CONCAT(_object_list_, name_)) }
72 
73 /** Object initialized */
74 #define K_OBJ_FLAG_INITIALIZED	BIT(0)
75 /** Object is Public */
76 #define K_OBJ_FLAG_PUBLIC	BIT(1)
77 /** Object allocated */
78 #define K_OBJ_FLAG_ALLOC	BIT(2)
79 /** Driver Object */
80 #define K_OBJ_FLAG_DRIVER	BIT(3)
81 
82 /**
83  * Grant a thread access to a kernel object
84  *
85  * The thread will be granted access to the object if the caller is from
86  * supervisor mode, or the caller is from user mode AND has permissions
87  * on both the object and the thread whose access is being granted.
88  *
89  * @param object Address of kernel object
90  * @param thread Thread to grant access to the object
91  */
92 __syscall void k_object_access_grant(const void *object,
93 				     struct k_thread *thread);
94 
95 /**
96  * Revoke a thread's access to a kernel object
97  *
98  * The thread will lose access to the object if the caller is from
99  * supervisor mode, or the caller is from user mode AND has permissions
100  * on both the object and the thread whose access is being revoked.
101  *
102  * @param object Address of kernel object
103  * @param thread Thread to remove access to the object
104  */
105 void k_object_access_revoke(const void *object, struct k_thread *thread);
106 
107 /**
108  * @brief Release an object
109  *
110  * Allows user threads to drop their own permission on an object
111  * Their permissions are automatically cleared when a thread terminates.
112  *
113  * @param object The object to be released
114  *
115  */
116 __syscall void k_object_release(const void *object);
117 
118 /**
119  * Grant all present and future threads access to an object
120  *
121  * If the caller is from supervisor mode, or the caller is from user mode and
122  * have sufficient permissions on the object, then that object will have
123  * permissions granted to it for *all* current and future threads running in
124  * the system, effectively becoming a public kernel object.
125  *
126  * Use of this API should be avoided on systems that are running untrusted code
127  * as it is possible for such code to derive the addresses of kernel objects
128  * and perform unwanted operations on them.
129  *
130  * It is not possible to revoke permissions on public objects; once public,
131  * any thread may use it.
132  *
133  * @param object Address of kernel object
134  */
135 void k_object_access_all_grant(const void *object);
136 
137 /**
138  * Check if a kernel object is of certain type and is valid.
139  *
140  * This checks if the kernel object exists, of certain type,
141  * and has been initialized.
142  *
143  * @param obj Address of the kernel object
144  * @param otype Object type (use K_OBJ_ANY for ignoring type checking)
145  * @return True if kernel object (@a obj) exists, of certain type, and
146  *         has been initialized. False otherwise.
147  */
148 bool k_object_is_valid(const void *obj, enum k_objects otype);
149 
150 #else
151 /* LCOV_EXCL_START */
152 #define K_THREAD_ACCESS_GRANT(thread, ...)
153 
154 /**
155  * @internal
156  */
z_impl_k_object_access_grant(const void * object,struct k_thread * thread)157 static inline void z_impl_k_object_access_grant(const void *object,
158 						struct k_thread *thread)
159 {
160 	ARG_UNUSED(object);
161 	ARG_UNUSED(thread);
162 }
163 
164 /**
165  * @internal
166  */
k_object_access_revoke(const void * object,struct k_thread * thread)167 static inline void k_object_access_revoke(const void *object,
168 					  struct k_thread *thread)
169 {
170 	ARG_UNUSED(object);
171 	ARG_UNUSED(thread);
172 }
173 
174 /**
175  * @internal
176  */
z_impl_k_object_release(const void * object)177 static inline void z_impl_k_object_release(const void *object)
178 {
179 	ARG_UNUSED(object);
180 }
181 
k_object_access_all_grant(const void * object)182 static inline void k_object_access_all_grant(const void *object)
183 {
184 	ARG_UNUSED(object);
185 }
186 
k_object_is_valid(const void * obj,enum k_objects otype)187 static inline bool k_object_is_valid(const void *obj, enum k_objects otype)
188 {
189 	ARG_UNUSED(obj);
190 	ARG_UNUSED(otype);
191 
192 	return true;
193 }
194 
195 /* LCOV_EXCL_STOP */
196 #endif /* !CONFIG_USERSPACE */
197 
198 #if defined(CONFIG_DYNAMIC_OBJECTS) || defined(__DOXYGEN__)
199 /**
200  * Allocate a kernel object of a designated type
201  *
202  * This will instantiate at runtime a kernel object of the specified type,
203  * returning a pointer to it. The object will be returned in an uninitialized
204  * state, with the calling thread being granted permission on it. The memory
205  * for the object will be allocated out of the calling thread's resource pool.
206  *
207  * @note This function is available only if @kconfig{CONFIG_DYNAMIC_OBJECTS}
208  * is selected.
209  *
210  * @note Thread stack object has to use k_object_alloc_size() since stacks may
211  * have different sizes.
212  *
213  * @param otype Requested kernel object type
214  * @return A pointer to the allocated kernel object, or NULL if memory wasn't
215  * available
216  */
217 __syscall void *k_object_alloc(enum k_objects otype);
218 
219 /**
220  * Allocate a kernel object of a designated type and a given size
221  *
222  * This will instantiate at runtime a kernel object of the specified type,
223  * returning a pointer to it. The object will be returned in an uninitialized
224  * state, with the calling thread being granted permission on it. The memory
225  * for the object will be allocated out of the calling thread's resource pool.
226  *
227  * This function is specially helpful for thread stack objects because
228  * their sizes can vary. Other objects should probably look k_object_alloc().
229  *
230  * @note This function is available only if @kconfig{CONFIG_DYNAMIC_OBJECTS}
231  * is selected.
232  *
233  * @param otype Requested kernel object type
234  * @param size Requested kernel object size
235  * @return A pointer to the allocated kernel object, or NULL if memory wasn't
236  * available
237  */
238 __syscall void *k_object_alloc_size(enum k_objects otype, size_t size);
239 
240 /**
241  * Free a kernel object previously allocated with k_object_alloc()
242  *
243  * This will return memory for a kernel object back to resource pool it was
244  * allocated from.  Care must be exercised that the object will not be used
245  * during or after when this call is made.
246  *
247  * @note This function is available only if @kconfig{CONFIG_DYNAMIC_OBJECTS}
248  * is selected.
249  *
250  * @param obj Pointer to the kernel object memory address.
251  */
252 void k_object_free(void *obj);
253 #else
254 
255 /* LCOV_EXCL_START */
z_impl_k_object_alloc(enum k_objects otype)256 static inline void *z_impl_k_object_alloc(enum k_objects otype)
257 {
258 	ARG_UNUSED(otype);
259 
260 	return NULL;
261 }
262 
z_impl_k_object_alloc_size(enum k_objects otype,size_t size)263 static inline void *z_impl_k_object_alloc_size(enum k_objects otype,
264 					size_t size)
265 {
266 	ARG_UNUSED(otype);
267 	ARG_UNUSED(size);
268 
269 	return NULL;
270 }
271 
272 /**
273  * @brief Free an object
274  *
275  * @param obj
276  */
k_object_free(void * obj)277 static inline void k_object_free(void *obj)
278 {
279 	ARG_UNUSED(obj);
280 }
281 /* LCOV_EXCL_STOP */
282 #endif /* CONFIG_DYNAMIC_OBJECTS */
283 
284 /** @} */
285 
286 #include <syscalls/kobject.h>
287 #ifdef __cplusplus
288 }
289 #endif
290 
291 #endif
292