Zephyr API Documentation 4.0.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
syscall_handler.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017, Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#ifndef ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_
7#define ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_
8
16#if defined(CONFIG_USERSPACE) || defined(__DOXYGEN__)
17
18#ifndef _ASMLANGUAGE
19#include <zephyr/kernel.h>
22#include <stdbool.h>
23#include <zephyr/logging/log.h>
24
25extern const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT];
26
27enum _obj_init_check {
28 _OBJ_INIT_TRUE = 0,
29 _OBJ_INIT_FALSE = -1,
30 _OBJ_INIT_ANY = 1
31};
32
57static inline bool k_is_in_user_syscall(void)
58{
59 /* This gets set on entry to the syscall's generated z_mrsh
60 * function and then cleared on exit. This code path is only
61 * encountered when a syscall is made from user mode, system
62 * calls from supervisor mode bypass everything directly to
63 * the implementation function.
64 */
65 return !k_is_in_isr() && (arch_current_thread()->syscall_frame != NULL);
66}
67
92int k_object_validate(struct k_object *ko, enum k_objects otype,
93 enum _obj_init_check init);
94
106void k_object_dump_error(int retval, const void *obj,
107 struct k_object *ko, enum k_objects otype);
108
122struct k_object *k_object_find(const void *obj);
123
124typedef void (*_wordlist_cb_func_t)(struct k_object *ko, void *context);
125
135void k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context);
136
146void k_thread_perms_inherit(struct k_thread *parent, struct k_thread *child);
147
157void k_thread_perms_set(struct k_object *ko, struct k_thread *thread);
158
168void k_thread_perms_clear(struct k_object *ko, struct k_thread *thread);
169
182
194void k_object_uninit(const void *obj);
195
215void k_object_recycle(const void *obj);
216
242static inline size_t k_usermode_string_nlen(const char *src, size_t maxlen,
243 int *err)
244{
245 return arch_user_string_nlen(src, maxlen, err);
246}
247
265void *k_usermode_alloc_from_copy(const void *src, size_t size);
266
282int k_usermode_from_copy(void *dst, const void *src, size_t size);
283
299int k_usermode_to_copy(void *dst, const void *src, size_t size);
300
317char *k_usermode_string_alloc_copy(const char *src, size_t maxlen);
318
337int k_usermode_string_copy(char *dst, const char *src, size_t maxlen);
338
350#define K_OOPS(expr) \
351 do { \
352 if (expr) { \
353 arch_syscall_oops(arch_current_thread()->syscall_frame); \
354 } \
355 } while (false)
356
372#define K_SYSCALL_VERIFY_MSG(expr, fmt, ...) ({ \
373 bool expr_copy = !(expr); \
374 if (expr_copy) { \
375 TOOLCHAIN_IGNORE_WSHADOW_BEGIN \
376 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); \
377 TOOLCHAIN_IGNORE_WSHADOW_END \
378 LOG_ERR("syscall %s failed check: " fmt, \
379 __func__, ##__VA_ARGS__); \
380 } \
381 expr_copy; })
382
395#define K_SYSCALL_VERIFY(expr) K_SYSCALL_VERIFY_MSG(expr, #expr)
396
410#define K_SYSCALL_MEMORY_SIZE_CHECK(ptr, size) \
411 (((uintptr_t)(ptr) + (size)) >= (uintptr_t)(ptr))
412
431#define K_SYSCALL_MEMORY(ptr, size, write) \
432 K_SYSCALL_VERIFY_MSG(K_SYSCALL_MEMORY_SIZE_CHECK(ptr, size) \
433 && !Z_DETECT_POINTER_OVERFLOW(ptr, size) \
434 && (arch_buffer_validate((void *)(ptr), (size), (write)) \
435 == 0), \
436 "Memory region %p (size %zu) %s access denied", \
437 (void *)(ptr), (size_t)(size), \
438 (write) ? "write" : "read")
439
455#define K_SYSCALL_MEMORY_READ(ptr, size) \
456 K_SYSCALL_MEMORY(ptr, size, 0)
457
474#define K_SYSCALL_MEMORY_WRITE(ptr, size) \
475 K_SYSCALL_MEMORY(ptr, size, 1)
476
477#define K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, write) \
478 ({ \
479 size_t product; \
480 K_SYSCALL_VERIFY_MSG(!size_mul_overflow((size_t)(nmemb), \
481 (size_t)(size), \
482 &product), \
483 "%zux%zu array is too large", \
484 (size_t)(nmemb), (size_t)(size)) || \
485 K_SYSCALL_MEMORY(ptr, product, write); \
486 })
487
502#define K_SYSCALL_MEMORY_ARRAY_READ(ptr, nmemb, size) \
503 K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, 0)
504
519#define K_SYSCALL_MEMORY_ARRAY_WRITE(ptr, nmemb, size) \
520 K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, 1)
521
522static inline int k_object_validation_check(struct k_object *ko,
523 const void *obj,
524 enum k_objects otype,
525 enum _obj_init_check init)
526{
527 int ret;
528
529 ret = k_object_validate(ko, otype, init);
530
531#ifdef CONFIG_LOG
532 if (ret != 0) {
533 k_object_dump_error(ret, obj, ko, otype);
534 }
535#else
536 ARG_UNUSED(obj);
537#endif
538
539 return ret;
540}
541
542#define K_SYSCALL_IS_OBJ(ptr, type, init) \
543 K_SYSCALL_VERIFY_MSG(k_object_validation_check( \
544 k_object_find((const void *)(ptr)), \
545 (const void *)(ptr), \
546 (type), (init)) == 0, "access denied")
547
562#define K_SYSCALL_DRIVER_OP(ptr, api_name, op) \
563 ({ \
564 struct api_name *__device__ = (struct api_name *) \
565 ((const struct device *)(ptr))->api; \
566 K_SYSCALL_VERIFY_MSG(__device__->op != NULL, \
567 "Operation %s not defined for driver " \
568 "instance %p", \
569 # op, __device__); \
570 })
571
592#define K_SYSCALL_SPECIFIC_DRIVER(_device, _dtype, _api) \
593 ({ \
594 const struct device *_dev = (const struct device *)_device; \
595 K_SYSCALL_OBJ(_dev, _dtype) || \
596 K_SYSCALL_VERIFY_MSG(_dev->api == _api, \
597 "API structure mismatch"); \
598 })
599
613#define K_SYSCALL_OBJ(ptr, type) \
614 K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_TRUE)
615
629#define K_SYSCALL_OBJ_INIT(ptr, type) \
630 K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_ANY)
631
647#define K_SYSCALL_OBJ_NEVER_INIT(ptr, type) \
648 K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_FALSE)
649
650#include <zephyr/driver-validation.h>
651
652#endif /* _ASMLANGUAGE */
653
654#endif /* CONFIG_USERSPACE */
659#endif /* ZEPHYR_INCLUDE_SYSCALL_HANDLER_H_ */
static ALWAYS_INLINE struct k_thread * arch_current_thread(void)
Definition arch_inlines.h:19
size_t arch_user_string_nlen(const char *s, size_t maxsize, int *err)
Safely take the length of a potentially bad string.
bool k_is_in_isr(void)
Determine if code is running at interrupt level.
struct k_object * k_object_find(const void *obj)
Kernel object validation function.
void k_thread_perms_clear(struct k_object *ko, struct k_thread *thread)
Revoke a thread's permission to a kernel object.
void k_thread_perms_set(struct k_object *ko, struct k_thread *thread)
Grant a thread permission to a kernel object.
void * k_usermode_alloc_from_copy(const void *src, size_t size)
Copy data from userspace into a resource pool allocation.
static size_t k_usermode_string_nlen(const char *src, size_t maxlen, int *err)
Obtain the size of a C string passed from user mode.
Definition syscall_handler.h:242
char * k_usermode_string_alloc_copy(const char *src, size_t maxlen)
Copy a C string from userspace into a resource pool allocation.
void k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context)
Iterate over all the kernel object metadata in the system.
void k_thread_perms_inherit(struct k_thread *parent, struct k_thread *child)
Copy all kernel object permissions from the parent to the child.
int k_usermode_string_copy(char *dst, const char *src, size_t maxlen)
Copy a C string from userspace into a provided buffer.
int k_object_validate(struct k_object *ko, enum k_objects otype, enum _obj_init_check init)
Ensure a system object is a valid object of the expected type.
static bool k_is_in_user_syscall(void)
Return true if we are currently handling a system call from user mode.
Definition syscall_handler.h:57
int k_usermode_from_copy(void *dst, const void *src, size_t size)
Copy data from user mode.
void k_thread_perms_all_clear(struct k_thread *thread)
Revoke access to all objects for the provided thread.
static int k_object_validation_check(struct k_object *ko, const void *obj, enum k_objects otype, enum _obj_init_check init)
Definition syscall_handler.h:522
void k_object_dump_error(int retval, const void *obj, struct k_object *ko, enum k_objects otype)
Dump out error information on failed k_object_validate() call.
void k_object_recycle(const void *obj)
Initialize and reset permissions to only access by the caller.
void k_object_uninit(const void *obj)
Clear initialization state of a kernel object.
int k_usermode_to_copy(void *dst, const void *src, size_t size)
Copy data to user mode.
Public kernel APIs.
k_objects
Kernel Object Types.
Definition kobject.h:30
Table generated by gperf, these objects are retrieved via k_object_find().
Definition kobject_internal.h:61
Thread Structure.
Definition thread.h:259
void * syscall_frame
current syscall frame pointer
Definition thread.h:333