Add use-media-dir config option and implement feature.

If enabled this will mount /run/media/citadel directory into Realm as
~/Media directory. This makes mounted storage devices visible inside of
Realms. By default this option is enabled only for the main realm.
This commit is contained in:
Bruce Leidl 2021-12-14 06:04:02 -05:00
parent 841ee6016b
commit 12eed4d557
7 changed files with 79 additions and 0 deletions

44
Cargo.lock generated
View File

@ -2,6 +2,15 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "acl-sys"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbc079f9bdd3124fd18df23c67f7e0f79d24751ae151dcffd095fcade07a3eb2"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "addr2line" name = "addr2line"
version = "0.15.2" version = "0.15.2"
@ -336,6 +345,7 @@ dependencies = [
"rpassword", "rpassword",
"serde", "serde",
"serde_derive", "serde_derive",
"tempfile",
"toml 0.5.8", "toml 0.5.8",
] ]
@ -1092,6 +1102,7 @@ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",
"nix 0.17.0", "nix 0.17.0",
"posix-acl",
"serde", "serde",
"serde_derive", "serde_derive",
"sodiumoxide", "sodiumoxide",
@ -1395,6 +1406,16 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "posix-acl"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ea5dae99e4365fa738533b43f4c649c0450ba7fbb81a984a4fba6a42ce91812"
dependencies = [
"acl-sys",
"libc",
]
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.10" version = "0.2.10"
@ -1645,6 +1666,15 @@ version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "rpassword" name = "rpassword"
version = "4.0.5" version = "4.0.5"
@ -1961,6 +1991,20 @@ dependencies = [
"version-compare 0.0.11", "version-compare 0.0.11",
] ]
[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if 1.0.0",
"libc",
"rand 0.8.4",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]] [[package]]
name = "termion" name = "termion"
version = "1.5.6" version = "1.5.6"

View File

@ -18,3 +18,4 @@ hex = "0.4"
byteorder = "1" byteorder = "1"
dbus = "0.8.4" dbus = "0.8.4"
pwhash = "0.3.1" pwhash = "0.3.1"
tempfile = "3"

View File

@ -49,6 +49,7 @@ extra-bindmounts-ro = [ '/usr/share/apt-cacher-ng' ]
const MAIN_CONFIG: &str = "\ const MAIN_CONFIG: &str = "\
terminal-scheme = '$SCHEME' terminal-scheme = '$SCHEME'
use-media-dir = true
"; ";
const MAIN_TERMINAL_SCHEME: &str = "embers"; const MAIN_TERMINAL_SCHEME: &str = "embers";

View File

@ -17,6 +17,7 @@ byteorder = "1"
bincode = "1.2" bincode = "1.2"
walkdir = "2" walkdir = "2"
dbus = "0.6" dbus = "0.6"
posix-acl = "1.0.0"
[dependencies.inotify] [dependencies.inotify]
version = "0.8" version = "0.8"

View File

@ -50,6 +50,9 @@ pub struct RealmConfig {
#[serde(rename="use-shared-dir")] #[serde(rename="use-shared-dir")]
pub use_shared_dir: Option<bool>, pub use_shared_dir: Option<bool>,
#[serde(rename="use-media-dir")]
pub use_media_dir: Option<bool>,
#[serde(rename="use-ephemeral-home")] #[serde(rename="use-ephemeral-home")]
pub use_ephemeral_home: Option<bool>, pub use_ephemeral_home: Option<bool>,
@ -187,6 +190,7 @@ impl RealmConfig {
pub fn default() -> Self { pub fn default() -> Self {
RealmConfig { RealmConfig {
use_shared_dir: Some(true), use_shared_dir: Some(true),
use_media_dir: Some(false),
use_ephemeral_home: Some(false), use_ephemeral_home: Some(false),
use_sound: Some(true), use_sound: Some(true),
use_x11: Some(true), use_x11: Some(true),
@ -217,6 +221,7 @@ impl RealmConfig {
pub fn empty() -> Self { pub fn empty() -> Self {
RealmConfig { RealmConfig {
use_shared_dir: None, use_shared_dir: None,
use_media_dir: None,
use_ephemeral_home: None, use_ephemeral_home: None,
use_sound: None, use_sound: None,
use_x11: None, use_x11: None,
@ -272,6 +277,12 @@ impl RealmConfig {
self.bool_value(|c| c.use_shared_dir) self.bool_value(|c| c.use_shared_dir)
} }
/// If `true` the mount directory for external storage devices will be bind mounted as /Media
///
pub fn media_dir(&self) -> bool {
self.bool_value(|c| c.use_media_dir)
}
/// If `true` the home directory of this realm will be set up in ephemeral mode. /// If `true` the home directory of this realm will be set up in ephemeral mode.
/// ///
/// The ephemeral home directory is set up with the following steps: /// The ephemeral home directory is set up with the following steps:

View File

@ -127,6 +127,10 @@ impl <'a> RealmLauncher <'a> {
writeln!(s, "Bind=/realms/Shared:/home/user/Shared")?; writeln!(s, "Bind=/realms/Shared:/home/user/Shared")?;
} }
if config.media_dir() && Path::new("/run/media/citadel").exists() {
writeln!(s, "Bind=/run/media/citadel:/home/user/Media")?;
}
for dev in &self.devices { for dev in &self.devices {
writeln!(s, "Bind={}", dev)?; writeln!(s, "Bind={}", dev)?;
} }

View File

@ -1,6 +1,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use posix_acl::{ACL_EXECUTE, ACL_READ, PosixACL, Qualifier};
use crate::{Mountpoint, Result, Realms, RealmFS, Realm, util}; use crate::{Mountpoint, Result, Realms, RealmFS, Realm, util};
use crate::realmfs::realmfs_set::RealmFSSet; use crate::realmfs::realmfs_set::RealmFSSet;
@ -197,6 +198,18 @@ impl RealmManager {
Ok(()) Ok(())
} }
fn ensure_run_media_directory(&self) -> Result<()> {
let dir = Path::new("/run/media/citadel");
if !dir.exists() {
util::create_dir(dir)?;
let mut acl = PosixACL::new(0o750);
acl.set(Qualifier::User(1000), ACL_READ|ACL_EXECUTE);
acl.write_acl(dir)
.map_err(context!("Failed writinf ACL to {}", dir.display()))?;
}
Ok(())
}
fn _start_realm(&self, realm: &Realm, starting: &mut HashSet<String>) -> Result<()> { fn _start_realm(&self, realm: &Realm, starting: &mut HashSet<String>) -> Result<()> {
self.start_realm_dependencies(realm, starting)?; self.start_realm_dependencies(realm, starting)?;
@ -212,6 +225,10 @@ impl RealmManager {
realm.update_timestamp()?; realm.update_timestamp()?;
if realm.config().media_dir() {
self.ensure_run_media_directory()?;
}
self.systemd.start_realm(realm, &rootfs)?; self.systemd.start_realm(realm, &rootfs)?;
self.create_realm_namefile(realm)?; self.create_realm_namefile(realm)?;