rutabaga_gfx: convert to SafeDescriptor

To be truly OS-agnostic, we need an OS-agnostic Rust wrapper over
the OS-specific handle type.  SafeDescriptor seems to be the best
option, and I hope it on crates.io in the future.

This converts virtio_gpu/rutabaga to use the SafeDescriptor handle
when practical.  minigbm still uses File in some places, since it
needs to SeekFrom(..), but minigbm is a Linux only thing anyways.

BUG=b:173630595
TEST=boot VM in 2D/3D mode

Change-Id: I18d735844d479f52d82d7976bf9b4e383b2e2252
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2779492
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
Commit-Queue: Zach Reizner <zachr@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Michael Hoyle <mikehoyle@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
diff --git a/base/src/shm.rs b/base/src/shm.rs
index 36c6f7e..fa7355a 100644
--- a/base/src/shm.rs
+++ b/base/src/shm.rs
@@ -8,7 +8,7 @@
 };
 use std::ffi::CStr;
 use std::fs::File;
-use std::os::unix::io::AsRawFd;
+use std::os::unix::io::{AsRawFd, IntoRawFd};
 use sys_util::SharedMemory as SysUtilSharedMemory;
 
 /// See [SharedMemory](sys_util::SharedMemory) for struct- and method-level
@@ -77,8 +77,15 @@
     }
 }
 
