Zephyr Project API 4.4.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_INTERNAL_SYSCALL_HANDLER_H_
7#define ZEPHYR_INCLUDE_INTERNAL_SYSCALL_HANDLER_H_
8
15
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() && (_current->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
144static inline bool k_object_is_dynamic(const void *obj)
145{
146 struct k_object *ko = k_object_find(obj);
147
148 return (ko != NULL) && ((ko->flags & K_OBJ_FLAG_ALLOC) != 0U);
149}
150
151typedef void (*_wordlist_cb_func_t)(struct k_object *ko, void *context);
152
162void k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context);
163
173void k_thread_perms_inherit(struct k_thread *parent, struct k_thread *child);
174
184void k_thread_perms_set(struct k_object *ko, struct k_thread *thread);
185
195void k_thread_perms_clear(struct k_object *ko, struct k_thread *thread);
196
209
221void k_object_uninit(const void *obj);
222
242void k_object_recycle(const void *obj);
243
269static inline size_t k_usermode_string_nlen(const char *src, size_t maxlen,
270 int *err)
271{
272 return arch_user_string_nlen(src, maxlen, err);
273}
274
292void *k_usermode_alloc_from_copy(const void *src, size_t size);
293
309int k_usermode_from_copy(void *dst, const void *src, size_t size);
310
326int k_usermode_to_copy(void *dst, const void *src, size_t size);
327
344char *k_usermode_string_alloc_copy(const char *src, size_t maxlen);
345
364int k_usermode_string_copy(char *dst, const char *src, size_t maxlen);
365
378#define K_OOPS(expr) \
379 do { \
380 if (expr) { \
381 arch_syscall_oops(_current->syscall_frame); \
382 } \
383 } while (false)
384
399#define K_SYSCALL_VERIFY_MSG(expr, fmt, ...) ({ \
400 bool expr_copy = !(expr); \
401 if (expr_copy) { \
402 TOOLCHAIN_DISABLE_WARNING(TOOLCHAIN_WARNING_SHADOW) \
403 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); \
404 TOOLCHAIN_ENABLE_WARNING(TOOLCHAIN_WARNING_SHADOW) \
405 LOG_ERR("syscall %s failed check: " fmt, \
406 __func__, ##__VA_ARGS__); \
407 } \
408 expr_copy; })
409
421#define K_SYSCALL_VERIFY(expr) K_SYSCALL_VERIFY_MSG(expr, #expr)
422
436#define K_SYSCALL_MEMORY_SIZE_CHECK(ptr, size) \
437 (((uintptr_t)(ptr) + (size)) >= (uintptr_t)(ptr))
438
457#define K_SYSCALL_MEMORY(ptr, size, write) \
458 K_SYSCALL_VERIFY_MSG(K_SYSCALL_MEMORY_SIZE_CHECK(ptr, size) \
459 && !Z_DETECT_POINTER_OVERFLOW(ptr, size) \
460 && (arch_buffer_validate((void *)(ptr), (size), (write)) \
461 == 0), \
462 "Memory region %p (size %zu) %s access denied", \
463 (void *)(ptr), (size_t)(size), \
464 (write) ? "write" : "read")
465
480#define K_SYSCALL_MEMORY_READ(ptr, size) \
481 K_SYSCALL_MEMORY(ptr, size, 0)
482
499#define K_SYSCALL_MEMORY_WRITE(ptr, size) \
500 K_SYSCALL_MEMORY(ptr, size, 1)
501
518#define K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, write) \
519 ({ \
520 size_t product; \
521 K_SYSCALL_VERIFY_MSG(!size_mul_overflow((size_t)(nmemb), \
522 (size_t)(size), \
523 &product), \
524 "%zux%zu array is too large", \
525 (size_t)(nmemb), (size_t)(size)) || \
526 K_SYSCALL_MEMORY(ptr, product, write); \
527 })
528
543#define K_SYSCALL_MEMORY_ARRAY_READ(ptr, nmemb, size) \
544 K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, 0)
545
560#define K_SYSCALL_MEMORY_ARRAY_WRITE(ptr, nmemb, size) \
561 K_SYSCALL_MEMORY_ARRAY(ptr, nmemb, size, 1)
562
563static inline int k_object_validation_check(struct k_object *ko,
564 const void *obj,
565 enum k_objects otype,
566 enum _obj_init_check init)
567{
568 int ret;
569
570 ret = k_object_validate(ko, otype, init);
571
572#ifdef CONFIG_LOG
573 if (ret != 0) {
574 k_object_dump_error(ret, obj, ko, otype);
575 }
576#else
577 ARG_UNUSED(obj);
578#endif
579
580 return ret;
581}
582
583#define K_SYSCALL_IS_OBJ(ptr, type, init) \
584 K_SYSCALL_VERIFY_MSG(k_object_validation_check( \
585 k_object_find((const void *)(ptr)), \
586 (const void *)(ptr), \
587 (type), (init)) == 0, "access denied")
588
603#define K_SYSCALL_DRIVER_OP(ptr, api_name, op) \
604 ({ \
605 struct api_name *__device__ = (struct api_name *) \
606 ((const struct device *)(ptr))->api; \
607 K_SYSCALL_VERIFY_MSG(__device__->op != NULL, \
608 "Operation %s not defined for driver " \
609 "instance %p", \
610 # op, __device__); \
611 })
612
633#define K_SYSCALL_SPECIFIC_DRIVER(_device, _dtype, _api) \
634 ({ \
635 const struct device *_dev = (const struct device *)_device; \
636 K_SYSCALL_OBJ(_dev, _dtype) || \
637 K_SYSCALL_VERIFY_MSG(_dev->api == _api, \
638 "API structure mismatch"); \
639 })
640
653#define K_SYSCALL_OBJ(ptr, type) \
654 K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_TRUE)
655
668
669#define K_SYSCALL_OBJ_INIT(ptr, type) \
670 K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_ANY)
671
686
687#define K_SYSCALL_OBJ_NEVER_INIT(ptr, type) \
688 K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_FALSE)
689
708
709#define K_SYSCALL_OBJ_STATIC(ptr, type) \
710 (K_SYSCALL_OBJ(ptr, type) || \
711 K_SYSCALL_VERIFY_MSG(!k_object_is_dynamic((const void *)(ptr)), \
712 "dynamically allocated kernel object %p may not " \
713 "be used here, it can be freed while still in use", \
714 (const void *)(ptr)))
715
716#include <zephyr/driver-validation.h>
717
718#endif /* _ASMLANGUAGE */
719
720#endif /* CONFIG_USERSPACE */
724
725#endif /* ZEPHYR_INCLUDE_INTERNAL_SYSCALL_HANDLER_H_ */
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.
static bool k_object_is_dynamic(const void *obj)
Check whether a kernel object was dynamically allocated.
Definition syscall_handler.h:144
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:269
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:563
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.
#define K_OBJ_FLAG_ALLOC
Object allocated.
Definition kobject.h:78
#define NULL
Definition iar_missing_defs.h:20
Public kernel APIs.
k_objects
Kernel Object Types.
Definition kobject.h:29
Header file for the logging subsystem.
Extra arithmetic and bit-manipulation functions.
Table generated by gperf, these objects are retrieved via k_object_find().
Definition kobject_internal.h:58
uint8_t flags
Definition kobject_internal.h:62
Thread Structure.
Definition thread.h:259