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