Skip to main content

starnix_uapi/
selinux.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use fuchsia_rcu::RcuDroppable;
6use std::num::NonZeroU32;
7use zerocopy::{Immutable, IntoBytes};
8
9/// Identifies a Security Context.
10#[derive(
11    Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, IntoBytes, Immutable, RcuDroppable,
12)]
13pub struct SecurityId(pub NonZeroU32);
14
15/// Initial Security Identifier (SID) values defined by the SELinux Reference Policy.
16/// Where the SELinux Reference Policy retains definitions for some deprecated initial SIDs, this
17/// enum omits deprecated entries for clarity.
18#[repr(u64)]
19pub enum ReferenceInitialSid {
20    Kernel = 1,
21    Security = 2,
22    Unlabeled = 3,
23    _Fs = 4,
24    File = 5,
25    Init = 7,
26    _Port = 9,
27    _Netif = 10,
28    _Netmsg = 11,
29    _Node = 12,
30    _Sysctl = 17,
31    Devnull = 27,
32
33    /// Lowest Security Identifier value guaranteed not to be used by this
34    /// implementation to refer to an initial Security Context.
35    FirstUnused,
36}
37
38#[macro_export]
39macro_rules! initial_sid_enum {
40    ($(#[$meta:meta])* $name:ident {
41        $($(#[$variant_meta:meta])* $variant:ident ($variant_name: literal)),*,
42    }) => {
43        $(#[$meta])*
44        pub enum $name {
45            $($(#[$variant_meta])* $variant = ReferenceInitialSid::$variant as isize),*
46        }
47
48        impl $name {
49            pub fn all_variants() -> &'static [Self] {
50                &[
51                    $($name::$variant),*
52                ]
53            }
54
55            pub fn name(&self) -> &'static str {
56                match self {
57                    $($name::$variant => $variant_name),*
58                }
59            }
60        }
61    }
62}
63
64initial_sid_enum! {
65/// Initial Security Identifier (SID) values actually used by this implementation.
66/// These must be present in the policy, for it to be valid.
67#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
68    InitialSid {
69        // keep-sorted start
70        Devnull("devnull"),
71        File("file"),
72        Init("init"),
73        Kernel("kernel"),
74        Security("security"),
75        Unlabeled("unlabeled"),
76        // keep-sorted end
77    }
78}
79
80impl From<InitialSid> for SecurityId {
81    fn from(initial_sid: InitialSid) -> Self {
82        // Initial SIDs are used by the kernel as placeholder `SecurityId` values for objects
83        // created prior to the SELinux policy being loaded, and are resolved to the policy-defined
84        // Security Context when referenced after policy load.
85        Self(NonZeroU32::new(initial_sid as u32).unwrap())
86    }
87}
88
89/// The SELinux security structure for `ThreadGroup`.
90#[derive(Clone, Debug, PartialEq, RcuDroppable)]
91pub struct TaskAttrs {
92    /// Current SID for the task.
93    pub current_sid: SecurityId,
94
95    /// SID for the task upon the next execve call.
96    pub exec_sid: Option<SecurityId>,
97
98    /// SID for files created by the task.
99    pub fscreate_sid: Option<SecurityId>,
100
101    /// SID for kernel-managed keys created by the task.
102    pub keycreate_sid: Option<SecurityId>,
103
104    /// SID prior to the last execve.
105    pub previous_sid: SecurityId,
106
107    /// SID for sockets created by the task.
108    pub sockcreate_sid: Option<SecurityId>,
109
110    /// Indicates that the task with these credentials is performing an internal operation where
111    /// access checks must be skipped.
112    pub internal_operation: bool,
113}
114
115impl TaskAttrs {
116    /// Returns initial state for kernel tasks.
117    pub fn for_kernel() -> Self {
118        Self::for_transition(InitialSid::Kernel.into(), InitialSid::Kernel.into())
119    }
120
121    /// Returns placeholder state for use when SELinux is not enabled.
122    pub fn for_selinux_disabled() -> Self {
123        Self::for_transition(InitialSid::Unlabeled.into(), InitialSid::Unlabeled.into())
124    }
125
126    /// Used to create new security state when transitioning a task to a new SID.
127    pub fn for_transition(new_sid: SecurityId, previous_sid: SecurityId) -> Self {
128        Self {
129            current_sid: new_sid,
130            previous_sid,
131            exec_sid: None,
132            fscreate_sid: None,
133            keycreate_sid: None,
134            sockcreate_sid: None,
135            internal_operation: false,
136        }
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn task_alloc_for_kernel() {
146        let for_kernel = TaskAttrs::for_kernel();
147        assert_eq!(for_kernel.current_sid, InitialSid::Kernel.into());
148        assert_eq!(for_kernel.previous_sid, for_kernel.current_sid);
149        assert_eq!(for_kernel.exec_sid, None);
150        assert_eq!(for_kernel.fscreate_sid, None);
151        assert_eq!(for_kernel.keycreate_sid, None);
152        assert_eq!(for_kernel.sockcreate_sid, None);
153    }
154}