1use super::arrays::{
6 ACCESS_VECTOR_RULE_TYPE_ALLOW, ACCESS_VECTOR_RULE_TYPE_ALLOWXPERM,
7 ACCESS_VECTOR_RULE_TYPE_AUDITALLOW, ACCESS_VECTOR_RULE_TYPE_AUDITALLOWXPERM,
8 ACCESS_VECTOR_RULE_TYPE_DONTAUDIT, ACCESS_VECTOR_RULE_TYPE_DONTAUDITXPERM, AccessVectorRule,
9 AccessVectorRuleMetadata, ConditionalNodes, Context, DeprecatedFilenameTransitions,
10 ExtendedPermissions, FilenameTransitionList, FilenameTransitions, FsUses, GenericFsContexts,
11 IPv6Nodes, InfinitiBandEndPorts, InfinitiBandPartitionKeys, InitialSids,
12 MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY, NamedContextPairs, Nodes, Ports,
13 RangeTransitions, RoleAllow, RoleAllows, RoleTransition, RoleTransitions, SimpleArray,
14 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES, XPERMS_TYPE_IOCTL_PREFIXES, XPERMS_TYPE_NLMSG,
15 XpermsBitmap,
16};
17use super::error::{ParseError, ValidateError};
18use super::extensible_bitmap::ExtensibleBitmap;
19use super::metadata::{Config, Counts, HandleUnknown, Magic, PolicyVersion, Signature};
20use super::parser::{PolicyCursor, PolicyData};
21use super::security_context::{Level, SecurityContext};
22use super::symbols::{
23 Category, Class, Classes, CommonSymbol, CommonSymbols, ConditionalBoolean, MlsLevel, Role,
24 Sensitivity, SymbolList, Type, User,
25};
26use super::view::{HashedArrayView, U24};
27use super::{
28 AccessDecision, AccessVector, CategoryId, ClassId, Parse, PolicyValidationContext, RoleId,
29 SELINUX_AVD_FLAGS_PERMISSIVE, SensitivityId, TypeId, UserId, Validate, XpermsAccessDecision,
30 XpermsKind,
31};
32use crate::{NullessByteStr, PolicyCap};
33
34use anyhow::Context as _;
35use itertools::Itertools;
36use std::collections::HashSet;
37use std::fmt::Debug;
38use std::hash::Hash;
39use std::iter::Iterator;
40use std::num::NonZeroU32;
41use zerocopy::little_endian as le;
42
43const MAXIMUM_POLICY_SIZE: usize = 1 << 24;
45
46#[derive(Debug)]
48pub struct ParsedPolicy {
49 pub data: PolicyData,
51
52 magic: Magic,
55 signature: Signature,
57 policy_version: PolicyVersion,
59 config: Config,
61 counts: Counts,
63 policy_capabilities: ExtensibleBitmap,
64 permissive_map: ExtensibleBitmap,
65 common_symbols: SymbolList<CommonSymbol>,
67 classes: SymbolList<Class>,
69 roles: SymbolList<Role>,
71 types: SymbolList<Type>,
73 users: SymbolList<User>,
75 conditional_booleans: SymbolList<ConditionalBoolean>,
77 sensitivities: SymbolList<Sensitivity>,
79 categories: SymbolList<Category>,
81 access_vector_rules: HashedArrayView<AccessVectorRule>,
83 conditional_lists: SimpleArray<ConditionalNodes>,
84 role_transitions: RoleTransitions,
86 role_allowlist: RoleAllows,
88 filename_transition_list: FilenameTransitionList,
89 initial_sids: SimpleArray<InitialSids>,
90 filesystems: SimpleArray<NamedContextPairs>,
91 ports: SimpleArray<Ports>,
92 network_interfaces: SimpleArray<NamedContextPairs>,
93 nodes: SimpleArray<Nodes>,
94 fs_uses: SimpleArray<FsUses>,
95 ipv6_nodes: SimpleArray<IPv6Nodes>,
96 infinitiband_partition_keys: Option<SimpleArray<InfinitiBandPartitionKeys>>,
97 infinitiband_end_ports: Option<SimpleArray<InfinitiBandEndPorts>>,
98 generic_fs_contexts: SimpleArray<GenericFsContexts>,
101 range_transitions: SimpleArray<RangeTransitions>,
102 attribute_maps: Vec<U24>,
104}
105
106impl ParsedPolicy {
107 pub fn policy_version(&self) -> u32 {
109 self.policy_version.policy_version()
110 }
111
112 pub fn handle_unknown(&self) -> HandleUnknown {
115 self.config.handle_unknown()
116 }
117
118 pub fn has_policycap(&self, policy_cap: PolicyCap) -> bool {
120 self.policy_capabilities.is_set(policy_cap as u32)
121 }
122
123 pub(super) fn compute_access_decision(
135 &self,
136 source_context: &SecurityContext,
137 target_context: &SecurityContext,
138 target_class: &Class,
139 ) -> AccessDecision {
140 let mut access_decision = self.compute_explicitly_allowed(
141 source_context.type_(),
142 target_context.type_(),
143 target_class,
144 );
145 access_decision.allow -=
146 self.compute_denied_by_constraints(source_context, target_context, target_class);
147 access_decision
148 }
149
150 pub(super) fn compute_explicitly_allowed(
155 &self,
156 source_type: TypeId,
157 target_type: TypeId,
158 target_class: &Class,
159 ) -> AccessDecision {
160 let target_class_id = target_class.id();
161
162 let mut computed_access_vector = AccessVector::NONE;
163 let mut computed_audit_allow = AccessVector::NONE;
164 let mut computed_audit_deny = AccessVector::ALL;
165
166 let source_attribute_bitmap =
167 self.reparse_attribute_map(self.attribute_maps[(source_type.0.get() - 1) as usize]);
168 let target_attribute_bitmap =
169 self.reparse_attribute_map(self.attribute_maps[(target_type.0.get() - 1) as usize]);
170
171 for (source_bit_index, target_bit_index) in Itertools::cartesian_product(
172 source_attribute_bitmap.indices_of_set_bits(),
173 target_attribute_bitmap.indices_of_set_bits(),
174 ) {
175 let source_id = TypeId(NonZeroU32::new(source_bit_index + 1).unwrap());
176 let target_id = TypeId(NonZeroU32::new(target_bit_index + 1).unwrap());
177
178 if let Some(allow_rule) = self.access_vector_rules_find(
179 source_id,
180 target_id,
181 target_class_id,
182 ACCESS_VECTOR_RULE_TYPE_ALLOW,
183 ) {
184 computed_access_vector |= allow_rule.access_vector().unwrap();
186 }
187 if let Some(auditallow_rule) = self.access_vector_rules_find(
188 source_id,
189 target_id,
190 target_class_id,
191 ACCESS_VECTOR_RULE_TYPE_AUDITALLOW,
192 ) {
193 computed_audit_allow |= auditallow_rule.access_vector().unwrap();
195 }
196 if let Some(dontaudit_rule) = self.access_vector_rules_find(
197 source_id,
198 target_id,
199 target_class_id,
200 ACCESS_VECTOR_RULE_TYPE_DONTAUDIT,
201 ) {
202 computed_audit_deny &= dontaudit_rule.access_vector().unwrap();
204 }
205 }
206
207 let mut flags = 0;
209 if self.permissive_types().is_set(source_type.0.get()) {
210 flags |= SELINUX_AVD_FLAGS_PERMISSIVE;
211 }
212 AccessDecision {
213 allow: computed_access_vector,
214 auditallow: computed_audit_allow,
215 auditdeny: computed_audit_deny,
216 flags,
217 todo_bug: None,
218 }
219 }
220
221 fn compute_denied_by_constraints(
223 &self,
224 source_context: &SecurityContext,
225 target_context: &SecurityContext,
226 target_class: &Class,
227 ) -> AccessVector {
228 let mut denied = AccessVector::NONE;
229 for constraint in target_class.constraints() {
230 match constraint.constraint_expr().evaluate(source_context, target_context) {
231 Err(err) => {
232 unreachable!("validated constraint expression failed to evaluate: {:?}", err)
233 }
234 Ok(false) => denied |= constraint.access_vector(),
235 Ok(true) => {}
236 }
237 }
238 denied
239 }
240
241 pub(super) fn compute_xperms_access_decision(
244 &self,
245 xperms_kind: XpermsKind,
246 source_context: &SecurityContext,
247 target_context: &SecurityContext,
248 target_class: &Class,
249 xperms_prefix: u8,
250 ) -> XpermsAccessDecision {
251 let target_class_id = target_class.id();
252
253 let mut explicit_allow: Option<XpermsBitmap> = None;
254 let mut auditallow = XpermsBitmap::NONE;
255 let mut auditdeny = XpermsBitmap::ALL;
256
257 let xperms_types = match xperms_kind {
258 XpermsKind::Ioctl => {
259 [XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES, XPERMS_TYPE_IOCTL_PREFIXES].as_slice()
260 }
261 XpermsKind::Nlmsg => [XPERMS_TYPE_NLMSG].as_slice(),
262 };
263 let bitmap_if_prefix_matches =
264 |xperms_prefix: u8, xperms: &ExtendedPermissions| match xperms_kind {
265 XpermsKind::Ioctl => match xperms.xperms_type {
266 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES => (xperms.xperms_optional_prefix
267 == xperms_prefix)
268 .then_some(xperms.xperms_bitmap),
269 XPERMS_TYPE_IOCTL_PREFIXES => {
270 xperms.xperms_bitmap.contains(xperms_prefix).then_some(XpermsBitmap::ALL)
271 }
272 _ => None,
273 },
274 XpermsKind::Nlmsg => match xperms.xperms_type {
275 XPERMS_TYPE_NLMSG => (xperms.xperms_optional_prefix == xperms_prefix)
276 .then_some(xperms.xperms_bitmap),
277 _ => None,
278 },
279 };
280
281 let source_attribute_bitmap = self.reparse_attribute_map(
282 self.attribute_maps[(source_context.type_().0.get() - 1) as usize],
283 );
284 let target_attribute_bitmap = self.reparse_attribute_map(
285 self.attribute_maps[(target_context.type_().0.get() - 1) as usize],
286 );
287
288 for (source_bit_index, target_bit_index) in Itertools::cartesian_product(
289 source_attribute_bitmap.indices_of_set_bits(),
290 target_attribute_bitmap.indices_of_set_bits(),
291 ) {
292 let source_id = TypeId(NonZeroU32::new(source_bit_index + 1).unwrap());
293 let target_id = TypeId(NonZeroU32::new(target_bit_index + 1).unwrap());
294
295 for xperms_allow_rule in self.access_vector_rules_find_all(
296 source_id,
297 target_id,
298 target_class_id,
299 ACCESS_VECTOR_RULE_TYPE_ALLOWXPERM,
300 ) {
301 let xperms = xperms_allow_rule.extended_permissions().unwrap();
302
303 if xperms_types.contains(&xperms.xperms_type) {
307 explicit_allow.get_or_insert(XpermsBitmap::NONE);
308 }
309
310 if let Some(ref xperms_bitmap) = bitmap_if_prefix_matches(xperms_prefix, xperms) {
311 (*explicit_allow.get_or_insert(XpermsBitmap::NONE)) |= xperms_bitmap;
312 }
313 }
314
315 for xperms_auditallow_rule in self.access_vector_rules_find_all(
316 source_id,
317 target_id,
318 target_class_id,
319 ACCESS_VECTOR_RULE_TYPE_AUDITALLOWXPERM,
320 ) {
321 let xperms = xperms_auditallow_rule.extended_permissions().unwrap();
322 if let Some(ref xperms_bitmap) = bitmap_if_prefix_matches(xperms_prefix, xperms) {
323 auditallow |= xperms_bitmap;
324 }
325 }
326
327 for xperms_dontaudit_rule in self.access_vector_rules_find_all(
328 source_id,
329 target_id,
330 target_class_id,
331 ACCESS_VECTOR_RULE_TYPE_DONTAUDITXPERM,
332 ) {
333 let xperms = xperms_dontaudit_rule.extended_permissions().unwrap();
334 if let Some(ref xperms_bitmap) = bitmap_if_prefix_matches(xperms_prefix, xperms) {
335 auditdeny -= xperms_bitmap;
336 }
337 }
338 }
339 let allow = explicit_allow.unwrap_or(XpermsBitmap::ALL);
340 XpermsAccessDecision { allow, auditallow, auditdeny }
341 }
342
343 pub(super) fn initial_context(&self, id: crate::InitialSid) -> &Context {
345 let id = le::U32::from(id as u32);
346 &self.initial_sids.data.iter().find(|initial| initial.id() == id).unwrap().context()
348 }
349
350 pub(super) fn user(&self, id: UserId) -> &User {
353 self.users.data.iter().find(|x| x.id() == id).unwrap()
354 }
355
356 pub(super) fn user_by_name(&self, name: &str) -> Option<&User> {
358 self.users.data.iter().find(|x| x.name_bytes() == name.as_bytes())
359 }
360
361 pub(super) fn role(&self, id: RoleId) -> &Role {
364 self.roles.data.iter().find(|x| x.id() == id).unwrap()
365 }
366
367 pub(super) fn role_by_name(&self, name: &str) -> Option<&Role> {
369 self.roles.data.iter().find(|x| x.name_bytes() == name.as_bytes())
370 }
371
372 pub(super) fn type_(&self, id: TypeId) -> &Type {
375 self.types.data.iter().find(|x| x.id() == id).unwrap()
376 }
377
378 pub(super) fn type_id_by_name(&self, name: &str) -> Option<TypeId> {
380 self.types.data.iter().find(|x| x.name_bytes() == name.as_bytes()).map(|x| x.id())
381 }
382
383 pub(super) fn permissive_types(&self) -> &ExtensibleBitmap {
386 &self.permissive_map
387 }
388
389 pub(super) fn sensitivity(&self, id: SensitivityId) -> &Sensitivity {
392 self.sensitivities.data.iter().find(|x| x.id() == id).unwrap()
393 }
394
395 pub(super) fn sensitivity_by_name(&self, name: &str) -> Option<&Sensitivity> {
397 self.sensitivities.data.iter().find(|x| x.name_bytes() == name.as_bytes())
398 }
399
400 pub(super) fn category(&self, id: CategoryId) -> &Category {
403 self.categories.data.iter().find(|y| y.id() == id).unwrap()
404 }
405
406 pub(super) fn category_by_name(&self, name: &str) -> Option<&Category> {
408 self.categories.data.iter().find(|x| x.name_bytes() == name.as_bytes())
409 }
410
411 pub(super) fn classes(&self) -> &Classes {
412 &self.classes.data
413 }
414
415 pub(super) fn common_symbols(&self) -> &CommonSymbols {
416 &self.common_symbols.data
417 }
418
419 pub(super) fn conditional_booleans(&self) -> &Vec<ConditionalBoolean> {
420 &self.conditional_booleans.data
421 }
422
423 pub(super) fn fs_uses(&self) -> &FsUses {
424 &self.fs_uses.data
425 }
426
427 pub(super) fn generic_fs_contexts(&self) -> &GenericFsContexts {
428 &self.generic_fs_contexts.data
429 }
430
431 pub(super) fn role_allowlist(&self) -> &[RoleAllow] {
432 &self.role_allowlist.data
433 }
434
435 pub(super) fn role_transitions(&self) -> &[RoleTransition] {
436 &self.role_transitions.data
437 }
438
439 pub(super) fn range_transitions(&self) -> &RangeTransitions {
440 &self.range_transitions.data
441 }
442
443 pub(super) fn access_vector_rules_find(
444 &self,
445 source: TypeId,
446 target: TypeId,
447 class: ClassId,
448 rule_type: u16,
449 ) -> Option<AccessVectorRule> {
450 let query = AccessVectorRuleMetadata::for_query(source, target, class, rule_type);
451 self.access_vector_rules.find(query, &self.data)
452 }
453
454 pub(super) fn access_vector_rules_find_all(
455 &self,
456 source: TypeId,
457 target: TypeId,
458 class: ClassId,
459 rule_type: u16,
460 ) -> impl Iterator<Item = AccessVectorRule> {
461 let query = AccessVectorRuleMetadata::for_query(source, target, class, rule_type);
462 self.access_vector_rules.find_all(query, &self.data)
463 }
464
465 #[cfg(test)]
466 pub(super) fn access_vector_rules_for_test(
467 &self,
468 ) -> impl Iterator<Item = AccessVectorRule> + use<'_> {
469 use super::arrays::testing::access_vector_rule_ordering;
470 use itertools::Itertools;
471
472 self.access_vector_rules
473 .iter(&self.data)
474 .map(|view| view.parse(&self.data))
475 .sorted_by(access_vector_rule_ordering)
476 }
477
478 pub(super) fn compute_filename_transition(
479 &self,
480 source_type: TypeId,
481 target_type: TypeId,
482 class: ClassId,
483 name: NullessByteStr<'_>,
484 ) -> Option<TypeId> {
485 match &self.filename_transition_list {
486 FilenameTransitionList::PolicyVersionGeq33(list) => {
487 let entry = list.data.iter().find(|transition| {
488 transition.target_type() == target_type
489 && transition.target_class() == class
490 && transition.name_bytes() == name.as_bytes()
491 })?;
492 entry
493 .outputs()
494 .iter()
495 .find(|entry| entry.has_source_type(source_type))
496 .map(|x| x.out_type())
497 }
498 FilenameTransitionList::PolicyVersionLeq32(list) => list
499 .data
500 .iter()
501 .find(|transition| {
502 transition.target_class() == class
503 && transition.target_type() == target_type
504 && transition.source_type() == source_type
505 && transition.name_bytes() == name.as_bytes()
506 })
507 .map(|x| x.out_type()),
508 }
509 }
510
511 fn validate_mls_range(
518 &self,
519 low_level: &MlsLevel,
520 high_level: &Option<MlsLevel>,
521 sensitivity_ids: &HashSet<SensitivityId>,
522 category_ids: &HashSet<CategoryId>,
523 ) -> Result<(), anyhow::Error> {
524 validate_id(sensitivity_ids, low_level.sensitivity(), "sensitivity")?;
525 for id in low_level.category_ids() {
526 validate_id(category_ids, id, "category")?;
527 }
528 if let Some(high) = high_level {
529 validate_id(sensitivity_ids, high.sensitivity(), "sensitivity")?;
530 for id in high.category_ids() {
531 validate_id(category_ids, id, "category")?;
532 }
533 if !high.dominates(low_level) {
534 return Err(ValidateError::InvalidMlsRange {
535 low: low_level.serialize(self).into(),
536 high: high.serialize(self).into(),
537 }
538 .into());
539 }
540 }
541 Ok(())
542 }
543
544 fn reparse_attribute_map(&self, offset: U24) -> ExtensibleBitmap {
545 let (attribute_map, _) =
546 ExtensibleBitmap::parse(PolicyCursor::new_at(&self.data, u32::from(offset)))
547 .expect("This parsed earlier; why not now?");
548 attribute_map
549 }
550}
551
552impl ParsedPolicy {
553 pub(super) fn parse(data: PolicyData) -> Result<Self, anyhow::Error> {
556 let policy_size = data.len();
557 if MAXIMUM_POLICY_SIZE <= policy_size {
558 return Err(anyhow::Error::from(ParseError::UnsupportedlyLarge {
559 observed: policy_size,
560 limit: MAXIMUM_POLICY_SIZE,
561 }));
562 }
563 let (policy, excess_bytes) = parse_policy_internal(data)?;
564 if excess_bytes > 0 {
565 return Err(anyhow::Error::from(ParseError::TrailingBytes { num_bytes: excess_bytes }));
566 }
567 Ok(policy)
568 }
569}
570
571fn parse_policy_internal<'a>(data: PolicyData) -> Result<(ParsedPolicy, usize), anyhow::Error> {
573 let tail = PolicyCursor::new(&data);
574
575 let (magic, tail) = PolicyCursor::parse::<Magic>(tail).context("parsing magic")?;
576
577 let (signature, tail) =
578 Signature::parse(tail).map_err(Into::<anyhow::Error>::into).context("parsing signature")?;
579
580 let (policy_version, tail) =
581 PolicyCursor::parse::<PolicyVersion>(tail).context("parsing policy version")?;
582 let policy_version_value = policy_version.policy_version();
583
584 let (config, tail) = Config::parse(tail)
585 .map_err(Into::<anyhow::Error>::into)
586 .context("parsing policy config")?;
587
588 let (counts, tail) =
589 PolicyCursor::parse::<Counts>(tail).context("parsing high-level policy object counts")?;
590
591 let (policy_capabilities, tail) = ExtensibleBitmap::parse(tail)
592 .map_err(Into::<anyhow::Error>::into)
593 .context("parsing policy capabilities")?;
594
595 let (permissive_map, tail) = ExtensibleBitmap::parse(tail)
596 .map_err(Into::<anyhow::Error>::into)
597 .context("parsing permissive map")?;
598
599 let (common_symbols, tail) = SymbolList::<CommonSymbol>::parse(tail)
600 .map_err(Into::<anyhow::Error>::into)
601 .context("parsing common symbols")?;
602
603 let (classes, tail) = SymbolList::<Class>::parse(tail)
604 .map_err(Into::<anyhow::Error>::into)
605 .context("parsing classes")?;
606
607 let (roles, tail) = SymbolList::<Role>::parse(tail)
608 .map_err(Into::<anyhow::Error>::into)
609 .context("parsing roles")?;
610
611 let (types, tail) = SymbolList::<Type>::parse(tail)
612 .map_err(Into::<anyhow::Error>::into)
613 .context("parsing types")?;
614
615 let (users, tail) = SymbolList::<User>::parse(tail)
616 .map_err(Into::<anyhow::Error>::into)
617 .context("parsing users")?;
618
619 let (conditional_booleans, tail) = SymbolList::<ConditionalBoolean>::parse(tail)
620 .map_err(Into::<anyhow::Error>::into)
621 .context("parsing conditional booleans")?;
622
623 let (sensitivities, tail) = SymbolList::<Sensitivity>::parse(tail)
624 .map_err(Into::<anyhow::Error>::into)
625 .context("parsing sensitivites")?;
626
627 let (categories, tail) = SymbolList::<Category>::parse(tail)
628 .map_err(Into::<anyhow::Error>::into)
629 .context("parsing categories")?;
630
631 let (access_vector_rules, tail) = HashedArrayView::<AccessVectorRule>::parse(tail)
632 .map_err(Into::<anyhow::Error>::into)
633 .context("parsing access vector rules")?;
634
635 let (conditional_lists, tail) = SimpleArray::<ConditionalNodes>::parse(tail)
636 .map_err(Into::<anyhow::Error>::into)
637 .context("parsing conditional lists")?;
638
639 let (role_transitions, tail) = RoleTransitions::parse(tail)
640 .map_err(Into::<anyhow::Error>::into)
641 .context("parsing role transitions")?;
642
643 let (role_allowlist, tail) = RoleAllows::parse(tail)
644 .map_err(Into::<anyhow::Error>::into)
645 .context("parsing role allow rules")?;
646
647 let (filename_transition_list, tail) = if policy_version_value >= 33 {
648 let (filename_transition_list, tail) = SimpleArray::<FilenameTransitions>::parse(tail)
649 .map_err(Into::<anyhow::Error>::into)
650 .context("parsing standard filename transitions")?;
651 (FilenameTransitionList::PolicyVersionGeq33(filename_transition_list), tail)
652 } else {
653 let (filename_transition_list, tail) =
654 SimpleArray::<DeprecatedFilenameTransitions>::parse(tail)
655 .map_err(Into::<anyhow::Error>::into)
656 .context("parsing deprecated filename transitions")?;
657 (FilenameTransitionList::PolicyVersionLeq32(filename_transition_list), tail)
658 };
659
660 let (initial_sids, tail) = SimpleArray::<InitialSids>::parse(tail)
661 .map_err(Into::<anyhow::Error>::into)
662 .context("parsing initial sids")?;
663
664 let (filesystems, tail) = SimpleArray::<NamedContextPairs>::parse(tail)
665 .map_err(Into::<anyhow::Error>::into)
666 .context("parsing filesystem contexts")?;
667
668 let (ports, tail) = SimpleArray::<Ports>::parse(tail)
669 .map_err(Into::<anyhow::Error>::into)
670 .context("parsing ports")?;
671
672 let (network_interfaces, tail) = SimpleArray::<NamedContextPairs>::parse(tail)
673 .map_err(Into::<anyhow::Error>::into)
674 .context("parsing network interfaces")?;
675
676 let (nodes, tail) = SimpleArray::<Nodes>::parse(tail)
677 .map_err(Into::<anyhow::Error>::into)
678 .context("parsing nodes")?;
679
680 let (fs_uses, tail) = SimpleArray::<FsUses>::parse(tail)
681 .map_err(Into::<anyhow::Error>::into)
682 .context("parsing fs uses")?;
683
684 let (ipv6_nodes, tail) = SimpleArray::<IPv6Nodes>::parse(tail)
685 .map_err(Into::<anyhow::Error>::into)
686 .context("parsing ipv6 nodes")?;
687
688 let (infinitiband_partition_keys, infinitiband_end_ports, tail) =
689 if policy_version_value >= MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY {
690 let (infinity_band_partition_keys, tail) =
691 SimpleArray::<InfinitiBandPartitionKeys>::parse(tail)
692 .map_err(Into::<anyhow::Error>::into)
693 .context("parsing infiniti band partition keys")?;
694 let (infinitiband_end_ports, tail) = SimpleArray::<InfinitiBandEndPorts>::parse(tail)
695 .map_err(Into::<anyhow::Error>::into)
696 .context("parsing infiniti band end ports")?;
697 (Some(infinity_band_partition_keys), Some(infinitiband_end_ports), tail)
698 } else {
699 (None, None, tail)
700 };
701
702 let (generic_fs_contexts, tail) = SimpleArray::<GenericFsContexts>::parse(tail)
703 .map_err(Into::<anyhow::Error>::into)
704 .context("parsing generic filesystem contexts")?;
705
706 let (range_transitions, tail) = SimpleArray::<RangeTransitions>::parse(tail)
707 .map_err(Into::<anyhow::Error>::into)
708 .context("parsing range transitions")?;
709
710 let primary_names_count = types.metadata.primary_names_count();
711 let mut attribute_maps = Vec::with_capacity(primary_names_count as usize);
712 let mut tail = tail;
713 for i in 0..primary_names_count {
714 let offset = U24::try_from(tail.offset()).expect("Policy offsets ought fit in U24!");
715 let (_, next_tail) = ExtensibleBitmap::parse(tail)
716 .map_err(Into::<anyhow::Error>::into)
717 .with_context(|| format!("parsing {}th attribute map", i))?;
718 attribute_maps.push(offset);
719 tail = next_tail;
720 }
721
722 let excess_bytes = data.len() - tail.offset() as usize;
723
724 Ok((
725 ParsedPolicy {
726 data,
727 magic,
728 signature,
729 policy_version,
730 config,
731 counts,
732 policy_capabilities,
733 permissive_map,
734 common_symbols,
735 classes,
736 roles,
737 types,
738 users,
739 conditional_booleans,
740 sensitivities,
741 categories,
742 access_vector_rules,
743 conditional_lists,
744 role_transitions,
745 role_allowlist,
746 filename_transition_list,
747 initial_sids,
748 filesystems,
749 ports,
750 network_interfaces,
751 nodes,
752 fs_uses,
753 ipv6_nodes,
754 infinitiband_partition_keys,
755 infinitiband_end_ports,
756 generic_fs_contexts,
757 range_transitions,
758 attribute_maps,
759 },
760 excess_bytes,
761 ))
762}
763
764impl ParsedPolicy {
765 pub fn validate(&self) -> Result<(), anyhow::Error> {
766 let context = PolicyValidationContext { data: self.data.clone() };
767
768 self.magic
769 .validate(&context)
770 .map_err(Into::<anyhow::Error>::into)
771 .context("validating magic")?;
772 self.signature
773 .validate(&context)
774 .map_err(Into::<anyhow::Error>::into)
775 .context("validating signature")?;
776 self.policy_version
777 .validate(&context)
778 .map_err(Into::<anyhow::Error>::into)
779 .context("validating policy_version")?;
780 self.config
781 .validate(&context)
782 .map_err(Into::<anyhow::Error>::into)
783 .context("validating config")?;
784 self.counts
785 .validate(&context)
786 .map_err(Into::<anyhow::Error>::into)
787 .context("validating counts")?;
788 self.policy_capabilities
789 .validate(&context)
790 .map_err(Into::<anyhow::Error>::into)
791 .context("validating policy_capabilities")?;
792 self.permissive_map
793 .validate(&context)
794 .map_err(Into::<anyhow::Error>::into)
795 .context("validating permissive_map")?;
796 self.common_symbols
797 .validate(&context)
798 .map_err(Into::<anyhow::Error>::into)
799 .context("validating common_symbols")?;
800 self.classes
801 .validate(&context)
802 .map_err(Into::<anyhow::Error>::into)
803 .context("validating classes")?;
804 self.roles
805 .validate(&context)
806 .map_err(Into::<anyhow::Error>::into)
807 .context("validating roles")?;
808 self.types
809 .validate(&context)
810 .map_err(Into::<anyhow::Error>::into)
811 .context("validating types")?;
812 self.users
813 .validate(&context)
814 .map_err(Into::<anyhow::Error>::into)
815 .context("validating users")?;
816 self.conditional_booleans
817 .validate(&context)
818 .map_err(Into::<anyhow::Error>::into)
819 .context("validating conditional_booleans")?;
820 self.sensitivities
821 .validate(&context)
822 .map_err(Into::<anyhow::Error>::into)
823 .context("validating sensitivities")?;
824 self.categories
825 .validate(&context)
826 .map_err(Into::<anyhow::Error>::into)
827 .context("validating categories")?;
828 self.access_vector_rules
829 .validate(&context)
830 .map_err(Into::<anyhow::Error>::into)
831 .context("validating access_vector_rules")?;
832 self.conditional_lists
833 .validate(&context)
834 .map_err(Into::<anyhow::Error>::into)
835 .context("validating conditional_lists")?;
836 self.role_transitions
837 .validate(&context)
838 .map_err(Into::<anyhow::Error>::into)
839 .context("validating role_transitions")?;
840 self.role_allowlist
841 .validate(&context)
842 .map_err(Into::<anyhow::Error>::into)
843 .context("validating role_allowlist")?;
844 self.filename_transition_list
845 .validate(&context)
846 .map_err(Into::<anyhow::Error>::into)
847 .context("validating filename_transition_list")?;
848 self.initial_sids
849 .validate(&context)
850 .map_err(Into::<anyhow::Error>::into)
851 .context("validating initial_sids")?;
852 self.filesystems
853 .validate(&context)
854 .map_err(Into::<anyhow::Error>::into)
855 .context("validating filesystems")?;
856 self.ports
857 .validate(&context)
858 .map_err(Into::<anyhow::Error>::into)
859 .context("validating ports")?;
860 self.network_interfaces
861 .validate(&context)
862 .map_err(Into::<anyhow::Error>::into)
863 .context("validating network_interfaces")?;
864 self.nodes
865 .validate(&context)
866 .map_err(Into::<anyhow::Error>::into)
867 .context("validating nodes")?;
868 self.fs_uses
869 .validate(&context)
870 .map_err(Into::<anyhow::Error>::into)
871 .context("validating fs_uses")?;
872 self.ipv6_nodes
873 .validate(&context)
874 .map_err(Into::<anyhow::Error>::into)
875 .context("validating ipv6 nodes")?;
876 self.infinitiband_partition_keys
877 .validate(&context)
878 .map_err(Into::<anyhow::Error>::into)
879 .context("validating infinitiband_partition_keys")?;
880 self.infinitiband_end_ports
881 .validate(&context)
882 .map_err(Into::<anyhow::Error>::into)
883 .context("validating infinitiband_end_ports")?;
884 self.generic_fs_contexts
885 .validate(&context)
886 .map_err(Into::<anyhow::Error>::into)
887 .context("validating generic_fs_contexts")?;
888 self.range_transitions
889 .validate(&context)
890 .map_err(Into::<anyhow::Error>::into)
891 .context("validating range_transitions")?;
892 for attribute_map_offset in &self.attribute_maps {
893 self.reparse_attribute_map(*attribute_map_offset)
894 .validate(&context)
895 .map_err(anyhow::Error::from)
896 .context("validating attribute_maps")?;
897 }
898
899 let user_ids: HashSet<UserId> = self.users.data.iter().map(|x| x.id()).collect();
901 let role_ids: HashSet<RoleId> = self.roles.data.iter().map(|x| x.id()).collect();
902 let class_ids: HashSet<ClassId> = self.classes.data.iter().map(|x| x.id()).collect();
903 let type_ids: HashSet<TypeId> = self.types.data.iter().map(|x| x.id()).collect();
904 let sensitivity_ids: HashSet<SensitivityId> =
905 self.sensitivities.data.iter().map(|x| x.id()).collect();
906 let category_ids: HashSet<CategoryId> =
907 self.categories.data.iter().map(|x| x.id()).collect();
908
909 for user in &self.users.data {
913 self.validate_mls_range(
914 user.mls_range().low(),
915 user.mls_range().high(),
916 &sensitivity_ids,
917 &category_ids,
918 )?;
919 }
920
921 for initial_sid in &self.initial_sids.data {
925 let context = initial_sid.context();
926 validate_id(&user_ids, context.user_id(), "user")?;
927 validate_id(&role_ids, context.role_id(), "role")?;
928 validate_id(&type_ids, context.type_id(), "type")?;
929 self.validate_mls_range(
930 context.low_level(),
931 context.high_level(),
932 &sensitivity_ids,
933 &category_ids,
934 )?;
935 }
936
937 for fs_use in &self.fs_uses.data {
941 let context = fs_use.context();
942 validate_id(&user_ids, context.user_id(), "user")?;
943 validate_id(&role_ids, context.role_id(), "role")?;
944 validate_id(&type_ids, context.type_id(), "type")?;
945 self.validate_mls_range(
946 context.low_level(),
947 context.high_level(),
948 &sensitivity_ids,
949 &category_ids,
950 )?;
951 }
952
953 for transition in &self.role_transitions.data {
955 validate_id(&role_ids, transition.current_role(), "current_role")?;
956 validate_id(&type_ids, transition.type_(), "type")?;
957 validate_id(&class_ids, transition.class(), "class")?;
958 validate_id(&role_ids, transition.new_role(), "new_role")?;
959 }
960 for allow in &self.role_allowlist.data {
961 validate_id(&role_ids, allow.source_role(), "source_role")?;
962 validate_id(&role_ids, allow.new_role(), "new_role")?;
963 }
964
965 for access_vector_rule_view in self.access_vector_rules.iter(&self.data) {
967 let access_vector_rule = access_vector_rule_view.parse(&self.data);
968 if let Some(type_id) = access_vector_rule.new_type() {
969 validate_id(&type_ids, type_id, "new_type")?;
970 }
971 }
972
973 let initial_context = SecurityContext::new_from_policy_context(
976 self.initial_context(crate::InitialSid::Kernel),
977 );
978 for class in self.classes() {
979 for constraint in class.constraints() {
980 constraint
981 .constraint_expr()
982 .evaluate(&initial_context, &initial_context)
983 .map_err(Into::<anyhow::Error>::into)
984 .context("validating constraints")?;
985 }
986 }
987
988 Ok(())
992 }
993}
994
995fn validate_id<IdType: Debug + Eq + Hash>(
996 id_set: &HashSet<IdType>,
997 id: IdType,
998 debug_kind: &'static str,
999) -> Result<(), anyhow::Error> {
1000 if !id_set.contains(&id) {
1001 return Err(ValidateError::UnknownId { kind: debug_kind, id: format!("{:?}", id) }.into());
1002 }
1003 Ok(())
1004}