From a831dc359dbf2c6947cd4679be4986d52ba08ef4 Mon Sep 17 00:00:00 2001 From: Henrik Akira Karlsson Date: Sun, 12 Nov 2023 13:42:23 +0100 Subject: [PATCH] Streamlines cap_ops --- kernel/inc/cap_ops.h | 2 +- kernel/inc/cap_types.h | 1 + kernel/src/cap_ops.c | 464 ++++++++++++++++++++++++++++++----------- kernel/src/cap_table.c | 4 +- kernel/src/cap_util.c | 104 --------- 5 files changed, 347 insertions(+), 228 deletions(-) diff --git a/kernel/inc/cap_ops.h b/kernel/inc/cap_ops.h index 86b2fc83..b1d15a2c 100644 --- a/kernel/inc/cap_ops.h +++ b/kernel/inc/cap_ops.h @@ -5,7 +5,7 @@ err_t cap_read(cte_t cte, cap_t *cap); err_t cap_move(cte_t src, cte_t dst); +err_t cap_ipc_move(cte_t src, cte_t dst); err_t cap_delete(cte_t cte); err_t cap_revoke(cte_t parent); -err_t cap_reset(cte_t cte); err_t cap_derive(cte_t src, cte_t dst, cap_t new_cap); diff --git a/kernel/inc/cap_types.h b/kernel/inc/cap_types.h index b212343c..b4d4095c 100644 --- a/kernel/inc/cap_types.h +++ b/kernel/inc/cap_types.h @@ -56,6 +56,7 @@ typedef enum capty { CAPTY_MONITOR = 4, ///< Monitor capability. CAPTY_CHANNEL = 5, ///< IPC Channel capability. CAPTY_SOCKET = 6, ///< IPC Socket capability. + CAPTY_COUNT ///< Number of capability types } capty_t; /// Capability description diff --git a/kernel/src/cap_ops.c b/kernel/src/cap_ops.c index de3b8096..fa321ce9 100644 --- a/kernel/src/cap_ops.c +++ b/kernel/src/cap_ops.c @@ -4,80 +4,153 @@ #include "cap_util.h" #include "sched.h" +typedef err_t (*ipc_move_handler)(cte_t, cap_t, cte_t); +typedef err_t (*delete_handler)(cte_t, cap_t); +typedef err_t (*revoke_handler)(cte_t, cap_t); +typedef err_t (*derive_handler)(cte_t, cap_t, cte_t, cap_t); + +static err_t cap_ipc_move_time(cte_t src, cap_t cap, cte_t dst); +static err_t cap_ipc_move_memory(cte_t src, cap_t cap, cte_t dst); +static err_t cap_ipc_move_pmp(cte_t src, cap_t cap, cte_t dst); +static err_t cap_ipc_move_monitor(cte_t src, cap_t cap, cte_t dst); +static err_t cap_ipc_move_channel(cte_t src, cap_t cap, cte_t dst); +static err_t cap_ipc_move_socket(cte_t src, cap_t cap, cte_t dst); + +static err_t cap_delete_time(cte_t src, cap_t cap); +static err_t cap_delete_memory(cte_t src, cap_t cap); +static err_t cap_delete_pmp(cte_t src, cap_t cap); +static err_t cap_delete_monitor(cte_t src, cap_t cap); +static err_t cap_delete_channel(cte_t src, cap_t cap); +static err_t cap_delete_socket(cte_t src, cap_t cap); + +static err_t cap_revoke_time(cte_t src, cap_t cap); +static err_t cap_revoke_memory(cte_t src, cap_t cap); +static err_t cap_revoke_pmp(cte_t src, cap_t cap); +static err_t cap_revoke_monitor(cte_t src, cap_t cap); +static err_t cap_revoke_channel(cte_t src, cap_t cap); +static err_t cap_revoke_socket(cte_t src, cap_t cap); + +static err_t cap_derive_time(cte_t src, cap_t cap, cte_t dst, cap_t new_cap); +static err_t cap_derive_memory(cte_t src, cap_t cap, cte_t dst, cap_t new_cap); +static err_t cap_derive_pmp(cte_t src, cap_t cap, cte_t dst, cap_t new_cap); +static err_t cap_derive_monitor(cte_t src, cap_t cap, cte_t dst, cap_t new_cap); +static err_t cap_derive_channel(cte_t src, cap_t cap, cte_t dst, cap_t new_cap); +static err_t cap_derive_socket(cte_t src, cap_t cap, cte_t dst, cap_t new_cap); + +static const ipc_move_handler ipc_move_handlers[CAPTY_COUNT] = { + NULL, + cap_ipc_move_time, + cap_ipc_move_memory, + cap_ipc_move_pmp, + cap_ipc_move_monitor, + cap_ipc_move_channel, + cap_ipc_move_socket, +}; +static const delete_handler delete_handlers[CAPTY_COUNT] = { + NULL, + cap_delete_time, + cap_delete_memory, + cap_delete_pmp, + cap_delete_monitor, + cap_delete_channel, + cap_delete_socket, +}; +static const revoke_handler revoke_handlers[CAPTY_COUNT] = { + NULL, + cap_revoke_time, + cap_revoke_memory, + cap_revoke_pmp, + cap_revoke_monitor, + cap_revoke_channel, + cap_revoke_socket, +}; +static const derive_handler derive_handlers[CAPTY_COUNT] = { + NULL, + cap_derive_time, + cap_derive_memory, + cap_derive_pmp, + cap_derive_monitor, + cap_derive_channel, + cap_derive_socket, +}; + err_t cap_read(cte_t c, cap_t *cap) { *cap = cte_cap(c); return cap->raw ? SUCCESS : ERR_EMPTY; } -static void ipc_move_hook(cte_t src, cte_t dst) +err_t cap_ipc_move(cte_t src, cte_t dst) { + if (cte_is_empty(src)) + return ERR_SRC_EMPTY; + if (!cte_is_empty(dst)) + return ERR_DST_OCCUPIED; cap_t cap = cte_cap(src); - switch (cap.type) { - case CAPTY_TIME: { - uint64_t pid = cte_pid(dst); - uint64_t end = cap.time.end; - uint64_t hartid = cap.time.hart; - uint64_t from = cap.time.mrk; - uint64_t to = cap.time.end; - sched_update(pid, end, hartid, from, to); - } break; - case CAPTY_PMP: - if (cap.pmp.used) { - proc_pmp_unload(proc_get(cte_pid(src)), cap.pmp.slot); - cap.pmp.used = 0; - cap.pmp.slot = 0; - cte_set_cap(src, cap); - } - break; - case CAPTY_SOCKET: - cap_sock_clear(cap, proc_get(cte_pid(src))); - break; - default: - break; - } + return ipc_move_handlers[cap.type](src, cap, dst); } err_t cap_move(cte_t src, cte_t dst) { - if (!cte_cap(src).type) + if (cte_is_empty(src)) return ERR_SRC_EMPTY; - - if (cte_cap(dst).type) + if (!cte_is_empty(dst)) return ERR_DST_OCCUPIED; - if (cte_pid(src) != cte_pid(dst)) - ipc_move_hook(src, dst); + return cap_ipc_move(src, dst); cte_move(src, dst); return SUCCESS; } err_t cap_delete(cte_t c) { + if (cte_is_empty(c)) + return ERR_EMPTY; cap_t cap = cte_cap(c); - proc_t *p = proc_get(cte_pid(c)); - switch (cap.type) { - case CAPTY_NONE: + return delete_handlers[cap.type](c, cap); +} + +err_t cap_revoke(cte_t parent) +{ + cap_t pcap = cte_cap(parent); + if (pcap.type == CAPTY_NONE) return ERR_EMPTY; - case CAPTY_TIME: - sched_delete(cap.time.hart, cap.time.mrk, cap.time.end); - break; - case CAPTY_PMP: - if (cap.pmp.used) - proc_pmp_unload(p, cap.pmp.slot); - break; - case CAPTY_SOCKET: - cap_sock_clear(cap, p); - break; - default: - break; - } + return revoke_handlers[pcap.type](parent, pcap); +} + +err_t cap_derive(cte_t src, cte_t dst, cap_t ncap) +{ + if (cte_is_empty(src)) + return ERR_SRC_EMPTY; + + if (!cte_is_empty(dst)) + return ERR_DST_OCCUPIED; + + cap_t scap = cte_cap(src); + return derive_handlers[scap.type](src, scap, dst, ncap); +} + +/********** HANDLERS ***********/ + +err_t cap_ipc_move_time(cte_t src, cap_t cap, cte_t dst) +{ + sched_update(cte_pid(dst), cap.time.end, cap.time.hart, cap.time.mrk, + cap.time.end); + cte_move(src, dst); + return SUCCESS; +} + +err_t cap_delete_time(cte_t c, cap_t cap) +{ + sched_delete(cap.time.hart, cap.time.mrk, cap.time.end); cte_delete(c); return SUCCESS; } -err_t cap_revoke_time(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) +err_t cap_revoke_time(cte_t parent, cap_t pcap) { + cte_t child = cte_next(parent); + cap_t ccap = cte_cap(child); if (ccap.type == CAPTY_TIME && pcap.time.hart == ccap.time.hart && pcap.time.bgn <= ccap.time.bgn) { // delete the child @@ -111,8 +184,44 @@ err_t cap_revoke_time(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) return SUCCESS; } -err_t cap_revoke_memory(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) +err_t cap_derive_time(cte_t src, cap_t cap, cte_t dst, cap_t new_cap) +{ + if (new_cap.type != CAPTY_TIME) + return ERR_INVALID_DERIVATION; + if (new_cap.time.bgn != new_cap.time.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.time.bgn >= new_cap.time.end) + return ERR_INVALID_DERIVATION; + if (new_cap.time.hart != cap.time.hart) + return ERR_INVALID_DERIVATION; + if (new_cap.time.bgn != cap.time.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.time.end >= cap.time.end) + return ERR_INVALID_DERIVATION; + sched_update(cte_pid(dst), new_cap.time.end, new_cap.time.hart, + new_cap.time.bgn, new_cap.time.end); + cap.time.mrk = cap.time.bgn; + cte_set_cap(src, cap); + cte_insert(dst, new_cap, src); + return SUCCESS; +} + +err_t cap_ipc_move_memory(cte_t src, cap_t cap, cte_t dst) +{ + cte_move(src, dst); + return SUCCESS; +} + +err_t cap_delete_memory(cte_t c, cap_t cap) { + cte_delete(c); + return SUCCESS; +} + +err_t cap_revoke_memory(cte_t parent, cap_t pcap) +{ + cte_t child = cte_next(parent); + cap_t ccap = cte_cap(child); if (ccap.type == CAPTY_MEMORY && pcap.mem.tag == ccap.mem.tag && pcap.mem.bgn <= ccap.mem.bgn) { // delete the child @@ -150,8 +259,101 @@ err_t cap_revoke_memory(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) return SUCCESS; } -err_t cap_revoke_monitor(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) +err_t cap_derive_memory(cte_t src, cap_t cap, cte_t dst, cap_t new_cap) +{ + if (new_cap.type == CAPTY_MEMORY) { + if (cap.mem.tag != new_cap.mem.tag) + return ERR_INVALID_DERIVATION; + if (new_cap.mem.bgn != new_cap.mem.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.mem.bgn >= new_cap.mem.end) + return ERR_INVALID_DERIVATION; + if (cap.mem.tag != new_cap.mem.tag) + return ERR_INVALID_DERIVATION; + if (new_cap.mem.bgn < cap.mem.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.mem.end >= cap.mem.end) + return ERR_INVALID_DERIVATION; + if ((new_cap.mem.rwx & cap.mem.rwx) != new_cap.mem.rwx) + return ERR_INVALID_DERIVATION; + if (cap.mem.lck) + return ERR_INVALID_DERIVATION; + cap.mem.mrk = new_cap.mem.bgn; + cte_set_cap(src, cap); + cte_insert(dst, new_cap, src); + return SUCCESS; + } + if (new_cap.type == CAPTY_PMP) { + uint64_t pmp_begin, pmp_end; + pmp_napot_decode(new_cap.pmp.addr, &pmp_begin, &pmp_end); + pmp_end += pmp_begin; + uint64_t mem_mrk, mem_end; + mem_mrk = tag_block_to_addr(cap.mem.tag, cap.mem.mrk); + mem_end = tag_block_to_addr(cap.mem.tag, cap.mem.end); + if (new_cap.pmp.used && new_cap.pmp.slot) + return ERR_INVALID_DERIVATION; + if (pmp_begin < mem_mrk) + return ERR_INVALID_DERIVATION; + if (pmp_end >= mem_end) + return ERR_INVALID_DERIVATION; + if ((new_cap.pmp.rwx & cap.mem.rwx) != new_cap.pmp.rwx) + return ERR_INVALID_DERIVATION; + cap.mem.lck = true; + cte_set_cap(src, cap); + cte_insert(dst, new_cap, src); + return SUCCESS; + } + return ERR_INVALID_DERIVATION; +} + +err_t cap_ipc_move_pmp(cte_t src, cap_t cap, cte_t dst) +{ + if (cap.pmp.used) { + proc_t *proc = proc_get(cte_pid(src)); + proc_pmp_unload(proc, cap.pmp.slot); + cap.pmp.used = 0; + cap.pmp.slot = 0; + cte_set_cap(src, cap); + } + cte_move(src, dst); + return SUCCESS; +} + +err_t cap_delete_pmp(cte_t c, cap_t cap) +{ + proc_t *proc = proc_get(cte_pid(c)); + if (cap.pmp.used) + proc_pmp_unload(proc, cap.pmp.slot); + cte_delete(c); + return SUCCESS; +} + +err_t cap_revoke_pmp(cte_t parent, cap_t pcap) +{ + return SUCCESS; +} + +err_t cap_derive_pmp(cte_t src, cap_t cap, cte_t dst, cap_t new_cap) +{ + return ERR_INVALID_DERIVATION; +} + +err_t cap_ipc_move_monitor(cte_t src, cap_t cap, cte_t dst) +{ + cte_move(src, dst); + return SUCCESS; +} + +err_t cap_delete_monitor(cte_t c, cap_t cap) +{ + cte_delete(c); + return SUCCESS; +} + +err_t cap_revoke_monitor(cte_t parent, cap_t pcap) { + cte_t child = cte_next(parent); + cap_t ccap = cte_cap(child); if (ccap.type == CAPTY_MONITOR && pcap.mon.bgn <= ccap.mon.bgn) { // delete the child cte_delete(child); @@ -169,8 +371,40 @@ err_t cap_revoke_monitor(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) return SUCCESS; } -err_t cap_revoke_channel(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) +err_t cap_derive_monitor(cte_t src, cap_t cap, cte_t dst, cap_t new_cap) +{ + if (new_cap.type != CAPTY_MONITOR) + return ERR_INVALID_DERIVATION; + if (new_cap.mon.bgn != new_cap.mon.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.mon.bgn >= new_cap.mon.end) + return ERR_INVALID_DERIVATION; + if (new_cap.mon.bgn < cap.mon.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.mon.end >= cap.mon.end) + return ERR_INVALID_DERIVATION; + cap.mon.mrk = cap.mon.bgn; + cte_set_cap(src, cap); + cte_insert(dst, new_cap, src); + return SUCCESS; +} + +err_t cap_ipc_move_channel(cte_t src, cap_t cap, cte_t dst) +{ + cte_move(src, dst); + return SUCCESS; +} + +err_t cap_delete_channel(cte_t c, cap_t cap) +{ + cte_delete(c); + return SUCCESS; +} + +err_t cap_revoke_channel(cte_t parent, cap_t pcap) { + cte_t child = cte_next(parent); + cap_t ccap = cte_cap(child); if (ccap.type == CAPTY_CHANNEL && pcap.chan.bgn <= ccap.chan.bgn) { // delete the child cte_delete(child); @@ -198,8 +432,56 @@ err_t cap_revoke_channel(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) return SUCCESS; } -err_t cap_revoke_socket(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) +err_t cap_derive_channel(cte_t src, cap_t cap, cte_t dst, cap_t new_cap) +{ + if (new_cap.type == CAPTY_CHANNEL) { + if (new_cap.chan.bgn != new_cap.chan.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.chan.bgn >= new_cap.chan.end) + return ERR_INVALID_DERIVATION; + if (new_cap.chan.bgn < cap.chan.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.chan.end >= cap.chan.end) + return ERR_INVALID_DERIVATION; + cap.chan.mrk = cap.chan.bgn; + cte_set_cap(src, cap); + cte_insert(dst, new_cap, src); + return SUCCESS; + } + + if (new_cap.type == CAPTY_SOCKET) { + if (new_cap.sock.chan < cap.chan.mrk) + return ERR_INVALID_DERIVATION; + if (new_cap.sock.chan >= cap.chan.end) + return ERR_INVALID_DERIVATION; + cap.chan.mrk = cap.sock.chan; + cte_set_cap(src, cap); + cte_insert(dst, new_cap, src); + return SUCCESS; + } + return ERR_INVALID_DERIVATION; +} + +err_t cap_ipc_move_socket(cte_t src, cap_t cap, cte_t dst) +{ + proc_t *proc = proc_get(cte_pid(src)); + cap_sock_clear(cap, proc); + cte_move(src, dst); + return SUCCESS; +} + +err_t cap_delete_socket(cte_t c, cap_t cap) +{ + proc_t *proc = proc_get(cte_pid(c)); + cap_sock_clear(cap, proc); + cte_delete(c); + return SUCCESS; +} + +err_t cap_revoke_socket(cte_t parent, cap_t pcap) { + cte_t child = cte_next(parent); + cap_t ccap = cte_cap(child); if (ccap.type == CAPTY_SOCKET && pcap.sock.tag == 0 && pcap.sock.chan == ccap.sock.chan) { return ERR_INVALID_CAPABILITY; @@ -216,78 +498,18 @@ err_t cap_revoke_socket(cte_t parent, cap_t pcap, cte_t child, cap_t ccap) return SUCCESS; } -err_t cap_revoke(cte_t parent) -{ - cte_t child = cte_next(parent); - cap_t pcap = cte_cap(parent); - cap_t ccap = cte_cap(child); - switch (pcap.type) { - case CAPTY_NONE: - return ERR_EMPTY; - case CAPTY_TIME: - return cap_revoke_time(parent, pcap, child, ccap); - case CAPTY_MEMORY: - return cap_revoke_memory(parent, pcap, child, ccap); - case CAPTY_PMP: - return SUCCESS; - case CAPTY_MONITOR: - return cap_revoke_monitor(parent, pcap, child, ccap); - case CAPTY_CHANNEL: - return cap_revoke_channel(parent, pcap, child, ccap); - case CAPTY_SOCKET: - return cap_revoke_socket(parent, pcap, child, ccap); - default: - KASSERT(0); - } -} - -static void derive(cte_t src, cap_t scap, cte_t dst, cap_t ncap) -{ - // Update the original capability - switch (ncap.type) { - case CAPTY_TIME: { - uint64_t pid = cte_pid(dst); - uint64_t end = ncap.time.end; - uint64_t hartid = ncap.time.hart; - uint64_t from = ncap.time.mrk; - uint64_t to = ncap.time.end; - sched_update(pid, end, hartid, from, to); - scap.time.mrk = ncap.time.end; - } break; - case CAPTY_MEMORY: - scap.mem.mrk = ncap.mem.end; - break; - case CAPTY_PMP: - scap.mem.lck = true; - break; - case CAPTY_MONITOR: - scap.mon.mrk = ncap.mon.end; - break; - case CAPTY_CHANNEL: - scap.chan.mrk = ncap.chan.end; - break; - case CAPTY_SOCKET: - if (ncap.sock.tag == 0) - scap.chan.mrk = ncap.sock.chan + 1; - break; - case CAPTY_NONE: - KASSERT(0); - } - cte_insert(dst, ncap, src); - cte_set_cap(src, scap); -} - -err_t cap_derive(cte_t src, cte_t dst, cap_t ncap) +err_t cap_derive_socket(cte_t src, cap_t cap, cte_t dst, cap_t new_cap) { - if (!cte_cap(src).type) - return ERR_SRC_EMPTY; - - if (cte_cap(dst).type) - return ERR_DST_OCCUPIED; - - cap_t scap = cte_cap(src); - if (!cap_is_derivable(scap, ncap)) + if (new_cap.type != CAPTY_SOCKET) + return ERR_INVALID_DERIVATION; + if (new_cap.sock.chan != cap.sock.chan) + return ERR_INVALID_DERIVATION; + if (new_cap.sock.perm != cap.sock.perm) + return ERR_INVALID_DERIVATION; + if (new_cap.sock.mode != cap.sock.mode) + return ERR_INVALID_DERIVATION; + if (new_cap.sock.tag == 0) return ERR_INVALID_DERIVATION; - derive(src, scap, dst, ncap); + cte_insert(dst, new_cap, src); return SUCCESS; } diff --git a/kernel/src/cap_table.c b/kernel/src/cap_table.c index 35889644..ee49f46a 100644 --- a/kernel/src/cap_table.c +++ b/kernel/src/cap_table.c @@ -85,8 +85,8 @@ void cte_move(cte_t src, cte_t dst) { if (src == dst) return; - dst->cap.raw = src->cap.raw; - src->cap.raw = 0; + cte_set_cap(dst, cte_cap(src)); + cte_set_cap(src, (cap_t){0}); cte_set_prev(dst, cte_prev(src)); cte_set_next(dst, cte_next(src)); cte_prev(dst)->next = offset(dst); diff --git a/kernel/src/cap_util.c b/kernel/src/cap_util.c index 7e7f6fb3..d8618559 100644 --- a/kernel/src/cap_util.c +++ b/kernel/src/cap_util.c @@ -127,107 +127,3 @@ void cap_snprint(char *restrict buf, size_t size, cap_t cap) alt_snprintf(buf, size, "UNKNOWN{raw=0x%X}", cap.raw); } } - -static inline bool is_range_subset(uint64_t a_bgn, uint64_t a_end, - uint64_t b_bgn, uint64_t b_end) -{ - return a_bgn <= b_bgn && b_end <= a_end; -} - -static inline bool is_range_prefix(uint64_t a_bgn, uint64_t a_end, - uint64_t b_bgn, uint64_t b_end) -{ - return a_bgn == b_bgn && b_end <= a_end; -} - -static inline bool is_bit_subset(uint64_t a, uint64_t b) -{ - return (a & b) == a; -} - -bool cap_is_valid(cap_t c) -{ - switch (c.type) { - case CAPTY_TIME: - return (c.time.bgn == c.time.mrk) && (c.time.bgn < c.time.end); - case CAPTY_MEMORY: - return (c.mem.bgn == c.mem.mrk) && (c.mem.bgn < c.mem.end); - case CAPTY_PMP: - return (c.pmp.used == 0) && (c.pmp.slot == 0); - case CAPTY_MONITOR: - return (c.mon.bgn == c.mon.mrk) && (c.mon.bgn < c.mon.end); - case CAPTY_CHANNEL: - return (c.chan.bgn == c.chan.mrk) && (c.chan.bgn < c.chan.end); - case CAPTY_SOCKET: - return is_bit_subset(c.sock.perm, IPC_SDATA | IPC_CDATA - | IPC_SCAP | IPC_CCAP) - && is_bit_subset(c.sock.mode, IPC_YIELD | IPC_NOYIELD); - default: - return false; - } -} - -static bool cap_time_derivable(cap_t p, cap_t c) -{ - return (c.type == CAPTY_TIME) && (p.time.hart == c.time.hart) - && is_range_prefix(p.time.mrk, p.time.end, c.time.bgn, - c.time.end); -} - -static bool cap_mem_derivable(cap_t p, cap_t c) -{ - if (c.type == CAPTY_PMP) { - uint64_t p_mrk, p_end, c_base, c_size; - p_mrk = tag_block_to_addr(p.mem.tag, p.mem.mrk); - p_end = tag_block_to_addr(p.mem.tag, p.mem.end); - pmp_napot_decode(c.pmp.addr, &c_base, &c_size); - return is_range_subset(p_mrk, p_end, c_base, c_base + c_size) - && is_bit_subset(c.pmp.rwx, p.mem.rwx); - } - return (c.type == CAPTY_MEMORY) && (p.mem.tag == c.mem.tag) - && is_range_subset(p.mem.mrk, p.mem.end, c.mem.bgn, c.mem.end) - && is_bit_subset(c.mem.rwx, p.mem.rwx); -} - -static bool cap_mon_derivable(cap_t p, cap_t c) -{ - return (c.type == CAPTY_MONITOR) - && is_range_subset(p.mon.mrk, p.mon.end, c.mon.bgn, c.mon.end); -} - -static bool cap_chan_derivable(cap_t p, cap_t c) -{ - if (c.type == CAPTY_SOCKET) { - return (c.sock.tag == 0) - && is_range_subset(p.chan.mrk, p.chan.end, c.sock.chan, - c.sock.chan + 1); - } - return (c.type == CAPTY_CHANNEL) - && is_range_subset(p.chan.mrk, p.chan.end, c.chan.bgn, - c.chan.end); -} - -static bool cap_sock_derivable(cap_t p, cap_t c) -{ - return (c.type == CAPTY_SOCKET) && (p.sock.chan == c.sock.chan) - && (p.sock.tag == 0) && (c.sock.tag != 0) - && (p.sock.mode == c.sock.mode) && (p.sock.perm == c.sock.perm); -} - -bool cap_is_derivable(cap_t p, cap_t c) -{ - switch (p.type) { - case CAPTY_TIME: - return cap_time_derivable(p, c); - case CAPTY_MEMORY: - return cap_mem_derivable(p, c); - case CAPTY_MONITOR: - return cap_mon_derivable(p, c); - case CAPTY_CHANNEL: - return cap_chan_derivable(p, c); - case CAPTY_SOCKET: - return cap_sock_derivable(p, c); - default: - return false; - } -}