1use std::num::NonZeroU16;
6
7use hashbrown::HashTable;
8use selinux_policy_derive::{HasPolicyId, Parse, Serialize};
9
10use super::bitmap::IdSet;
11use super::error::{ParseError, SerializeError, ValidateError};
12use super::id_type::IdType;
13use super::indexed::hash_name;
14use super::parser::{Array, PolicyCursor};
15use super::traits::{HasName, Parse, PolicyId, Serialize, Validate};
16use super::{NewPolicy, U24Index};
17
18#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
20pub struct TypeTag;
21
22pub type TypeId = IdType<NonZeroU16, TypeTag>;
24
25pub type PermissiveTypeSet = IdSet<TypeId, true>;
27
28pub type TypeSet = IdSet<TypeId>;
30
31impl Validate for TypeId {
32 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
33 policy
34 .types()
35 .get_by_id(*self)
36 .map(|_| ())
37 .ok_or_else(|| ValidateError::UnknownId { kind: "type", id: self.as_u32() })
38 }
39}
40
41#[derive(Copy, Clone, Debug, PartialEq, Eq)]
42pub enum TypeKind {
43 Alias,
44 Type,
45 Attribute,
46}
47
48impl TypeKind {
49 pub const ALIAS: u32 = 0;
50 pub const TYPE: u32 = 1;
51 pub const ATTRIBUTE: u32 = 3;
52}
53
54#[derive(Debug, Clone, PartialEq, Eq, HasPolicyId)]
56pub struct Type {
57 pub(super) id: TypeId,
58 pub(super) name: Box<[u8]>,
59 pub(super) properties: TypeKind,
60 pub(super) bounds: Option<TypeId>,
61}
62
63impl HasName for Type {
64 fn name(&self) -> &[u8] {
65 &self.name
66 }
67}
68
69impl Type {
70 pub fn bounded_by(&self) -> Option<TypeId> {
71 self.bounds
72 }
73}
74
75#[derive(Parse, Serialize)]
76struct BinaryTypeMetadata {
77 length: u32,
78 id: u32,
79 properties: u32,
80 bounds: u32,
81}
82
83impl Parse for Type {
84 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
85 let metadata = BinaryTypeMetadata::parse(cursor)?;
86 let name = cursor.read_bytes(metadata.length as usize)?.to_vec().into_boxed_slice();
87
88 let properties_val = metadata.properties;
89 let properties = match properties_val {
90 TypeKind::ALIAS => TypeKind::Alias,
91 TypeKind::TYPE => TypeKind::Type,
92 TypeKind::ATTRIBUTE => TypeKind::Attribute,
93 v => {
94 return Err(ParseError::InvalidEnumValue {
95 enum_name: "TypeKind",
96 value: v as u64,
97 });
98 }
99 };
100
101 let bounds = TypeId::from_u32(metadata.bounds);
102 let id =
103 TypeId::from_u32(metadata.id).ok_or(ParseError::InvalidId { value: metadata.id })?;
104
105 Ok(Self { id, name, properties, bounds })
106 }
107}
108
109impl Serialize for Type {
110 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
111 let properties_val = match self.properties {
112 TypeKind::Alias => TypeKind::ALIAS,
113 TypeKind::Type => TypeKind::TYPE,
114 TypeKind::Attribute => TypeKind::ATTRIBUTE,
115 };
116 let metadata = BinaryTypeMetadata {
117 length: self.name.len() as u32,
118 id: self.id.as_u32(),
119 properties: properties_val,
120 bounds: self.bounds.map_or(0, |id| id.as_u32()),
121 };
122 metadata.serialize(writer)?;
123 writer.extend_from_slice(&self.name);
124 Ok(())
125 }
126}
127
128impl Validate for Type {
129 fn validate(&self, _policy: &NewPolicy) -> Result<(), ValidateError> {
130 Ok(())
132 }
133}
134
135#[derive(Debug, Clone)]
137pub struct Types {
138 primary_names_count: u32,
139 ordered: Array<Type>,
141
142 by_id: Box<[Option<U24Index>]>,
145
146 by_name: HashTable<U24Index>,
148 hasher: rapidhash::RapidBuildHasher,
149}
150
151impl PartialEq for Types {
152 fn eq(&self, other: &Self) -> bool {
153 self.primary_names_count == other.primary_names_count && self.ordered == other.ordered
154 }
155}
156
157impl Eq for Types {}
158
159impl Parse for Types {
160 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
161 let primary_names_count = u32::parse(cursor)?;
162 let ordered = Array::<Type>::parse(cursor)?;
163
164 let mut by_id = Vec::new();
166 let hasher = rapidhash::RapidBuildHasher::default();
167 let mut by_name = HashTable::new();
168
169 for (index, t) in ordered.iter().enumerate() {
170 let u24_idx: U24Index = index.try_into()?;
171 if t.properties == TypeKind::Type || t.properties == TypeKind::Attribute {
172 let id = t.id.as_u32() as usize;
173 if id > by_id.len() {
174 by_id.resize(id, None);
175 }
176 by_id[id - 1] = Some(u24_idx);
177 }
178 if t.properties == TypeKind::Type || t.properties == TypeKind::Alias {
179 let hash = hash_name(&hasher, t.name.as_ref());
180 by_name.insert_unique(hash, u24_idx, |&idx| {
181 hash_name(&hasher, ordered[idx].name.as_ref())
182 });
183 }
184 }
185
186 Ok(Self { primary_names_count, ordered, by_id: by_id.into_boxed_slice(), by_name, hasher })
187 }
188}
189
190impl Serialize for Types {
191 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
192 self.primary_names_count.serialize(writer)?;
193 self.ordered.serialize(writer)
194 }
195}
196
197impl Validate for Types {
198 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
199 for t in self.ordered.iter() {
200 t.validate(policy)?;
201 }
202 Ok(())
203 }
204}
205
206impl Types {
207 pub fn primary_names_count(&self) -> u32 {
208 self.primary_names_count
209 }
210
211 pub fn get_by_id(&self, id: TypeId) -> Option<&Type> {
212 let index = self.by_id.get((id.as_u32() - 1) as usize)?.as_ref()?;
213 Some(&self.ordered[*index])
214 }
215
216 pub fn get_by_name(&self, name: &[u8]) -> Option<&Type> {
217 let hash = hash_name(&self.hasher, name);
218 let idx = self.by_name.find(hash, |&idx| self.ordered[idx].name.as_ref() == name)?;
219 Some(&self.ordered[*idx])
220 }
221
222 pub fn is_empty(&self) -> bool {
223 self.ordered.is_empty()
224 }
225
226 pub fn iter(&self) -> impl Iterator<Item = &Type> {
227 self.ordered.iter()
228 }
229}