Skip to main content

selinux/kernel/
mod.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
5//! Starnix kernel object class and permission definitions, policy-to-kernel index, and access
6//! vector cache (AVC).
7
8mod avc;
9mod index;
10mod permissions;
11
12pub use avc::{
13    AccessCacheStorage, AccessQueryArgs, CacheStats, ConcurrentAccessCache, DEFAULT_SHARED_SIZE,
14    PerThreadCache, QueryCacheCapacity,
15};
16pub(crate) use avc::{AccessVectorCache, Query};
17pub(crate) use index::PolicyIndex;
18pub use permissions::*;
19
20use crate::policy::{AccessVector, ClassId, XpermsBitmap};
21use fuchsia_rcu::RcuDroppable;
22use std::num::NonZeroU32;
23
24/// Identifies a specific class by its policy-defined Id, or as a kernel object class enum Id.
25#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, RcuDroppable)]
26pub enum ObjectClass {
27    /// Refers to a well-known SELinux [`KernelClass`] (e.g. "process", "file", "capability").
28    Kernel(KernelClass),
29    /// Refers to a policy-defined class by its policy-defined numeric [`ClassId`]. This is most
30    /// commonly used when handling queries from userspace, which refer to classes by ID.
31    ClassId(ClassId),
32}
33
34impl From<ClassId> for ObjectClass {
35    fn from(id: ClassId) -> Self {
36        Self::ClassId(id)
37    }
38}
39
40impl<T: Into<KernelClass>> From<T> for ObjectClass {
41    fn from(class: T) -> Self {
42        Self::Kernel(class.into())
43    }
44}
45
46/// Access decision translated into kernel permission bit positions for a [`KernelClass`].
47#[derive(Clone, Copy, Debug, PartialEq, Eq)]
48pub struct KernelAccessDecision {
49    pub allow: AccessVector,
50    pub audit: AccessVector,
51    pub flags: u32,
52    pub todo_bug: Option<NonZeroU32>,
53}
54
55/// Extended permission access decision as seen from the kernel.
56#[derive(Clone, Copy, PartialEq, Debug)]
57pub(crate) struct KernelXpermsAccessDecision {
58    /// Set of xperms that are allowed.
59    pub allow: XpermsBitmap,
60    /// Set of xperms that should be audited (as allowed or denials depending on `allow`).
61    pub audit: XpermsBitmap,
62    /// Whether the domain is permissive.
63    pub permissive: bool,
64    /// Whether the entry has an associated todo.
65    pub has_todo: bool,
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn object_class_permissions() {
74        let test_class_id = ClassId::for_test(20);
75        assert_eq!(ObjectClass::ClassId(test_class_id), test_class_id.into());
76        for variant in KernelClass::Process.permissions() {
77            assert_eq!(KernelClass::Process, variant.class());
78            assert_eq!("process", variant.class().name());
79            assert_eq!(ObjectClass::Kernel(KernelClass::Process), variant.class().into());
80        }
81    }
82
83    #[test]
84    fn kernel_class_from_name() {
85        assert_eq!(KernelClass::from_name("process"), Some(KernelClass::Process));
86        assert_eq!(KernelClass::from_name("file"), Some(KernelClass::File));
87        assert_eq!(KernelClass::from_name("socket"), Some(KernelClass::Socket));
88        assert_eq!(KernelClass::from_name("non_existent_class"), None);
89    }
90}