gpui: Fix double-close of fd in read_fd on linux (#48850)

Albab Hasan created

`read_fd` calls `File::from_raw_fd(fd.as_raw_fd())`, which creates a new
`File` that assumes ownership of the raw fd, while the original
`FileDescriptor` also retains ownership. when both drop at the end of
the function, the same fd is closed twice. between the two closes
another thread can receive that fd number from the kernel for an
unrelated file/socket, and the second close silently kills it. this can
cause hard to diagnose data corruption or i/o failures.

fix: use `fd.into_raw_fd()` instead of `fd.as_raw_fd()` to transfer
ownership to the `File` without running `FileDescriptor`'s drop.

Release Notes:

- N/A

Change summary

crates/gpui/src/platform/linux/platform.rs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

Detailed changes

crates/gpui/src/platform/linux/platform.rs 🔗

@@ -9,7 +9,7 @@ use std::{
     ffi::OsString,
     fs::File,
     io::Read as _,
-    os::fd::{AsFd, AsRawFd, FromRawFd},
+    os::fd::{AsFd, FromRawFd, IntoRawFd},
     time::Duration,
 };
 
@@ -737,8 +737,8 @@ pub(super) fn get_xkb_compose_state(cx: &xkb::Context) -> Option<xkb::compose::S
 }
 
 #[cfg(any(feature = "wayland", feature = "x11"))]
-pub(super) unsafe fn read_fd(mut fd: filedescriptor::FileDescriptor) -> Result<Vec<u8>> {
-    let mut file = unsafe { File::from_raw_fd(fd.as_raw_fd()) };
+pub(super) unsafe fn read_fd(fd: filedescriptor::FileDescriptor) -> Result<Vec<u8>> {
+    let mut file = unsafe { File::from_raw_fd(fd.into_raw_fd()) };
     let mut buffer = Vec::new();
     file.read_to_end(&mut buffer)?;
     Ok(buffer)