Skip to content

Commit b71407a

Browse files
petrosaggdianpopa
authored andcommitted
jailer: rely on RAII to close file descriptors
There were a couple of places where the manual calls to `libc::close`, which also required an unsafe block, could be omitted if the original RAII resources was retained until the end of its scope where its `Drop` implementation would clean it up automatically. Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
1 parent e6ce775 commit b71407a

File tree

1 file changed

+13
-48
lines changed

1 file changed

+13
-48
lines changed

src/jailer/src/env.rs

Lines changed: 13 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::fs::{self, canonicalize, File, OpenOptions, Permissions};
66
use std::io;
77
use std::io::Write;
88
use std::os::unix::fs::PermissionsExt;
9-
use std::os::unix::io::IntoRawFd;
9+
use std::os::unix::io::AsRawFd;
1010
use std::os::unix::process::CommandExt;
1111
use std::path::{Component, Path, PathBuf};
1212
use std::process::{Command, Stdio};
@@ -43,8 +43,6 @@ const DEV_URANDOM_WITH_NUL: &[u8] = b"/dev/urandom\0";
4343
const DEV_URANDOM_MAJOR: u32 = 1;
4444
const DEV_URANDOM_MINOR: u32 = 9;
4545

46-
const DEV_NULL_WITH_NUL: &[u8] = b"/dev/null\0";
47-
4846
// Relevant folders inside the jail that we create or/and for which we change ownership.
4947
// We need /dev in order to be able to create /dev/kvm and /dev/net/tun device.
5048
// We need /run for the default location of the api socket.
@@ -403,23 +401,13 @@ impl Env {
403401
}
404402

405403
fn join_netns(path: &str) -> Result<()> {
406-
// Not used `as_raw_fd` as it will create a dangling fd (object will be freed immediately)
407-
// instead used `into_raw_fd` which provides underlying fd ownership to caller.
408-
let netns_fd = File::open(path)
409-
.map_err(|err| Error::FileOpen(PathBuf::from(path), err))?
410-
.into_raw_fd();
411-
412-
// SAFETY: Safe because we are passing valid parameters.
413-
SyscallReturnCode(unsafe { libc::setns(netns_fd, libc::CLONE_NEWNET) })
414-
.into_empty_result()
415-
.map_err(Error::SetNetNs)?;
404+
// The fd backing the file will be automatically dropped at the end of the scope
405+
let netns = File::open(path).map_err(|err| Error::FileOpen(PathBuf::from(path), err))?;
416406

417-
// Since we have ownership here, we also have to close the fd after joining the
418-
// namespace.
419407
// SAFETY: Safe because we are passing valid parameters.
420-
SyscallReturnCode(unsafe { libc::close(netns_fd) })
408+
SyscallReturnCode(unsafe { libc::setns(netns.as_raw_fd(), libc::CLONE_NEWNET) })
421409
.into_empty_result()
422-
.map_err(Error::CloseNetNsFd)
410+
.map_err(Error::SetNetNs)
423411
}
424412

425413
fn exec_command(&self, chroot_exec_file: PathBuf) -> io::Error {
@@ -553,18 +541,7 @@ impl Env {
553541

554542
// If daemonization was requested, open /dev/null before chrooting.
555543
let dev_null = if self.daemonize {
556-
Some(
557-
// SAFETY: Safe because we use a constant null-terminated string and verify the
558-
// result.
559-
SyscallReturnCode(unsafe {
560-
libc::open(
561-
DEV_NULL_WITH_NUL.as_ptr().cast::<libc::c_char>(),
562-
libc::O_RDWR,
563-
)
564-
})
565-
.into_result()
566-
.map_err(Error::OpenDevNull)?,
567-
)
544+
Some(File::open("/dev/null").map_err(Error::OpenDevNull)?)
568545
} else {
569546
None
570547
};
@@ -606,22 +583,17 @@ impl Env {
606583
});
607584

608585
// Daemonize before exec, if so required (when the dev_null variable != None).
609-
if let Some(fd) = dev_null {
586+
if let Some(dev_null) = dev_null {
610587
// Call setsid().
611588
// SAFETY: Safe because it's a library function.
612589
SyscallReturnCode(unsafe { libc::setsid() })
613590
.into_empty_result()
614591
.map_err(Error::SetSid)?;
615592

616593
// Replace the stdio file descriptors with the /dev/null fd.
617-
dup2(fd, STDIN_FILENO)?;
618-
dup2(fd, STDOUT_FILENO)?;
619-
dup2(fd, STDERR_FILENO)?;
620-
621-
// SAFETY: Safe because we are passing valid parameters, and checking the result.
622-
SyscallReturnCode(unsafe { libc::close(fd) })
623-
.into_empty_result()
624-
.map_err(Error::CloseDevNullFd)?;
594+
dup2(dev_null.as_raw_fd(), STDIN_FILENO)?;
595+
dup2(dev_null.as_raw_fd(), STDOUT_FILENO)?;
596+
dup2(dev_null.as_raw_fd(), STDERR_FILENO)?;
625597
}
626598

627599
// If specified, exec the provided binary into a new PID namespace.
@@ -892,18 +864,11 @@ mod tests {
892864
#[test]
893865
fn test_dup2() {
894866
// Open /dev/kvm since it should be available anyway.
895-
let fd1 = fs::File::open("/dev/kvm").unwrap().into_raw_fd();
867+
let file1 = fs::File::open("/dev/kvm").unwrap();
896868
// We open a second file to make sure its associated fd is not used by something else.
897-
let fd2 = fs::File::open("/dev/kvm").unwrap().into_raw_fd();
869+
let file2 = fs::File::open("/dev/kvm").unwrap();
898870

899-
dup2(fd1, fd2).unwrap();
900-
901-
unsafe {
902-
libc::close(fd1);
903-
}
904-
unsafe {
905-
libc::close(fd2);
906-
}
871+
dup2(file1.as_raw_fd(), file2.as_raw_fd()).unwrap();
907872
}
908873

909874
#[test]

0 commit comments

Comments
 (0)