xref: /aosp_15_r20/external/crosvm/base/src/descriptor.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::fs::File;
6 use std::mem;
7 use std::mem::ManuallyDrop;
8 use std::sync::Arc;
9 
10 use serde::Deserialize;
11 use serde::Serialize;
12 use serde::Serializer;
13 
14 use crate::EventToken;
15 use crate::RawDescriptor;
16 
17 /// Wraps a RawDescriptor and safely closes it when self falls out of scope.
18 #[derive(Serialize, Deserialize, Debug, Eq)]
19 #[serde(transparent)]
20 pub struct SafeDescriptor {
21     #[serde(with = "super::with_raw_descriptor")]
22     pub(crate) descriptor: RawDescriptor,
23 }
24 
25 /// Trait for forfeiting ownership of the current raw descriptor, and returning the raw descriptor
26 pub trait IntoRawDescriptor {
into_raw_descriptor(self) -> RawDescriptor27     fn into_raw_descriptor(self) -> RawDescriptor;
28 }
29 
30 /// Trait for returning the underlying raw descriptor, without giving up ownership of the
31 /// descriptor.
32 pub trait AsRawDescriptor {
33     /// Returns the underlying raw descriptor.
34     ///
35     /// Since the descriptor is still owned by the provider, callers should not assume that it will
36     /// remain open for longer than the immediate call of this method. In particular, it is a
37     /// dangerous practice to store the result of this method for future use: instead, it should be
38     /// used to e.g. obtain a raw descriptor that is immediately passed to a system call.
39     ///
40     /// If you need to use the descriptor for a longer time (and particularly if you cannot reliably
41     /// track the lifetime of the providing object), you should probably consider using
42     /// [`SafeDescriptor`] (possibly along with [`trait@IntoRawDescriptor`]) to get full ownership
43     /// over a descriptor pointing to the same resource.
as_raw_descriptor(&self) -> RawDescriptor44     fn as_raw_descriptor(&self) -> RawDescriptor;
45 }
46 
47 /// A trait similar to `AsRawDescriptor` but supports an arbitrary number of descriptors.
48 pub trait AsRawDescriptors {
49     /// Returns the underlying raw descriptors.
50     ///
51     /// Please refer to the documentation of [`AsRawDescriptor::as_raw_descriptor`] for limitations
52     /// and recommended use.
as_raw_descriptors(&self) -> Vec<RawDescriptor>53     fn as_raw_descriptors(&self) -> Vec<RawDescriptor>;
54 }
55 
56 pub trait FromRawDescriptor {
57     /// # Safety
58     /// Safe only if the caller ensures nothing has access to the descriptor after passing it to
59     /// `from_raw_descriptor`
from_raw_descriptor(descriptor: RawDescriptor) -> Self60     unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self;
61 }
62 
63 impl AsRawDescriptor for SafeDescriptor {
as_raw_descriptor(&self) -> RawDescriptor64     fn as_raw_descriptor(&self) -> RawDescriptor {
65         self.descriptor
66     }
67 }
68 
69 impl<T> AsRawDescriptor for Arc<T>
70 where
71     T: AsRawDescriptor,
72 {
as_raw_descriptor(&self) -> RawDescriptor73     fn as_raw_descriptor(&self) -> RawDescriptor {
74         self.as_ref().as_raw_descriptor()
75     }
76 }
77 
78 impl<T> AsRawDescriptors for T
79 where
80     T: AsRawDescriptor,
81 {
as_raw_descriptors(&self) -> Vec<RawDescriptor>82     fn as_raw_descriptors(&self) -> Vec<RawDescriptor> {
83         vec![self.as_raw_descriptor()]
84     }
85 }
86 
87 impl IntoRawDescriptor for SafeDescriptor {
into_raw_descriptor(self) -> RawDescriptor88     fn into_raw_descriptor(self) -> RawDescriptor {
89         let descriptor = self.descriptor;
90         mem::forget(self);
91         descriptor
92     }
93 }
94 
95 impl FromRawDescriptor for SafeDescriptor {
from_raw_descriptor(descriptor: RawDescriptor) -> Self96     unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
97         SafeDescriptor { descriptor }
98     }
99 }
100 
101 impl TryFrom<&dyn AsRawDescriptor> for SafeDescriptor {
102     type Error = std::io::Error;
103 
104     /// Clones the underlying descriptor (handle), internally creating a new descriptor.
105     ///
106     /// WARNING: Windows does NOT support cloning/duplicating all types of handles. DO NOT use this
107     /// function on IO completion ports, sockets, or pseudo-handles (except those from
108     /// GetCurrentProcess or GetCurrentThread). See
109     /// <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-duplicatehandle>
110     /// for further details.
111     ///
112     /// TODO(b/191800567): this API has sharp edges on Windows. We should evaluate making some
113     /// adjustments to smooth those edges.
try_from(rd: &dyn AsRawDescriptor) -> std::result::Result<Self, Self::Error>114     fn try_from(rd: &dyn AsRawDescriptor) -> std::result::Result<Self, Self::Error> {
115         // SAFETY:
116         // Safe because the underlying raw descriptor is guaranteed valid by rd's existence.
117         //
118         // Note that we are cloning the underlying raw descriptor since we have no guarantee of
119         // its existence after this function returns.
120         let rd_as_safe_desc = ManuallyDrop::new(unsafe {
121             SafeDescriptor::from_raw_descriptor(rd.as_raw_descriptor())
122         });
123 
124         // We have to clone rd because we have no guarantee ownership was transferred (rd is
125         // borrowed).
126         rd_as_safe_desc
127             .try_clone()
128             .map_err(|e| Self::Error::from_raw_os_error(e.errno()))
129     }
130 }
131 
132 impl From<File> for SafeDescriptor {
from(f: File) -> SafeDescriptor133     fn from(f: File) -> SafeDescriptor {
134         // SAFETY:
135         // Safe because we own the File at this point.
136         unsafe { SafeDescriptor::from_raw_descriptor(f.into_raw_descriptor()) }
137     }
138 }
139 
140 /// For use cases where a simple wrapper around a [`RawDescriptor`] is needed, in order to e.g.
141 /// implement [`trait@AsRawDescriptor`].
142 ///
143 /// This is a simply a wrapper and does not manage the lifetime of the descriptor. As such it is the
144 /// responsibility of the user to ensure that the wrapped descriptor will not be closed for as long
145 /// as the `Descriptor` is alive.
146 ///
147 /// Most use-cases should prefer [`SafeDescriptor`] or implementing and using
148 /// [`trait@AsRawDescriptor`] on the type providing the descriptor. Using this wrapper usually means
149 /// something can be improved in your code.
150 ///
151 /// Valid uses of this struct include:
152 /// * You only have a valid [`RawDescriptor`] and need to pass something that implements
153 ///   [`trait@AsRawDescriptor`] to a function,
154 /// * You need to serialize a [`RawDescriptor`],
155 /// * You need [`trait@Send`] or [`trait@Sync`] for your descriptor and properly handle the case
156 ///   where your descriptor gets closed.
157 ///
158 /// Note that with the exception of the last use-case (which requires proper error checking against
159 /// the descriptor being closed), the `Descriptor` instance would be very short-lived.
160 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
161 #[repr(transparent)]
162 pub struct Descriptor(pub RawDescriptor);
163 impl AsRawDescriptor for Descriptor {
as_raw_descriptor(&self) -> RawDescriptor164     fn as_raw_descriptor(&self) -> RawDescriptor {
165         self.0
166     }
167 }
168 impl FromRawDescriptor for Descriptor {
from_raw_descriptor(desc: RawDescriptor) -> Self169     unsafe fn from_raw_descriptor(desc: RawDescriptor) -> Self {
170         Descriptor(desc)
171     }
172 }
173 
174 /// Implement token for implementations that wish to use this struct as such
175 impl EventToken for Descriptor {
as_raw_token(&self) -> u64176     fn as_raw_token(&self) -> u64 {
177         self.0 as u64
178     }
179 
from_raw_token(data: u64) -> Self180     fn from_raw_token(data: u64) -> Self {
181         Descriptor(data as RawDescriptor)
182     }
183 }
184 
185 impl Serialize for Descriptor {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,186     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
187     where
188         S: Serializer,
189     {
190         serializer.serialize_u64(self.0 as u64)
191     }
192 }
193 
194 impl<'de> Deserialize<'de> for Descriptor {
deserialize<D>(deserializer: D) -> Result<Descriptor, D::Error> where D: serde::Deserializer<'de>,195     fn deserialize<D>(deserializer: D) -> Result<Descriptor, D::Error>
196     where
197         D: serde::Deserializer<'de>,
198     {
199         u64::deserialize(deserializer).map(|data| Descriptor(data as RawDescriptor))
200     }
201 }
202