kernel: userspace: add k_object_is_valid()

This adds a function k_object_is_valid() to check if a kernel
object exists, of certain type, and has been initialized.
This replaces the same (or very similar) code that has been
copied from kernel into the network subsystem.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2023-09-27 13:06:16 -07:00 committed by Anas Nashif
parent cc219c0132
commit d47b1c05f3
5 changed files with 46 additions and 27 deletions

View file

@ -192,6 +192,19 @@ __syscall void k_object_release(const void *object);
*/
void k_object_access_all_grant(const void *object);
/**
* Check if a kernel object is of certain type and is valid.
*
* This checks if the kernel object exists, of certain type,
* and has been initialized.
*
* @param obj Address of the kernel object
* @param otype Object type (use K_OBJ_ANY for ignoring type checking)
* @return True if kernel object (@a obj) exists, of certain type, and
* has been initialized. False otherwise.
*/
bool k_object_is_valid(const void *obj, enum k_objects otype);
#else
/* LCOV_EXCL_START */
#define K_THREAD_ACCESS_GRANT(thread, ...)
@ -236,6 +249,15 @@ static inline void k_object_access_all_grant(const void *object)
{
ARG_UNUSED(object);
}
static inline bool k_object_is_valid(const void *obj, enum k_objects otype)
{
ARG_UNUSED(obj);
ARG_UNUSED(otype);
return true;
}
/* LCOV_EXCL_STOP */
#endif /* !CONFIG_USERSPACE */

View file

@ -7,8 +7,11 @@
#include <zephyr/kernel.h>
#include <zephyr/syscall_handler.h>
#include <zephyr/kernel_structs.h>
#include <zephyr/toolchain.h>
static struct z_object *validate_any_object(const void *obj)
static struct z_object *validate_kernel_object(const void *obj,
enum k_objects otype,
enum _obj_init_check init)
{
struct z_object *ko;
int ret;
@ -18,10 +21,10 @@ static struct z_object *validate_any_object(const void *obj)
/* This can be any kernel object and it doesn't have to be
* initialized
*/
ret = z_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_ANY);
ret = z_object_validate(ko, otype, init);
if (ret != 0) {
#ifdef CONFIG_LOG
z_dump_object_error(ret, obj, ko, K_OBJ_ANY);
z_dump_object_error(ret, obj, ko, otype);
#endif
return NULL;
}
@ -29,6 +32,20 @@ static struct z_object *validate_any_object(const void *obj)
return ko;
}
static ALWAYS_INLINE struct z_object *validate_any_object(const void *obj)
{
return validate_kernel_object(obj, K_OBJ_ANY, _OBJ_INIT_ANY);
}
bool k_object_is_valid(const void *obj, enum k_objects otype)
{
struct z_object *ko;
ko = validate_kernel_object(obj, otype, _OBJ_INIT_TRUE);
return (ko != NULL);
}
/* Normally these would be included in userspace.c, but the way
* syscall_dispatch.c declares weak handlers results in build errors if these
* are located in userspace.c. Just put in a separate file.

View file

@ -152,19 +152,13 @@ struct net_if *z_impl_net_if_get_by_index(int index)
struct net_if *z_vrfy_net_if_get_by_index(int index)
{
struct net_if *iface;
struct z_object *zo;
int ret;
iface = net_if_get_by_index(index);
if (!iface) {
return NULL;
}
zo = z_object_find(iface);
ret = z_object_validate(zo, K_OBJ_NET_IF, _OBJ_INIT_TRUE);
if (ret != 0) {
z_dump_object_error(ret, iface, zo, K_OBJ_NET_IF);
if (!k_object_is_valid(iface, K_OBJ_NET_IF)) {
return NULL;
}

View file

@ -78,14 +78,7 @@ static inline void *get_sock_vtable(int sock,
#ifdef CONFIG_USERSPACE
if (ctx != NULL && z_is_in_user_syscall()) {
struct z_object *zo;
int ret;
zo = z_object_find(ctx);
ret = z_object_validate(zo, K_OBJ_NET_SOCKET, _OBJ_INIT_TRUE);
if (ret != 0) {
z_dump_object_error(ret, ctx, zo, K_OBJ_NET_SOCKET);
if (!k_object_is_valid(ctx, K_OBJ_NET_SOCKET)) {
/* Invalidate the context, the caller doesn't have
* sufficient permission or there was some other
* problem with the net socket object

View file

@ -1034,18 +1034,11 @@ ZTEST(mem_protect_kobj, test_create_new_invalid_prio_thread_from_user)
/* Function to init thread's stack objects */
static void thread_stack_init_objects(void *p1, void *p2, void *p3)
{
int ret;
struct z_object *ko;
/* check that thread is initialized when running */
ko = z_object_find(&child_thread);
ret = z_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_TRUE);
zassert_equal(ret, _OBJ_INIT_TRUE);
zassert_true(k_object_is_valid(&child_thread, K_OBJ_ANY));
/* check that stack is initialized when running */
ko = z_object_find(child_stack);
ret = z_object_validate(ko, K_OBJ_ANY, _OBJ_INIT_TRUE);
zassert_equal(ret, _OBJ_INIT_TRUE);
zassert_true(k_object_is_valid(child_stack, K_OBJ_ANY));
}
/**