Skip to content

Commit 4fe7205

Browse files
committed
feature: allow users to specify a config without a mount namespace
1 parent 50f8087 commit 4fe7205

1 file changed

Lines changed: 94 additions & 83 deletions

File tree

src/wrap.rs

Lines changed: 94 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,95 @@ impl CreateRequest {
224224

225225
Ok(())
226226
}
227+
228+
fn pivot_fs(&self) -> Result<()> {
229+
debug!("early mount!");
230+
231+
let rootfs = self
232+
.rootfs
233+
.clone()
234+
.expect("expected rootfs to be configured");
235+
236+
// Unshare rootfs mount so we can later pivot to a new rootfs.
237+
// The unshared root mount will be cleaned up once the new rootfs is
238+
// in place.
239+
let oldroot = MountSpec {
240+
source: None,
241+
target: "/".to_string(),
242+
fstype: None,
243+
bind: false,
244+
recurse: true,
245+
unshare: true,
246+
safe: false,
247+
create_mountpoint: false,
248+
};
249+
250+
oldroot
251+
.mount()
252+
.expect("failed to unshare / in new mount namespace");
253+
254+
// Now mount the new rootfs.
255+
let newroot = MountSpec {
256+
source: Some(rootfs.clone()),
257+
target: rootfs.clone(),
258+
fstype: Some("none".to_string()),
259+
bind: true,
260+
recurse: true,
261+
unshare: false,
262+
safe: false,
263+
create_mountpoint: false,
264+
};
265+
266+
newroot.mount().expect("failed to bind new rootfs");
267+
268+
// Mount /proc.
269+
let procfs = MountSpec {
270+
source: Some("proc".to_string()),
271+
target: format!("{rootfs}/proc"),
272+
fstype: Some("proc".to_string()),
273+
bind: false,
274+
recurse: true,
275+
unshare: false,
276+
safe: true,
277+
create_mountpoint: false,
278+
};
279+
280+
procfs.mount().expect("failed to mount /proc");
281+
282+
if let Some(mounts) = &self.mounts {
283+
for mount in mounts {
284+
let parented_target = format!("{}/{}", rootfs, mount.target);
285+
let parented_mount = MountSpec {
286+
source: mount.source.clone(),
287+
target: parented_target.clone(),
288+
fstype: mount.fstype.clone(),
289+
bind: mount.bind,
290+
recurse: mount.recurse,
291+
unshare: mount.unshare,
292+
safe: mount.safe,
293+
create_mountpoint: mount.create_mountpoint,
294+
};
295+
296+
parented_mount
297+
.mount()
298+
.expect("failed to process mount spec");
299+
}
300+
}
301+
302+
if let Some(mutations) = &self.mutations {
303+
for mutation in mutations {
304+
match mutation {
305+
Mutation::CreateDir(cdm) => {
306+
cdm.mutate(&rootfs).expect("failed to create directory");
307+
}
308+
};
309+
}
310+
}
311+
312+
newroot.pivot().expect("failed to pivot to new rootfs");
313+
314+
Ok(())
315+
}
227316
}
228317

229318
impl Wrappable for CreateRequest {
@@ -312,91 +401,13 @@ impl Wrappable for CreateRequest {
312401
process::exit(exitcode);
313402
}
314403

315-
debug!("early mount!");
316-
317-
let rootfs = self
318-
.rootfs
319-
.clone()
320-
.expect("expected rootfs to be configured");
321-
322-
// Unshare rootfs mount so we can later pivot to a new rootfs.
323-
// The unshared root mount will be cleaned up once the new rootfs is
324-
// in place.
325-
let oldroot = MountSpec {
326-
source: None,
327-
target: "/".to_string(),
328-
fstype: None,
329-
bind: false,
330-
recurse: true,
331-
unshare: true,
332-
safe: false,
333-
create_mountpoint: false,
334-
};
335-
336-
oldroot
337-
.mount()
338-
.expect("failed to unshare / in new mount namespace");
339-
340-
// Now mount the new rootfs.
341-
let newroot = MountSpec {
342-
source: Some(rootfs.clone()),
343-
target: rootfs.clone(),
344-
fstype: Some("none".to_string()),
345-
bind: true,
346-
recurse: true,
347-
unshare: false,
348-
safe: false,
349-
create_mountpoint: false,
350-
};
351-
352-
newroot.mount().expect("failed to bind new rootfs");
353-
354-
// Mount /proc.
355-
let procfs = MountSpec {
356-
source: Some("proc".to_string()),
357-
target: format!("{rootfs}/proc"),
358-
fstype: Some("proc".to_string()),
359-
bind: false,
360-
recurse: true,
361-
unshare: false,
362-
safe: true,
363-
create_mountpoint: false,
364-
};
365-
366-
procfs.mount().expect("failed to mount /proc");
367-
368-
if let Some(mounts) = &self.mounts {
369-
for mount in mounts {
370-
let parented_target = format!("{}/{}", rootfs, mount.target);
371-
let parented_mount = MountSpec {
372-
source: mount.source.clone(),
373-
target: parented_target.clone(),
374-
fstype: mount.fstype.clone(),
375-
bind: mount.bind,
376-
recurse: mount.recurse,
377-
unshare: mount.unshare,
378-
safe: mount.safe,
379-
create_mountpoint: mount.create_mountpoint,
380-
};
381-
382-
parented_mount
383-
.mount()
384-
.expect("failed to process mount spec");
385-
}
386-
}
387-
388-
if let Some(mutations) = &self.mutations {
389-
for mutation in mutations {
390-
match mutation {
391-
Mutation::CreateDir(cdm) => {
392-
cdm.mutate(&rootfs).expect("failed to create directory");
393-
}
394-
};
395-
}
404+
if target_ns.contains(&Namespace::Mount) {
405+
self.pivot_fs()?;
406+
} else {
407+
warn!("mount namespace not present in requested namespaces, trying to work anyway...");
408+
warn!("this is an insecure configuration!");
396409
}
397410

398-
newroot.pivot().expect("failed to pivot to new rootfs");
399-
400411
debug!("mount tree finalized, doing final prep");
401412
let mut pef = unsafe { File::from_raw_fd(parent_efd) };
402413

0 commit comments

Comments
 (0)