feat: added mounts to sandboxing
This commit is contained in:
parent
2bc1a89f9f
commit
6d7080fbde
3 changed files with 108 additions and 6 deletions
|
@ -24,5 +24,5 @@ pub mod prelude {
|
|||
pub use super::gamescope::prelude::*;
|
||||
|
||||
#[cfg(feature = "sandbox")]
|
||||
pub use super::sandbox::Sandbox;
|
||||
pub use super::sandbox::*;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
mod mounts;
|
||||
|
||||
pub use mounts::Mounts;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Sandbox {
|
||||
/// Use `bwrap` to run the game. Default is `true`
|
||||
|
@ -9,8 +13,14 @@ pub struct Sandbox {
|
|||
/// Mount tmpfs to `/home`, `/var/home/$USER` and `$HOME`. Default is `true`
|
||||
pub isolate_home: bool,
|
||||
|
||||
/// Spoof original hostname. Default is `None`
|
||||
pub hostname: Option<String>,
|
||||
|
||||
/// List of paths to which tmpfs will be mounted. Default is empty
|
||||
pub private: Vec<String>
|
||||
pub private: Vec<String>,
|
||||
|
||||
/// Maps of directories mounts
|
||||
pub mounts: Mounts
|
||||
}
|
||||
|
||||
impl Default for Sandbox {
|
||||
|
@ -19,7 +29,9 @@ impl Default for Sandbox {
|
|||
Self {
|
||||
enabled: false,
|
||||
isolate_home: true,
|
||||
private: vec![]
|
||||
hostname: None,
|
||||
private: vec![],
|
||||
mounts: Mounts::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +51,20 @@ impl From<&JsonValue> for Sandbox {
|
|||
None => default.isolate_home
|
||||
},
|
||||
|
||||
hostname: match value.get("hostname") {
|
||||
Some(value) => {
|
||||
if value.is_null() {
|
||||
None
|
||||
} else {
|
||||
match value.as_str() {
|
||||
Some(value) => Some(value.to_string()),
|
||||
None => default.hostname
|
||||
}
|
||||
}
|
||||
},
|
||||
None => default.hostname
|
||||
},
|
||||
|
||||
private: match value.get("private") {
|
||||
Some(value) => match value.as_array() {
|
||||
Some(values) => {
|
||||
|
@ -55,6 +81,11 @@ impl From<&JsonValue> for Sandbox {
|
|||
None => default.private
|
||||
},
|
||||
None => default.private
|
||||
},
|
||||
|
||||
mounts: match value.get("mounts") {
|
||||
Some(value) => Mounts::from(value),
|
||||
None => default.mounts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,9 +106,15 @@ impl Sandbox {
|
|||
/// | `wine_dir` | `/tmp/sandbox/wine` | bind | false |
|
||||
/// | `prefix_dir` | `/tmp/sandbox/prefix` | bind | false |
|
||||
/// | `game_dir` | `/tmp/sandbox/game` | bind | false |
|
||||
/// | <mounts/read_only> | <mounts/read_only> | read-only bind | true |
|
||||
/// | <mounts/binds> | <mounts/binds> | bind | true |
|
||||
pub fn get_command(&self, wine_dir: impl AsRef<str>, prefix_dir: impl AsRef<str>, game_dir: impl AsRef<str>) -> String {
|
||||
let mut command = String::from("bwrap --ro-bind / /");
|
||||
|
||||
if let Some(hostname) = &self.hostname {
|
||||
command += &format!(" --hostname '{hostname}'");
|
||||
}
|
||||
|
||||
if self.isolate_home {
|
||||
command.push_str(" --tmpfs /home");
|
||||
command.push_str(" --tmpfs /var/home");
|
||||
|
@ -97,9 +134,17 @@ impl Sandbox {
|
|||
|
||||
command.push_str(" --tmpfs /tmp");
|
||||
|
||||
command.push_str(&format!(" --bind '{}' /tmp/sandbox/wine", wine_dir.as_ref()));
|
||||
command.push_str(&format!(" --bind '{}' /tmp/sandbox/prefix", prefix_dir.as_ref()));
|
||||
command.push_str(&format!(" --bind '{}' /tmp/sandbox/game", game_dir.as_ref()));
|
||||
for (from, to) in &self.mounts.read_only {
|
||||
command += &format!(" --ro-bind '{}' '{}'", from.trim(), to.trim());
|
||||
}
|
||||
|
||||
for (from, to) in &self.mounts.bind {
|
||||
command += &format!(" --bind '{}' '{}'", from.trim(), to.trim());
|
||||
}
|
||||
|
||||
command += &format!(" --bind '{}' /tmp/sandbox/wine", wine_dir.as_ref());
|
||||
command += &format!(" --bind '{}' /tmp/sandbox/prefix", prefix_dir.as_ref());
|
||||
command += &format!(" --bind '{}' /tmp/sandbox/game", game_dir.as_ref());
|
||||
|
||||
command.push_str(" --chdir /");
|
||||
command.push_str(" --die-with-parent");
|
57
src/config/schema_blanks/sandbox/mounts.rs
Normal file
57
src/config/schema_blanks/sandbox/mounts.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Mounts {
|
||||
/// Bind original directory into the sandbox in read-only state
|
||||
pub read_only: HashMap<String, String>,
|
||||
|
||||
/// Bind original directory into the sandbox with writing access
|
||||
pub bind: HashMap<String, String>
|
||||
}
|
||||
|
||||
impl From<&JsonValue> for Mounts {
|
||||
fn from(value: &JsonValue) -> Self {
|
||||
let default = Self::default();
|
||||
|
||||
Self {
|
||||
read_only: match value.get("read_only") {
|
||||
Some(value) => match value.as_object() {
|
||||
Some(values) => {
|
||||
let mut vars = HashMap::new();
|
||||
|
||||
for (name, value) in values {
|
||||
if let Some(value) = value.as_str() {
|
||||
vars.insert(name.clone(), value.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
vars
|
||||
},
|
||||
None => default.read_only
|
||||
},
|
||||
None => default.read_only
|
||||
},
|
||||
|
||||
bind: match value.get("bind") {
|
||||
Some(value) => match value.as_object() {
|
||||
Some(values) => {
|
||||
let mut vars = HashMap::new();
|
||||
|
||||
for (name, value) in values {
|
||||
if let Some(value) = value.as_str() {
|
||||
vars.insert(name.clone(), value.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
vars
|
||||
},
|
||||
None => default.bind
|
||||
},
|
||||
None => default.bind
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue