diff --git a/include/kernel.h b/include/kernel.h index 7dd572367c9..4d4dbd7e7fe 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -204,6 +204,13 @@ static inline void _impl_k_object_access_grant(void *object, ARG_UNUSED(thread); } +static inline void _impl_k_object_access_revoke(void *object, + struct k_thread *thread) +{ + ARG_UNUSED(object); + ARG_UNUSED(thread); +} + static inline void _impl_k_object_access_all_grant(void *object) { ARG_UNUSED(object); @@ -215,13 +222,24 @@ static inline void _impl_k_object_access_all_grant(void *object) * * The thread will be granted access to the object if the caller is from * supervisor mode, or the caller is from user mode AND has permissions - * on the object already. + * on both the object and the thread whose access is being granted. * * @param object Address of kernel object * @param thread Thread to grant access to the object */ __syscall void k_object_access_grant(void *object, struct k_thread *thread); +/** + * grant a thread access to a kernel object + * + * The thread will lose access to the object if the caller is from + * supervisor mode, or the caller is from user mode AND has permissions + * on both the object and the thread whose access is being revoked. + * + * @param object Address of kernel object + * @param thread Thread to remove access to the object + */ +__syscall void k_object_access_revoke(void *object, struct k_thread *thread); /** * grant all present and future threads access to an object diff --git a/kernel/include/syscall_handler.h b/kernel/include/syscall_handler.h index 696b66e702b..b2fe6b4e214 100644 --- a/kernel/include/syscall_handler.h +++ b/kernel/include/syscall_handler.h @@ -90,6 +90,14 @@ extern void _thread_perms_inherit(struct k_thread *parent, */ extern void _thread_perms_set(struct _k_object *ko, struct k_thread *thread); +/** + * Revoke a thread's permission to a kernel object + * + * @param ko Kernel object metadata to update + * @param thread The thread to grant permission + */ +extern void _thread_perms_clear(struct _k_object *ko, struct k_thread *thread); + /** * Grant all current and future threads access to a kernel object * diff --git a/kernel/userspace.c b/kernel/userspace.c index 80e8d14b68d..8f97957dd16 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -130,6 +130,14 @@ void _thread_perms_set(struct _k_object *ko, struct k_thread *thread) } } +void _thread_perms_clear(struct _k_object *ko, struct k_thread *thread) +{ + if (thread->base.perm_index < 8 * CONFIG_MAX_THREAD_BYTES) { + sys_bitfield_clear_bit((mem_addr_t)&ko->perms, + thread->base.perm_index); + } +} + static int thread_perms_test(struct _k_object *ko) { if (_current->base.perm_index < 8 * CONFIG_MAX_THREAD_BYTES) { @@ -180,6 +188,15 @@ void _impl_k_object_access_grant(void *object, struct k_thread *thread) } } +void _impl_k_object_access_revoke(void *object, struct k_thread *thread) +{ + struct _k_object *ko = _k_object_find(object); + + if (ko) { + _thread_perms_clear(ko, thread); + } +} + void _impl_k_object_access_all_grant(void *object) { struct _k_object *ko = _k_object_find(object); diff --git a/kernel/userspace_handler.c b/kernel/userspace_handler.c index e0379d6b9cb..cc25e11823f 100644 --- a/kernel/userspace_handler.c +++ b/kernel/userspace_handler.c @@ -47,6 +47,18 @@ _SYSCALL_HANDLER2(k_object_access_grant, object, thread) return 0; } +_SYSCALL_HANDLER2(k_object_access_revoke, object, thread) +{ + struct _k_object *ko; + + _SYSCALL_OBJ(thread, K_OBJ_THREAD); + ko = validate_any_object((void *)object); + _SYSCALL_VERIFY_MSG(ko, "object %p access denied", (void *)object); + _thread_perms_clear(ko, (struct k_thread *)thread); + + return 0; +} + _SYSCALL_HANDLER1(k_object_access_all_grant, object) { struct _k_object *ko;