Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

userspace: easy checking for specific driver #12056

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/kernel/usermode/syscalls.rst
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,14 @@ Several macros exist to validate arguments:
instance, to validate the GPIO driver, one could use the
:c:macro:`Z_SYSCALL_DRIVER_GPIO()` macro.

* :c:macro:`Z_SYSCALL_SPECIFIC_DRIVER()` is a runtime check to verify that
a provided pointer is a valid instance of a specific device driver, that
the calling thread has permissions on it, and that the driver has been
initialized. It does this by checking the init function pointer that
is stored within the driver instance and ensuring that it matches the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by ensuring?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think "by ensuring" would be correct. The ensuring is part of the checking that's already under "by". Perhaps:

It does this by checking that the init function pointer stored within the driver instance matches the provided value, which should be the address of the specific driver's init function.

provided value, which should be the address of the specific driver's
init function.

If any check fails, the macros will return a nonzero value. The macro
:c:macro:`Z_OOPS()` can be used to induce a kernel oops which will kill the
calling thread. This is done instead of returning some error condition to
Expand Down
27 changes: 27 additions & 0 deletions kernel/include/syscall_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,33 @@ static inline int _obj_validation_check(struct _k_object *ko,
# op, __device__); \
})

/**
* @brief Runtime check that device object is of a specific driver type
*
* Checks that the driver object passed in is initialized, the caller has
* correct permissions, and that it belongs to the specified driver
* subsystems. Additionally, all devices store a function pointer to the
* driver's init function. If this doesn't match the value provided, the
* check will fail.
*
* This provides an easy way to determine if a device object not only
* belongs to a particular subsystem, but is of a specific device driver
* implementation. Useful for defining out-of-subsystem system calls
* which are implemented for only one driver.
*
* @param _device Untrusted device pointer
* @param _dtype Expected kernel object type for the provided device pointer
* @param _init_fn Expected init function memory address
* @return 0 on success, nonzero on failure
*/
#define Z_SYSCALL_SPECIFIC_DRIVER(_device, _dtype, _init_fn) \
({ \
struct device *_dev = (struct device *)_device; \
Z_SYSCALL_OBJ(_dev, _dtype) || \
Z_SYSCALL_VERIFY_MSG(_dev->config->init == _init_fn, \
"init function mismatch"); \
})

/**
* @brief Runtime check kernel object pointer for non-init functions
*
Expand Down