-impl Into<File> for SharedMemory {
-    fn into(self) -> File {
-        self.0.into()
+impl IntoRawDescriptor for SharedMemory {
+    fn into_raw_descriptor(self) -> RawDescriptor {
+        self.0.into_raw_fd()
+    }
+}
+
+impl Into<SafeDescriptor> for SharedMemory {
+    fn into(self) -> SafeDescriptor {
+        // Safe because we own the SharedMemory at this point.
+        unsafe { SafeDescriptor::from_raw_descriptor(self.into_raw_descriptor()) }
     }
 }
diff --git a/devices/src/virtio/gpu/virtio_gpu.rs b/devices/src/virtio/gpu/virtio_gpu.rs
index 0e23c6a..58d3dcf 100644
--- a/devices/src/virtio/gpu/virtio_gpu.rs
+++ b/devices/src/virtio/gpu/virtio_gpu.rs
@@ -427,7 +427,7 @@
     /// If supported, export the resource with the given `resource_id` to a file.
     pub fn export_resource(&mut self, resource_id: u32) -> ResourceResponse {
         let file = match self.rutabaga.export_blob(resource_id) {
-            Ok(handle) => handle.os_handle,
+            Ok(handle) => handle.os_handle.into(),
             Err(_) => return ResourceResponse::Invalid,
         };
 
@@ -463,7 +463,7 @@
     pub fn export_fence(&self, fence_id: u32) -> ResourceResponse {
         match self.rutabaga.export_fence(fence_id) {
             Ok(handle) => ResourceResponse::Resource(ResourceInfo::Fence {
-                file: handle.os_handle,
+                file: handle.os_handle.into(),
             }),
             Err(_) => ResourceResponse::Invalid,
         }
diff --git a/rutabaga_gfx/src/rutabaga_gralloc/minigbm.rs b/rutabaga_gfx/src/rutabaga_gralloc/minigbm.rs
index bdf62e7..c20438d 100644
--- a/rutabaga_gfx/src/rutabaga_gralloc/minigbm.rs
+++ b/rutabaga_gfx/src/rutabaga_gralloc/minigbm.rs
@@ -143,7 +143,7 @@
                 return Err(RutabagaError::SpecViolation);
             }
 
-            let dmabuf = gbm_buffer.export()?;
+            let dmabuf = gbm_buffer.export()?.into();
             return Ok(RutabagaHandle {
                 os_handle: dmabuf,
                 handle_type: RUTABAGA_MEM_HANDLE_TYPE_DMABUF,
@@ -165,7 +165,7 @@
         }
 
         let gbm_buffer = MinigbmBuffer(bo, self.clone());
-        let dmabuf = gbm_buffer.export()?;
+        let dmabuf = gbm_buffer.export()?.into();
         Ok(RutabagaHandle {
             os_handle: dmabuf,
             handle_type: RUTABAGA_MEM_HANDLE_TYPE_DMABUF,
diff --git a/rutabaga_gfx/src/rutabaga_gralloc/vulkano_gralloc.rs b/rutabaga_gfx/src/rutabaga_gralloc/vulkano_gralloc.rs
index b74908a..c122224 100644
--- a/rutabaga_gfx/src/rutabaga_gralloc/vulkano_gralloc.rs
+++ b/rutabaga_gfx/src/rutabaga_gralloc/vulkano_gralloc.rs
@@ -269,10 +269,10 @@
                 .export_info(handle_type)
                 .build()?;
 
-        let file = device_memory.export_fd(handle_type)?;
+        let descriptor = device_memory.export_fd(handle_type)?.into();
 
         Ok(RutabagaHandle {
-            os_handle: file,
+            os_handle: descriptor,
             handle_type: rutabaga_type,
         })
     }
diff --git a/rutabaga_gfx/src/rutabaga_utils.rs b/rutabaga_gfx/src/rutabaga_utils.rs
index 943f36c..b81989d 100644
--- a/rutabaga_gfx/src/rutabaga_utils.rs
+++ b/rutabaga_gfx/src/rutabaga_utils.rs
@@ -5,13 +5,12 @@
 //! rutabaga_utils: Utility enums, structs, and implementations needed by the rest of the crate.
 
 use std::fmt::{self, Display};
-use std::fs::File;
 use std::io::Error as IoError;
 use std::os::raw::c_void;
 use std::path::PathBuf;
 use std::str::Utf8Error;
 
-use base::{Error as SysError, ExternalMappingError};
+use base::{Error as SysError, ExternalMappingError, SafeDescriptor};
 use data_model::VolatileMemoryError;
 
 #[cfg(feature = "vulkano")]
@@ -463,7 +462,7 @@
 
 /// Handle to OS-specific memory or synchronization objects.
 pub struct RutabagaHandle {
-    pub os_handle: File,
+    pub os_handle: SafeDescriptor,
     pub handle_type: u32,
 }
 
diff --git a/rutabaga_gfx/src/virgl_renderer.rs b/rutabaga_gfx/src/virgl_renderer.rs
index 55c5cda..fcd2156 100644
--- a/rutabaga_gfx/src/virgl_renderer.rs
+++ b/rutabaga_gfx/src/virgl_renderer.rs
@@ -9,7 +9,6 @@
 
 use std::cell::RefCell;
 use std::ffi::CString;
-use std::fs::File;
 use std::mem::{size_of, transmute};
 use std::os::raw::{c_char, c_void};
 use std::ptr::null_mut;
@@ -19,7 +18,7 @@
 
 use base::{
     warn, Error as SysError, ExternalMapping, ExternalMappingError, ExternalMappingResult,
-    FromRawDescriptor,
+    FromRawDescriptor, SafeDescriptor,
 };
 
 use crate::generated::virgl_renderer_bindings::*;
@@ -269,7 +268,7 @@
                 return Err(RutabagaError::Unsupported);
             }
 
-            let dmabuf = unsafe { File::from_raw_descriptor(fd) };
+            let dmabuf = unsafe { SafeDescriptor::from_raw_descriptor(fd) };
             Ok(Arc::new(RutabagaHandle {
                 os_handle: dmabuf,
                 handle_type: RUTABAGA_MEM_HANDLE_TYPE_DMABUF,
@@ -539,7 +538,7 @@
 
             // Safe because the FD was just returned by a successful virglrenderer call so it must
             // be valid and owned by us.
-            let fence = unsafe { File::from_raw_descriptor(fd) };
+            let fence = unsafe { SafeDescriptor::from_raw_descriptor(fd) };
             Ok(RutabagaHandle {
                 os_handle: fence,
                 handle_type: RUTABAGA_FENCE_HANDLE_TYPE_SYNC_FD,
diff --git a/sys_util/src/descriptor.rs b/sys_util/src/descriptor.rs
index 5ee075a..4c86ca2 100644
--- a/sys_util/src/descriptor.rs
+++ b/sys_util/src/descriptor.rs
@@ -113,6 +113,20 @@
     }
 }
 
+impl Into<File> for SafeDescriptor {
+    fn into(self) -> File {
+        // Safe because we own the SafeDescriptor at this point.
+        unsafe { File::from_raw_fd(self.into_raw_descriptor()) }
+    }
+}
+
+impl Into<SafeDescriptor> for File {
+    fn into(self) -> SafeDescriptor {
+        // Safe because we own the File at this point.
+        unsafe { SafeDescriptor::from_raw_descriptor(self.into_raw_descriptor()) }
+    }
+}
+
 /// For use cases where a simple wrapper around a RawDescriptor is needed.
 /// This is a simply a wrapper and does not manage the lifetime of the descriptor.
 /// Most usages should prefer SafeDescriptor or using a RawDescriptor directly
diff --git a/sys_util/src/shm.rs b/sys_util/src/shm.rs
index d9a5839..6bfe206 100644
--- a/sys_util/src/shm.rs
+++ b/sys_util/src/shm.rs
@@ -5,7 +5,7 @@
 use std::ffi::{CStr, CString};
 use std::fs::{read_link, File};
 use std::io::{self, Read, Seek, SeekFrom, Write};
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
 
 use libc::{
     self, c_char, c_int, c_long, c_uint, close, fcntl, ftruncate64, off64_t, syscall, EINVAL,
@@ -267,6 +267,12 @@
     }
 }
 
+impl IntoRawFd for SharedMemory {
+    fn into_raw_fd(self) -> RawFd {
+        self.fd.into_raw_fd()
+    }
+}
+
 impl Into<File> for SharedMemory {
     fn into(self) -> File {
         self.fd