diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-02-06 20:39:14 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-02-06 20:39:14 +0100 |
commit | d0f30c132627bdd9d02c48adc76e9bd97688bd8f (patch) | |
tree | 6d777d94d68f27d94fbc6c63a7f1a9c30e31a016 /src | |
parent | e78e29eae4a0cf2e3f46c6a117e1fe86219efe96 (diff) | |
download | rebel-d0f30c132627bdd9d02c48adc76e9bd97688bd8f.tar rebel-d0f30c132627bdd9d02c48adc76e9bd97688bd8f.zip |
runc: map upper user to regular UID instead of root
Diffstat (limited to 'src')
-rw-r--r-- | src/runner/runc.rs | 24 | ||||
-rw-r--r-- | src/unshare.rs | 41 |
2 files changed, 52 insertions, 13 deletions
diff --git a/src/runner/runc.rs b/src/runner/runc.rs index 663dc7a..6a60eea 100644 --- a/src/runner/runc.rs +++ b/src/runner/runc.rs @@ -14,7 +14,11 @@ use crate::util::CheckDisconnect; #[derive(Debug, Deserialize, Serialize)] struct Request(TaskRef, Task, ipc::IpcSender<run::Error>); -fn runner(init_error_sender: ipc::IpcSender<init::Error>, channel: ipc::IpcReceiver<Request>) -> ! { +fn runner( + idmap_finished: ipc::IpcReceiver<()>, + init_error_sender: ipc::IpcSender<init::Error>, + channel: ipc::IpcReceiver<Request>, +) -> ! { if let Err(error) = init::runc_initialize() { init_error_sender.send(error).expect("IPC send() failed"); process::exit(1); @@ -22,6 +26,16 @@ fn runner(init_error_sender: ipc::IpcSender<init::Error>, channel: ipc::IpcRecei drop(init_error_sender); + idmap_finished + .recv() + .check_disconnect() + .expect("IPC recv() error") + .expect("Unexpected IPC message"); + + unistd::setuid(unistd::Uid::from_raw(0)).expect("setuid()"); + unistd::setgid(unistd::Gid::from_raw(0)).expect("setgid()"); + unistd::setgroups(&[]).expect("setgroups()"); + while let Ok(request) = channel.recv() { let Request(task, task_def, reply_sender) = request; if let Err(error) = run::handle_task(task, task_def) { @@ -42,18 +56,22 @@ impl RuncRunner { /// Unsafe: Do not call in multithreaded processes pub unsafe fn new() -> io::Result<Self> { let (tx, rx) = ipc::channel().expect("IPC channel creation failed"); + let (idmap_finished_tx, idmap_finished_rx) = + ipc::channel().expect("IPC channel creation failed"); let (init_error_tx, init_error_rx) = ipc::channel().expect("IPC channel creation failed"); let pid = match unistd::fork().expect("fork()") { unistd::ForkResult::Parent { child } => { drop(rx); + drop(idmap_finished_rx); drop(init_error_tx); child } unistd::ForkResult::Child => { drop(tx); + drop(idmap_finished_tx); drop(init_error_rx); - runner(init_error_tx, rx); + runner(idmap_finished_rx, init_error_tx, rx); /* Not reached */ } }; @@ -65,6 +83,8 @@ impl RuncRunner { unshare::idmap(pid)?; + drop(idmap_finished_tx); + Ok(RuncRunner { channel: tx }) } } diff --git a/src/unshare.rs b/src/unshare.rs index da16d24..98ebe90 100644 --- a/src/unshare.rs +++ b/src/unshare.rs @@ -60,25 +60,44 @@ struct SubIDMap { count: libc::uid_t, } -fn generate_idmap(id: libc::uid_t, mut ranges: Vec<SubIDRange>) -> Vec<SubIDMap> { +pub const BUILD_UID: libc::uid_t = 800; +pub const BUILD_GID: libc::uid_t = 800; + +fn generate_idmap( + id: libc::uid_t, + mapped_id: libc::uid_t, + mut ranges: Vec<SubIDRange>, +) -> Vec<SubIDMap> { let mut map = Vec::new(); map.push(SubIDMap { - lower: 0, + lower: mapped_id, upper: id, count: 1, }); - let mut lower = 1; + let mut add_map = |lower, upper, count| { + if count > 0 { + map.push(SubIDMap { + lower, + upper, + count, + }); + } + count + }; + + let mut lower = 0; ranges.sort(); for range in &ranges { - map.push(SubIDMap { - lower, - upper: range.start, - count: range.count, - }); - lower += range.count; + if mapped_id >= lower && mapped_id < lower + range.count { + let offset = mapped_id - lower; + lower += add_map(lower, range.start, offset) + 1; + lower += add_map(lower, range.start + offset, range.count - offset); + } else { + lower += add_map(lower, range.start, range.count); + } } map @@ -87,13 +106,13 @@ fn generate_idmap(id: libc::uid_t, mut ranges: Vec<SubIDRange>) -> Vec<SubIDMap> fn get_uid_map() -> Result<Vec<SubIDMap>> { let uid = users::get_effective_uid(); let uid_ranges = read_id_ranges(Path::new("/etc/subuid"))?; - Ok(generate_idmap(uid, uid_ranges)) + Ok(generate_idmap(uid, BUILD_UID, uid_ranges)) } fn get_gid_map() -> Result<Vec<SubIDMap>> { let gid = users::get_effective_gid(); let gid_ranges = read_id_ranges(Path::new("/etc/subgid"))?; - Ok(generate_idmap(gid, gid_ranges)) + Ok(generate_idmap(gid, BUILD_GID, gid_ranges)) } fn run_idmap_cmd(cmd: &str, pid: &str, map: &Vec<SubIDMap>) -> Result<()> { |