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