1use std::num::NonZeroU16;
6
7use fuchsia_rcu::RcuDroppable;
8use selinux_policy_derive::{HasName, HasPolicyId, Parse, Serialize, Validate};
9
10use super::Policy;
11use super::constraints::{Constraint, ConstraintTerm};
12use super::error::{ParseError, SerializeError, ValidateError};
13use super::id_type::IdType;
14use super::indexed::IdAndNameIndexed;
15use super::parser::{Array, PolicyCursor, PolicyWriter};
16use super::permissions::Permission;
17use super::traits::{Parse, PolicyId, Serialize, Validate};
18
19#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, RcuDroppable)]
21pub struct ClassTag;
22
23pub type ClassId = IdType<NonZeroU16, ClassTag>;
25
26#[derive(Parse, Serialize)]
27struct BinaryClassMetadata {
28 key_length: u32,
29 common_key_length: u32,
30 id: u32,
31 permission_primary_names_count: u32,
33 permission_count: u32,
34 constraint_count: u32,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Parse, Serialize, Validate)]
39#[policy(wire_type = u32)]
40pub enum ClassDefault {
41 Unspecified = 0,
42 Source = 1,
43 Target = 2,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Parse, Serialize, Validate)]
48#[policy(wire_type = u32)]
49pub enum ClassDefaultRange {
50 Unspecified = 0,
51 SourceLow = 1,
52 SourceHigh = 2,
53 SourceLowHigh = 3,
54 TargetLow = 4,
55 TargetHigh = 5,
56 TargetLowHigh = 6,
57 Glblub = 7,
60}
61
62#[derive(Debug, Parse, Serialize, Validate)]
64pub struct ClassDefaults {
65 default_user: ClassDefault,
66 default_role: ClassDefault,
67 default_range: ClassDefaultRange,
68 default_type: ClassDefault,
69}
70
71impl ClassDefaults {
72 pub fn user(&self) -> ClassDefault {
73 self.default_user
74 }
75
76 pub fn role(&self) -> ClassDefault {
77 self.default_role
78 }
79
80 pub fn range(&self) -> ClassDefaultRange {
81 self.default_range
82 }
83
84 pub fn type_(&self) -> ClassDefault {
85 self.default_type
86 }
87}
88
89#[derive(Debug, HasName, HasPolicyId)]
91pub struct Class {
92 id: ClassId,
93 name: Box<[u8]>,
94 common_name: Box<[u8]>,
95 permission_primary_names_count: u32,
97 permissions: IdAndNameIndexed<Box<[Permission]>>,
98 constraints: Box<[Constraint]>,
99 validate_transitions: Array<ConstraintTerm>,
100 defaults: ClassDefaults,
101}
102
103impl Class {
104 pub(super) fn common_name(&self) -> &[u8] {
110 &self.common_name
111 }
112
113 pub(super) fn permissions(&self) -> &IdAndNameIndexed<Box<[Permission]>> {
114 &self.permissions
115 }
116
117 pub(super) fn constraints(&self) -> &[Constraint] {
118 &self.constraints
119 }
120
121 #[cfg(test)]
122 pub(super) fn validate_transitions(&self) -> &[ConstraintTerm] {
123 &self.validate_transitions
124 }
125
126 pub(super) fn defaults(&self) -> &ClassDefaults {
127 &self.defaults
128 }
129}
130
131impl Parse for Class {
132 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
133 let metadata = BinaryClassMetadata::parse(cursor)?;
134
135 let id_val = metadata.id;
136 let id = ClassId::from_u32(id_val).ok_or(ParseError::InvalidId { value: id_val })?;
137
138 let name_len = metadata.key_length as usize;
139 let name = Box::from(cursor.read_bytes(name_len)?);
140
141 let common_name_len = metadata.common_key_length as usize;
142 let common_name = Box::from(cursor.read_bytes(common_name_len)?);
143
144 let permissions_count = metadata.permission_count as usize;
145 let mut permissions = Vec::with_capacity(permissions_count);
146 for _ in 0..permissions_count {
147 permissions.push(Permission::parse(cursor)?);
148 }
149 let permissions = IdAndNameIndexed::new(permissions.into_boxed_slice())?;
150
151 let constraint_count = metadata.constraint_count as usize;
152 let mut constraints = Vec::with_capacity(constraint_count);
153 for _ in 0..constraint_count {
154 constraints.push(Constraint::parse(cursor)?);
155 }
156 let constraints = constraints.into_boxed_slice();
157
158 let validate_transitions = Array::<ConstraintTerm>::parse(cursor)?;
159 let defaults = ClassDefaults::parse(cursor)?;
160
161 Ok(Self {
162 id,
163 name,
164 common_name,
165 permission_primary_names_count: metadata.permission_primary_names_count,
166 permissions,
167 constraints,
168 validate_transitions,
169 defaults,
170 })
171 }
172}
173
174impl Serialize for Class {
175 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
176 let metadata = BinaryClassMetadata {
177 key_length: self.name.len() as u32,
178 common_key_length: self.common_name.len() as u32,
179 id: self.id.as_u32(),
180 permission_primary_names_count: self.permission_primary_names_count,
181 permission_count: self.permissions.len() as u32,
182 constraint_count: self.constraints.len() as u32,
183 };
184 metadata.serialize(writer)?;
185
186 writer.write_bytes(&self.name);
187 writer.write_bytes(&self.common_name);
188
189 self.permissions.serialize(writer)?;
190 self.constraints.serialize(writer)?;
191 self.validate_transitions.serialize(writer)?;
192 self.defaults.serialize(writer)?;
193 Ok(())
194 }
195}
196
197impl Validate for Class {
198 fn validate(&self, policy: &Policy) -> Result<(), ValidateError> {
199 self.permissions.validate(policy)?;
200 self.constraints.validate(policy)?;
201 self.validate_transitions.validate(policy)?;
202 self.defaults.validate(policy)?;
203
204 let mut common_permissions_count = 0;
205 if !self.common_name.is_empty() {
206 let common_symbol =
207 policy.common_symbols().get_by_name(&self.common_name).ok_or_else(|| {
208 ValidateError::UndefinedCommonSymbol { name: self.common_name.as_ref().into() }
209 })?;
210 common_permissions_count = common_symbol.permissions().len();
211 }
212
213 let expected_at_most = self.permissions.len() + common_permissions_count;
214 if self.permission_primary_names_count > expected_at_most as u32 {
215 return Err(ValidateError::InvalidPrimaryNamesCount {
216 expected_at_most: expected_at_most as u32,
217 found: self.permission_primary_names_count,
218 });
219 }
220
221 Ok(())
222 }
223}
224
225impl Validate for ClassId {
226 fn validate(&self, policy: &Policy) -> Result<(), ValidateError> {
227 policy
228 .classes()
229 .get_by_id(*self)
230 .map(|_| ())
231 .ok_or_else(|| ValidateError::UnknownId { kind: "class", id: self.as_u32() })
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::{PolicyCursor, *};
238 use crate::policy::metadata::PolicyVersion;
239 use crate::policy::parser::PolicyWriter;
240 use crate::policy::traits::{HasName, HasPolicyId};
241
242 #[test]
243 fn test_class_defaults_parse_and_serialize() {
244 let data = [
245 1, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, ];
250 let mut cursor = PolicyCursor::new(&data);
251 let defaults = ClassDefaults::parse(&mut cursor).unwrap();
252 assert_eq!(defaults.user(), ClassDefault::Source);
253 assert_eq!(defaults.role(), ClassDefault::Target);
254 assert_eq!(defaults.range(), ClassDefaultRange::TargetLowHigh);
255 assert_eq!(defaults.type_(), ClassDefault::Source);
256
257 let mut writer = Vec::new();
258 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
259 defaults.serialize(&mut policy_writer).unwrap();
260 assert_eq!(writer, data);
261 }
262
263 #[test]
264 fn test_minimal_class_parse_and_serialize() {
265 let data = [
266 4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277 ];
278 let mut cursor = PolicyCursor::new(&data);
279 let class = Class::parse(&mut cursor).unwrap();
280 assert_eq!(class.id(), ClassId::from_u32(1).unwrap());
281 assert_eq!(class.name(), b"test");
282 assert!(class.common_name().is_empty());
283 assert!(class.permissions().is_empty());
284 assert!(class.constraints().is_empty());
285 assert!(class.validate_transitions().is_empty());
286
287 let mut writer = Vec::new();
288 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
289 class.serialize(&mut policy_writer).unwrap();
290 assert_eq!(writer, data);
291 }
292}