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