Skip to content

Commit c6b8b21

Browse files
committed
Support containers launched with user namespace
1 parent 0af2316 commit c6b8b21

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

src/util/namespace.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use std::fs::File;
22
use std::os::fd::AsFd;
3+
use std::os::unix::fs::MetadataExt;
34

45
use anyhow::Result;
6+
use rustix::fs::{Gid, Uid};
57
use rustix::process::Pid;
6-
use rustix::thread::{LinkNameSpaceType, UnshareFlags};
8+
use rustix::thread::{CapabilitiesSecureBits, LinkNameSpaceType, UnshareFlags};
79

810
pub struct MntNamespace {
911
fd: File,
@@ -33,6 +35,35 @@ impl MntNamespace {
3335
self.fd.as_fd(),
3436
Some(LinkNameSpaceType::Mount),
3537
)?;
38+
39+
// If user namespace is used, we must act like the root user *inside*
40+
// namespace to be able to create files properly (otherwise EOVERFLOW
41+
// will be returned when creating file).
42+
//
43+
// Entering the user namespace turns out to be problematic.
44+
// The reason seems to be this line [1]:
45+
// which means `CAP_MKNOD` capability of the *init* namespace is needed.
46+
// However task's associated security context is all relative to its current
47+
// user namespace [2], so once you enter a user namespace there's no way of getting
48+
// back `CAP_MKNOD` of the init namespace anymore.
49+
// (Yes this means that even if CAP_MKNOD is granted to the container, you canot
50+
// create device nodes within it.)
51+
//
52+
// https://elixir.bootlin.com/linux/v6.11.1/source/fs/namei.c#L4073
53+
// https://elixir.bootlin.com/linux/v6.11.1/source/include/linux/cred.h#L111
54+
let metadata = std::fs::metadata("/")?;
55+
let uid = metadata.uid();
56+
let gid = metadata.gid();
57+
58+
// By default `setuid` will drop capabilities when transitioning from root
59+
// to non-root user. This bit prevents it so our code still have superpower.
60+
rustix::thread::set_capabilities_secure_bits(
61+
CapabilitiesSecureBits::NO_SETUID_FIXUP,
62+
)?;
63+
64+
rustix::thread::set_thread_uid(unsafe { Uid::from_raw(uid) })?;
65+
rustix::thread::set_thread_gid(unsafe { Gid::from_raw(gid) })?;
66+
3667
Ok(f())
3768
})
3869
.join()

0 commit comments

Comments
 (0)