proxy: move permissions drop outside tokio rt

This commit is contained in:
Robin Appelman 2025-12-03 02:10:01 +01:00
commit d48f61b4fa

View file

@ -13,6 +13,7 @@ use std::net::SocketAddr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{Child, Command}; use std::process::{Child, Command};
use std::thread::spawn; use std::thread::spawn;
use nix::errno::Errno;
use thiserror::Error; use thiserror::Error;
use tokio::runtime::Builder; use tokio::runtime::Builder;
use tokio::signal::ctrl_c; use tokio::signal::ctrl_c;
@ -135,6 +136,51 @@ pub fn proxy(
))?) ))?)
}; };
let rt = match Builder::new_current_thread().enable_io().build() {
Ok(rt) => rt,
Err(error) => {
error!(%error, "Error setting up tokio runtime");
return Err(error.into());
}
};
if let Some(listen_namespace) = listen_namespace
&& let Err(error) = setns(listen_namespace, CloneFlags::CLONE_NEWNET)
{
error!(%error, "Failed to join listen network namespace for proxy");
return Err(error.into());
}
let proxy = match Proxy::listen(&source) {
Ok(proxy) => proxy,
Err(error) => {
error!(%error, "Failed to listen to {source}");
return Err(error.into());
}
};
if let Err(error) = setns(target_namespace, CloneFlags::CLONE_NEWNET) {
error!(%error, "Failed to join target network namespace for proxy");
return Err(error.into());
}
if let Err(error) = drop_to_nobody() {
error!(%error, "Failed to drop privileges");
}
rt.block_on(async {
tokio::spawn(async move {
let _ = ctrl_c().await;
abort.abort();
});
proxy.run(target, abort_reg).await;
Ok(())
})
}
fn drop_to_nobody() -> Result<(), Errno> {
let nobody_uid = Uid::from( let nobody_uid = Uid::from(
get_user_by_name("nobody") get_user_by_name("nobody")
.map(|user| user.uid()) .map(|user| user.uid())
@ -146,46 +192,5 @@ pub fn proxy(
.unwrap_or(65534), .unwrap_or(65534),
); );
let rt = match Builder::new_current_thread().enable_io().build() { setgid(nobody_gid).and_then(|_| setuid(nobody_uid))
Ok(rt) => rt,
Err(error) => {
error!(%error, "Error setting up tokio runtime");
return Err(error.into());
}
};
rt.block_on(async {
if let Some(listen_namespace) = listen_namespace
&& let Err(error) = setns(listen_namespace, CloneFlags::CLONE_NEWNET)
{
error!(%error, "Failed to join listen network namespace for proxy");
return Err(error.into());
}
let proxy = match Proxy::listen(&source) {
Ok(proxy) => proxy,
Err(error) => {
error!(%error, "Failed to listen to {source}");
return Err(error.into());
}
};
if let Err(error) = setns(target_namespace, CloneFlags::CLONE_NEWNET) {
error!(%error, "Failed to join target network namespace for proxy");
return Err(error.into());
}
if let Err(error) = setgid(nobody_gid).and_then(|_| setuid(nobody_uid)) {
error!(%error, "Failed to drop privileges");
}
tokio::spawn(async move {
let _ = ctrl_c().await;
abort.abort();
});
proxy.run(target, abort_reg).await;
Ok(())
})
} }