tracexec_core/
tracee.rs

1//! Common operations to run in tracee process
2
3use std::{
4  ffi::CString,
5  os::fd::{AsFd, FromRawFd, OwnedFd},
6};
7
8use nix::{
9  errno::Errno,
10  libc,
11  unistd::{Gid, Uid, User, dup2, getpid, initgroups, setpgid, setresgid, setresuid, setsid},
12};
13
14pub fn nullify_stdio() -> Result<(), std::io::Error> {
15  let dev_null = std::fs::File::options()
16    .read(true)
17    .write(true)
18    .open("/dev/null")?;
19  let mut stdin = unsafe { OwnedFd::from_raw_fd(0) };
20  let mut stdout = unsafe { OwnedFd::from_raw_fd(1) };
21  let mut stderr = unsafe { OwnedFd::from_raw_fd(2) };
22  dup2(dev_null.as_fd(), &mut stdin)?;
23  dup2(dev_null.as_fd(), &mut stdout)?;
24  dup2(dev_null.as_fd(), &mut stderr)?;
25  std::mem::forget(stdin);
26  std::mem::forget(stdout);
27  std::mem::forget(stderr);
28  Ok(())
29}
30
31pub fn runas(user: &User, effective: Option<(Uid, Gid)>) -> Result<(), Errno> {
32  let (euid, egid) = effective.unwrap_or((user.uid, user.gid));
33  initgroups(&CString::new(user.name.as_str()).unwrap()[..], user.gid)?;
34  setresgid(user.gid, egid, Gid::from_raw(u32::MAX))?;
35  setresuid(user.uid, euid, Uid::from_raw(u32::MAX))?;
36  Ok(())
37}
38
39pub fn lead_process_group() -> Result<(), Errno> {
40  let me = getpid();
41  setpgid(me, me)
42}
43
44pub fn lead_session_and_control_terminal() -> Result<(), Errno> {
45  setsid()?;
46  if unsafe { libc::ioctl(0, libc::TIOCSCTTY as _, 0) } == -1 {
47    Err(Errno::last())?;
48  }
49  Ok(())
50}