1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2024 Google LLC. 4 5 //! Linux Security Modules (LSM). 6 //! 7 //! C header: [`include/linux/security.h`](srctree/include/linux/security.h). 8 9 use crate::{ 10 bindings, 11 error::{to_result, Result}, 12 }; 13 14 /// A security context string. 15 /// 16 /// # Invariants 17 /// 18 /// The `ctx` field corresponds to a valid security context as returned by a successful call to 19 /// `security_secid_to_secctx`, that has not yet been destroyed by `security_release_secctx`. 20 pub struct SecurityCtx { 21 ctx: bindings::lsm_context, 22 } 23 24 impl SecurityCtx { 25 /// Get the security context given its id. 26 pub fn from_secid(secid: u32) -> Result<Self> { 27 // SAFETY: `struct lsm_context` can be initialized to all zeros. 28 let mut ctx: bindings::lsm_context = unsafe { core::mem::zeroed() }; 29 30 // SAFETY: Just a C FFI call. The pointer is valid for writes. 31 to_result(unsafe { bindings::security_secid_to_secctx(secid, &mut ctx) })?; 32 33 // INVARIANT: If the above call did not fail, then we have a valid security context. 34 Ok(Self { ctx }) 35 } 36 37 /// Returns whether the security context is empty. 38 pub fn is_empty(&self) -> bool { 39 self.ctx.len == 0 40 } 41 42 /// Returns the length of this security context. 43 pub fn len(&self) -> usize { 44 self.ctx.len as usize 45 } 46 47 /// Returns the bytes for this security context. 48 pub fn as_bytes(&self) -> &[u8] { 49 let ptr = self.ctx.context; 50 if ptr.is_null() { 51 debug_assert_eq!(self.len(), 0); 52 // We can't pass a null pointer to `slice::from_raw_parts` even if the length is zero. 53 return &[]; 54 } 55 56 // SAFETY: The call to `security_secid_to_secctx` guarantees that the pointer is valid for 57 // `self.len()` bytes. Furthermore, if the length is zero, then we have ensured that the 58 // pointer is not null. 59 unsafe { core::slice::from_raw_parts(ptr.cast(), self.len()) } 60 } 61 } 62 63 impl Drop for SecurityCtx { 64 fn drop(&mut self) { 65 // SAFETY: By the invariant of `Self`, this frees a context that came from a successful 66 // call to `security_secid_to_secctx` and has not yet been destroyed by 67 // `security_release_secctx`. 68 unsafe { bindings::security_release_secctx(&mut self.ctx) }; 69 } 70 } 71