1use std::num::{NonZeroU16, NonZeroUsize};
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;
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
31#[derive(Copy, Clone, Debug, PartialEq, Eq)]
36pub struct NonMaxUsize {
37 value: NonZeroUsize,
38}
39
40impl NonMaxUsize {
41 pub fn new(value: usize) -> Option<Self> {
42 NonZeroUsize::new(value.wrapping_add(1)).map(|value| Self { value })
43 }
44
45 pub fn get(self) -> usize {
46 self.value.get().wrapping_sub(1)
47 }
48}
49
50impl Validate for TypeId {
51 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
52 policy
53 .types()
54 .get_by_id(*self)
55 .map(|_| ())
56 .ok_or_else(|| ValidateError::UnknownId { kind: "type", id: self.as_u32() })
57 }
58}
59
60#[derive(Copy, Clone, Debug, PartialEq, Eq)]
61pub enum TypeKind {
62 Alias,
63 Type,
64 Attribute,
65}
66
67impl TypeKind {
68 pub const ALIAS: u32 = 0;
69 pub const TYPE: u32 = 1;
70 pub const ATTRIBUTE: u32 = 3;
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, HasPolicyId)]
75pub struct Type {
76 pub(super) id: TypeId,
77 pub(super) name: Box<[u8]>,
78 pub(super) properties: TypeKind,
79 pub(super) bounds: Option<TypeId>,
80}
81
82impl HasName for Type {
83 fn name(&self) -> &[u8] {
84 &self.name
85 }
86}
87
88impl Type {
89 pub fn bounded_by(&self) -> Option<TypeId> {
90 self.bounds
91 }
92}
93
94#[derive(Parse, Serialize)]
95struct BinaryTypeMetadata {
96 length: u32,
97 id: u32,
98 properties: u32,
99 bounds: u32,
100}
101
102impl Parse for Type {
103 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
104 let metadata = BinaryTypeMetadata::parse(cursor)?;
105 let name = cursor.read_bytes(metadata.length as usize)?.to_vec().into_boxed_slice();
106
107 let properties_val = metadata.properties;
108 let properties = match properties_val {
109 TypeKind::ALIAS => TypeKind::Alias,
110 TypeKind::TYPE => TypeKind::Type,
111 TypeKind::ATTRIBUTE => TypeKind::Attribute,
112 v => {
113 return Err(ParseError::InvalidEnumValue {
114 enum_name: "TypeKind",
115 value: v as u64,
116 });
117 }
118 };
119
120 let bounds = TypeId::from_u32(metadata.bounds);
121 let id =
122 TypeId::from_u32(metadata.id).ok_or(ParseError::InvalidId { value: metadata.id })?;
123
124 Ok(Self { id, name, properties, bounds })
125 }
126}
127
128impl Serialize for Type {
129 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
130 let properties_val = match self.properties {
131 TypeKind::Alias => TypeKind::ALIAS,
132 TypeKind::Type => TypeKind::TYPE,
133 TypeKind::Attribute => TypeKind::ATTRIBUTE,
134 };
135 let metadata = BinaryTypeMetadata {
136 length: self.name.len() as u32,
137 id: self.id.as_u32(),
138 properties: properties_val,
139 bounds: self.bounds.map_or(0, |id| id.as_u32()),
140 };
141 metadata.serialize(writer)?;
142 writer.extend_from_slice(&self.name);
143 Ok(())
144 }
145}
146
147impl Validate for Type {
148 fn validate(&self, _policy: &NewPolicy) -> Result<(), ValidateError> {
149 Ok(())
151 }
152}
153
154#[derive(Debug, Clone)]
156pub struct Types {
157 pub primary_names_count: u32,
158 pub ordered: Array<Type>,
160
161 by_id: Box<[Option<NonMaxUsize>]>,
164
165 by_name: HashTable<u32>,
168 hasher: rapidhash::RapidBuildHasher,
169}
170
171impl PartialEq for Types {
172 fn eq(&self, other: &Self) -> bool {
173 self.primary_names_count == other.primary_names_count && self.ordered == other.ordered
174 }
175}
176
177impl Eq for Types {}
178
179impl Parse for Types {
180 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
181 let primary_names_count = u32::parse(cursor)?;
182 let ordered = Array::<Type>::parse(cursor)?;
183
184 let mut by_id = Vec::new();
186 let hasher = rapidhash::RapidBuildHasher::default();
187 let mut by_name = HashTable::new();
188
189 for (index, t) in ordered.iter().enumerate() {
190 if t.properties == TypeKind::Type || t.properties == TypeKind::Attribute {
191 let id = t.id.as_u32() as usize;
192 if id > by_id.len() {
193 by_id.resize(id, None);
194 }
195 by_id[id - 1] = Some(NonMaxUsize::new(index).expect("index overflow"));
196 }
197 if t.properties == TypeKind::Type || t.properties == TypeKind::Alias {
198 let hash = hash_name(&hasher, t.name.as_ref());
199 by_name.insert_unique(hash, index as u32, |&idx| {
200 hash_name(&hasher, ordered[idx as usize].name.as_ref())
201 });
202 }
203 }
204
205 Ok(Self { primary_names_count, ordered, by_id: by_id.into_boxed_slice(), by_name, hasher })
206 }
207}
208
209impl Serialize for Types {
210 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
211 self.primary_names_count.serialize(writer)?;
212 self.ordered.serialize(writer)
213 }
214}
215
216impl Validate for Types {
217 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
218 for t in self.ordered.iter() {
219 t.validate(policy)?;
220 }
221 Ok(())
222 }
223}
224
225impl Types {
226 pub fn primary_names_count(&self) -> u32 {
227 self.primary_names_count
228 }
229
230 pub fn get_by_id(&self, id: TypeId) -> Option<&Type> {
231 let index = self.by_id.get((id.as_u32() - 1) as usize)?.as_ref()?;
232 Some(&self.ordered[index.get()])
233 }
234
235 pub fn get_by_name(&self, name: &[u8]) -> Option<&Type> {
236 let hash = hash_name(&self.hasher, name);
237 let idx =
238 self.by_name.find(hash, |&idx| self.ordered[idx as usize].name.as_ref() == name)?;
239 Some(&self.ordered[*idx as usize])
240 }
241
242 pub fn is_empty(&self) -> bool {
243 self.ordered.is_empty()
244 }
245
246 pub fn iter(&self) -> impl Iterator<Item = &Type> {
247 self.ordered.iter()
248 }
249}