The dup2_std* functions had a few soundness issues that allowed safe code to close the stdio file descriptors.
AsFd::as_fd() was called twice, possibly returning a different BorrowedFd each time. This would allow safe code to bypass the fd.as_fd().as_raw_fd() != c::STDOUT_FILENO check.
AsFd::as_fd() was called between let mut target = unsafe { take_stdout() }; and forget(target);. If as_fd() panics, then target would be automatically dropped without the call to forget. This violates exception safety.
If backend::io::syscalls::dup2 returns an error, this was immediately returned from the function using the ? operator, so forget(target); wasn't called resulting in target getting dropped closing the stdio file descriptor.
Fix these issues by only calling AsFd::as_fd() once and by using ManuallyDrop instead of forget.
The
dup2_std*
functions had a few soundness issues that allowed safe code to close the stdio file descriptors.AsFd::as_fd()
was called twice, possibly returning a differentBorrowedFd
each time. This would allow safe code to bypass thefd.as_fd().as_raw_fd() != c::STDOUT_FILENO
check.AsFd::as_fd()
was called betweenlet mut target = unsafe { take_stdout() };
andforget(target);
. Ifas_fd()
panics, thentarget
would be automatically dropped without the call toforget
. This violates exception safety.backend::io::syscalls::dup2
returns an error, this was immediately returned from the function using the?
operator, soforget(target);
wasn't called resulting intarget
getting dropped closing the stdio file descriptor.Fix these issues by only calling
AsFd::as_fd()
once and by usingManuallyDrop
instead offorget
.