xref: /linux/rust/kernel/security.rs (revision f2ad904e923f70a80f478febf001f88dfd65a64c)
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