Skip to main content

selinux/new_policy/
users.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 super::context::{MlsLevel, MlsRange};
6use super::error::{ParseError, SerializeError, ValidateError};
7use super::parser::PolicyCursor;
8use super::traits::{Parse, PolicyId, Serialize, Validate};
9use super::{NewPolicy, RoleSet, UserId};
10
11use selinux_policy_derive::{HasName, HasPolicyId, Parse, Serialize, Validate};
12
13/// Parsed SELinux user definition.
14#[derive(Debug, Clone, PartialEq, Eq, Validate, HasName, HasPolicyId)]
15pub struct User {
16    id: UserId,
17    name: Box<[u8]>,
18    bounds: Option<UserId>,
19    roles: RoleSet,
20    range: MlsRange,
21    default_level: MlsLevel,
22}
23
24impl User {
25    pub fn bounds(&self) -> Option<UserId> {
26        self.bounds
27    }
28
29    pub fn roles(&self) -> &RoleSet {
30        &self.roles
31    }
32
33    pub fn mls_range(&self) -> &MlsRange {
34        &self.range
35    }
36
37    pub fn default_level(&self) -> &MlsLevel {
38        &self.default_level
39    }
40}
41
42#[derive(Parse, Serialize)]
43struct BinaryUserMetadata {
44    key_length: u32,
45    id: u32,
46    bounds: u32,
47}
48
49impl Parse for User {
50    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
51        let metadata = BinaryUserMetadata::parse(cursor)?;
52        let name = Box::from(cursor.read_bytes(metadata.key_length as usize)?);
53        let roles = RoleSet::parse(cursor)?;
54        let range = MlsRange::parse(cursor)?;
55        let default_level = MlsLevel::parse(cursor)?;
56
57        let bounds = UserId::from_u32(metadata.bounds);
58
59        let id =
60            UserId::from_u32(metadata.id).ok_or(ParseError::InvalidId { value: metadata.id })?;
61
62        Ok(Self { id, name, bounds, roles, range, default_level })
63    }
64}
65
66impl Serialize for User {
67    fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
68        let metadata = BinaryUserMetadata {
69            key_length: self.name.len() as u32,
70            id: self.id.as_u32(),
71            bounds: self.bounds.map_or(0, |id| id.as_u32()),
72        };
73        metadata.serialize(writer)?;
74        writer.extend_from_slice(&self.name);
75        self.roles.serialize(writer)?;
76        self.range.serialize(writer)?;
77        self.default_level.serialize(writer)?;
78        Ok(())
79    }
80}
81
82impl Validate for UserId {
83    fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
84        policy
85            .users()
86            .get_by_id(*self)
87            .map(|_| ())
88            .ok_or_else(|| ValidateError::UnknownId { kind: "user", id: self.as_u32() })
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use crate::new_policy::traits::{HasName, HasPolicyId};
96
97    #[test]
98    fn test_user_parse_and_serialize() {
99        let data = [
100            // BinaryUserMetadata
101            4, 0, 0, 0, // key_length = 4
102            1, 0, 0, 0, // id = 1
103            0, 0, 0, 0, // bounds = 0 (None)
104            // name: "test"
105            b't', b'e', b's', b't', // roles (empty RoleSet)
106            64, 0, 0, 0, // map_item_size_bits = 64
107            0, 0, 0, 0, // high_bit = 0
108            0, 0, 0, 0, // count = 0
109            // range (MlsRange with low level only)
110            1, 0, 0, 0, // count = 1
111            1, 0, 0, 0, // sensitivity_low = 1
112            // low_categories (empty CategorySet)
113            64, 0, 0, 0, // map_item_size_bits = 64
114            0, 0, 0, 0, // high_bit = 0
115            0, 0, 0, 0, // count = 0
116            // default_level (MlsLevel)
117            1, 0, 0, 0, // sensitivity = 1
118            // categories (empty CategorySet)
119            64, 0, 0, 0, // map_item_size_bits = 64
120            0, 0, 0, 0, // high_bit = 0
121            0, 0, 0, 0, // count = 0
122        ];
123        let mut cursor = PolicyCursor::new(&data);
124        let user = User::parse(&mut cursor).unwrap();
125        assert_eq!(user.id(), UserId::from_u32(1).unwrap());
126        assert_eq!(user.name(), b"test");
127        assert!(user.bounds().is_none());
128        assert!(user.roles().is_empty());
129        assert_eq!(user.mls_range().low().sensitivity().as_u32(), 1);
130        assert_eq!(user.default_level().sensitivity().as_u32(), 1);
131
132        let mut writer = Vec::new();
133        user.serialize(&mut writer).unwrap();
134        assert_eq!(writer, data);
135    }
136}