1a3df991dSWedson Almeida Filho // SPDX-License-Identifier: GPL-2.0 2a3df991dSWedson Almeida Filho 3a3df991dSWedson Almeida Filho // Copyright (C) 2024 Google LLC. 4a3df991dSWedson Almeida Filho 5a3df991dSWedson Almeida Filho //! Credentials management. 6a3df991dSWedson Almeida Filho //! 7a3df991dSWedson Almeida Filho //! C header: [`include/linux/cred.h`](srctree/include/linux/cred.h). 8a3df991dSWedson Almeida Filho //! 9a3df991dSWedson Almeida Filho //! Reference: <https://www.kernel.org/doc/html/latest/security/credentials.html> 10a3df991dSWedson Almeida Filho 11a3df991dSWedson Almeida Filho use crate::{ 12a3df991dSWedson Almeida Filho bindings, 138ad1a41fSAlice Ryhl task::Kuid, 14a3df991dSWedson Almeida Filho types::{AlwaysRefCounted, Opaque}, 15a3df991dSWedson Almeida Filho }; 16a3df991dSWedson Almeida Filho 17a3df991dSWedson Almeida Filho /// Wraps the kernel's `struct cred`. 18a3df991dSWedson Almeida Filho /// 19a3df991dSWedson Almeida Filho /// Credentials are used for various security checks in the kernel. 20a3df991dSWedson Almeida Filho /// 21a3df991dSWedson Almeida Filho /// Most fields of credentials are immutable. When things have their credentials changed, that 22a3df991dSWedson Almeida Filho /// happens by replacing the credential instead of changing an existing credential. See the [kernel 23a3df991dSWedson Almeida Filho /// documentation][ref] for more info on this. 24a3df991dSWedson Almeida Filho /// 25a3df991dSWedson Almeida Filho /// # Invariants 26a3df991dSWedson Almeida Filho /// 27a3df991dSWedson Almeida Filho /// Instances of this type are always ref-counted, that is, a call to `get_cred` ensures that the 28a3df991dSWedson Almeida Filho /// allocation remains valid at least until the matching call to `put_cred`. 29a3df991dSWedson Almeida Filho /// 30a3df991dSWedson Almeida Filho /// [ref]: https://www.kernel.org/doc/html/latest/security/credentials.html 31a3df991dSWedson Almeida Filho #[repr(transparent)] 32a3df991dSWedson Almeida Filho pub struct Credential(Opaque<bindings::cred>); 33a3df991dSWedson Almeida Filho 34a3df991dSWedson Almeida Filho // SAFETY: 35a3df991dSWedson Almeida Filho // - `Credential::dec_ref` can be called from any thread. 36a3df991dSWedson Almeida Filho // - It is okay to send ownership of `Credential` across thread boundaries. 37a3df991dSWedson Almeida Filho unsafe impl Send for Credential {} 38a3df991dSWedson Almeida Filho 39a3df991dSWedson Almeida Filho // SAFETY: It's OK to access `Credential` through shared references from other threads because 40a3df991dSWedson Almeida Filho // we're either accessing properties that don't change or that are properly synchronised by C code. 41a3df991dSWedson Almeida Filho unsafe impl Sync for Credential {} 42a3df991dSWedson Almeida Filho 43a3df991dSWedson Almeida Filho impl Credential { 44a3df991dSWedson Almeida Filho /// Creates a reference to a [`Credential`] from a valid pointer. 45a3df991dSWedson Almeida Filho /// 46a3df991dSWedson Almeida Filho /// # Safety 47a3df991dSWedson Almeida Filho /// 48a3df991dSWedson Almeida Filho /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the 49a3df991dSWedson Almeida Filho /// returned [`Credential`] reference. 50*ab938b59SAlice Ryhl #[inline] 51a3df991dSWedson Almeida Filho pub unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Credential { 52a3df991dSWedson Almeida Filho // SAFETY: The safety requirements guarantee the validity of the dereference, while the 53a3df991dSWedson Almeida Filho // `Credential` type being transparent makes the cast ok. 54a3df991dSWedson Almeida Filho unsafe { &*ptr.cast() } 55a3df991dSWedson Almeida Filho } 56a3df991dSWedson Almeida Filho 5794d356c0SAlice Ryhl /// Get the id for this security context. 58*ab938b59SAlice Ryhl #[inline] 5994d356c0SAlice Ryhl pub fn get_secid(&self) -> u32 { 6094d356c0SAlice Ryhl let mut secid = 0; 6194d356c0SAlice Ryhl // SAFETY: The invariants of this type ensures that the pointer is valid. 6294d356c0SAlice Ryhl unsafe { bindings::security_cred_getsecid(self.0.get(), &mut secid) }; 6394d356c0SAlice Ryhl secid 6494d356c0SAlice Ryhl } 6594d356c0SAlice Ryhl 66a3df991dSWedson Almeida Filho /// Returns the effective UID of the given credential. 67*ab938b59SAlice Ryhl #[inline] 688ad1a41fSAlice Ryhl pub fn euid(&self) -> Kuid { 69a3df991dSWedson Almeida Filho // SAFETY: By the type invariant, we know that `self.0` is valid. Furthermore, the `euid` 70a3df991dSWedson Almeida Filho // field of a credential is never changed after initialization, so there is no potential 71a3df991dSWedson Almeida Filho // for data races. 728ad1a41fSAlice Ryhl Kuid::from_raw(unsafe { (*self.0.get()).euid }) 73a3df991dSWedson Almeida Filho } 74a3df991dSWedson Almeida Filho } 75a3df991dSWedson Almeida Filho 76a3df991dSWedson Almeida Filho // SAFETY: The type invariants guarantee that `Credential` is always ref-counted. 77a3df991dSWedson Almeida Filho unsafe impl AlwaysRefCounted for Credential { 78*ab938b59SAlice Ryhl #[inline] 79a3df991dSWedson Almeida Filho fn inc_ref(&self) { 80a3df991dSWedson Almeida Filho // SAFETY: The existence of a shared reference means that the refcount is nonzero. 81a3df991dSWedson Almeida Filho unsafe { bindings::get_cred(self.0.get()) }; 82a3df991dSWedson Almeida Filho } 83a3df991dSWedson Almeida Filho 84*ab938b59SAlice Ryhl #[inline] 85a3df991dSWedson Almeida Filho unsafe fn dec_ref(obj: core::ptr::NonNull<Credential>) { 86a3df991dSWedson Almeida Filho // SAFETY: The safety requirements guarantee that the refcount is nonzero. The cast is okay 87a3df991dSWedson Almeida Filho // because `Credential` has the same representation as `struct cred`. 88a3df991dSWedson Almeida Filho unsafe { bindings::put_cred(obj.cast().as_ptr()) }; 89a3df991dSWedson Almeida Filho } 90a3df991dSWedson Almeida Filho } 91