• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         // Safe because 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         // Safe as 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         // Safe because 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         // Safe because the underlying pointer is guaranteed to be properly
205         // aligned, dereferenceable, and point to a valid T. The underlying
206         // value will not be modified through the pointer and can only be
207         // accessed through these returned references.
208         unsafe { &*self.token_info }
209     }
210 }
211 
212 impl<T> AsMut<T> for TokenInformation<T> {
as_mut(&mut self) -> &mut T213     fn as_mut(&mut self) -> &mut T {
214         // Safe because the underlying pointer is guaranteed to be properly
215         // aligned, dereferenceable, and point to a valid T. The underlying
216         // value will not be modified through the pointer and can only be
217         // accessed through these returned references.
218         unsafe { &mut *self.token_info }
219     }
220 }
221 
222 impl<T> Drop for TokenInformation<T> {
drop(&mut self)223     fn drop(&mut self) {
224         // Safe because we ensure the pointer is valid in the constructor, and
225         // we are using the same layout struct as during the allocation.
226         unsafe { dealloc(self.token_info as *mut u8, self.layout) }
227     }
228 }
229 
230 pub struct Token {
231     token: RawHandle,
232 }
233 
234 impl Token {
235     /// Open the current process's token.
new_for_process() -> io::Result<Self>236     pub fn new_for_process() -> io::Result<Self> {
237         // Safe because GetCurrentProcess is an alias for -1.
238         Self::from_process(unsafe { GetCurrentProcess() })
239     }
240 
241     /// Open the token of a process.
from_process(proc_handle: RawHandle) -> io::Result<Self>242     pub fn from_process(proc_handle: RawHandle) -> io::Result<Self> {
243         let mut token: RawHandle = ptr::null_mut();
244 
245         // Safe because token is valid.
246         if unsafe {
247             OpenProcessToken(
248                 /* ProcessHandle= */ proc_handle,
249                 /* DesiredAccess= */ TOKEN_ALL_ACCESS,
250                 /* TokenHandle= */ &mut token,
251             ) == 0
252         } {
253             return Err(io::Error::last_os_error());
254         }
255         Ok(Token { token })
256     }
257 
258     /// Open the token of a thread.
from_thread(thread_handle: RawHandle) -> io::Result<Self>259     pub fn from_thread(thread_handle: RawHandle) -> io::Result<Self> {
260         let mut token: RawHandle = ptr::null_mut();
261 
262         // Safe because token is valid. We use OpenAsSelf to ensure the token access is measured
263         // using the caller's non-impersonated identity.
264         if unsafe {
265             OpenThreadToken(
266                 thread_handle,
267                 TOKEN_ALL_ACCESS,
268                 /*OpenAsSelf=*/ TRUE,
269                 &mut token,
270             ) == 0
271         } {
272             return Err(io::Error::last_os_error());
273         }
274         Ok(Token { token })
275     }
276 
get(&mut self) -> RawHandle277     fn get(&mut self) -> RawHandle {
278         self.token
279     }
280 }
281 
282 impl Drop for Token {
drop(&mut self)283     fn drop(&mut self) {
284         // Safe as token is valid, but the call should be safe regardless.
285         unsafe {
286             CloseHandle(self.token);
287         }
288     }
289 }
290 
291 pub trait SecurityDescriptor {
security_descriptor(&self) -> *const SECURITY_DESCRIPTOR292     fn security_descriptor(&self) -> *const SECURITY_DESCRIPTOR;
293 }
294 
295 pub struct AbsoluteSecurityDescriptor {
296     descriptor: SECURITY_DESCRIPTOR,
297     acl: *mut ACL,
298 }
299 
300 impl AbsoluteSecurityDescriptor {
301     /// Creates a `SECURITY_DESCRIPTOR` struct which gives full access rights
302     /// (`GENERIC_ALL`) to only the current user.
new() -> io::Result<AbsoluteSecurityDescriptor>303     fn new() -> io::Result<AbsoluteSecurityDescriptor> {
304         let token = Token::new_for_process()?;
305         let token_user = TokenInformation::<TOKEN_USER>::new(token)?;
306         let sid = token_user.as_ref().User.Sid;
307 
308         let mut ea = EXPLICIT_ACCESS_A {
309             grfAccessPermissions: GENERIC_ALL,
310             grfAccessMode: SET_ACCESS,
311             grfInheritance: NO_INHERITANCE,
312             Trustee: TRUSTEE_A {
313                 TrusteeForm: TRUSTEE_IS_SID,
314                 TrusteeType: TRUSTEE_IS_USER,
315                 ptstrName: sid as *mut i8,
316                 pMultipleTrustee: ptr::null_mut(),
317                 MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE,
318             },
319         };
320 
321         let mut security_descriptor: std::mem::MaybeUninit<AbsoluteSecurityDescriptor> =
322             std::mem::MaybeUninit::uninit();
323 
324         let ptr = security_descriptor.as_mut_ptr();
325 
326         // Safe because security_descriptor is valid but uninitialized, and
327         // InitializeSecurityDescriptor will initialize it.
328         if unsafe {
329             InitializeSecurityDescriptor(
330                 /* pSecurityDescriptor= */
331                 ptr::addr_of_mut!((*ptr).descriptor) as PSECURITY_DESCRIPTOR,
332                 /* dwRevision= */ SECURITY_DESCRIPTOR_REVISION,
333             ) == 0
334         } {
335             return Err(io::Error::last_os_error());
336         }
337 
338         // Safe because ea and acl are valid and OldAcl is allowed to be null.
339         if unsafe {
340             SetEntriesInAclA(
341                 /* cCountOfExplicitEntries= */ 1,
342                 /* pListOfExplicitEntries= */ &mut ea as PEXPLICIT_ACCESSA,
343                 /* OldAcl= */ ptr::null_mut(),
344                 /* NewAcl= */
345                 ptr::addr_of_mut!((*ptr).acl) as *mut PACL,
346             )
347         } != ERROR_SUCCESS
348         {
349             return Err(io::Error::last_os_error());
350         }
351 
352         // Safe because security_descriptor is valid and initialized after
353         // InitializeSecurityDescriptor() and SetEntriesInAclA().
354         let mut security_descriptor = unsafe { security_descriptor.assume_init() };
355         let sd = &mut security_descriptor.descriptor as *mut SECURITY_DESCRIPTOR;
356 
357         // Safe because the descriptor is valid, and acl is valid after SetEntriesInAclA()
358         if unsafe {
359             SetSecurityDescriptorDacl(
360                 /* pSecurityDescriptor= */ sd as PSECURITY_DESCRIPTOR,
361                 /* bDaclPresent= */ TRUE,
362                 /* pDacl= */ security_descriptor.acl,
363                 /* bDaclDefaulted= */ FALSE,
364             ) == 0
365         } {
366             return Err(io::Error::last_os_error());
367         }
368 
369         Ok(security_descriptor)
370     }
371 }
372 
373 impl SecurityDescriptor for AbsoluteSecurityDescriptor {
security_descriptor(&self) -> *const SECURITY_DESCRIPTOR374     fn security_descriptor(&self) -> *const SECURITY_DESCRIPTOR {
375         &self.descriptor as *const SECURITY_DESCRIPTOR
376     }
377 }
378 
379 impl Drop for AbsoluteSecurityDescriptor {
drop(&mut self)380     fn drop(&mut self) {
381         // Safe because we guarantee that on creation acl is initialized to a
382         // pointer that can be freed.
383         unsafe { LocalFree(self.acl as HLOCAL) };
384     }
385 }
386 
387 pub struct SelfRelativeSecurityDescriptor {
388     descriptor: *mut SECURITY_DESCRIPTOR,
389     layout: Layout,
390 }
391 
392 impl Drop for SelfRelativeSecurityDescriptor {
drop(&mut self)393     fn drop(&mut self) {
394         unsafe { dealloc(self.descriptor as *mut u8, self.layout) }
395     }
396 }
397 
398 impl Clone for SelfRelativeSecurityDescriptor {
clone(&self) -> Self399     fn clone(&self) -> Self {
400         // Safe because we know that the layout's size is non-zero.
401         let descriptor = unsafe { alloc_zeroed(self.layout) } as *mut SECURITY_DESCRIPTOR;
402         if descriptor.is_null() {
403             handle_alloc_error(self.layout);
404         }
405         let sd = SelfRelativeSecurityDescriptor {
406             descriptor,
407             layout: self.layout,
408         };
409         // Safe because:
410         //  * `src` is at least `count` bytes, as it was allocated using the above layout.
411         //  * `dst` is at least `count` bytes, as we just allocated it using the above layout.
412         //  * `src` and `dst` are aligned according to the layout, and we are copying byte-wise.
413         //  * `src` and `dst` do not overlap, as we just allocated new memory for `dst`.
414         unsafe {
415             std::ptr::copy_nonoverlapping::<u8>(
416                 /* src= */ self.descriptor as *const u8,
417                 /* dst= */ sd.descriptor as *mut u8,
418                 /* count= */ self.layout.size(),
419             )
420         };
421         sd
422     }
423 }
424 
425 impl TryFrom<AbsoluteSecurityDescriptor> for SelfRelativeSecurityDescriptor {
426     type Error = io::Error;
427 
try_from(sd: AbsoluteSecurityDescriptor) -> io::Result<Self>428     fn try_from(sd: AbsoluteSecurityDescriptor) -> io::Result<Self> {
429         let mut size: u32 = 0;
430         let descriptor = &sd.descriptor as *const SECURITY_DESCRIPTOR;
431 
432         // Safe because descriptor and size are valid, and pSelfRelativeSD is
433         // optional and allowed to be null.
434         if unsafe {
435             MakeSelfRelativeSD(
436                 /* pAbsoluteSD= */ descriptor as PSECURITY_DESCRIPTOR,
437                 /* pSelfRelativeSD= */ ptr::null_mut(),
438                 /* lpdwBufferLength= */ &mut size as LPDWORD,
439             )
440         } == 0
441         {
442             const INSUFFICIENT_BUFFER: i32 = ERROR_INSUFFICIENT_BUFFER as i32;
443             match io::Error::last_os_error().raw_os_error() {
444                 Some(INSUFFICIENT_BUFFER) => {
445                     // Despite returning failure, the function will fill in the
446                     // expected buffer length into the lpdwBufferLength parameter.
447                     // It may fail in other ways (e.g. if an invalid pAbsoluteSD
448                     // is provided), so we check that we receive the expected
449                     // error code before assuming that we received a valid
450                     // lpdwBufferLength. In this case, we can ignore the error.
451                 }
452                 _ => return Err(io::Error::last_os_error()),
453             }
454         }
455         // size must be > 0. 0-sized layouts break alloc()'s assumptions.
456         assert!(size > 0, "Unable to get size of self-relative SD");
457 
458         // Since we don't statically know the full size of the struct, we
459         // allocate memory for it based on the previous call, aligned to pointer
460         // size.
461         let layout = Layout::from_size_align(size as usize, size_of::<LPVOID>())
462             .expect("Failed to create layout");
463         assert!(layout.size() > 0, "Failed to create valid layout");
464         // Safe as we assert that layout's size is non-zero.
465         let self_relative_sd = unsafe { alloc_zeroed(layout) } as *mut SECURITY_DESCRIPTOR;
466         if self_relative_sd.is_null() {
467             handle_alloc_error(layout);
468         }
469 
470         let self_relative_sd = SelfRelativeSecurityDescriptor {
471             descriptor: self_relative_sd,
472             layout,
473         };
474 
475         // Safe because descriptor is valid, the newly allocated
476         // self_relative_sd descriptor is valid, and size is valid.
477         if unsafe {
478             MakeSelfRelativeSD(
479                 /* pAbsoluteSD= */ descriptor as PSECURITY_DESCRIPTOR,
480                 /* pSelfRelativeSD= */ self_relative_sd.descriptor as PSECURITY_DESCRIPTOR,
481                 /* lpdwBufferLength= */ &mut size as LPDWORD,
482             )
483         } == 0
484         {
485             return Err(io::Error::last_os_error());
486         }
487 
488         Ok(self_relative_sd)
489     }
490 }
491 
492 impl SelfRelativeSecurityDescriptor {
493     /// Creates a `SECURITY_DESCRIPTOR` struct which gives full access rights
494     /// (`GENERIC_ALL`) to only the current user.
new() -> io::Result<Self>495     fn new() -> io::Result<Self> {
496         AbsoluteSecurityDescriptor::new()?.try_into()
497     }
498 
499     /// Gets a copy of a singleton `SelfRelativeSecurityDescriptor`.
get_singleton() -> SelfRelativeSecurityDescriptor500     pub fn get_singleton() -> SelfRelativeSecurityDescriptor {
501         static DEFAULT_SECURITY_DESCRIPTOR: OnceCell<SelfRelativeSecurityDescriptor> =
502             OnceCell::new();
503         DEFAULT_SECURITY_DESCRIPTOR
504             .get_or_init(|| {
505                 SelfRelativeSecurityDescriptor::new().expect("Failed to create security descriptor")
506             })
507             .clone()
508     }
509 }
510 
511 impl SecurityDescriptor for SelfRelativeSecurityDescriptor {
security_descriptor(&self) -> *const SECURITY_DESCRIPTOR512     fn security_descriptor(&self) -> *const SECURITY_DESCRIPTOR {
513         self.descriptor
514     }
515 }
516 
517 // Safe because the descriptor and ACLs are treated as immutable by consuming
518 // functions and can be safely shared between threads.
519 unsafe impl Send for SelfRelativeSecurityDescriptor {}
520 
521 // Safe because the descriptor and ACLs are treated as immutable by consuming
522 // functions.
523 unsafe impl Sync for SelfRelativeSecurityDescriptor {}
524