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