summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-02-06 20:39:14 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-02-06 20:39:14 +0100
commitd0f30c132627bdd9d02c48adc76e9bd97688bd8f (patch)
tree6d777d94d68f27d94fbc6c63a7f1a9c30e31a016
parente78e29eae4a0cf2e3f46c6a117e1fe86219efe96 (diff)
downloadrebel-d0f30c132627bdd9d02c48adc76e9bd97688bd8f.tar
rebel-d0f30c132627bdd9d02c48adc76e9bd97688bd8f.zip
runc: map upper user to regular UID instead of root
-rw-r--r--src/runner/runc.rs24
-rw-r--r--src/unshare.rs41
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<()> {