diff options
Diffstat (limited to 'src/uapi/cap.c')
| -rw-r--r-- | src/uapi/cap.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/uapi/cap.c b/src/uapi/cap.c new file mode 100644 index 0000000..157ef47 --- /dev/null +++ b/src/uapi/cap.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: copyleft-next-0.3.1 */ +/* Copyright 2023 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ + +#include <kmi/uapi.h> +#include <kmi/caps.h> +#include <kmi/tcb.h> + +/** + * @file cap.c + * Sycalls handlers for thread capabilities. + */ + +/** + * Check that values are legal for thread ID and offset. + * + * @param tid Thread ID of thread whose caps should be fetched. + * @param off Offset of capabilities. + * @return Pointer to capabilities of \p tid, \c 0 otherwise. + */ +static capflags_t *__get_tcb_caps(id_t tid, size_t off) +{ + if (!cap_off_ok(off)) + return NULL; + + struct tcb *t = get_tcb(tid); + if (!t) + return NULL; + + return &t->caps; +} + +/** + * Set capabilities. + * + * @param t Current tcb. + * @param tid Thread ID whose capabilities to set. + * @param off Offset of capability, multiple of \c bits(cap). + * @param caps Mask of capabilities to set. + * @return \ref OK on success, \ref ERR_INVAL on invalid input. + */ +SYSCALL_DEFINE3(set_cap)(struct tcb *t, sys_arg_t tid, sys_arg_t off, + sys_arg_t caps) +{ + if (!is_set(t->caps, CAP_CAPS)) + return_args1(t, ERR_PERM); + + capflags_t *c; + if (!(c = __get_tcb_caps(tid, off))) + return_args1(t, ERR_INVAL); + + set_caps(*c, off, caps); + return_args1(t, OK); +} + +/** + * Get capabilities. + * + * @param t Current tcb. + * @param tid Thread ID whose capabilities to get. + * @param off Offset of capability, multiple of \c bits(cap). + * @return \ref OK, capabilities. + */ +SYSCALL_DEFINE2(get_cap)(struct tcb *t, sys_arg_t tid, sys_arg_t off) +{ + capflags_t *c; + if (!(c = __get_tcb_caps(tid, off))) + return_args1(t, ERR_INVAL); + + return_args2(t, OK, get_caps(*c, off)); +} + +/** + * Clear capabilities. + * + * @param t Current tcb. + * @param tid Thread ID whose capabilities to clear. + * @param off Offset of capability, multiple of \c bits(cap). + * @param caps Mask of capabilities to clear. + * @return ERR_LERM if invalid permissions, ERR_INVAL if \p tid doesn't exist, + * otherwise OK. + */ +SYSCALL_DEFINE3(clear_cap)(struct tcb *t, sys_arg_t tid, sys_arg_t off, + sys_arg_t caps) +{ + if (!is_set(t->caps, CAP_CAPS)) + return_args1(t, ERR_PERM); + + capflags_t *c; + if (!(c = __get_tcb_caps(tid, off))) + return_args1(t, ERR_INVAL); + + clear_caps(*c, off, caps); + return_args1(t, OK); +} |
