Skip to main content

selinux/new_policy/
permissions.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::NonZeroU8;
6
7use super::NewPolicy;
8use super::error::{ParseError, SerializeError, ValidateError};
9use super::id_type::IdType;
10use super::parser::PolicyCursor;
11use super::traits::{Parse, PolicyId, Serialize, Validate};
12use selinux_policy_derive::{HasName, HasPolicyId};
13
14/// Tag type for type safety of policy permission identifiers.
15#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
16pub struct PermissionTag;
17
18/// Identifies a permission within an object class (class-relative, 1-indexed).
19pub type PermissionId = IdType<NonZeroU8, PermissionTag>;
20
21/// Parsed SELinux permission, containing a type-safe ID and a name.
22#[derive(Debug, Clone, PartialEq, Eq, HasName, HasPolicyId)]
23pub struct Permission {
24    id: PermissionId,
25    name: Box<[u8]>,
26}
27
28impl Permission {
29    /// Returns the class-relative permission ID.
30    pub fn id(&self) -> PermissionId {
31        self.id
32    }
33
34    /// Returns the 0-based index of this permission in the access vector (0..31).
35    pub fn index(&self) -> u8 {
36        (self.id.as_u32() - 1) as u8
37    }
38
39    /// Returns the name of the permission as a byte slice.
40    pub fn name_bytes(&self) -> &[u8] {
41        &self.name
42    }
43}
44
45impl Parse for Permission {
46    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
47        let length = u32::parse(cursor)? as usize;
48        let id_val = u32::parse(cursor)?;
49
50        // Validate permission ID range (1..=32) during parsing
51        if id_val == 0 || id_val > 32 {
52            return Err(ParseError::InvalidId { value: id_val });
53        }
54
55        let name = Box::from(cursor.read_bytes(length)?);
56        let id = PermissionId::from_u32(id_val).ok_or(ParseError::InvalidId { value: id_val })?;
57
58        Ok(Self { id, name })
59    }
60}
61
62impl Serialize for Permission {
63    fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
64        let length = self.name.len() as u32;
65        length.serialize(writer)?;
66        self.id.as_u32().serialize(writer)?;
67        writer.extend_from_slice(&self.name);
68        Ok(())
69    }
70}
71
72impl Validate for Permission {
73    fn validate(&self, _policy: &NewPolicy) -> Result<(), ValidateError> {
74        // Validation is complete structurally during parsing (ID is non-zero and <= 32).
75        Ok(())
76    }
77}