Skip to main content

selinux/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 fuchsia_rcu::RcuDroppable;
8use selinux_policy_derive::{HasName, HasPolicyId, Validate};
9
10use super::Policy;
11use super::error::{ParseError, SerializeError, ValidateError};
12use super::id_type::IdType;
13use super::parser::{PolicyCursor, PolicyWriter};
14use super::traits::{Parse, PolicyId, Serialize, Validate};
15
16/// Tag type for type safety of policy permission identifiers.
17#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, RcuDroppable)]
18pub struct PermissionTag;
19
20/// Identifies a permission within an object class (class-relative, 1-indexed).
21pub type PermissionId = IdType<NonZeroU8, PermissionTag>;
22
23/// Parsed SELinux permission, containing a type-safe ID and a name.
24#[derive(Debug, Validate, HasName, HasPolicyId)]
25pub struct Permission {
26    id: PermissionId,
27    name: Box<[u8]>,
28}
29
30impl Parse for Permission {
31    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
32        let length = u32::parse(cursor)? as usize;
33        let id_val = u32::parse(cursor)?;
34
35        // Validate permission ID range (1..=32) during parsing
36        if id_val == 0 || id_val > 32 {
37            return Err(ParseError::InvalidId { value: id_val });
38        }
39
40        let name = Box::from(cursor.read_bytes(length)?);
41        let id = PermissionId::from_u32(id_val).ok_or(ParseError::InvalidId { value: id_val })?;
42
43        Ok(Self { id, name })
44    }
45}
46
47impl Serialize for Permission {
48    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
49        let length = self.name.len() as u32;
50        length.serialize(writer)?;
51        self.id.as_u32().serialize(writer)?;
52        writer.write_bytes(&self.name);
53        Ok(())
54    }
55}
56
57impl Validate for PermissionId {
58    fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
59        Ok(())
60    }
61}