kernel: add K_INHERIT_PERMS flag

By default, threads are created only having access to their own thread
object and nothing else. This new flag to k_thread_create() gives the
thread access to all objects that the parent had at the time it was
created, with the exception of the parent thread itself.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-10-05 11:11:02 -07:00 committed by Andrew Boie
commit 47f8fd1d4d
6 changed files with 75 additions and 2 deletions

View file

@ -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 */

View file

@ -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 */

View file

@ -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
*

View file

@ -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
}

View file

@ -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) {

View file

@ -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 <kernel.h>
#include <syscall_handler.h>
#include <string.h>
%}
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);
}
}
}
"""