1use crate::error::OciSpecError;
2use derive_builder::Builder;
3use getset::{CopyGetters, Getters, MutGetters, Setters};
4use serde::{Deserialize, Serialize};
5use std::path::PathBuf;
6
7#[derive(
8 Builder, Clone, CopyGetters, Debug, Deserialize, Eq, Getters, Setters, PartialEq, Serialize,
9)]
10#[builder(
11 default,
12 pattern = "owned",
13 setter(into, strip_option),
14 build_fn(error = "OciSpecError")
15)]
16pub struct Root {
19 #[serde(default)]
21 #[getset(get = "pub", set = "pub")]
22 path: PathBuf,
23
24 #[serde(default, skip_serializing_if = "Option::is_none")]
27 #[getset(get_copy = "pub", set = "pub")]
28 readonly: Option<bool>,
29}
30
31impl Default for Root {
34 fn default() -> Self {
35 Root {
36 path: PathBuf::from("rootfs"),
37 readonly: true.into(),
38 }
39 }
40}
41
42#[derive(
43 Builder,
44 Clone,
45 Debug,
46 Default,
47 Deserialize,
48 Eq,
49 Getters,
50 MutGetters,
51 Setters,
52 PartialEq,
53 Serialize,
54)]
55#[builder(
56 default,
57 pattern = "owned",
58 setter(into, strip_option),
59 build_fn(error = "OciSpecError")
60)]
61#[getset(get_mut = "pub", get = "pub", set = "pub")]
62pub struct Mount {
64 destination: PathBuf,
67
68 #[serde(default, skip_serializing_if = "Option::is_none", rename = "type")]
69 typ: Option<String>,
71
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 source: Option<PathBuf>,
75
76 #[serde(default, skip_serializing_if = "Option::is_none")]
77 options: Option<Vec<String>>,
79}
80
81pub fn get_default_mounts() -> Vec<Mount> {
83 vec![
84 Mount {
85 destination: PathBuf::from("/proc"),
86 typ: "proc".to_string().into(),
87 source: PathBuf::from("proc").into(),
88 options: None,
89 },
90 Mount {
91 destination: PathBuf::from("/dev"),
92 typ: "tmpfs".to_string().into(),
93 source: PathBuf::from("tmpfs").into(),
94 options: vec![
95 "nosuid".into(),
96 "strictatime".into(),
97 "mode=755".into(),
98 "size=65536k".into(),
99 ]
100 .into(),
101 },
102 Mount {
103 destination: PathBuf::from("/dev/pts"),
104 typ: "devpts".to_string().into(),
105 source: PathBuf::from("devpts").into(),
106 options: vec![
107 "nosuid".into(),
108 "noexec".into(),
109 "newinstance".into(),
110 "ptmxmode=0666".into(),
111 "mode=0620".into(),
112 "gid=5".into(),
113 ]
114 .into(),
115 },
116 Mount {
117 destination: PathBuf::from("/dev/shm"),
118 typ: "tmpfs".to_string().into(),
119 source: PathBuf::from("shm").into(),
120 options: vec![
121 "nosuid".into(),
122 "noexec".into(),
123 "nodev".into(),
124 "mode=1777".into(),
125 "size=65536k".into(),
126 ]
127 .into(),
128 },
129 Mount {
130 destination: PathBuf::from("/dev/mqueue"),
131 typ: "mqueue".to_string().into(),
132 source: PathBuf::from("mqueue").into(),
133 options: vec!["nosuid".into(), "noexec".into(), "nodev".into()].into(),
134 },
135 Mount {
136 destination: PathBuf::from("/sys"),
137 typ: "sysfs".to_string().into(),
138 source: PathBuf::from("sysfs").into(),
139 options: vec![
140 "nosuid".into(),
141 "noexec".into(),
142 "nodev".into(),
143 "ro".into(),
144 ]
145 .into(),
146 },
147 Mount {
148 destination: PathBuf::from("/sys/fs/cgroup"),
149 typ: "cgroup".to_string().into(),
150 source: PathBuf::from("cgroup").into(),
151 options: vec![
152 "nosuid".into(),
153 "noexec".into(),
154 "nodev".into(),
155 "relatime".into(),
156 "ro".into(),
157 ]
158 .into(),
159 },
160 ]
161}
162
163#[allow(clippy::manual_inspect)]
168pub fn get_rootless_mounts() -> Vec<Mount> {
169 let mut mounts = get_default_mounts();
170 mounts
171 .iter_mut()
172 .find(|m| m.destination.to_string_lossy() == "/dev/pts")
173 .map(|m| {
174 if let Some(opts) = &mut m.options {
175 opts.retain(|o| o != "gid=5")
176 }
177 m
178 });
179 mounts
180 .iter_mut()
181 .find(|m| m.destination.to_string_lossy() == "/sys")
182 .map(|m| {
183 m.typ = Some("none".to_string());
184 m.source = Some("/sys".into());
185 if let Some(o) = m.options.as_mut() {
186 o.push("rbind".to_string())
187 }
188 m
189 });
190 mounts
191}