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, gv, gb) = try_syscall!(ctx, cnode::cnode_coords(pid, &ptable));
20
21 let mut pool = POOL.lock_after(&ptable);
22
23 ctx.rax = match ops::derive_via_cnode(
24 &mut pool,
25 cnode_id,
26 cnode_gen,
27 src_addr,
28 dest_addr,
29 depth,
30 gv,
31 gb,
32 rights_mask,
33 ) {
34 Ok(()) => SyscallResult::ok().raw(),
35 Err(e) => SyscallResult::error(e).raw(),
36 };
37}
38
39pub fn sys_cap_revoke(ctx: &mut CpuContext) {
40 let address = ctx.rdi;
41 let pid = crate::arch::syscall::current_pid();
42
43 let mut ptable = PROCESSES.lock();
44 if ptable.get(pid).is_none() {
45 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw();
46 return;
47 }
48
49 ctx.rax = match ops::revoke_via_cnode(pid, address, &mut ptable) {
50 Ok(()) => SyscallResult::ok().raw(),
51 Err(e) => SyscallResult::error(e).raw(),
52 };
53}
54
55pub fn sys_cap_identify(ctx: &mut CpuContext) {
56 let address = ctx.rdi;
57 let pid = crate::arch::syscall::current_pid();
58
59 let ptable = PROCESSES.lock();
60 let (cnode_id, cnode_gen, depth, gv, gb) = try_syscall!(ctx, cnode::cnode_coords(pid, &ptable));
61 let pool = POOL.lock_after(&ptable);
62
63 match ops::identify_via_cnode(&pool, cnode_id, cnode_gen, address, depth, gv, gb) {
64 Ok((tag, rights)) => {
65 ctx.rdx = rights.bits() as u64;
66 ctx.rax = tag as u8 as u64;
67 }
68 Err(e) => ctx.rax = SyscallResult::error(e).raw(),
69 }
70}
71
72pub fn sys_cap_grant(ctx: &mut CpuContext) {
73 let src_addr = ctx.rdi;
74 let proc_cap_addr = ctx.rsi;
75 let dest_addr = ctx.rdx;
76 let rights_mask = match super::u16_from_reg(ctx.r10) {
77 Ok(v) => Rights::from_bits(v),
78 Err(e) => {
79 ctx.rax = SyscallResult::error(e).raw();
80 return;
81 }
82 };
83 let pid = crate::arch::syscall::current_pid();
84
85 let ptable = PROCESSES.lock();
86
87 let (child_pid, cap_to_grant) = {
88 let pool = POOL.lock_after(&ptable);
89
90 let proc_cap = try_syscall!(
91 ctx,
92 cnode::resolve_caller_validate(
93 pid,
94 proc_cap_addr,
95 ObjectTag::Process,
96 Rights::WRITE,
97 &ptable,
98 &pool,
99 )
100 );
101
102 let child_pid = try_syscall!(ctx, ops::resolve_process_cap(&proc_cap, &pool));
103
104 let src_cap = try_syscall!(
105 ctx,
106 cnode::resolve_caller_read(pid, src_addr, &ptable, &pool)
107 );
108
109 if !src_cap.rights().contains(Rights::GRANT) {
110 ctx.rax = SyscallResult::error(KernelError::InsufficientRights).raw();
111 return;
112 }
113 let granted = src_cap.with_rights(src_cap.rights() & rights_mask);
114 (child_pid, granted)
115 };
116
117 if ptable.get(child_pid).is_none() {
118 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw();
119 return;
120 }
121
122 let mut pool = POOL.lock_after(&ptable);
123 if let Err(e) = pool.inc_ref(cap_to_grant.phys(), cap_to_grant.generation()) {
124 ctx.rax = SyscallResult::error(e).raw();
125 return;
126 }
127
128 ctx.rax = match cnode::resolve_caller_insert(child_pid, dest_addr, cap_to_grant, &ptable, &pool)
129 {
130 Ok(()) => SyscallResult::ok().raw(),
131 Err(e) => {
132 pool.dec_ref_phys(cap_to_grant.phys(), cap_to_grant.generation());
133 SyscallResult::error(e).raw()
134 }
135 };
136}