mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-12-23 00:21:38 +03:00
caps revoked on process kill
This commit is contained in:
parent
f0c8c2308c
commit
4d97def768
@ -23,7 +23,6 @@ enum TerminalAction {
|
||||
alias: String,
|
||||
process: Option<ProcessId>,
|
||||
},
|
||||
ProcessEnded(Vec<(ProcessId, Capability)>),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -145,12 +144,6 @@ impl Guest for Component {
|
||||
Err(e) => println!("terminal: {e}"),
|
||||
};
|
||||
}
|
||||
TerminalAction::ProcessEnded(drop_caps) => {
|
||||
match handle_process_cleanup(drop_caps) {
|
||||
Ok(()) => continue,
|
||||
Err(e) => println!("terminal: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("terminal: ignoring message from: {}", source);
|
||||
@ -261,17 +254,7 @@ fn handle_run(
|
||||
id: parsed_new_process_id.clone(),
|
||||
wasm_bytes_handle: wasm_path.clone(),
|
||||
wit_version: None,
|
||||
on_exit: kt::OnExit::Requests(vec![(
|
||||
kt::de_wit_address(our.clone()),
|
||||
kt::Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
body: serde_json::to_vec(&TerminalAction::ProcessEnded(granted_caps))?,
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)]),
|
||||
on_exit: kt::OnExit::None,
|
||||
initial_capabilities: HashSet::new(),
|
||||
public: entry.public,
|
||||
})?)
|
||||
@ -318,7 +301,6 @@ fn handle_run(
|
||||
}
|
||||
}
|
||||
// always give it the cap to message the terminal back
|
||||
// NOTE a malicious script could use this to drop a ton of caps from other processes
|
||||
requested_caps.push(kt::de_wit_capability(Capability {
|
||||
issuer: our.clone(),
|
||||
params: "\"messaging\"".to_string(),
|
||||
@ -341,7 +323,7 @@ fn handle_run(
|
||||
parsed_new_process_id.clone(),
|
||||
wasm_path.clone(),
|
||||
"None",
|
||||
kt::OnExit::None, // TODO fix this
|
||||
kt::OnExit::None,
|
||||
entry.public,
|
||||
{
|
||||
let mut caps_string = "[".to_string();
|
||||
@ -426,20 +408,6 @@ fn handle_alias_change(
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_process_cleanup(caps_to_remove: Vec<(ProcessId, Capability)>) -> anyhow::Result<()> {
|
||||
for (process, cap) in caps_to_remove {
|
||||
println!("terminal: cleaning up process {}, {}", process, cap);
|
||||
Request::new()
|
||||
.target(("our", "kernel", "distro", "sys"))
|
||||
.body(serde_json::to_vec(&kt::KernelCommand::DropCapabilities {
|
||||
target: process,
|
||||
capabilities: vec![kt::de_wit_capability(cap)],
|
||||
})?)
|
||||
.send()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_entry(process: &ProcessId) -> anyhow::Result<kt::DotScriptsEntry> {
|
||||
let drive_path = format!("/{}:{}/pkg", process.package(), process.publisher());
|
||||
Request::new()
|
||||
|
@ -86,6 +86,7 @@ async fn handle_kernel_request(
|
||||
senders: &mut Senders,
|
||||
process_handles: &mut ProcessHandles,
|
||||
process_map: &mut t::ProcessMap,
|
||||
reverse_cap_index: &mut t::ReverseCapIndex,
|
||||
caps_oracle: t::CapMessageSender,
|
||||
engine: &Engine,
|
||||
) {
|
||||
@ -334,7 +335,16 @@ async fn handle_kernel_request(
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
entry.capabilities.extend(signed_caps);
|
||||
entry.capabilities.extend(signed_caps.clone());
|
||||
// add these to reverse cap index
|
||||
for (cap, _) in &signed_caps {
|
||||
reverse_cap_index
|
||||
.entry(cap.clone().issuer.process)
|
||||
.or_insert_with(HashMap::new)
|
||||
.entry(target.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(cap.clone());
|
||||
}
|
||||
let _ = persist_state(&our_name, &send_to_loop, process_map).await;
|
||||
}
|
||||
t::KernelCommand::DropCapabilities {
|
||||
@ -444,7 +454,14 @@ async fn handle_kernel_request(
|
||||
t::KernelCommand::KillProcess(process_id) => {
|
||||
// brutal and savage killing: aborting the task.
|
||||
// do not do this to a process if you don't want to risk
|
||||
// dropped messages / un-replied-to-requests
|
||||
// dropped messages / un-replied-to-requests / revoked caps
|
||||
caps_oracle
|
||||
.send(t::CapMessage::RevokeAll {
|
||||
on: process_id.clone(),
|
||||
responder: tokio::sync::oneshot::channel().0,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
let _ = senders.remove(&process_id);
|
||||
let process_handle = match process_handles.remove(&process_id) {
|
||||
Some(ph) => ph,
|
||||
@ -643,6 +660,7 @@ pub async fn kernel(
|
||||
our: t::Identity,
|
||||
keypair: Arc<signature::Ed25519KeyPair>,
|
||||
mut process_map: t::ProcessMap,
|
||||
mut reverse_cap_index: t::ReverseCapIndex,
|
||||
caps_oracle_sender: t::CapMessageSender,
|
||||
mut caps_oracle_receiver: t::CapMessageReceiver,
|
||||
send_to_loop: t::MessageSender,
|
||||
@ -1025,6 +1043,7 @@ pub async fn kernel(
|
||||
&mut senders,
|
||||
&mut process_handles,
|
||||
&mut process_map,
|
||||
&mut reverse_cap_index,
|
||||
caps_oracle_sender.clone(),
|
||||
&engine,
|
||||
).await;
|
||||
@ -1081,7 +1100,16 @@ pub async fn kernel(
|
||||
cap.clone(),
|
||||
keypair.sign(&rmp_serde::to_vec(&cap).unwrap()).as_ref().to_vec()
|
||||
)).collect();
|
||||
entry.capabilities.extend(signed_caps);
|
||||
entry.capabilities.extend(signed_caps.clone());
|
||||
// now we have to insert all caps into the reverse cap index
|
||||
for (cap, _) in &signed_caps {
|
||||
reverse_cap_index
|
||||
.entry(cap.clone().issuer.process)
|
||||
.or_insert_with(HashMap::new)
|
||||
.entry(on.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(cap.clone());
|
||||
}
|
||||
let _ = persist_state(&our.name, &send_to_loop, &process_map).await;
|
||||
let _ = responder.send(true);
|
||||
},
|
||||
@ -1115,6 +1143,21 @@ pub async fn kernel(
|
||||
}
|
||||
);
|
||||
},
|
||||
t::CapMessage::RevokeAll { on, responder } => {
|
||||
let Some(granter) = reverse_cap_index.get(&on) else {
|
||||
let _ = responder.send(true);
|
||||
continue;
|
||||
};
|
||||
for (grantee, caps) in granter {
|
||||
let Some(entry) = process_map.get_mut(&grantee) else {
|
||||
continue;
|
||||
};
|
||||
for cap in caps {
|
||||
entry.capabilities.remove(&cap);
|
||||
}
|
||||
}
|
||||
let _ = responder.send(true);
|
||||
}
|
||||
t::CapMessage::FilterCaps { on, caps, responder } => {
|
||||
let _ = responder.send(
|
||||
match process_map.get(&on) {
|
||||
|
@ -989,6 +989,11 @@ pub enum CapMessage {
|
||||
on: ProcessId,
|
||||
responder: tokio::sync::oneshot::Sender<Vec<(Capability, Vec<u8>)>>,
|
||||
},
|
||||
/// Remove all caps issued by `on` from every process on the entire system
|
||||
RevokeAll {
|
||||
on: ProcessId,
|
||||
responder: tokio::sync::oneshot::Sender<bool>,
|
||||
},
|
||||
/// before `on` sends a message, filter out any bogus caps it may have attached, sign any new
|
||||
/// caps it may have created, and retreive the signature for the caps in its store.
|
||||
FilterCaps {
|
||||
@ -998,6 +1003,8 @@ pub enum CapMessage {
|
||||
},
|
||||
}
|
||||
|
||||
pub type ReverseCapIndex = HashMap<ProcessId, HashMap<ProcessId, Vec<Capability>>>;
|
||||
|
||||
pub type ProcessMap = HashMap<ProcessId, PersistedProcess>;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
|
Loading…
Reference in New Issue
Block a user