diff --git a/libcitadel/src/realm/manager.rs b/libcitadel/src/realm/manager.rs index 3805935..84053a3 100644 --- a/libcitadel/src/realm/manager.rs +++ b/libcitadel/src/realm/manager.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::{Mountpoint, Activation,Result, Realms, RealmFS, Realm, util}; @@ -330,6 +330,28 @@ impl RealmManager { self.inner().realms.by_name(name) } + pub fn realm_by_pid(&self, pid: u32) -> Option { + match Self::read_realm_name_by_pid(pid) { + Ok(name) => self.realm_by_name(name.as_str()), + Err(_) => None, + } + } + + fn read_realm_name_by_pid(pid: u32) -> Result { + let run = PathBuf::from(format!("/proc/{}/root/run", pid)); + let realm_name = run.join("realm-name"); + + // ensure that /proc/pid/root/run and /proc/pid/root/run/realm-name + // are not symlinks + let run_meta = run.symlink_metadata()?; + let name_meta = realm_name.symlink_metadata()?; + if !run_meta.file_type().is_dir() || !name_meta.file_type().is_file() { + bail!("invalid path"); + } + let bytes = fs::read(realm_name)?; + Ok(String::from_utf8(bytes)?) + } + pub fn rescan_realms(&self) -> Result<(Vec,Vec)> { self.inner_mut().realms.rescan_realms() } diff --git a/realmsd/src/dbus.rs b/realmsd/src/dbus.rs index 386f505..640a6d5 100644 --- a/realmsd/src/dbus.rs +++ b/realmsd/src/dbus.rs @@ -62,6 +62,10 @@ impl DbusServer { .in_arg(("name", "s")) .in_arg(("args", "as"))) + .add_m(f.method("RealmFromCitadelPid", (), Self::do_pid_to_realm) + .in_arg(("pid", "u")) + .out_arg(("realm", "s"))) + // Signals .add_s(f.signal("RealmStarted", ()) .arg(("realm", "s"))) @@ -168,6 +172,18 @@ impl DbusServer { Ok(vec![m.msg.method_return()]) } + fn do_pid_to_realm(m: &MethodInfo) -> MethodResult { + let pid = m.msg.read1::()?; + let manager = m.tree.get_data().manager(); + let ret = m.msg.method_return(); + let msg = match manager.realm_by_pid(pid) { + Some(realm) => ret.append(realm.name()), + None => ret.append(""), + }; + Ok(vec![msg]) + } + + pub fn start(&self) -> Result<()> { let tree = self.build_tree(); self.connection.register_name(BUS_NAME, NameFlag::ReplaceExisting as u32)?; @@ -219,6 +235,7 @@ impl DbusServer { let member = dbus::Member::new(name).unwrap(); Message::signal(&path, &iface, &member) } + } /// Wraps a connection instance and only expose the send() method.