mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-12-29 19:41:39 +03:00
sqlite: overhaul, fix caps vuln
This commit is contained in:
parent
58f3892bae
commit
7626f8eb34
84
Cargo.lock
generated
84
Cargo.lock
generated
@ -94,7 +94,7 @@ name = "alias"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -1275,7 +1275,7 @@ dependencies = [
|
||||
"alloy-sol-types 0.8.15",
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
@ -1858,7 +1858,7 @@ name = "cat"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -1922,7 +1922,7 @@ dependencies = [
|
||||
"alloy-sol-types 0.8.15",
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
@ -1941,7 +1941,7 @@ version = "0.2.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"pleco",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -2139,7 +2139,7 @@ checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||
name = "contacts"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -2735,7 +2735,7 @@ name = "download"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -2747,7 +2747,7 @@ name = "downloads"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
@ -2784,7 +2784,7 @@ dependencies = [
|
||||
name = "echo"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"wit-bindgen 0.36.0",
|
||||
]
|
||||
|
||||
@ -3052,7 +3052,7 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
@ -3206,7 +3206,7 @@ dependencies = [
|
||||
name = "get_block"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -3402,7 +3402,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
name = "help"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"wit-bindgen 0.36.0",
|
||||
]
|
||||
|
||||
@ -3431,7 +3431,7 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
|
||||
name = "hi"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -3464,7 +3464,7 @@ version = "0.1.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -3907,7 +3907,7 @@ name = "install"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -4085,7 +4085,7 @@ name = "kfetch"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -4097,7 +4097,7 @@ name = "kill"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -4191,29 +4191,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "kinode_process_lib"
|
||||
version = "0.10.0"
|
||||
source = "git+https://github.com/kinode-dao/process_lib?rev=d97e012#d97e012842dd4cc0e036d5de5048064e770302ab"
|
||||
dependencies = [
|
||||
"alloy 0.8.1",
|
||||
"alloy-primitives 0.8.15",
|
||||
"alloy-sol-macro 0.8.15",
|
||||
"alloy-sol-types 0.8.15",
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http 1.2.0",
|
||||
"mime_guess",
|
||||
"rand 0.8.5",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 1.0.69",
|
||||
"url",
|
||||
"wit-bindgen 0.36.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kinode_process_lib"
|
||||
version = "0.10.0"
|
||||
source = "git+https://github.com/kinode-dao/process_lib?rev=ea8490a#ea8490aba4837d04243d84b4f5b76fbefb498007"
|
||||
source = "git+https://github.com/kinode-dao/process_lib?rev=ef78f0e#ef78f0eb18d00826874258131a1bf471e55796f0"
|
||||
dependencies = [
|
||||
"alloy 0.8.1",
|
||||
"alloy-primitives 0.8.15",
|
||||
@ -4278,7 +4256,7 @@ dependencies = [
|
||||
"alloy-sol-types 0.8.15",
|
||||
"anyhow",
|
||||
"hex",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
@ -4515,7 +4493,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -4684,7 +4662,7 @@ dependencies = [
|
||||
name = "net-diagnostics"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -4727,7 +4705,7 @@ dependencies = [
|
||||
name = "node_info"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -5054,7 +5032,7 @@ dependencies = [
|
||||
name = "peer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -5064,7 +5042,7 @@ dependencies = [
|
||||
name = "peers"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -5721,7 +5699,7 @@ dependencies = [
|
||||
name = "reset"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -6191,7 +6169,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
"bincode",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -6412,7 +6390,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
name = "state"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=d97e012)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -6625,7 +6603,7 @@ version = "0.1.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
"serde",
|
||||
@ -6639,7 +6617,7 @@ version = "0.1.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -6930,7 +6908,7 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wit-bindgen 0.36.0",
|
||||
@ -7297,7 +7275,7 @@ name = "uninstall"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kinode_process_lib 0.10.0 (git+https://github.com/kinode-dao/process_lib?rev=ea8490a)",
|
||||
"kinode_process_lib 0.10.0",
|
||||
"process_macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -4,8 +4,9 @@ use dashmap::DashMap;
|
||||
use lib::types::core::{
|
||||
Address, CapMessage, CapMessageSender, Capability, FdManagerRequest, KernelMessage,
|
||||
LazyLoadBlob, Message, MessageReceiver, MessageSender, PackageId, PrintSender, Printout,
|
||||
ProcessId, Request, Response, SqlValue, SqliteAction, SqliteError, SqliteRequest,
|
||||
SqliteResponse, FD_MANAGER_PROCESS_ID, SQLITE_PROCESS_ID,
|
||||
ProcessId, Request, Response, SqlValue, SqliteAction, SqliteCapabilityKind,
|
||||
SqliteCapabilityParams, SqliteError, SqliteRequest, SqliteResponse, FD_MANAGER_PROCESS_ID,
|
||||
SQLITE_PROCESS_ID,
|
||||
};
|
||||
use rusqlite::Connection;
|
||||
use std::{
|
||||
@ -54,51 +55,46 @@ impl SqliteState {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn open_db(&mut self, package_id: PackageId, db: String) -> Result<(), SqliteError> {
|
||||
let key = (package_id.clone(), db.clone());
|
||||
if self.open_dbs.contains_key(&key) {
|
||||
pub async fn open_db(&mut self, key: &(PackageId, String)) -> Result<(), SqliteError> {
|
||||
if self.open_dbs.contains_key(key) {
|
||||
let mut access_order = self.access_order.lock().await;
|
||||
access_order.remove(&key);
|
||||
access_order.push_back(key);
|
||||
access_order.remove(key);
|
||||
access_order.push_back(key.clone());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if self.open_dbs.len() as u64 >= self.fds_limit {
|
||||
// close least recently used db
|
||||
let key = self.access_order.lock().await.pop_front().unwrap();
|
||||
self.remove_db(key.0, key.1).await;
|
||||
let to_close = self.access_order.lock().await.pop_front().unwrap();
|
||||
self.remove_db(&to_close).await;
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
let db_path = self.sqlite_path.join(format!("{package_id}")).join(&db);
|
||||
let db_path = self.sqlite_path.join(format!("{}", key.0)).join(&key.1);
|
||||
#[cfg(target_os = "windows")]
|
||||
let db_path = self
|
||||
.sqlite_path
|
||||
.join(format!(
|
||||
"{}_{}",
|
||||
package_id._package(),
|
||||
package_id._publisher()
|
||||
))
|
||||
.join(&db);
|
||||
.join(format!("{}_{}", key.0._package(), key.0._publisher()))
|
||||
.join(&key.1);
|
||||
|
||||
fs::create_dir_all(&db_path).await?;
|
||||
|
||||
let db_file_path = db_path.join(format!("{}.db", db));
|
||||
let db_file_path = db_path.join(format!("{}.db", key.1));
|
||||
|
||||
let db_conn = Connection::open(db_file_path)?;
|
||||
let _: String = db_conn.query_row("PRAGMA journal_mode=WAL", [], |row| row.get(0))?;
|
||||
|
||||
self.open_dbs.insert(key, Mutex::new(db_conn));
|
||||
self.open_dbs.insert(key.clone(), Mutex::new(db_conn));
|
||||
|
||||
let mut access_order = self.access_order.lock().await;
|
||||
access_order.push_back((package_id, db));
|
||||
access_order.push_back(key.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove_db(&mut self, package_id: PackageId, db: String) {
|
||||
self.open_dbs.remove(&(package_id.clone(), db.to_string()));
|
||||
pub async fn remove_db(&mut self, key: &(PackageId, String)) {
|
||||
self.open_dbs.remove(key);
|
||||
let mut access_order = self.access_order.lock().await;
|
||||
access_order.remove(&(package_id, db));
|
||||
access_order.remove(key);
|
||||
}
|
||||
|
||||
pub async fn remove_least_recently_used_dbs(&mut self, n: u64) {
|
||||
@ -106,7 +102,7 @@ impl SqliteState {
|
||||
let mut lock = self.access_order.lock().await;
|
||||
let key = lock.pop_front().unwrap();
|
||||
drop(lock);
|
||||
self.remove_db(key.0, key.1).await;
|
||||
self.remove_db(&key).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,8 +172,7 @@ pub async fn sqlite(
|
||||
tokio::spawn(async move {
|
||||
let mut queue_lock = queue.lock().await;
|
||||
if let Some(km) = queue_lock.pop_front() {
|
||||
let (km_id, km_rsvp) =
|
||||
(km.id.clone(), km.rsvp.clone().unwrap_or(km.source.clone()));
|
||||
let (km_id, km_rsvp) = (km.id, km.rsvp.clone().unwrap_or(km.source.clone()));
|
||||
|
||||
if let Err(e) = handle_request(km, &mut state, &send_to_caps_oracle).await {
|
||||
Printout::new(1, SQLITE_PROCESS_ID.clone(), format!("sqlite: {e}"))
|
||||
@ -226,27 +221,31 @@ async fn handle_request(
|
||||
..
|
||||
}) = message
|
||||
else {
|
||||
return Err(SqliteError::InputError {
|
||||
error: "not a request".into(),
|
||||
});
|
||||
// we got a response -- safe to ignore
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let request: SqliteRequest = match serde_json::from_slice(&body) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
println!("sqlite: got invalid Request: {}", e);
|
||||
return Err(SqliteError::InputError {
|
||||
error: "didn't serialize to SqliteRequest.".into(),
|
||||
});
|
||||
println!("sqlite: got invalid request: {e}");
|
||||
return Err(SqliteError::MalformedRequest);
|
||||
}
|
||||
};
|
||||
|
||||
check_caps(&source, state, send_to_caps_oracle, &request).await?;
|
||||
let db_key = (request.package_id, request.db);
|
||||
|
||||
check_caps(
|
||||
&source,
|
||||
state,
|
||||
send_to_caps_oracle,
|
||||
&request.action,
|
||||
&db_key,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// always open to ensure db exists
|
||||
state
|
||||
.open_db(request.package_id.clone(), request.db.clone())
|
||||
.await?;
|
||||
state.open_db(&db_key).await?;
|
||||
|
||||
let (body, bytes) = match request.action {
|
||||
SqliteAction::Open => {
|
||||
@ -257,11 +256,11 @@ async fn handle_request(
|
||||
// handled in check_caps
|
||||
(serde_json::to_vec(&SqliteResponse::Ok).unwrap(), None)
|
||||
}
|
||||
SqliteAction::Read { query } => {
|
||||
let db = match state.open_dbs.get(&(request.package_id, request.db)) {
|
||||
SqliteAction::Query(query) => {
|
||||
let db = match state.open_dbs.get(&db_key) {
|
||||
Some(db) => db,
|
||||
None => {
|
||||
return Err(SqliteError::NoDb);
|
||||
return Err(SqliteError::NoDb(db_key.0, db_key.1));
|
||||
}
|
||||
};
|
||||
let db = db.lock().await;
|
||||
@ -314,10 +313,10 @@ async fn handle_request(
|
||||
)
|
||||
}
|
||||
SqliteAction::Write { statement, tx_id } => {
|
||||
let db = match state.open_dbs.get(&(request.package_id, request.db)) {
|
||||
let db = match state.open_dbs.get(&db_key) {
|
||||
Some(db) => db,
|
||||
None => {
|
||||
return Err(SqliteError::NoDb);
|
||||
return Err(SqliteError::NoDb(db_key.0, db_key.1));
|
||||
}
|
||||
};
|
||||
let db = db.lock().await;
|
||||
@ -359,17 +358,17 @@ async fn handle_request(
|
||||
)
|
||||
}
|
||||
SqliteAction::Commit { tx_id } => {
|
||||
let db = match state.open_dbs.get(&(request.package_id, request.db)) {
|
||||
let db = match state.open_dbs.get(&db_key) {
|
||||
Some(db) => db,
|
||||
None => {
|
||||
return Err(SqliteError::NoDb);
|
||||
return Err(SqliteError::NoDb(db_key.0, db_key.1));
|
||||
}
|
||||
};
|
||||
let mut db = db.lock().await;
|
||||
|
||||
let txs = match state.txs.remove(&tx_id).map(|(_, tx)| tx) {
|
||||
None => {
|
||||
return Err(SqliteError::NoTx);
|
||||
return Err(SqliteError::NoTx(tx_id));
|
||||
}
|
||||
Some(tx) => tx,
|
||||
};
|
||||
@ -389,9 +388,7 @@ async fn handle_request(
|
||||
.query_row("PRAGMA wal_checkpoint(TRUNCATE)", [], |_| Ok(()))
|
||||
.map(|_| ());
|
||||
if let Err(e) = result {
|
||||
return Err(SqliteError::RusqliteError {
|
||||
error: e.to_string(),
|
||||
});
|
||||
return Err(SqliteError::RusqliteError(e.to_string()));
|
||||
}
|
||||
}
|
||||
(serde_json::to_vec(&SqliteResponse::Ok).unwrap(), None)
|
||||
@ -429,119 +426,105 @@ async fn check_caps(
|
||||
source: &Address,
|
||||
state: &mut SqliteState,
|
||||
send_to_caps_oracle: &CapMessageSender,
|
||||
request: &SqliteRequest,
|
||||
action: &SqliteAction,
|
||||
db_key: &(PackageId, String),
|
||||
) -> Result<(), SqliteError> {
|
||||
let (send_cap_bool, recv_cap_bool) = tokio::sync::oneshot::channel();
|
||||
let src_package_id = PackageId::new(source.process.package(), source.process.publisher());
|
||||
|
||||
match &request.action {
|
||||
match action {
|
||||
SqliteAction::Write { .. } | SqliteAction::BeginTx | SqliteAction::Commit { .. } => {
|
||||
send_to_caps_oracle
|
||||
let Ok(()) = send_to_caps_oracle
|
||||
.send(CapMessage::Has {
|
||||
on: source.process.clone(),
|
||||
cap: Capability::new(
|
||||
state.our.as_ref().clone(),
|
||||
serde_json::json!({
|
||||
"kind": "write",
|
||||
"db": request.db.to_string(),
|
||||
serde_json::to_string(&SqliteCapabilityParams {
|
||||
kind: SqliteCapabilityKind::Write,
|
||||
db_key: db_key.clone(),
|
||||
})
|
||||
.to_string(),
|
||||
.unwrap(),
|
||||
),
|
||||
responder: send_cap_bool,
|
||||
})
|
||||
.await?;
|
||||
let has_cap = recv_cap_bool.await?;
|
||||
if !has_cap {
|
||||
return Err(SqliteError::NoCap {
|
||||
error: request.action.to_string(),
|
||||
});
|
||||
}
|
||||
.await
|
||||
else {
|
||||
return Err(SqliteError::AddCapFailed);
|
||||
};
|
||||
let Ok(_) = recv_cap_bool.await else {
|
||||
return Err(SqliteError::AddCapFailed);
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
SqliteAction::Read { .. } => {
|
||||
send_to_caps_oracle
|
||||
SqliteAction::Query { .. } => {
|
||||
let Ok(()) = send_to_caps_oracle
|
||||
.send(CapMessage::Has {
|
||||
on: source.process.clone(),
|
||||
cap: Capability::new(
|
||||
state.our.as_ref().clone(),
|
||||
serde_json::json!({
|
||||
"kind": "read",
|
||||
"db": request.db.to_string(),
|
||||
serde_json::to_string(&SqliteCapabilityParams {
|
||||
kind: SqliteCapabilityKind::Read,
|
||||
db_key: db_key.clone(),
|
||||
})
|
||||
.to_string(),
|
||||
.unwrap(),
|
||||
),
|
||||
responder: send_cap_bool,
|
||||
})
|
||||
.await?;
|
||||
let has_cap = recv_cap_bool.await?;
|
||||
if !has_cap {
|
||||
return Err(SqliteError::NoCap {
|
||||
error: request.action.to_string(),
|
||||
});
|
||||
}
|
||||
.await
|
||||
else {
|
||||
return Err(SqliteError::AddCapFailed);
|
||||
};
|
||||
let Ok(_) = recv_cap_bool.await else {
|
||||
return Err(SqliteError::AddCapFailed);
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
SqliteAction::Open => {
|
||||
if src_package_id != request.package_id {
|
||||
return Err(SqliteError::NoCap {
|
||||
error: request.action.to_string(),
|
||||
});
|
||||
if src_package_id != db_key.0 {
|
||||
return Err(SqliteError::MismatchingPackageId);
|
||||
}
|
||||
|
||||
add_capability(
|
||||
"read",
|
||||
&request.db.to_string(),
|
||||
SqliteCapabilityKind::Read,
|
||||
db_key,
|
||||
&state.our,
|
||||
&source,
|
||||
send_to_caps_oracle,
|
||||
)
|
||||
.await?;
|
||||
add_capability(
|
||||
"write",
|
||||
&request.db.to_string(),
|
||||
SqliteCapabilityKind::Write,
|
||||
db_key,
|
||||
&state.our,
|
||||
&source,
|
||||
send_to_caps_oracle,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if state
|
||||
.open_dbs
|
||||
.contains_key(&(request.package_id.clone(), request.db.clone()))
|
||||
{
|
||||
if state.open_dbs.contains_key(db_key) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
state
|
||||
.open_db(request.package_id.clone(), request.db.clone())
|
||||
.await?;
|
||||
state.open_db(db_key).await?;
|
||||
Ok(())
|
||||
}
|
||||
SqliteAction::RemoveDb => {
|
||||
if src_package_id != request.package_id {
|
||||
return Err(SqliteError::NoCap {
|
||||
error: request.action.to_string(),
|
||||
});
|
||||
if src_package_id != db_key.0 {
|
||||
return Err(SqliteError::MismatchingPackageId);
|
||||
}
|
||||
|
||||
state
|
||||
.remove_db(request.package_id.clone(), request.db.clone())
|
||||
.await;
|
||||
state.remove_db(db_key).await;
|
||||
|
||||
#[cfg(unix)]
|
||||
let db_path = state
|
||||
.sqlite_path
|
||||
.join(format!("{}", request.package_id))
|
||||
.join(&request.db);
|
||||
.join(format!("{}", db_key.0))
|
||||
.join(&db_key.1);
|
||||
#[cfg(target_os = "windows")]
|
||||
let db_path = state
|
||||
.sqlite_path
|
||||
.join(format!(
|
||||
"{}_{}",
|
||||
request.package_id._package(),
|
||||
request.package_id._publisher()
|
||||
))
|
||||
.join(&request.db);
|
||||
.join(format!("{}_{}", db_key.0._package(), db_key.0._publisher()))
|
||||
.join(&db_key.1);
|
||||
|
||||
fs::remove_dir_all(&db_path).await?;
|
||||
|
||||
@ -559,9 +542,7 @@ async fn handle_fd_request(km: KernelMessage, state: &mut SqliteState) -> anyhow
|
||||
return Err(anyhow::anyhow!("not a request"));
|
||||
};
|
||||
|
||||
let request: FdManagerRequest = serde_json::from_slice(&body)?;
|
||||
|
||||
match request {
|
||||
match serde_json::from_slice(&body)? {
|
||||
FdManagerRequest::FdsLimit(new_fds_limit) => {
|
||||
state.fds_limit = new_fds_limit;
|
||||
if state.open_dbs.len() as u64 >= state.fds_limit {
|
||||
@ -581,25 +562,34 @@ async fn handle_fd_request(km: KernelMessage, state: &mut SqliteState) -> anyhow
|
||||
}
|
||||
|
||||
async fn add_capability(
|
||||
kind: &str,
|
||||
db: &str,
|
||||
kind: SqliteCapabilityKind,
|
||||
db_key: &(PackageId, String),
|
||||
our: &Address,
|
||||
source: &Address,
|
||||
send_to_caps_oracle: &CapMessageSender,
|
||||
) -> Result<(), SqliteError> {
|
||||
let cap = Capability {
|
||||
issuer: our.clone(),
|
||||
params: serde_json::json!({ "kind": kind, "db": db }).to_string(),
|
||||
params: serde_json::to_string(&SqliteCapabilityParams {
|
||||
kind,
|
||||
db_key: db_key.clone(),
|
||||
})
|
||||
.unwrap(),
|
||||
};
|
||||
let (send_cap_bool, recv_cap_bool) = tokio::sync::oneshot::channel();
|
||||
send_to_caps_oracle
|
||||
let Ok(()) = send_to_caps_oracle
|
||||
.send(CapMessage::Add {
|
||||
on: source.process.clone(),
|
||||
caps: vec![cap],
|
||||
responder: Some(send_cap_bool),
|
||||
})
|
||||
.await?;
|
||||
let _ = recv_cap_bool.await?;
|
||||
.await
|
||||
else {
|
||||
return Err(SqliteError::AddCapFailed);
|
||||
};
|
||||
let Ok(_) = recv_cap_bool.await else {
|
||||
return Err(SqliteError::AddCapFailed);
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
use crate::types::core::{CapMessage, PackageId};
|
||||
use crate::types::core::PackageId;
|
||||
use rusqlite::types::{FromSql, FromSqlError, ToSql, ValueRef};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
/// IPC Request format for the sqlite:distro:sys runtime module.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct SqliteRequest {
|
||||
pub package_id: PackageId,
|
||||
pub db: String,
|
||||
pub action: SqliteAction,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum SqliteAction {
|
||||
Open,
|
||||
RemoveDb,
|
||||
@ -19,9 +19,7 @@ pub enum SqliteAction {
|
||||
statement: String,
|
||||
tx_id: Option<u64>,
|
||||
},
|
||||
Read {
|
||||
query: String,
|
||||
},
|
||||
Query(String),
|
||||
BeginTx,
|
||||
Commit {
|
||||
tx_id: u64,
|
||||
@ -29,7 +27,7 @@ pub enum SqliteAction {
|
||||
Backup,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum SqliteResponse {
|
||||
Ok,
|
||||
Read,
|
||||
@ -37,7 +35,7 @@ pub enum SqliteResponse {
|
||||
Err(SqliteError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum SqlValue {
|
||||
Integer(i64),
|
||||
Real(f64),
|
||||
@ -47,28 +45,45 @@ pub enum SqlValue {
|
||||
Null,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Error)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Error)]
|
||||
pub enum SqliteError {
|
||||
#[error("sqlite: DbDoesNotExist")]
|
||||
NoDb,
|
||||
#[error("sqlite: NoTx")]
|
||||
NoTx,
|
||||
#[error("sqlite: No capability: {error}")]
|
||||
NoCap { error: String },
|
||||
#[error("sqlite: UnexpectedResponse")]
|
||||
UnexpectedResponse,
|
||||
#[error("sqlite: NotAWriteKeyword")]
|
||||
#[error("db [{0}, {1}] does not exist")]
|
||||
NoDb(PackageId, String),
|
||||
#[error("no transaction {0} found")]
|
||||
NoTx(u64),
|
||||
#[error("no write capability for requested DB")]
|
||||
NoWriteCap,
|
||||
#[error("no read capability for requested DB")]
|
||||
NoReadCap,
|
||||
#[error("request to open or remove DB with mismatching package ID")]
|
||||
MismatchingPackageId,
|
||||
#[error("failed to generate capability for new DB")]
|
||||
AddCapFailed,
|
||||
#[error("write statement started with non-existent write keyword")]
|
||||
NotAWriteKeyword,
|
||||
#[error("sqlite: NotAReadKeyword")]
|
||||
#[error("read query started with non-existent read keyword")]
|
||||
NotAReadKeyword,
|
||||
#[error("sqlite: Invalid Parameters")]
|
||||
#[error("parameters blob in read/write was misshapen or contained invalid JSON objects")]
|
||||
InvalidParameters,
|
||||
#[error("sqlite: IO error: {error}")]
|
||||
IOError { error: String },
|
||||
#[error("sqlite: rusqlite error: {error}")]
|
||||
RusqliteError { error: String },
|
||||
#[error("sqlite: input bytes/json/key error: {error}")]
|
||||
InputError { error: String },
|
||||
#[error("sqlite got a malformed request that failed to deserialize")]
|
||||
MalformedRequest,
|
||||
#[error("rusqlite error: {0}")]
|
||||
RusqliteError(String),
|
||||
#[error("IO error: {0}")]
|
||||
IOError(String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct SqliteCapabilityParams {
|
||||
pub kind: SqliteCapabilityKind,
|
||||
pub db_key: (PackageId, String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SqliteCapabilityKind {
|
||||
Read,
|
||||
Write,
|
||||
}
|
||||
|
||||
impl ToSql for SqlValue {
|
||||
@ -109,32 +124,12 @@ impl std::fmt::Display for SqliteAction {
|
||||
|
||||
impl From<std::io::Error> for SqliteError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
SqliteError::IOError {
|
||||
error: err.to_string(),
|
||||
}
|
||||
SqliteError::IOError(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<rusqlite::Error> for SqliteError {
|
||||
fn from(err: rusqlite::Error) -> Self {
|
||||
SqliteError::RusqliteError {
|
||||
error: err.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tokio::sync::oneshot::error::RecvError> for SqliteError {
|
||||
fn from(err: tokio::sync::oneshot::error::RecvError) -> Self {
|
||||
SqliteError::NoCap {
|
||||
error: err.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tokio::sync::mpsc::error::SendError<CapMessage>> for SqliteError {
|
||||
fn from(err: tokio::sync::mpsc::error::SendError<CapMessage>) -> Self {
|
||||
SqliteError::NoCap {
|
||||
error: err.to_string(),
|
||||
}
|
||||
SqliteError::RusqliteError(err.to_string())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user