Skip to content

Commit 84b588a

Browse files
authored
Merge pull request #59 from cgwalters/dup2-fix
cmdext: Fix bug when srcfd == targetfd
2 parents bfbb355 + 3a0803d commit 84b588a

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

src/cmdext.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use cap_std::io_lifetimes;
1010
use cap_tempfile::cap_std;
1111
use io_lifetimes::OwnedFd;
1212
use rustix::fd::{AsFd, FromRawFd, IntoRawFd};
13+
use rustix::io::FdFlags;
14+
use std::os::fd::AsRawFd;
1315
use std::os::unix::process::CommandExt;
1416
use std::sync::Arc;
1517

@@ -30,7 +32,15 @@ impl CapStdExtCommandExt for std::process::Command {
3032
unsafe {
3133
self.pre_exec(move || {
3234
let mut target = OwnedFd::from_raw_fd(target);
33-
rustix::io::dup2(&*fd, &mut target)?;
35+
// If the fd is already what we want, then just ensure that
36+
// O_CLOEXEC is stripped off.
37+
if target.as_raw_fd() == fd.as_raw_fd() {
38+
let fl = rustix::io::fcntl_getfd(&target)?;
39+
rustix::io::fcntl_setfd(&mut target, fl.difference(FdFlags::CLOEXEC))?;
40+
} else {
41+
// Otherwise create a dup, which will also default to not setting O_CLOEXEC.
42+
rustix::io::dup2(&*fd, &mut target)?;
43+
}
3444
// Intentionally leak into the child.
3545
let _ = target.into_raw_fd();
3646
Ok(())
@@ -49,3 +59,25 @@ impl CapStdExtCommandExt for std::process::Command {
4959
self
5060
}
5161
}
62+
63+
#[cfg(test)]
64+
mod tests {
65+
use super::*;
66+
use std::sync::Arc;
67+
68+
#[test]
69+
fn test_take_fdn() -> anyhow::Result<()> {
70+
// Pass srcfd == destfd and srcfd != destfd
71+
for i in 0..1 {
72+
let tempd = cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
73+
let tempd_fd = Arc::new(tempd.as_fd().try_clone_to_owned()?);
74+
let n = tempd_fd.as_raw_fd() + i;
75+
let st = std::process::Command::new("ls")
76+
.arg(format!("/proc/self/fd/{n}"))
77+
.take_fd_n(tempd_fd, n)
78+
.status()?;
79+
assert!(st.success());
80+
}
81+
Ok(())
82+
}
83+
}

0 commit comments

Comments
 (0)