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 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 struct k_thread;
19 struct k_mutex;
20 struct z_futex_data;
21 
22 /**
23  * @brief Kernel Object Types
24  *
25  * This enumeration needs to be kept in sync with the lists of kernel objects
26  * and subsystems in scripts/build/gen_kobject_list.py, as well as the otype_to_str()
27  * function in kernel/userspace.c
28  */
29 enum k_objects {
30 	K_OBJ_ANY,
31 
32 	/** @cond
33 	 *  Doxygen should ignore this build-time generated include file
34 	 *  when generating API documentation.  Enumeration values are
35 	 *  generated during build by gen_kobject_list.py.  It includes
36 	 *  basic kernel objects (e.g.  pipes and mutexes) and driver types.
37 	 */
38 #include <kobj-types-enum.h>
39 	/** @endcond
40 	 */
41 
42 	K_OBJ_LAST
43 };
44 /**
45  * @defgroup usermode_apis User Mode APIs
46  * @ingroup kernel_apis
47  * @{
48  */
49 
50 #ifdef CONFIG_USERSPACE
51 #ifdef CONFIG_GEN_PRIV_STACKS
52 /* Metadata struct for K_OBJ_THREAD_STACK_ELEMENT */
53 struct z_stack_data {
54 	/* Size of the entire stack object, including reserved areas */
55 	size_t size;
56 
57 	/* Stack buffer for privilege mode elevations */
58 	uint8_t *priv;
59 };
60 #endif /* CONFIG_GEN_PRIV_STACKS */
61 
62 /* Object extra data. Only some objects use this, determined by object type */
63 union z_object_data {
64 	/* Backing mutex for K_OBJ_SYS_MUTEX */
65 	struct k_mutex *mutex;
66 
67 	/* Numerical thread ID for K_OBJ_THREAD */
68 	unsigned int thread_id;
69 
70 #ifdef CONFIG_GEN_PRIV_STACKS
71 	/* Metadata for K_OBJ_THREAD_STACK_ELEMENT */
72 	const struct z_stack_data *stack_data;
73 #else
74 	/* Stack buffer size for K_OBJ_THREAD_STACK_ELEMENT */
75 	size_t stack_size;
76 #endif /* CONFIG_GEN_PRIV_STACKS */
77 
78 	/* Futex wait queue and spinlock for K_OBJ_FUTEX */
79 	struct z_futex_data *futex_data;
80 
81 	/* All other objects */
82 	int unused;
83 };
84 
85 /* Table generated by gperf, these objects are retrieved via
86  * z_object_find() */
87 struct z_object {
88 	void *name;
89 	uint8_t perms[CONFIG_MAX_THREAD_BYTES];
90 	uint8_t type;
91 	uint8_t flags;
92 	union z_object_data data;
93 } __packed __aligned(4);
94 
95 struct z_object_assignment {
96 	struct k_thread *thread;
97 	void * const *objects;
98 };
99 
100 /**
101  * @brief Grant a static thread access to a list of kernel objects
102  *
103  * For threads declared with K_THREAD_DEFINE(), grant the thread access to
104  * a set of kernel objects. These objects do not need to be in an initialized
105  * state. The permissions will be granted when the threads are initialized
106  * in the early boot sequence.
107  *
108  * All arguments beyond the first must be pointers to kernel objects.
109  *
110  * @param name_ Name of the thread, as passed to K_THREAD_DEFINE()
111  */
112 #define K_THREAD_ACCESS_GRANT(name_, ...) \
113 	static void * const _CONCAT(_object_list_, name_)[] = \
114 		{ __VA_ARGS__, NULL }; \
115 	static const STRUCT_SECTION_ITERABLE(z_object_assignment, \
116 					_CONCAT(_object_access_, name_)) = \
117 			{ (&_k_thread_obj_ ## name_), \
118 			  (_CONCAT(_object_list_, name_)) }
119 
120 /** Object initialized */
121 #define K_OBJ_FLAG_INITIALIZED	BIT(0)
122 /** Object is Public */
123 #define K_OBJ_FLAG_PUBLIC	BIT(1)
124 /** Object allocated */
125 #define K_OBJ_FLAG_ALLOC	BIT(2)
126 /** Driver Object */
127 #define K_OBJ_FLAG_DRIVER	BIT(3)
128 
129 /**
130  * Lookup a kernel object and init its metadata if it exists
131  *
132  * Calling this on an object will make it usable from userspace.
133  * Intended to be called as the last statement in kernel object init
134  * functions.
135  *
136  * @param obj Address of the kernel object
137  */
138 void z_object_init(const void *obj);
139 
140 /**
141  * Grant a thread access to a kernel object
142  *
143  * The thread will be granted access to the object if the caller is from
144  * supervisor mode, or the caller is from user mode AND has permissions
145  * on both the object and the thread whose access is being granted.
146  *
147  * @param object Address of kernel object
148  * @param thread Thread to grant access to the object
149  */
150 __syscall void k_object_access_grant(const void *object,
151 				     struct k_thread *thread);
152 
153 /**
154  * Revoke a thread's access to a kernel object
155  *
156  * The thread will lose access to the object if the caller is from
157  * supervisor mode, or the caller is from user mode AND has permissions
158  * on both the object and the thread whose access is being revoked.
159  *
160  * @param object Address of kernel object
161  * @param thread Thread to remove access to the object
162  */
163 void k_object_access_revoke(const void *object, struct k_thread *thread);
164 
165 /**
166  * @brief Release an object
167  *
168  * Allows user threads to drop their own permission on an object
169  * Their permissions are automatically cleared when a thread terminates.
170  *
171  * @param object The object to be released
172  *
173  */
174 __syscall void k_object_release(const void *object);
175 
176 /**
177  * Grant all present and future threads access to an object
178  *
179  * If the caller is from supervisor mode, or the caller is from user mode and
180  * have sufficient permissions on the object, then that object will have
181  * permissions granted to it for *all* current and future threads running in
182  * the system, effectively becoming a public kernel object.
183  *
184  * Use of this API should be avoided on systems that are running untrusted code
185  * as it is possible for such code to derive the addresses of kernel objects
186  * and perform unwanted operations on them.
187  *
188  * It is not possible to revoke permissions on public objects; once public,
189  * any thread may use it.
190  *
191  * @param object Address of kernel object
192  */
193 void k_object_access_all_grant(const void *object);
194 
195 /**
196  * Check if a kernel object is of certain type and is valid.
197  *
198  * This checks if the kernel object exists, of certain type,
199  * and has been initialized.
200  *
201  * @param obj Address of the kernel object
202  * @param otype Object type (use K_OBJ_ANY for ignoring type checking)
203  * @return True if kernel object (@a obj) exists, of certain type, and
204  *         has been initialized. False otherwise.
205  */
206 bool k_object_is_valid(const void *obj, enum k_objects otype);
207 
208 #else
209 /* LCOV_EXCL_START */
210 #define K_THREAD_ACCESS_GRANT(thread, ...)
211 
212 /**
213  * @internal
214  */
z_object_init(const void * obj)215 static inline void z_object_init(const void *obj)
216 {
217 	ARG_UNUSED(obj);
218 }
219 
220 /**
221  * @internal
222  */
z_impl_k_object_access_grant(const void * object,struct k_thread * thread)223 static inline void z_impl_k_object_access_grant(const void *object,
224 						struct k_thread *thread)
225 {
226 	ARG_UNUSED(object);
227 	ARG_UNUSED(thread);
228 }
229 
230 /**
231  * @internal
232  */
k_object_access_revoke(const void * object,struct k_thread * thread)233 static inline void k_object_access_revoke(const void *object,
234 					  struct k_thread *thread)
235 {
236 	ARG_UNUSED(object);
237 	ARG_UNUSED(thread);
238 }
239 
240 /**
241  * @internal
242  */
z_impl_k_object_release(const void * object)243 static inline void z_impl_k_object_release(const void *object)
244 {
245 	ARG_UNUSED(object);
246 }
247 
k_object_access_all_grant(const void * object)248 static inline void k_object_access_all_grant(const void *object)
249 {
250 	ARG_UNUSED(object);
251 }
252 
k_object_is_valid(const void * obj,enum k_objects otype)253 static inline bool k_object_is_valid(const void *obj, enum k_objects otype)
254 {
255 	ARG_UNUSED(obj);
256 	ARG_UNUSED(otype);
257 
258 	return true;
259 }
260 
261 /* LCOV_EXCL_STOP */
262 #endif /* !CONFIG_USERSPACE */
263 
264 #ifdef CONFIG_DYNAMIC_OBJECTS
265 /**
266  * Allocate a kernel object of a designated type
267  *
268  * This will instantiate at runtime a kernel object of the specified type,
269  * returning a pointer to it. The object will be returned in an uninitialized
270  * state, with the calling thread being granted permission on it. The memory
271  * for the object will be allocated out of the calling thread's resource pool.
272  *
273  * @note Thread stack object has to use k_object_alloc_size() since stacks may
274  * have different sizes.
275  *
276  * @param otype Requested kernel object type
277  * @return A pointer to the allocated kernel object, or NULL if memory wasn't
278  * available
279  */
280 __syscall void *k_object_alloc(enum k_objects otype);
281 
282 /**
283  * Allocate a kernel object of a designated type and a given size
284  *
285  * This will instantiate at runtime a kernel object of the specified type,
286  * returning a pointer to it. The object will be returned in an uninitialized
287  * state, with the calling thread being granted permission on it. The memory
288  * for the object will be allocated out of the calling thread's resource pool.
289  *
290  * This function is specially helpful for thread stack objects because
291  * their sizes can vary. Other objects should probably look k_object_alloc().
292  *
293  * @param otype Requested kernel object type
294  * @param size Requested kernel object size
295  * @return A pointer to the allocated kernel object, or NULL if memory wasn't
296  * available
297  */
298 __syscall void *k_object_alloc_size(enum k_objects otype, size_t size);
299 
300 /**
301  * Allocate memory and install as a generic kernel object
302  *
303  * This is a low-level function to allocate some memory, and register that
304  * allocated memory in the kernel object lookup tables with type K_OBJ_ANY.
305  * Initialization state and thread permissions will be cleared. The
306  * returned z_object's data value will be uninitialized.
307  *
308  * Most users will want to use k_object_alloc() instead.
309  *
310  * Memory allocated will be drawn from the calling thread's reasource pool
311  * and may be freed later by passing the actual object pointer (found
312  * in the returned z_object's 'name' member) to k_object_free().
313  *
314  * @param align Required memory alignment for the allocated object
315  * @param size Size of the allocated object
316  * @return NULL on insufficient memory
317  * @return A pointer to the associated z_object that is installed in the
318  *	kernel object tables
319  */
320 struct z_object *z_dynamic_object_aligned_create(size_t align, size_t size);
321 
322 /**
323  * Allocate memory and install as a generic kernel object
324  *
325  * This is a low-level function to allocate some memory, and register that
326  * allocated memory in the kernel object lookup tables with type K_OBJ_ANY.
327  * Initialization state and thread permissions will be cleared. The
328  * returned z_object's data value will be uninitialized.
329  *
330  * Most users will want to use k_object_alloc() instead.
331  *
332  * Memory allocated will be drawn from the calling thread's reasource pool
333  * and may be freed later by passing the actual object pointer (found
334  * in the returned z_object's 'name' member) to k_object_free().
335  *
336  * @param size Size of the allocated object
337  * @return NULL on insufficient memory
338  * @return A pointer to the associated z_object that is installed in the
339  *	kernel object tables
340  */
z_dynamic_object_create(size_t size)341 static inline struct z_object *z_dynamic_object_create(size_t size)
342 {
343 	return z_dynamic_object_aligned_create(0, size);
344 }
345 
346 /**
347  * Free a kernel object previously allocated with k_object_alloc()
348  *
349  * This will return memory for a kernel object back to resource pool it was
350  * allocated from.  Care must be exercised that the object will not be used
351  * during or after when this call is made.
352  *
353  * @param obj Pointer to the kernel object memory address.
354  */
355 void k_object_free(void *obj);
356 #else
357 
358 /* LCOV_EXCL_START */
z_impl_k_object_alloc(enum k_objects otype)359 static inline void *z_impl_k_object_alloc(enum k_objects otype)
360 {
361 	ARG_UNUSED(otype);
362 
363 	return NULL;
364 }
365 
z_impl_k_object_alloc_size(enum k_objects otype,size_t size)366 static inline void *z_impl_k_object_alloc_size(enum k_objects otype,
367 					size_t size)
368 {
369 	ARG_UNUSED(otype);
370 	ARG_UNUSED(size);
371 
372 	return NULL;
373 }
374 
z_dynamic_object_aligned_create(size_t align,size_t size)375 static inline struct z_object *z_dynamic_object_aligned_create(size_t align,
376 							       size_t size)
377 {
378 	ARG_UNUSED(align);
379 	ARG_UNUSED(size);
380 
381 	return NULL;
382 }
383 
z_dynamic_object_create(size_t size)384 static inline struct z_object *z_dynamic_object_create(size_t size)
385 {
386 	ARG_UNUSED(size);
387 
388 	return NULL;
389 }
390 
391 /**
392  * @brief Free an object
393  *
394  * @param obj
395  */
k_object_free(void * obj)396 static inline void k_object_free(void *obj)
397 {
398 	ARG_UNUSED(obj);
399 }
400 /* LCOV_EXCL_STOP */
401 #endif /* CONFIG_DYNAMIC_OBJECTS */
402 
403 /** @} */
404 
405 #include <syscalls/kobject.h>
406 #ifdef __cplusplus
407 }
408 #endif
409 
410 #endif
411