Nothing to see here, move along
1use crate::cap::cnode;
2use crate::cap::object::ObjectTag;
3use crate::cap::ops;
4use crate::cap::pool::POOL;
5use crate::cap::table::Rights;
6use crate::error::KernelError;
7use crate::proc::PROCESSES;
8use crate::proc::context::CpuContext;
9use crate::syscall::{SyscallResult, try_syscall};
10
11pub fn sys_cap_derive(ctx: &mut CpuContext) {
12 let src_addr = ctx.rdi;
13 let dest_addr = ctx.rsi;
14 let rights_raw = try_syscall!(ctx, super::u16_from_reg(ctx.rdx));
15 let rights_mask = Rights::from_bits(rights_raw);
16 let pid = crate::arch::syscall::current_pid();
17
18 let ptable = PROCESSES.lock();
19 let (cnode_id, cnode_gen, depth) = try_syscall!(ctx, cnode::cnode_coords(pid, &ptable));
20
21 let mut pool = POOL.lock_after(&ptable);
22
23 ctx.rax =
24 match ops::derive_via_cnode(&mut pool, cnode_id, cnode_gen, src_addr, dest_addr, depth, rights_mask) {
25 Ok(()) => SyscallResult::ok().raw(),
26 Err(e) => SyscallResult::error(e).raw(),
27 };
28}
29
30pub fn sys_cap_revoke(ctx: &mut CpuContext) {
31 let address = ctx.rdi;
32 let pid = crate::arch::syscall::current_pid();
33
34 let mut ptable = PROCESSES.lock();
35 if ptable.get(pid).is_none() {
36 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw();
37 return;
38 }
39
40 ctx.rax = match ops::revoke_via_cnode(pid, address, &mut ptable) {
41 Ok(()) => SyscallResult::ok().raw(),
42 Err(e) => SyscallResult::error(e).raw(),
43 };
44}
45
46pub fn sys_cap_identify(ctx: &mut CpuContext) {
47 let address = ctx.rdi;
48 let pid = crate::arch::syscall::current_pid();
49
50 let ptable = PROCESSES.lock();
51 let (cnode_id, cnode_gen, depth) = try_syscall!(ctx, cnode::cnode_coords(pid, &ptable));
52 let pool = POOL.lock_after(&ptable);
53
54 match ops::identify_via_cnode(&pool, cnode_id, cnode_gen, address, depth) {
55 Ok((tag, rights)) => {
56 ctx.rdx = rights.bits() as u64;
57 ctx.rax = tag as u8 as u64;
58 }
59 Err(e) => ctx.rax = SyscallResult::error(e).raw(),
60 }
61}
62
63pub fn sys_cap_grant(ctx: &mut CpuContext) {
64 let src_addr = ctx.rdi;
65 let proc_cap_addr = ctx.rsi;
66 let dest_addr = ctx.rdx;
67 let rights_mask = match super::u16_from_reg(ctx.r10) {
68 Ok(v) => Rights::from_bits(v),
69 Err(e) => {
70 ctx.rax = SyscallResult::error(e).raw();
71 return;
72 }
73 };
74 let pid = crate::arch::syscall::current_pid();
75
76 let ptable = PROCESSES.lock();
77
78 let (child_pid, cap_to_grant) = {
79 let pool = POOL.lock_after(&ptable);
80
81 let proc_cap = try_syscall!(
82 ctx,
83 cnode::resolve_caller_validate(
84 pid,
85 proc_cap_addr,
86 ObjectTag::Process,
87 Rights::WRITE,
88 &ptable,
89 &pool,
90 )
91 );
92
93 let child_pid = try_syscall!(ctx, ops::resolve_process_cap(&proc_cap, &pool));
94
95 let src_cap = try_syscall!(
96 ctx,
97 cnode::resolve_caller_read(pid, src_addr, &ptable, &pool)
98 );
99
100 if !src_cap.rights().contains(Rights::GRANT) {
101 ctx.rax = SyscallResult::error(KernelError::InsufficientRights).raw();
102 return;
103 }
104 let granted = src_cap.with_rights(src_cap.rights() & rights_mask);
105 (child_pid, granted)
106 };
107
108 if ptable.get(child_pid).is_none() {
109 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw();
110 return;
111 }
112
113 let mut pool = POOL.lock_after(&ptable);
114 if let Err(e) = pool.inc_ref(cap_to_grant.object_id(), cap_to_grant.generation()) {
115 ctx.rax = SyscallResult::error(e).raw();
116 return;
117 }
118
119 ctx.rax = match cnode::resolve_caller_insert(child_pid, dest_addr, cap_to_grant, &ptable, &pool) {
120 Ok(()) => SyscallResult::ok().raw(),
121 Err(e) => {
122 pool.dec_ref(cap_to_grant.object_id(), cap_to_grant.generation());
123 SyscallResult::error(e).raw()
124 }
125 };
126}