From d2f2714398d415eb9a628aab82b332b92ad5c923 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 20 Sep 2022 15:38:06 +0300 Subject: add capability subsystem and syscalls --- common/uapi/cap.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/uapi/dispatch.c | 5 +++ 2 files changed, 92 insertions(+) create mode 100644 common/uapi/cap.c (limited to 'common/uapi') diff --git a/common/uapi/cap.c b/common/uapi/cap.c new file mode 100644 index 0000000..84dbc45 --- /dev/null +++ b/common/uapi/cap.c @@ -0,0 +1,87 @@ +#include +#include +#include + +/** + * @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 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)(sys_arg_t tid, sys_arg_t off, sys_arg_t caps) +{ + struct tcb *t = cur_tcb(); + if (!is_set(t->caps, CAP_CAPS)) + return (struct sys_ret){ERR_PERM, 0, 0, 0, 0, 0}; + + capflags_t *c; + if (!(c = __get_tcb_caps(tid, off))) + return (struct sys_ret){ERR_INVAL, 0, 0, 0, 0, 0}; + + set_caps(*c, off, caps); + return (struct sys_ret){OK, 0, 0, 0, 0, 0}; +} + +/** + * Get capabilities. + * + * @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)(sys_arg_t tid, sys_arg_t off) +{ + capflags_t *c; + if (!(c = __get_tcb_caps(tid, off))) + return (struct sys_ret){ERR_INVAL, 0, 0, 0, 0, 0}; + + return (struct sys_ret){OK, get_caps(*c, off), 0, 0, 0, 0}; +} + +/** + * Clear capabilities. + * + * @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 \ref OK. + */ +SYSCALL_DEFINE3(clear_cap)(sys_arg_t tid, sys_arg_t off, sys_arg_t caps) +{ + struct tcb *t = cur_tcb(); + if (!is_set(t->caps, CAP_CAPS)) + return (struct sys_ret){ERR_PERM, 0, 0, 0, 0, 0}; + + capflags_t *c; + if (!(c = __get_tcb_caps(tid, off))) + return (struct sys_ret){ERR_INVAL, 0, 0, 0, 0, 0}; + + clear_caps(*c, off, caps); + return (struct sys_ret){OK, 0, 0, 0, 0, 0}; +} diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c index f0f6ae0..30b2e2e 100644 --- a/common/uapi/dispatch.c +++ b/common/uapi/dispatch.c @@ -46,6 +46,11 @@ static const sys_t syscall_table[] = { /* conf */ [SYS_CONF_SET] = sys_conf_set, [SYS_CONF_GET] = sys_conf_get, + + [SYS_SET_CAP] = sys_set_cap, + [SYS_GET_CAP] = sys_get_cap, + [SYS_CLEAR_CAP] = sys_clear_cap, + [SYS_POWEROFF] = sys_poweroff, }; -- cgit v1.3