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