xref: /aosp_15_r20/external/crosvm/win_util/src/security_attributes.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::alloc::alloc_zeroed;
6 use std::alloc::dealloc;
7 use std::alloc::handle_alloc_error;
8 use std::alloc::Layout;
9 use std::convert::TryFrom;
10 use std::convert::TryInto;
11 use std::io;
12 use std::mem::size_of;
13 use std::os::windows::io::RawHandle;
14 use std::ptr;
15 
16 use once_cell::sync::OnceCell;
17 use winapi::shared::minwindef::FALSE;
18 use winapi::shared::minwindef::HLOCAL;
19 use winapi::shared::minwindef::LPDWORD;
20 use winapi::shared::minwindef::LPVOID;
21 use winapi::shared::minwindef::TRUE;
22 use winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER;
23 use winapi::shared::winerror::ERROR_SUCCESS;
24 use winapi::um::accctrl::EXPLICIT_ACCESS_A;
25 use winapi::um::accctrl::NO_INHERITANCE;
26 use winapi::um::accctrl::NO_MULTIPLE_TRUSTEE;
27 use winapi::um::accctrl::PEXPLICIT_ACCESSA;
28 use winapi::um::accctrl::SET_ACCESS;
29 use winapi::um::accctrl::TRUSTEE_A;
30 use winapi::um::accctrl::TRUSTEE_IS_SID;
31 use winapi::um::accctrl::TRUSTEE_IS_USER;
32 use winapi::um::aclapi::SetEntriesInAclA;
33 use winapi::um::handleapi::CloseHandle;
34 use winapi::um::minwinbase::SECURITY_ATTRIBUTES;
35 use winapi::um::processthreadsapi::GetCurrentProcess;
36 use winapi::um::processthreadsapi::OpenProcessToken;
37 use winapi::um::processthreadsapi::OpenThreadToken;
38 use winapi::um::securitybaseapi::GetTokenInformation;
39 use winapi::um::securitybaseapi::InitializeSecurityDescriptor;
40 use winapi::um::securitybaseapi::MakeSelfRelativeSD;
41 use winapi::um::securitybaseapi::SetSecurityDescriptorDacl;
42 use winapi::um::winbase::LocalFree;
43 use winapi::um::winnt::TokenIntegrityLevel;
44 use winapi::um::winnt::TokenStatistics;
45 use winapi::um::winnt::TokenUser;
46 use winapi::um::winnt::ACL;
47 use winapi::um::winnt::GENERIC_ALL;
48 use winapi::um::winnt::PACL;
49 use winapi::um::winnt::PSECURITY_DESCRIPTOR;
50 use winapi::um::winnt::SECURITY_DESCRIPTOR;
51 use winapi::um::winnt::SECURITY_DESCRIPTOR_REVISION;
52 use winapi::um::winnt::TOKEN_ALL_ACCESS;
53 use winapi::um::winnt::TOKEN_INFORMATION_CLASS;
54 use winapi::um::winnt::TOKEN_MANDATORY_LABEL;
55 use winapi::um::winnt::TOKEN_STATISTICS;
56 use winapi::um::winnt::TOKEN_USER;
57 
58 /// Struct for wrapping `SECURITY_ATTRIBUTES` and `SECURITY_DESCRIPTOR`.
59 pub struct SecurityAttributes<T: SecurityDescriptor> {
60     // The security descriptor shouldn't move, as it will be referenced by the
61     // security attributes. We already limit what can be done with the security
62     // attributes by only providing a reference to it, but we also want to
63     // ensure the security descriptor pointer remains valid even if this struct
64     // moves around.
65     _security_descriptor: T,
66     security_attributes: SECURITY_ATTRIBUTES,
67 }
68 
69 impl<T: SecurityDescriptor> SecurityAttributes<T> {
70     /// Create a new `SecurityAttributes` struct with the provided `security_descriptor`.
new_with_security_descriptor(security_descriptor: T, inherit: bool) -> Self71     pub fn new_with_security_descriptor(security_descriptor: T, inherit: bool) -> Self {
72         let sd = security_descriptor.security_descriptor();
73         let security_attributes = SECURITY_ATTRIBUTES {
74             nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
75             lpSecurityDescriptor: sd as PSECURITY_DESCRIPTOR,
76             bInheritHandle: if inherit { TRUE } else { FALSE },
77         };
78         SecurityAttributes {
79             _security_descriptor: security_descriptor,
80             security_attributes,
81         }
82     }
83 }
84 
85 impl SecurityAttributes<SelfRelativeSecurityDescriptor> {
86     /// Create a new `SecurityAttributes` struct. This struct will have a
87     /// `SECURITY_DESCRIPTOR` that allows full access (`GENERIC_ALL`) to only
88     /// the current user.
new(inherit: bool) -> io::Result<Self>89     pub fn new(inherit: bool) -> io::Result<Self> {
90         Ok(Self::new_with_security_descriptor(
91             SelfRelativeSecurityDescriptor::new()?,
92             inherit,
93         ))
94     }
95 }
96 
97 impl<T: SecurityDescriptor> AsRef<SECURITY_ATTRIBUTES> for SecurityAttributes<T> {
as_ref(&self) -> &SECURITY_ATTRIBUTES98     fn as_ref(&self) -> &SECURITY_ATTRIBUTES {
99         &self.security_attributes
100     }
101 }
102 
103 impl<T: SecurityDescriptor> AsMut<SECURITY_ATTRIBUTES> for SecurityAttributes<T> {
as_mut(&mut self) -> &mut SECURITY_ATTRIBUTES104     fn as_mut(&mut self) -> &mut SECURITY_ATTRIBUTES {
105         &mut self.security_attributes
106     }
107 }
108 
109 pub trait TokenClass {
class() -> TOKEN_INFORMATION_CLASS110     fn class() -> TOKEN_INFORMATION_CLASS;
111 }
112 
113 impl TokenClass for TOKEN_MANDATORY_LABEL {
class() -> TOKEN_INFORMATION_CLASS114     fn class() -> TOKEN_INFORMATION_CLASS {
115         TokenIntegrityLevel
116     }
117 }
118 
119 impl TokenClass for TOKEN_STATISTICS {
class() -> TOKEN_INFORMATION_CLASS120     fn class() -> TOKEN_INFORMATION_CLASS {
121         TokenStatistics
122     }
123 }
124 
125 impl TokenClass for TOKEN_USER {
class() -> TOKEN_INFORMATION_CLASS126     fn class() -> TOKEN_INFORMATION_CLASS {
127         TokenUser
128     }
129 }
130 
131 pub struct TokenInformation<T> {
132     token_info: *mut T,
133     layout: Layout,
134 }
135 
136 impl<T: TokenClass> TokenInformation<T> {
new(mut token: Token) -> io::Result<Self>137     pub fn new(mut token: Token) -> io::Result<Self> {
138         let token_handle = token.get();
139         // Retrieve the size of the struct.
140         let mut size: u32 = 0;
141         // SAFETY: size is valid, and TokenInformation is optional and allowed to be null.
142         if unsafe {
143             // The idiomatic usage of GetTokenInformation() requires two calls
144             // to the function: the first to get the length of the data that the
145             // function would return, and the second to fetch the data.
146             GetTokenInformation(
147                 /* TokenHandle= */ token_handle,
148                 /* TokenInformationClass= */ T::class(),
149                 /* TokenInformation= */ ptr::null_mut(),
150                 /* TokenInformationLength= */ 0,
151                 /* ReturnLength= */ &mut size,
152             ) == 0
153         } {
154             const INSUFFICIENT_BUFFER: i32 = ERROR_INSUFFICIENT_BUFFER as i32;
155             match io::Error::last_os_error().raw_os_error() {
156                 Some(INSUFFICIENT_BUFFER) => {
157                     // Despite returning failure, the function will fill in the
158                     // expected buffer length into the ReturnLength parameter.
159                     // It may fail in other ways (e.g. if an invalid TokenHandle
160                     // is provided), so we check that we receive the expected
161                     // error code before assuming that we received a valid
162                     // ReturnLength. In this case, we can ignore the error.
163                 }
164                 _ => return Err(io::Error::last_os_error()),
165             };
166         }
167 
168         // size must be > 0. 0-sized layouts break alloc()'s assumptions.
169         assert!(size > 0, "Unable to get size of token information");
170 
171         // Since we don't statically know the full size of the struct, we
172         // allocate memory for it based on the previous call, aligned to pointer
173         // size.
174         let layout = Layout::from_size_align(size as usize, size_of::<LPVOID>())
175             .expect("Failed to create layout");
176         assert!(layout.size() > 0, "Failed to create valid layout");
177         // SAFETY: We assert that layout's size is non-zero.
178         let token_info = unsafe { alloc_zeroed(layout) } as *mut T;
179         if token_info.is_null() {
180             handle_alloc_error(layout);
181         }
182 
183         let token_info = TokenInformation::<T> { token_info, layout };
184 
185         // SAFETY: token_user and size are valid.
186         if unsafe {
187             GetTokenInformation(
188                 /* TokenHandle= */ token_handle,
189                 /* TokenInformationClass= */ T::class(),
190                 /* TokenInformation= */ token_info.token_info as LPVOID,
191                 /* TokenInformationLength= */ size,
192                 /* ReturnLength= */ &mut size,
193             ) == 0
194         } {
195             return Err(io::Error::last_os_error());
196         }
197 
198         Ok(token_info)
199     }
200 }
201 
202 impl<T> AsRef<T> for TokenInformation<T> {
as_ref(&self) -> &T203     fn as_ref(&self) -> &T {
204         // SAFETY: The underlying pointer is guaranteed to be properly aligned, dereferenceable, and
205         // point to a valid T. The underlying value will not be modified through the pointer and can
206         // only be accessed through these returned references.
207         unsafe { &*self.token_info }
208     }
209 }
210 
211 impl<T> AsMut<T> for TokenInformation<T> {
as_mut(&mut self) -> &mut T212     fn as_mut(&mut self) -> &mut T {
213         // SAFETY: The underlying pointer is guaranteed to be properly aligned, dereferenceable, and
214         // point to a valid T. The underlying value will not be modified through the pointer and can
215         // only be accessed through these returned references.
216         unsafe { &mut *self.token_info }
217     }
218 }
219 
220 impl<T> Drop for TokenInformation<T> {
drop(&mut self)221     fn drop(&mut self) {
222         // SAFETY: We ensure the pointer is valid in the constructor, and we are using the same
223         // layout struct as during the allocation.
224         unsafe { dealloc(self.token_info as *mut u8, self.layout) }
225     }
226 }
227 
228 pub struct Token {
229     token: RawHandle,
230 }
231 
232 impl Token {
233     /// Open the current process's token.
new_for_process() -> io::Result<Self>234     pub fn new_for_process() -> io::Result<Self> {
235         // SAFETY: GetCurrentProcess is an alias for -1.
236         Self::from_process(unsafe { GetCurrentProcess() })
237     }
238 
239     /// Open the token of a process.
from_process(proc_handle: RawHandle) -> io::Result<Self>240     pub fn from_process(proc_handle: RawHandle) -> io::Result<Self> {
241         let mut token: RawHandle = ptr::null_mut();
242 
243         // SAFETY: Token is valid.
244         if unsafe {
245             OpenProcessToken(
246                 /* ProcessHandle= */ proc_handle,
247                 /* DesiredAccess= */ TOKEN_ALL_ACCESS,
248                 /* TokenHandle= */ &mut token,
249             ) == 0
250         } {
251             return Err(io::Error::last_os_error());
252         }
253         Ok(Token { token })
254     }
255 
256     /// Open the token of a thread.
from_thread(thread_handle: RawHandle) -> io::Result<Self>257     pub fn from_thread(thread_handle: RawHandle) -> io::Result<Self> {
258         let mut token: RawHandle = ptr::null_mut();
259 
260         // SAFETY: Token is valid. We use OpenAsSelf to ensure the token access is measured
261         // using the caller's non-impersonated identity.
262         if unsafe {
263             OpenThreadToken(
264                 thread_handle,
265                 TOKEN_ALL_ACCESS,
266                 /* OpenAsSelf= */ TRUE,
267                 &mut token,
268             ) == 0
269         } {
270             return Err(io::Error::last_os_error());
271         }
272         Ok(Token { token })
273     }
274 
get(&mut self) -> RawHandle275     fn get(&mut self) -> RawHandle {
276         self.token
277     }
278 }
279 
280 impl Drop for Token {
drop(&mut self)281     fn drop(&mut self) {
282         // SAFETY: Token is valid, but the call should be safe regardless.
283         unsafe {
284             CloseHandle(self.token);
285         }
286     }
287 }
288 
289 pub trait SecurityDescriptor {
security_descriptor(&self) -> *const SECURITY_DESCRIPTOR290     fn security_descriptor(&self) -> *const SECURITY_DESCRIPTOR;
291 }
292 
293 pub struct AbsoluteSecurityDescriptor {
294     descriptor: SECURITY_DESCRIPTOR,
295     acl: *mut ACL,
296 }
297 
298 impl AbsoluteSecurityDescriptor {
299     /// Creates a `SECURITY_DESCRIPTOR` struct which gives full access rights
300     /// (`GENERIC_ALL`) to only the current user.
new() -> io::Result<AbsoluteSecurityDescriptor>301     fn new() -> io::Result<AbsoluteSecurityDescriptor> {
302         let token = Token::new_for_process()?;
303         let token_user = TokenInformation::<TOKEN_USER>::new(token)?;
304         let sid = token_user.as_ref().User.Sid;
305 
306         let mut ea = EXPLICIT_ACCESS_A {
307             grfAccessPermissions: GENERIC_ALL,
308             grfAccessMode: SET_ACCESS,
309             grfInheritance: NO_INHERITANCE,
310             Trustee: TRUSTEE_A {
311                 TrusteeForm: TRUSTEE_IS_SID,
312                 TrusteeType: TRUSTEE_IS_USER,
313                 ptstrName: sid as *mut i8,
314                 pMultipleTrustee: ptr::null_mut(),
315                 MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
316             },
317         };
318 
319         let mut security_descriptor: std::mem::MaybeUninit<AbsoluteSecurityDescriptor> =
320             std::mem::MaybeUninit::uninit();
321 
322         let ptr = security_descriptor.as_mut_ptr();
323 
324         // SAFETY: security_descriptor is valid but uninitialized, and
325         // InitializeSecurityDescriptor will initialize it.
326         if unsafe {
327             InitializeSecurityDescriptor(
328                 /* pSecurityDescriptor= */
329                 ptr::addr_of_mut!((*ptr).descriptor) as PSECURITY_DESCRIPTOR,
330                 /* dwRevision= */ SECURITY_DESCRIPTOR_REVISION,
331             ) == 0
332         } {
333             return Err(io::Error::last_os_error());
334         }
335 
336         // SAFETY: ea and acl are valid and OldAcl is allowed to be null.
337         if unsafe {
338             SetEntriesInAclA(
339                 /* cCountOfExplicitEntries= */ 1,
340                 /* pListOfExplicitEntries= */ &mut ea as PEXPLICIT_ACCESSA,
341                 /* OldAcl= */ ptr::null_mut(),
342                 /* NewAcl= */
343                 ptr::addr_of_mut!((*ptr).acl) as *mut PACL,
344             )
345         } != ERROR_SUCCESS
346         {
347             return Err(io::Error::last_os_error());
348         }
349 
350         // SAFETY: security_descriptor is valid and initialized after
351         // InitializeSecurityDescriptor() and SetEntriesInAclA().
352         let mut security_descriptor = unsafe { security_descriptor.assume_init() };
353         let sd = &mut security_descriptor.descriptor as *mut SECURITY_DESCRIPTOR;
354 
355         // SAFETY: The descriptor is valid, and acl is valid after SetEntriesInAclA()
356         if unsafe {
357             SetSecurityDescriptorDacl(
358                 /* pSecurityDescriptor= */ sd as PSECURITY_DESCRIPTOR,
359                 /* bDaclPresent= */ TRUE,
360                 /* pDacl= */ security_descriptor.acl,
361                 /* bDaclDefaulted= */ FALSE,
362             ) == 0
363         } {
364             return Err(io::Error::last_os_error());
365         }
366 
367         Ok(security_descriptor)
368     }
369 }
370 
371 impl SecurityDescriptor for AbsoluteSecurityDescriptor {
security_descriptor(&self) -> *const SECURITY_DESCRIPTOR372     fn security_descriptor(&self) -> *const SECURITY_DESCRIPTOR {
373         &self.descriptor as *const SECURITY_DESCRIPTOR
374     }
375 }
376 
377 impl Drop for AbsoluteSecurityDescriptor {
drop(&mut self)378     fn drop(&mut self) {
379         // SAFETY: We guarantee that on creation acl is initialized to a pointer that can be freed.
380         unsafe { LocalFree(self.acl as HLOCAL) };
381     }
382 }
383 
384 pub struct SelfRelativeSecurityDescriptor {
385     descriptor: *mut SECURITY_DESCRIPTOR,
386     layout: Layout,
387 }
388 
389 impl Drop for SelfRelativeSecurityDescriptor {
drop(&mut self)390     fn drop(&mut self) {
391         // SAFETY: We own self.descriptor and guarantee it is a valid pointer.
392         unsafe { dealloc(self.descriptor as *mut u8, self.layout) }
393     }
394 }
395 
396 impl Clone for SelfRelativeSecurityDescriptor {
clone(&self) -> Self397     fn clone(&self) -> Self {
398         // SAFETY: We know that the layout's size is non-zero.
399         let descriptor = unsafe { alloc_zeroed(self.layout) } as *mut SECURITY_DESCRIPTOR;
400         if descriptor.is_null() {
401             handle_alloc_error(self.layout);
402         }
403         let sd = SelfRelativeSecurityDescriptor {
404             descriptor,
405             layout: self.layout,
406         };
407         // SAFETY:
408         //  * `src` is at least `count` bytes, as it was allocated using the above layout.
409         //  * `dst` is at least `count` bytes, as we just allocated it using the above layout.
410         //  * `src` and `dst` are aligned according to the layout, and we are copying byte-wise.
411         //  * `src` and `dst` do not overlap, as we just allocated new memory for `dst`.
412         unsafe {
413             std::ptr::copy_nonoverlapping::<u8>(
414                 /* src= */ self.descriptor as *const u8,
415                 /* dst= */ sd.descriptor as *mut u8,
416                 /* count= */ self.layout.size(),
417             )
418         };
419         sd
420     }
421 }
422 
423 impl TryFrom<AbsoluteSecurityDescriptor> for SelfRelativeSecurityDescriptor {
424     type Error = io::Error;
425 
try_from(sd: AbsoluteSecurityDescriptor) -> io::Result<Self>426     fn try_from(sd: AbsoluteSecurityDescriptor) -> io::Result<Self> {
427         let mut size: u32 = 0;
428         let descriptor = &sd.descriptor as *const SECURITY_DESCRIPTOR;
429 
430         // SAFETY: Descriptor and size are valid, and pSelfRelativeSD is optional and allowed to be
431         // null.
432         if unsafe {
433             MakeSelfRelativeSD(
434                 /* pAbsoluteSD= */ descriptor as PSECURITY_DESCRIPTOR,
435                 /* pSelfRelativeSD= */ ptr::null_mut(),
436                 /* lpdwBufferLength= */ &mut size as LPDWORD,
437             )
438         } == 0
439         {
440             const INSUFFICIENT_BUFFER: i32 = ERROR_INSUFFICIENT_BUFFER as i32;
441             match io::Error::last_os_error().raw_os_error() {
442                 Some(INSUFFICIENT_BUFFER) => {
443                     // Despite returning failure, the function will fill in the
444                     // expected buffer length into the lpdwBufferLength parameter.
445                     // It may fail in other ways (e.g. if an invalid pAbsoluteSD
446                     // is provided), so we check that we receive the expected
447                     // error code before assuming that we received a valid
448                     // lpdwBufferLength. In this case, we can ignore the error.
449                 }
450                 _ => return Err(io::Error::last_os_error()),
451             }
452         }
453         // size must be > 0. 0-sized layouts break alloc()'s assumptions.
454         assert!(size > 0, "Unable to get size of self-relative SD");
455 
456         // Since we don't statically know the full size of the struct, we
457         // allocate memory for it based on the previous call, aligned to pointer
458         // size.
459         let layout = Layout::from_size_align(size as usize, size_of::<LPVOID>())
460             .expect("Failed to create layout");
461         assert!(layout.size() > 0, "Failed to create valid layout");
462         // SAFETY: We assert that layout's size is non-zero.
463         let self_relative_sd = unsafe { alloc_zeroed(layout) } as *mut SECURITY_DESCRIPTOR;
464         if self_relative_sd.is_null() {
465             handle_alloc_error(layout);
466         }
467 
468         let self_relative_sd = SelfRelativeSecurityDescriptor {
469             descriptor: self_relative_sd,
470             layout,
471         };
472 
473         // SAFETY: Descriptor is valid, the newly allocated self_relative_sd descriptor is valid,
474         // and size is valid.
475         if unsafe {
476             MakeSelfRelativeSD(
477                 /* pAbsoluteSD= */ descriptor as PSECURITY_DESCRIPTOR,
478                 /* pSelfRelativeSD= */ self_relative_sd.descriptor as PSECURITY_DESCRIPTOR,
479                 /* lpdwBufferLength= */ &mut size as LPDWORD,
480             )
481         } == 0
482         {
483             return Err(io::Error::last_os_error());
484         }
485 
486         Ok(self_relative_sd)
487     }
488 }
489 
490 impl SelfRelativeSecurityDescriptor {
491     /// Creates a `SECURITY_DESCRIPTOR` struct which gives full access rights
492     /// (`GENERIC_ALL`) to only the current user.
new() -> io::Result<Self>493     fn new() -> io::Result<Self> {
494         AbsoluteSecurityDescriptor::new()?.try_into()
495     }
496 
497     /// Gets a copy of a singleton `SelfRelativeSecurityDescriptor`.
get_singleton() -> SelfRelativeSecurityDescriptor498     pub fn get_singleton() -> SelfRelativeSecurityDescriptor {
499         static DEFAULT_SECURITY_DESCRIPTOR: OnceCell<SelfRelativeSecurityDescriptor> =
500             OnceCell::new();
501         DEFAULT_SECURITY_DESCRIPTOR
502             .get_or_init(|| {
503                 SelfRelativeSecurityDescriptor::new().expect("Failed to create security descriptor")
504             })
505             .clone()
506     }
507 }
508 
509 impl SecurityDescriptor for SelfRelativeSecurityDescriptor {
security_descriptor(&self) -> *const SECURITY_DESCRIPTOR510     fn security_descriptor(&self) -> *const SECURITY_DESCRIPTOR {
511         self.descriptor
512     }
513 }
514 
515 // SAFETY: The descriptor and ACLs are treated as immutable by consuming functions and can be safely
516 // shared between threads.
517 unsafe impl Send for SelfRelativeSecurityDescriptor {}
518 
519 //SAFETY: The descriptor and ACLs are treated as immutable by consuming functions.
520 unsafe impl Sync for SelfRelativeSecurityDescriptor {}
521