diff options
| author | The 8472 <git@infinite-source.de> | 2024-04-21 17:19:15 +0200 |
|---|---|---|
| committer | The 8472 <git@infinite-source.de> | 2024-04-28 01:44:25 +0200 |
| commit | 1ba00d9cb2fcfef464b6a188fa3a7543c66eecaa (patch) | |
| tree | 2626b8a704fa0f5eaaccda41cd9950da8ea3b6f4 /library/std/src | |
| parent | 25babe9a79a2c5d35211e0d6bad348637ef2a246 (diff) | |
| download | rust-1ba00d9cb2fcfef464b6a188fa3a7543c66eecaa.tar.gz rust-1ba00d9cb2fcfef464b6a188fa3a7543c66eecaa.zip | |
put FD validity behind late debug_asserts checking
uses the same machinery as assert_unsafe_precondition
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/os/fd/owned.rs | 14 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/fs.rs | 47 |
2 files changed, 32 insertions, 29 deletions
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 8c421540af4..8c7fc4cb2e4 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -177,17 +177,9 @@ impl Drop for OwnedFd { // opened after we closed ours. #[cfg(not(target_os = "hermit"))] { - use crate::sys::os::errno; - // ideally this would use assert_unsafe_precondition!, but that's only in core - if cfg!(debug_assertions) { - // close() can bubble up error codes from FUSE which can send semantically - // inappropriate error codes including EBADF. - // So we check file flags instead which live on the file descriptor and not the underlying file. - // The downside is that it costs an extra syscall, so we only do it for debug. - if libc::fcntl(self.fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { - rtabort!("IO Safety violation: owned file descriptor already closed"); - } - } + #[cfg(unix)] + crate::sys::fs::debug_assert_fd_is_open(self.fd); + let _ = libc::close(self.fd); } #[cfg(target_os = "hermit")] diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 2d57a9d81c9..0a86d28c2e3 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -868,28 +868,39 @@ impl Iterator for ReadDir { } } +/// Aborts the process if a file desceriptor is not open, if debug asserts are enabled +/// +/// Many IO syscalls can't be fully trusted about EBADF error codes because those +/// might get bubbled up from a remote FUSE server rather than the file descriptor +/// in the current process being invalid. +/// +/// So we check file flags instead which live on the file descriptor and not the underlying file. +/// The downside is that it costs an extra syscall, so we only do it for debug. +#[inline] +pub(crate) fn debug_assert_fd_is_open(fd: RawFd) { + use crate::sys::os::errno; + + // this is similar to assert_unsafe_precondition!() but it doesn't require const + if core::ub_checks::check_library_ub() { + if unsafe { libc::fcntl(fd, libc::F_GETFD) } == -1 && errno() == libc::EBADF { + rtabort!("IO Safety violation: owned file descriptor already closed"); + } + } +} + impl Drop for Dir { fn drop(&mut self) { - // ideally this would use assert_unsafe_precondition!, but that's only in core - #[cfg(all( - debug_assertions, - not(any( - target_os = "redox", - target_os = "nto", - target_os = "vita", - target_os = "hurd", - )) - ))] + // dirfd isn't supported everywhere + #[cfg(not(any( + miri, + target_os = "redox", + target_os = "nto", + target_os = "vita", + target_os = "hurd", + )))] { - use crate::sys::os::errno; - // close() can bubble up error codes from FUSE which can send semantically - // inappropriate error codes including EBADF. - // So we check file flags instead which live on the file descriptor and not the underlying file. - // The downside is that it costs an extra syscall, so we only do it for debug. let fd = unsafe { libc::dirfd(self.0) }; - if unsafe { libc::fcntl(fd, libc::F_GETFD) } == -1 && errno() == libc::EBADF { - rtabort!("IO Safety violation: DIR*'s owned file descriptor already closed"); - } + debug_assert_fd_is_open(fd); } let r = unsafe { libc::closedir(self.0) }; assert!( |
