1use std::num::NonZeroU16;
6use std::ops::Index;
7
8use hashbrown::HashTable;
9use hashbrown::hash_table::Entry;
10use selinux_policy_derive::{HasPolicyId, Parse, Serialize, Validate};
11
12use super::bitmap::IdSet;
13use super::error::{ParseError, SerializeError, ValidateError};
14use super::id_type::IdType;
15use super::indexed::hash_name;
16use super::parser::{Array, PolicyCursor, PolicyWriter};
17use super::traits::{HasName, Parse, PolicyId, Serialize, Validate};
18use super::{NewPolicy, U24Index};
19
20#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
22pub struct TypeTag;
23
24pub type TypeId = IdType<NonZeroU16, TypeTag>;
26
27pub type PermissiveTypeSet = IdSet<TypeId, true>;
29
30pub type TypeSet = IdSet<TypeId>;
32
33impl Validate for TypeId {
34 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
35 policy
36 .types()
37 .get_by_id(*self)
38 .map(|_| ())
39 .ok_or_else(|| ValidateError::UnknownId { kind: "type", id: self.as_u32() })
40 }
41}
42
43#[derive(Copy, Clone, Debug, PartialEq, Eq, Parse, Serialize, Validate)]
45#[policy(wire_type = u32)]
46pub enum TypeKind {
47 Alias = 0,
48 Type = 1,
49 Attribute = 3,
50}
51
52#[derive(Debug, Validate, HasPolicyId)]
54pub struct Type {
55 id: TypeId,
56 name: Box<[u8]>,
57 properties: TypeKind,
58 bounds: Option<TypeId>,
59}
60
61impl HasName for Type {
62 fn name(&self) -> &[u8] {
63 &self.name
64 }
65}
66
67impl Type {
68 pub fn bounded_by(&self) -> Option<TypeId> {
69 self.bounds
70 }
71}
72
73#[derive(Parse, Serialize)]
74struct BinaryTypeMetadata {
75 length: u32,
76 id: TypeId,
77 properties: TypeKind,
78 bounds: Option<TypeId>,
79}
80
81impl Parse for Type {
82 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
83 let metadata = BinaryTypeMetadata::parse(cursor)?;
84 let name = cursor.read_bytes(metadata.length as usize)?.to_vec().into_boxed_slice();
85
86 Ok(Self { id: metadata.id, name, properties: metadata.properties, bounds: metadata.bounds })
87 }
88}
89
90impl Serialize for Type {
91 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
92 let metadata = BinaryTypeMetadata {
93 length: self.name.len() as u32,
94 id: self.id,
95 properties: self.properties,
96 bounds: self.bounds,
97 };
98 metadata.serialize(writer)?;
99 writer.write_bytes(&self.name);
100 Ok(())
101 }
102}
103
104#[derive(Debug)]
106pub struct Types {
107 primary_names_count: u32,
108 ordered: Array<Type>,
110
111 by_id: Box<[Option<U24Index>]>,
114
115 by_name: HashTable<U24Index>,
117 hasher: rapidhash::RapidBuildHasher,
118}
119
120impl Parse for Types {
121 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
122 let primary_names_count = u32::parse(cursor)?;
123 cursor.set_types_count(primary_names_count);
124 let ordered = Array::<Type>::parse(cursor)?;
125
126 let mut by_id = Vec::with_capacity(ordered.len());
128 let hasher = rapidhash::RapidBuildHasher::default();
129 let mut by_name = HashTable::with_capacity(ordered.len());
130
131 for (index, item) in ordered.iter().enumerate() {
132 let u24_idx: U24Index = index.try_into()?;
133 if item.properties == TypeKind::Type || item.properties == TypeKind::Attribute {
134 let id = item.id.as_u32() as usize;
135 if id > by_id.len() {
136 by_id.resize(id, None);
137 } else if by_id[id - 1].is_some() {
138 return Err(ParseError::DuplicateId { id: item.id.as_u32() });
139 }
140 by_id[id - 1] = Some(u24_idx);
141 }
142 if item.properties == TypeKind::Type || item.properties == TypeKind::Alias {
143 let name = item.name.as_ref();
144 let hash = hash_name(&hasher, name);
145 let Entry::Vacant(entry) = by_name.entry(
146 hash,
147 |&idx| ordered[usize::from(idx)].name.as_ref() == name,
148 |&idx| hash_name(&hasher, ordered[usize::from(idx)].name.as_ref()),
149 ) else {
150 return Err(ParseError::DuplicateName { name: name.into() });
151 };
152 entry.insert(u24_idx);
153 }
154 }
155
156 by_id.shrink_to_fit();
157 by_name.shrink_to_fit(|&idx| hash_name(&hasher, ordered[usize::from(idx)].name.as_ref()));
158
159 Ok(Self { primary_names_count, ordered, by_id: by_id.into_boxed_slice(), by_name, hasher })
160 }
161}
162
163impl Serialize for Types {
164 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
165 self.primary_names_count.serialize(writer)?;
166 self.ordered.serialize(writer)
167 }
168}
169
170impl Validate for Types {
171 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
172 self.ordered.validate(policy)
173 }
174}
175
176impl Types {
177 pub fn primary_names_count(&self) -> u32 {
178 self.primary_names_count
179 }
180
181 pub fn get_by_id(&self, id: TypeId) -> Option<&Type> {
182 let index = self.by_id.get((id.as_u32() - 1) as usize)?.as_ref()?;
183 Some(&self.ordered[*index])
184 }
185
186 pub fn get_by_name(&self, name: &[u8]) -> Option<&Type> {
187 let hash = hash_name(&self.hasher, name);
188 let idx = self.by_name.find(hash, |&idx| self.ordered[idx].name.as_ref() == name)?;
189 Some(&self.ordered[*idx])
190 }
191
192 pub fn is_empty(&self) -> bool {
193 self.ordered.is_empty()
194 }
195
196 pub fn iter(&self) -> impl Iterator<Item = &Type> {
197 self.ordered.iter()
198 }
199}
200
201#[derive(Clone, Debug, PartialEq, Eq, Serialize, Validate)]
203pub struct TypeAttributeMaps {
204 maps: Box<[TypeSet]>,
205}
206
207impl TypeAttributeMaps {
208 pub fn get(&self, type_id: TypeId) -> Option<&TypeSet> {
210 self.maps.get((type_id.as_u32() - 1) as usize)
211 }
212}
213
214impl Index<TypeId> for TypeAttributeMaps {
215 type Output = TypeSet;
216
217 fn index(&self, id: TypeId) -> &Self::Output {
218 &self.maps[(id.as_u32() - 1) as usize]
219 }
220}
221
222impl Parse for TypeAttributeMaps {
223 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
224 let count = cursor.types_count() as usize;
225 let mut maps = Vec::with_capacity(count);
226 for _ in 0..count {
227 maps.push(TypeSet::parse(cursor)?);
228 }
229 Ok(Self { maps: maps.into_boxed_slice() })
230 }
231}
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236 use crate::new_policy::metadata::PolicyVersion;
237
238 #[test]
239 fn test_types_lookup() {
240 let mut bytes = Vec::new();
241 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut bytes);
242 2u32.serialize(&mut policy_writer).unwrap(); 2u32.serialize(&mut policy_writer).unwrap(); let t1 = Type {
246 id: TypeId::new(NonZeroU16::new(1).unwrap()),
247 name: Box::from(b"foo".as_slice()),
248 properties: TypeKind::Type,
249 bounds: None,
250 };
251 t1.serialize(&mut policy_writer).unwrap();
252
253 let t2 = Type {
254 id: TypeId::new(NonZeroU16::new(2).unwrap()),
255 name: Box::from(b"bar".as_slice()),
256 properties: TypeKind::Type,
257 bounds: None,
258 };
259 t2.serialize(&mut policy_writer).unwrap();
260
261 let mut cursor = PolicyCursor::new(&bytes);
262 let types = Types::parse(&mut cursor).expect("parse types");
263
264 assert_eq!(
265 types.get_by_id(TypeId::new(NonZeroU16::new(1).unwrap())).map(|t| t.name()),
266 Some(b"foo".as_slice())
267 );
268 assert_eq!(
269 types.get_by_id(TypeId::new(NonZeroU16::new(2).unwrap())).map(|t| t.name()),
270 Some(b"bar".as_slice())
271 );
272 assert!(types.get_by_id(TypeId::new(NonZeroU16::new(3).unwrap())).is_none());
273
274 assert_eq!(
275 types.get_by_name(b"foo").map(|t| t.id),
276 Some(TypeId::new(NonZeroU16::new(1).unwrap()))
277 );
278 assert_eq!(
279 types.get_by_name(b"bar").map(|t| t.id),
280 Some(TypeId::new(NonZeroU16::new(2).unwrap()))
281 );
282 assert!(types.get_by_name(b"baz").is_none());
283 }
284
285 #[test]
286 fn test_types_duplicate_id() {
287 let mut bytes = Vec::new();
288 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut bytes);
289 2u32.serialize(&mut policy_writer).unwrap(); 2u32.serialize(&mut policy_writer).unwrap(); let t1 = Type {
293 id: TypeId::new(NonZeroU16::new(1).unwrap()),
294 name: Box::from(b"foo".as_slice()),
295 properties: TypeKind::Type,
296 bounds: None,
297 };
298 t1.serialize(&mut policy_writer).unwrap();
299
300 let t2 = Type {
301 id: TypeId::new(NonZeroU16::new(1).unwrap()),
302 name: Box::from(b"bar".as_slice()),
303 properties: TypeKind::Type,
304 bounds: None,
305 };
306 t2.serialize(&mut policy_writer).unwrap();
307
308 let mut cursor = PolicyCursor::new(&bytes);
309 let result = Types::parse(&mut cursor);
310 assert!(matches!(result, Err(ParseError::DuplicateId { id: 1 })));
311 }
312
313 #[test]
314 fn test_types_duplicate_name() {
315 let mut bytes = Vec::new();
316 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut bytes);
317 2u32.serialize(&mut policy_writer).unwrap(); 2u32.serialize(&mut policy_writer).unwrap(); let t1 = Type {
321 id: TypeId::new(NonZeroU16::new(1).unwrap()),
322 name: Box::from(b"foo".as_slice()),
323 properties: TypeKind::Type,
324 bounds: None,
325 };
326 t1.serialize(&mut policy_writer).unwrap();
327
328 let t2 = Type {
329 id: TypeId::new(NonZeroU16::new(2).unwrap()),
330 name: Box::from(b"foo".as_slice()),
331 properties: TypeKind::Type,
332 bounds: None,
333 };
334 t2.serialize(&mut policy_writer).unwrap();
335
336 let mut cursor = PolicyCursor::new(&bytes);
337 let result = Types::parse(&mut cursor);
338 assert!(matches!(result, Err(ParseError::DuplicateName { name }) if name == b"foo"));
339 }
340
341 #[test]
342 fn test_types_duplicate_alias_name() {
343 let mut bytes = Vec::new();
344 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut bytes);
345 1u32.serialize(&mut policy_writer).unwrap(); 2u32.serialize(&mut policy_writer).unwrap(); let t1 = Type {
349 id: TypeId::new(NonZeroU16::new(1).unwrap()),
350 name: Box::from(b"foo".as_slice()),
351 properties: TypeKind::Type,
352 bounds: None,
353 };
354 t1.serialize(&mut policy_writer).unwrap();
355
356 let t2 = Type {
357 id: TypeId::new(NonZeroU16::new(1).unwrap()),
358 name: Box::from(b"foo".as_slice()),
359 properties: TypeKind::Alias,
360 bounds: None,
361 };
362 t2.serialize(&mut policy_writer).unwrap();
363
364 let mut cursor = PolicyCursor::new(&bytes);
365 let result = Types::parse(&mut cursor);
366 assert!(matches!(result, Err(ParseError::DuplicateName { name }) if name == b"foo"));
367 }
368}