diff --git a/include/kernel.h b/include/kernel.h index 8b7e230572b..7dd572367c9 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -471,6 +471,12 @@ extern void k_call_stacks_analyze(void); */ #define K_USER (1 << 2) +/* Indicates that the thread being created should inherit all kernel object + * permissions from the thread that created it. No effect if CONFIG_USERSPACE + * is not enabled. + */ +#define K_INHERIT_PERMS (1 << 3) + #ifdef CONFIG_X86 /* x86 Bitmask definitions for threads user options */ diff --git a/include/linker/kobject-text.ld b/include/linker/kobject-text.ld index 04671667a82..5a46a286f26 100644 --- a/include/linker/kobject-text.ld +++ b/include/linker/kobject-text.ld @@ -2,14 +2,14 @@ #if defined(CONFIG_DEBUG) || defined(CONFIG_STACK_CANARIES) #define KOBJECT_TEXT_AREA 256 #else -#define KOBJECT_TEXT_AREA 78 +#define KOBJECT_TEXT_AREA 118 #endif #endif #ifdef CONFIG_USERSPACE /* We need to reserve room for the gperf generated hash functions. * Fortunately, unlike the data tables, the size of the code is - * reasonably predictable; on x86 usually about 44 bytes with -Os. + * reasonably predictable. * * The linker will error out complaining that the location pointer * is moving backwards if the reserved room isn't large enough. @@ -19,6 +19,7 @@ _kobject_text_area_end = .; #ifndef LINKER_PASS2 PROVIDE(_k_object_find = .); + PROVIDE(_k_object_wordlist_foreach = .); #endif . += KOBJECT_TEXT_AREA - (_kobject_text_area_end - _kobject_text_area_start); #endif /* CONFIG_USERSPACE */ diff --git a/kernel/include/syscall_handler.h b/kernel/include/syscall_handler.h index e068f1cd219..696b66e702b 100644 --- a/kernel/include/syscall_handler.h +++ b/kernel/include/syscall_handler.h @@ -63,6 +63,25 @@ extern void _dump_object_error(int retval, void *obj, struct _k_object *ko, */ extern struct _k_object *_k_object_find(void *obj); +typedef void (*_wordlist_cb_func_t)(struct _k_object *ko, void *context); + +/** + * Iterate over all the kernel object metadata in the system + * + * @param func function to run on each struct _k_object + * @param context Context pointer to pass to each invocation + */ +extern void _k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context); + +/** + * Copy all kernel object permissions from the parent to the child + * + * @param parent Parent thread, to get permissions from + * @param child Child thread, to copy permissions to + */ +extern void _thread_perms_inherit(struct k_thread *parent, + struct k_thread *child); + /** * Grant a thread permission to a kernel object * diff --git a/kernel/thread.c b/kernel/thread.c index d930d1679f5..1a7c496b2a4 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -286,6 +286,10 @@ void _setup_new_thread(struct k_thread *new_thread, /* Any given thread has access to itself */ k_object_access_grant(new_thread, new_thread); + + if (options & K_INHERIT_PERMS) { + _thread_perms_inherit(_current, new_thread); + } #endif } diff --git a/kernel/userspace.c b/kernel/userspace.c index a8c6ef7b962..80e8d14b68d 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -92,6 +92,36 @@ const char *otype_to_str(enum k_objects otype) #endif } +struct perm_ctx { + int parent_id; + int child_id; + struct k_thread *parent; +}; + +static void wordlist_cb(struct _k_object *ko, void *ctx_ptr) +{ + struct perm_ctx *ctx = (struct perm_ctx *)ctx_ptr; + + if (sys_bitfield_test_bit((mem_addr_t)&ko->perms, ctx->parent_id) && + (struct k_thread *)ko->name != ctx->parent) { + sys_bitfield_set_bit((mem_addr_t)&ko->perms, ctx->child_id); + } +} + +void _thread_perms_inherit(struct k_thread *parent, struct k_thread *child) +{ + struct perm_ctx ctx = { + parent->base.perm_index, + child->base.perm_index, + parent + }; + + if ((ctx.parent_id < 8 * CONFIG_MAX_THREAD_BYTES) && + (ctx.child_id < 8 * CONFIG_MAX_THREAD_BYTES)) { + _k_object_wordlist_foreach(wordlist_cb, &ctx); + } +} + void _thread_perms_set(struct _k_object *ko, struct k_thread *thread) { if (thread->base.perm_index < 8 * CONFIG_MAX_THREAD_BYTES) { diff --git a/scripts/gen_kobject_list.py b/scripts/gen_kobject_list.py index 4eca4855d0d..761f0e9023c 100755 --- a/scripts/gen_kobject_list.py +++ b/scripts/gen_kobject_list.py @@ -467,9 +467,11 @@ def find_kobjects(elf, syms): header = """%compare-lengths %define lookup-function-name _k_object_lookup %language=ANSI-C +%global-table %struct-type %{ #include +#include #include %} struct _k_object; @@ -485,6 +487,17 @@ struct _k_object *_k_object_find(void *obj) { return _k_object_lookup((const char *)obj, sizeof(void *)); } + +void _k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) +{ + int i; + + for (i = MIN_HASH_VALUE; i <= MAX_HASH_VALUE; i++) { + if (wordlist[i].name) { + func(&wordlist[i], context); + } + } +} """