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