Skip to main content

selinux/
lib.rs

1// Copyright 2024 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
5#![warn(variant_size_differences)]
6
7mod exceptions_config;
8mod kernel;
9pub mod permission_check;
10pub mod policy;
11pub mod security_server;
12mod sid_table;
13mod sync;
14
15pub use kernel::*;
16pub use policy::{ClassId, FsUseType, PolicyCap};
17pub use security_server::{PolicySeqNo, SecurityServer};
18pub use starnix_uapi::selinux::{InitialSid, ReferenceInitialSid, SecurityId, TaskAttrs};
19
20/// A borrowed byte slice that contains no `NUL` characters by truncating the input slice at the
21/// first `NUL` (if any) upon construction.
22#[derive(Clone, Copy, Debug, PartialEq)]
23pub struct NullessByteStr<'a>(&'a [u8]);
24
25impl<'a> NullessByteStr<'a> {
26    /// Returns a non-null-terminated representation of the security context string.
27    pub fn as_bytes(&self) -> &[u8] {
28        &self.0
29    }
30}
31
32impl<'a, S: AsRef<[u8]> + ?Sized> From<&'a S> for NullessByteStr<'a> {
33    /// Any `AsRef<[u8]>` can be processed into a [`NullessByteStr`]. The [`NullessByteStr`] will
34    /// retain everything up to (but not including) a null character, or else the complete byte
35    /// string.
36    fn from(s: &'a S) -> Self {
37        let value = s.as_ref();
38        match value.iter().position(|c| *c == 0) {
39            Some(end) => Self(&value[..end]),
40            None => Self(value),
41        }
42    }
43}
44
45#[derive(Clone, Debug, PartialEq)]
46pub struct FileSystemMountSids {
47    pub context: Option<SecurityId>,
48    pub fs_context: Option<SecurityId>,
49    pub def_context: Option<SecurityId>,
50    pub root_context: Option<SecurityId>,
51}
52
53#[derive(Clone, Debug, PartialEq)]
54pub struct FileSystemLabel {
55    pub sid: SecurityId,
56    pub scheme: FileSystemLabelingScheme,
57    // Sids obtained by parsing the mount options of the FileSystem.
58    pub mount_sids: FileSystemMountSids,
59}
60
61#[derive(Clone, Debug, PartialEq)]
62pub enum FileSystemLabelingScheme {
63    /// This filesystem was mounted with "context=".
64    Mountpoint { sid: SecurityId },
65    /// This filesystem has an "fs_use_xattr", "fs_use_task", or "fs_use_trans" entry in the
66    /// policy. If the `fs_use_type` is "fs_use_xattr" then the `default_sid` specifies the SID
67    /// with which to label `FsNode`s of files that do not have the "security.selinux" xattr.
68    FsUse { fs_use_type: FsUseType, default_sid: SecurityId },
69    /// This filesystem has one or more "genfscon" statements associated with it in the policy.
70    /// If `supports_seclabel` is true then nodes in the filesystem may be dynamically relabeled.
71    GenFsCon { supports_seclabel: bool },
72}
73
74/// SELinux security context-related filesystem mount options. These options are documented in the
75/// `context=context, fscontext=context, defcontext=context, and rootcontext=context` section of
76/// the `mount(8)` manpage.
77#[derive(Clone, Debug, Default, PartialEq)]
78pub struct FileSystemMountOptions {
79    /// Specifies the effective security context to use for all nodes in the filesystem, and the
80    /// filesystem itself. If the filesystem already contains security attributes then these are
81    /// ignored. May not be combined with any of the other options.
82    pub context: Option<Vec<u8>>,
83    /// Specifies an effective security context to use for un-labeled nodes in the filesystem,
84    /// rather than falling-back to the policy-defined "file" context.
85    pub def_context: Option<Vec<u8>>,
86    /// The value of the `fscontext=[security-context]` mount option. This option is used to
87    /// label the filesystem (superblock) itself.
88    pub fs_context: Option<Vec<u8>>,
89    /// The value of the `rootcontext=[security-context]` mount option. This option is used to
90    /// (re)label the inode located at the filesystem mountpoint.
91    pub root_context: Option<Vec<u8>>,
92}
93
94/// Status information parameter for the [`SeLinuxStatusPublisher`] interface.
95pub struct SeLinuxStatus {
96    /// SELinux-wide enforcing vs. permissive mode  bit.
97    pub is_enforcing: bool,
98    /// Number of times the policy has been changed since SELinux started.
99    pub change_count: u32,
100    /// Bit indicating whether operations unknown SELinux abstractions will be denied.
101    pub deny_unknown: bool,
102}
103
104/// Interface for security server to interact with selinuxfs status file.
105pub trait SeLinuxStatusPublisher: Send + Sync {
106    /// Sets the value part of the associated selinuxfs status file.
107    fn set_status(&mut self, policy_status: SeLinuxStatus);
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn nulless_byte_str_equivalence() {
116        let unterminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0".into();
117        let nul_terminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0\0".into();
118        let nul_containing: NullessByteStr<'_> =
119            b"u:object_r:test_valid_t:s0\0IGNORE THIS\0!\0".into();
120
121        for context in [nul_terminated, nul_containing] {
122            assert_eq!(unterminated, context);
123            assert_eq!(unterminated.as_bytes(), context.as_bytes());
124        }
125    }
126}