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