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