mirror of
https://github.com/joleuger/vuinputd.git
synced 2026-07-17 16:36:03 +00:00
Enter user namespace in the incus case
This commit is contained in:
parent
6eb5a2985a
commit
152ffd9711
6 changed files with 88 additions and 54 deletions
|
|
@ -83,8 +83,9 @@ impl InjectionStrategy for GenericPlacementInContainer {
|
|||
minor: minor,
|
||||
};
|
||||
|
||||
let child_pid = process_tools::start_action(mknod_device_action, &requesting_process)
|
||||
.expect("subprocess should work");
|
||||
let child_pid =
|
||||
process_tools::start_action(mknod_device_action, &requesting_process, false)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let _exit_info = process_tools::await_process(Pid::Pid(child_pid))
|
||||
.await
|
||||
|
|
@ -106,8 +107,9 @@ impl InjectionStrategy for GenericPlacementInContainer {
|
|||
minor: minor,
|
||||
};
|
||||
|
||||
let child_pid_1 = process_tools::start_action(remove_device_action, &requesting_process)
|
||||
.expect("subprocess should work");
|
||||
let child_pid_1 =
|
||||
process_tools::start_action(remove_device_action, &requesting_process, false)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let _exit_info = process_tools::await_process(Pid::Pid(child_pid_1)).await;
|
||||
Ok(())
|
||||
|
|
@ -126,8 +128,9 @@ impl InjectionStrategy for GenericPlacementInContainer {
|
|||
minor: minor,
|
||||
};
|
||||
|
||||
let child_pid = process_tools::start_action(write_udev_runtime_data, &requesting_process)
|
||||
.expect("subprocess should work");
|
||||
let child_pid =
|
||||
process_tools::start_action(write_udev_runtime_data, &requesting_process, false)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let _exit_info = process_tools::await_process(Pid::Pid(child_pid))
|
||||
.await
|
||||
|
|
@ -148,7 +151,7 @@ impl InjectionStrategy for GenericPlacementInContainer {
|
|||
};
|
||||
|
||||
let child_pid_2 =
|
||||
process_tools::start_action(write_udev_runtime_data_action, &requesting_process)
|
||||
process_tools::start_action(write_udev_runtime_data_action, &requesting_process, false)
|
||||
.expect("subprocess should work");
|
||||
let _exit_info = process_tools::await_process(Pid::Pid(child_pid_2)).await;
|
||||
Ok(())
|
||||
|
|
@ -164,8 +167,9 @@ impl InjectionStrategy for GenericPlacementInContainer {
|
|||
netlink_message: netlink_message,
|
||||
};
|
||||
|
||||
let child_pid = process_tools::start_action(emit_netlink_message, requesting_process)
|
||||
.expect("subprocess should work");
|
||||
let child_pid =
|
||||
process_tools::start_action(emit_netlink_message, requesting_process, false)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let _exit_info = process_tools::await_process(Pid::Pid(child_pid)).await;
|
||||
Ok(())
|
||||
|
|
@ -235,7 +239,6 @@ impl InjectionStrategy for GenericPlacementOnHost {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
/// Emit netlink message.
|
||||
async fn emit_netlink_message(
|
||||
&self,
|
||||
|
|
@ -382,14 +385,21 @@ impl InjectionStrategy for Incus {
|
|||
.await
|
||||
}
|
||||
|
||||
/// Emit netlink message.
|
||||
/// Emit netlink message.
|
||||
async fn emit_netlink_message(
|
||||
&self,
|
||||
requesting_process: &RequestingProcess,
|
||||
netlink_message: HashMap<String, String>,
|
||||
) -> anyhow::Result<()> {
|
||||
PLACEMENT_IN_CONTAINER
|
||||
.emit_netlink_message(requesting_process, netlink_message)
|
||||
.await
|
||||
let emit_netlink_message = Action::EmitNetlinkMessage {
|
||||
netlink_message: netlink_message,
|
||||
};
|
||||
|
||||
let child_pid = process_tools::start_action(emit_netlink_message, requesting_process, true)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let _exit_info = process_tools::await_process(Pid::Pid(child_pid)).await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ pub unsafe extern "C" fn vuinput_poll(
|
|||
get_vuinput_state(&VuFileHandle::from_fuse_file_info(fi.as_ref().unwrap())).unwrap();
|
||||
let mut vuinput_state = vuinput_state_mutex.lock().unwrap();
|
||||
|
||||
debug!("poll");
|
||||
|
||||
match vuinput_state.poll.pollphase {
|
||||
PollPhase::Empty => {
|
||||
if ph != std::ptr::null_mut() {
|
||||
|
|
|
|||
|
|
@ -158,7 +158,10 @@ impl EmitUdevEventJob {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
injector.emit_netlink_message(&self.requesting_process, netlink_data).await.unwrap();
|
||||
injector
|
||||
.emit_netlink_message(&self.requesting_process, netlink_data)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
self.set_state(&State::Finished);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,16 +142,10 @@ impl RemoveDeviceJob {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
// this is always in the container
|
||||
let emit_netlink_message = Action::EmitNetlinkMessage {
|
||||
netlink_message: netlink_data.clone(),
|
||||
};
|
||||
|
||||
let child_pid_netlink =
|
||||
process_tools::start_action(emit_netlink_message, &self.requesting_process)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let _exit_info = await_process(Pid::Pid(child_pid_netlink)).await;
|
||||
injector
|
||||
.emit_netlink_message(&self.requesting_process, netlink_data)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
self.set_state(&State::Finished);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,14 +82,22 @@ struct Args {
|
|||
#[arg(long = "action-base64", value_name = "BASE64")]
|
||||
pub action_base64: Option<String>,
|
||||
|
||||
/// Process id that is used as the namespace source (e.g. 1234 is used to read the namespaces from /proc/1234/ns).
|
||||
/// Process id that is used as the namespace source (e.g. 1234 is used to read the namespaces from /proc/1234/ns). Enters net and
|
||||
/// mnt namespaces by default.
|
||||
#[arg(
|
||||
long = "target-pid",
|
||||
value_name = "PID",
|
||||
help = "Process id that is used as the namespace source (e.g. 1234 is used to read the namespaces from /proc/1234/ns)."
|
||||
help = "Process id that is used as the namespace source (e.g. 1234 is used to read the namespaces from /proc/1234/ns). Enters net and mnt namespaces by default."
|
||||
)]
|
||||
pub target_pid: Option<String>,
|
||||
|
||||
/// Enter also the user namespace. Used together with --target-pid.
|
||||
#[arg(
|
||||
long = "enter-user-namespace",
|
||||
help = "Enter also the user namespace. Used together with --target-pid."
|
||||
)]
|
||||
pub enter_user_namespace: bool,
|
||||
|
||||
#[arg(
|
||||
long = "vt-guard",
|
||||
help = "Prevent all keyboard input from reaching the VT by setting K_OFF on /dev/tty0.",
|
||||
|
|
@ -229,8 +237,12 @@ fn main() -> std::io::Result<()> {
|
|||
|
||||
if action.is_some() {
|
||||
if let Some(target_pid) = args.target_pid {
|
||||
process_tools::run_in_net_and_mnt_namespace(target_pid.as_str(), &args.device_owner)
|
||||
.unwrap();
|
||||
process_tools::run_in_net_and_mnt_namespace(
|
||||
target_pid.as_str(),
|
||||
&args.device_owner,
|
||||
args.enter_user_namespace,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
let error_code = actions::handle_action::handle_cli_action(action.unwrap());
|
||||
std::process::exit(error_code);
|
||||
|
|
@ -245,7 +257,7 @@ fn main() -> std::io::Result<()> {
|
|||
vt_tools::check_vt_status();
|
||||
|
||||
let container_runtime = args.resolve_runtime();
|
||||
let scope= args.get_scope();
|
||||
let scope = args.get_scope();
|
||||
|
||||
global_config::initialize_global_config(
|
||||
&args.device_policy,
|
||||
|
|
|
|||
|
|
@ -282,46 +282,57 @@ fn print_debug_string(action: &str, ns: &RequestingProcess) {
|
|||
|
||||
/// Runs a function inside the given network and mount namespaces.
|
||||
/// Returns the child PID so the caller can `waitpid` on it.
|
||||
pub fn start_action(action: Action, ns: &RequestingProcess) -> anyhow::Result<u32> {
|
||||
pub fn start_action(
|
||||
action: Action,
|
||||
ns: &RequestingProcess,
|
||||
enter_user_ns: bool,
|
||||
) -> anyhow::Result<u32> {
|
||||
let action_json = serde_json::to_string(&action).unwrap();
|
||||
print_debug_string(&action_json, &ns);
|
||||
|
||||
let device_owner = get_device_owner().to_string_rep();
|
||||
|
||||
let child = unsafe {
|
||||
Command::new("/proc/self/exe")
|
||||
.args([
|
||||
"--action",
|
||||
action_json.as_str(),
|
||||
"--target-pid",
|
||||
ns.pid_requestor_root.to_string_rep().as_str(),
|
||||
"--device-owner",
|
||||
device_owner.as_str(),
|
||||
])
|
||||
.pre_exec(|| {
|
||||
// Last resort, if the parent just is killed.
|
||||
libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL);
|
||||
Ok(())
|
||||
})
|
||||
.spawn()
|
||||
.expect("failed to start vuinputd")
|
||||
let mut cmd = Command::new("/proc/self/exe");
|
||||
cmd.args([
|
||||
"--action",
|
||||
action_json.as_str(),
|
||||
"--target-pid",
|
||||
ns.pid_requestor_root.to_string_rep().as_str(),
|
||||
"--device-owner",
|
||||
device_owner.as_str(),
|
||||
]);
|
||||
if enter_user_ns {
|
||||
cmd.arg("--enter-user-namespace");
|
||||
}
|
||||
cmd.pre_exec(|| {
|
||||
// Last resort, if the parent just is killed.
|
||||
libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL);
|
||||
Ok(())
|
||||
})
|
||||
.spawn()
|
||||
.expect("failed to start vuinputd")
|
||||
};
|
||||
|
||||
Result::Ok(child.id())
|
||||
}
|
||||
|
||||
pub fn run_in_net_and_mnt_namespace(target_pid: &str, device_owner: &DeviceOwner) -> anyhow::Result<()> {
|
||||
pub fn run_in_net_and_mnt_namespace(
|
||||
target_pid: &str,
|
||||
device_owner: &DeviceOwner,
|
||||
enter_user_ns: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
debug!(
|
||||
"Entering namespaces of process {}. We assume this is the root process of the container.",
|
||||
target_pid
|
||||
);
|
||||
|
||||
let fs_uid_gid = if *device_owner == DeviceOwner::ContainerDevFolder {
|
||||
let pid:u32 = target_pid.trim().parse()?;
|
||||
let pid: u32 = target_pid.trim().parse()?;
|
||||
let pid = Pid::Pid(pid);
|
||||
let fs_uid=ns_fscreds::get_uid_in_container(pid, 0)?;
|
||||
let fs_gid=ns_fscreds::get_gid_in_container(pid, 0)?;
|
||||
Some((fs_uid,fs_gid))
|
||||
let fs_uid = ns_fscreds::get_uid_in_container(pid, 0)?;
|
||||
let fs_gid = ns_fscreds::get_gid_in_container(pid, 0)?;
|
||||
Some((fs_uid, fs_gid))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -331,16 +342,22 @@ pub fn run_in_net_and_mnt_namespace(target_pid: &str, device_owner: &DeviceOwner
|
|||
if !fs::exists(path).unwrap() {
|
||||
return Err(anyhow!("the root process of the container whose namespaces we want to enter does not exist anymore"));
|
||||
}
|
||||
let user = File::open(nspath.to_string() + "/user")?;
|
||||
let net = File::open(nspath.to_string() + "/net")?;
|
||||
let mnt = File::open(nspath.to_string() + "/mnt")?;
|
||||
|
||||
unsafe {
|
||||
// enter namespaces
|
||||
if enter_user_ns {
|
||||
libc::setns(user.as_raw_fd(), libc::CLONE_NEWUSER);
|
||||
libc::setresgid(0, 0, 0);
|
||||
libc::setresuid(0, 0, 0);
|
||||
}
|
||||
libc::setns(net.as_raw_fd(), libc::CLONE_NEWNET);
|
||||
libc::setns(mnt.as_raw_fd(), libc::CLONE_NEWNS);
|
||||
};
|
||||
|
||||
if let Some((fs_uid,fs_gid)) = fs_uid_gid {
|
||||
if let Some((fs_uid, fs_gid)) = fs_uid_gid {
|
||||
ns_fscreds::acquire_uid_and_gid(fs_uid, fs_gid)?;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue