diff --git a/src/jailer/src/main.rs b/src/jailer/src/main.rs index ceff5a12a607..a60c3ca19c84 100644 --- a/src/jailer/src/main.rs +++ b/src/jailer/src/main.rs @@ -235,19 +235,51 @@ pub fn readln_special>(file_path: &T) -> Result { Ok(line) } -fn sanitize_process() { - // First thing to do is make sure we don't keep any inherited FDs - // other that IN, OUT and ERR. +// Closes all FDs other than 0 (STDIN), 1 (STDOUT) and 2 (STDERR) +fn close_inherited_fds() { + // First try using the close_range syscall to close all open FDs in the range of 4..UINT_MAX + // SAFETY: if the syscall is not available then ENOSYS will be returned + if unsafe { + libc::syscall(libc::SYS_close_range, 3, libc::c_uint::MAX, libc::CLOSE_RANGE_UNSHARE) + } == 0 { + return + } + + // Probably the kernel does not support close_range, kernel < 5.9 // SAFETY: Always safe. let fd_limit = i32::try_from(unsafe { libc::sysconf(libc::_SC_OPEN_MAX) }).unwrap(); - // Close all file descriptors excluding 0 (STDIN), 1 (STDOUT) and 2 (STDERR). - for fd in 3..fd_limit { - // SAFETY: Safe because close() cannot fail when passed a valid parameter. - unsafe { - libc::close(fd); + + // Check if the fd_limit is small enough to iterate through + if fd_limit <= 2_i32.pow(20) { + for fd in 3..fd_limit { + // SAFETY: Safe because close() cannot fail when passed a valid parameter. + unsafe { + libc::close(fd); + } } + return } + + // If both methods failed then fallback to reading /proc + // This means that we are on kernel < 5.9 and OPEN_MAX is set to a pathological size + if let Ok(mut paths) = fs::read_dir("/proc/self/fd") { + while let Some(Ok(path)) = paths.next() { + let file_name = path.file_name(); + let fd_str = file_name.to_str().unwrap_or("0"); + let fd = fd_str.parse::().unwrap_or(0); + + if fd > 2 { + // SAFETY: Safe because close() cannot fail when passed a valid parameter. + unsafe { libc::close(fd) }; + } + } + } +} +fn sanitize_process() { + // First thing to do is make sure we don't keep any inherited FDs + // other that IN, OUT and ERR. + close_inherited_fds(); // Cleanup environment variables clean_env_vars(); }