userspace: do not auto-cleanup static objects

Dynamic kernel objects enforce that the permission state
of an object is also a reference count; using a kernel
object without permission regardless of caller privilege
level is a programming bug.

However, this is not the case for static objects. In
particular, supervisor threads are allowed to use any
object they like without worrying about permissions, and
the logic here was causing cleanup functions to be called
over and over again on kernel objects that were actually
in use.

The automatic cleanup mechanism was intended for
dynamic objects anyway, so just skip it entirely for
static objects.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-01-31 12:09:06 -08:00 committed by Anas Nashif
commit 7ecc359f2c

View file

@ -331,11 +331,23 @@ static int thread_index_get(struct k_thread *t)
return ko->data; return ko->data;
} }
static void unref_check(struct _k_object *ko) static void unref_check(struct _k_object *ko, int index)
{ {
int key = irq_lock();
sys_bitfield_clear_bit((mem_addr_t)&ko->perms, index);
#ifdef CONFIG_DYNAMIC_OBJECTS
struct dyn_obj *dyn_obj =
CONTAINER_OF(ko, struct dyn_obj, kobj);
if ((ko->flags & K_OBJ_FLAG_ALLOC) == 0) {
goto out;
}
for (int i = 0; i < CONFIG_MAX_THREAD_BYTES; i++) { for (int i = 0; i < CONFIG_MAX_THREAD_BYTES; i++) {
if (ko->perms[i] != 0) { if (ko->perms[i] != 0) {
return; goto out;
} }
} }
@ -359,15 +371,12 @@ static void unref_check(struct _k_object *ko)
break; break;
} }
#ifdef CONFIG_DYNAMIC_OBJECTS rb_remove(&obj_rb_tree, &dyn_obj->node);
if ((ko->flags & K_OBJ_FLAG_ALLOC) != 0) { sys_dlist_remove(&dyn_obj->obj_list);
struct dyn_obj *dyn_obj = k_free(dyn_obj);
CONTAINER_OF(ko, struct dyn_obj, kobj); out:
rb_remove(&obj_rb_tree, &dyn_obj->node);
sys_dlist_remove(&dyn_obj->obj_list);
k_free(dyn_obj);
}
#endif #endif
irq_unlock(key);
} }
static void wordlist_cb(struct _k_object *ko, void *ctx_ptr) static void wordlist_cb(struct _k_object *ko, void *ctx_ptr)
@ -407,22 +416,15 @@ void _thread_perms_clear(struct _k_object *ko, struct k_thread *thread)
int index = thread_index_get(thread); int index = thread_index_get(thread);
if (index != -1) { if (index != -1) {
unsigned int key = irq_lock(); unref_check(ko, index);
sys_bitfield_clear_bit((mem_addr_t)&ko->perms, index);
unref_check(ko);
irq_unlock(key);
} }
} }
static void clear_perms_cb(struct _k_object *ko, void *ctx_ptr) static void clear_perms_cb(struct _k_object *ko, void *ctx_ptr)
{ {
int id = (int)ctx_ptr; int id = (int)ctx_ptr;
unsigned int key = irq_lock();
sys_bitfield_clear_bit((mem_addr_t)&ko->perms, id); unref_check(ko, id);
unref_check(ko);
irq_unlock(key);
} }
void _thread_perms_all_clear(struct k_thread *thread) void _thread_perms_all_clear(struct k_thread *thread)