From d0f30c132627bdd9d02c48adc76e9bd97688bd8f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 6 Feb 2021 20:39:14 +0100 Subject: runc: map upper user to regular UID instead of root --- src/runner/runc.rs | 24 ++++++++++++++++++++++-- src/unshare.rs | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 52 insertions(+), 13 deletions(-) (limited to 'src') 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); -fn runner(init_error_sender: ipc::IpcSender, channel: ipc::IpcReceiver) -> ! { +fn runner( + idmap_finished: ipc::IpcReceiver<()>, + init_error_sender: ipc::IpcSender, + channel: ipc::IpcReceiver, +) -> ! { 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, 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 { 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) -> Vec { +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, +) -> Vec { 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) -> Vec fn get_uid_map() -> Result> { 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> { 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) -> Result<()> { -- cgit v1.2.3