1use crate::NullessByteStr;
6
7use super::arrays::{
8 AccessVectorRules, ConditionalNodes, Context, DeprecatedFilenameTransitions,
9 FilenameTransitionList, FilenameTransitions, FsUses, GenericFsContexts, IPv6Nodes,
10 InfinitiBandEndPorts, InfinitiBandPartitionKeys, InitialSids, NamedContextPairs, Nodes, Ports,
11 RangeTransitions, RoleAllow, RoleAllows, RoleTransition, RoleTransitions, SimpleArray,
12 MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY, XPERMS_TYPE_IOCTL_PREFIXES,
13 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES,
14};
15use super::error::{ParseError, ValidateError};
16use super::extensible_bitmap::ExtensibleBitmap;
17use super::metadata::{Config, Counts, HandleUnknown, Magic, PolicyVersion, Signature};
18use super::parser::ParseStrategy;
19use super::security_context::{Level, SecurityContext};
20use super::symbols::{
21 find_class_by_name, Category, Class, Classes, CommonSymbol, CommonSymbols, ConditionalBoolean,
22 MlsLevel, Role, Sensitivity, SymbolList, Type, User,
23};
24use super::{
25 AccessDecision, AccessVector, CategoryId, ClassId, IoctlAccessDecision, Parse, RoleId,
26 SensitivityId, TypeId, UserId, Validate, XpermsBitmap, SELINUX_AVD_FLAGS_PERMISSIVE,
27};
28
29use anyhow::Context as _;
30use std::collections::HashSet;
31use std::fmt::Debug;
32use std::hash::Hash;
33use zerocopy::little_endian as le;
34
35#[derive(Debug)]
37pub struct ParsedPolicy<PS: ParseStrategy> {
38 magic: PS::Output<Magic>,
41 signature: Signature<PS>,
43 policy_version: PS::Output<PolicyVersion>,
45 config: Config<PS>,
47 counts: PS::Output<Counts>,
49 policy_capabilities: ExtensibleBitmap<PS>,
50 permissive_map: ExtensibleBitmap<PS>,
51 common_symbols: SymbolList<PS, CommonSymbol<PS>>,
53 classes: SymbolList<PS, Class<PS>>,
55 roles: SymbolList<PS, Role<PS>>,
57 types: SymbolList<PS, Type<PS>>,
59 users: SymbolList<PS, User<PS>>,
61 conditional_booleans: SymbolList<PS, ConditionalBoolean<PS>>,
63 sensitivities: SymbolList<PS, Sensitivity<PS>>,
65 categories: SymbolList<PS, Category<PS>>,
67 access_vector_rules: SimpleArray<PS, AccessVectorRules<PS>>,
69 conditional_lists: SimpleArray<PS, ConditionalNodes<PS>>,
70 role_transitions: RoleTransitions<PS>,
72 role_allowlist: RoleAllows<PS>,
74 filename_transition_list: FilenameTransitionList<PS>,
75 initial_sids: SimpleArray<PS, InitialSids<PS>>,
76 filesystems: SimpleArray<PS, NamedContextPairs<PS>>,
77 ports: SimpleArray<PS, Ports<PS>>,
78 network_interfaces: SimpleArray<PS, NamedContextPairs<PS>>,
79 nodes: SimpleArray<PS, Nodes<PS>>,
80 fs_uses: SimpleArray<PS, FsUses<PS>>,
81 ipv6_nodes: SimpleArray<PS, IPv6Nodes<PS>>,
82 infinitiband_partition_keys: Option<SimpleArray<PS, InfinitiBandPartitionKeys<PS>>>,
83 infinitiband_end_ports: Option<SimpleArray<PS, InfinitiBandEndPorts<PS>>>,
84 generic_fs_contexts: SimpleArray<PS, GenericFsContexts<PS>>,
87 range_transitions: SimpleArray<PS, RangeTransitions<PS>>,
88 attribute_maps: Vec<ExtensibleBitmap<PS>>,
90}
91
92impl<PS: ParseStrategy> ParsedPolicy<PS> {
93 pub fn policy_version(&self) -> u32 {
95 PS::deref(&self.policy_version).policy_version()
96 }
97
98 pub fn handle_unknown(&self) -> HandleUnknown {
101 self.config.handle_unknown()
102 }
103
104 pub(super) fn compute_access_decision(
116 &self,
117 source_context: &SecurityContext,
118 target_context: &SecurityContext,
119 target_class: &Class<PS>,
120 ) -> AccessDecision {
121 let mut access_decision = self.compute_explicitly_allowed(
122 source_context.type_(),
123 target_context.type_(),
124 target_class,
125 );
126 access_decision.allow -=
127 self.compute_denied_by_constraints(source_context, target_context, target_class);
128 access_decision
129 }
130
131 pub(super) fn compute_access_decision_custom(
134 &self,
135 source_context: &SecurityContext,
136 target_context: &SecurityContext,
137 target_class_name: &str,
138 ) -> AccessDecision {
139 let mut access_decision = self.compute_explicitly_allowed_custom(
140 source_context.type_(),
141 target_context.type_(),
142 target_class_name,
143 );
144 access_decision.allow -= self.compute_denied_by_constraints_custom(
145 source_context,
146 target_context,
147 target_class_name,
148 );
149 access_decision
150 }
151
152 pub(super) fn compute_explicitly_allowed_custom(
158 &self,
159 source_type_name: TypeId,
160 target_type_name: TypeId,
161 target_class_name: &str,
162 ) -> AccessDecision {
163 if let Some(target_class) = find_class_by_name(self.classes(), target_class_name) {
164 self.compute_explicitly_allowed(source_type_name, target_type_name, target_class)
165 } else {
166 AccessDecision::allow(if self.handle_unknown() == HandleUnknown::Allow {
167 AccessVector::ALL
168 } else {
169 AccessVector::NONE
170 })
171 }
172 }
173
174 pub(super) fn compute_explicitly_allowed(
179 &self,
180 source_type: TypeId,
181 target_type: TypeId,
182 target_class: &Class<PS>,
183 ) -> AccessDecision {
184 let target_class_id = target_class.id();
185
186 let mut computed_access_vector = AccessVector::NONE;
187 let mut computed_audit_allow = AccessVector::NONE;
188 let mut computed_audit_deny = AccessVector::ALL;
189
190 for access_vector_rule in self.access_vector_rules.data.iter() {
191 if !access_vector_rule.is_allow()
198 && !access_vector_rule.is_auditallow()
199 && !access_vector_rule.is_dontaudit()
200 {
201 continue;
202 }
203
204 if access_vector_rule.target_class() != target_class_id {
207 continue;
208 }
209
210 let source_attribute_bitmap: &ExtensibleBitmap<PS> =
218 &self.attribute_maps[(source_type.0.get() - 1) as usize];
219 if !source_attribute_bitmap.is_set(access_vector_rule.source_type().0.get() - 1) {
220 continue;
221 }
222
223 let target_attribute_bitmap: &ExtensibleBitmap<PS> =
226 &self.attribute_maps[(target_type.0.get() - 1) as usize];
227 if !target_attribute_bitmap.is_set(access_vector_rule.target_type().0.get() - 1) {
228 continue;
229 }
230
231 if let Some(access_vector) = access_vector_rule.access_vector() {
234 if access_vector_rule.is_allow() {
235 computed_access_vector |= access_vector;
237 } else if access_vector_rule.is_auditallow() {
238 computed_audit_allow |= access_vector;
240 } else if access_vector_rule.is_dontaudit() {
241 computed_audit_deny &= access_vector;
243 }
244 }
245 }
246
247 let mut flags = 0;
249 if self.permissive_types().is_set(source_type.0.get()) {
250 flags |= SELINUX_AVD_FLAGS_PERMISSIVE;
251 }
252 AccessDecision {
253 allow: computed_access_vector,
254 auditallow: computed_audit_allow,
255 auditdeny: computed_audit_deny,
256 flags,
257 todo_bug: None,
258 }
259 }
260
261 fn compute_denied_by_constraints(
263 &self,
264 source_context: &SecurityContext,
265 target_context: &SecurityContext,
266 target_class: &Class<PS>,
267 ) -> AccessVector {
268 let mut denied = AccessVector::NONE;
269 for constraint in target_class.constraints().iter() {
270 match constraint.constraint_expr().evaluate(source_context, target_context) {
271 Err(err) => {
272 unreachable!("validated constraint expression failed to evaluate: {:?}", err)
273 }
274 Ok(false) => denied |= constraint.access_vector(),
275 Ok(true) => {}
276 }
277 }
278 denied
279 }
280
281 fn compute_denied_by_constraints_custom(
285 &self,
286 source_context: &SecurityContext,
287 target_context: &SecurityContext,
288 target_class_name: &str,
289 ) -> AccessVector {
290 if let Some(target_class) = find_class_by_name(self.classes(), target_class_name) {
291 self.compute_denied_by_constraints(source_context, target_context, target_class)
292 } else {
293 AccessVector::NONE
294 }
295 }
296
297 pub(super) fn compute_ioctl_access_decision(
307 &self,
308 source_context: &SecurityContext,
309 target_context: &SecurityContext,
310 target_class: &Class<PS>,
311 ioctl_prefix: u8,
312 ) -> IoctlAccessDecision {
313 let target_class_id = target_class.id();
314
315 let mut explicit_allow: Option<XpermsBitmap> = None;
316 let mut auditallow = XpermsBitmap::NONE;
317 let mut auditdeny = XpermsBitmap::ALL;
318
319 for access_vector_rule in self.access_vector_rules.data.iter() {
320 if !access_vector_rule.is_allowxperm()
321 && !access_vector_rule.is_auditallowxperm()
322 && !access_vector_rule.is_dontauditxperm()
323 {
324 continue;
325 }
326 if access_vector_rule.target_class() != target_class_id {
327 continue;
328 }
329 let source_attribute_bitmap: &ExtensibleBitmap<PS> =
330 &self.attribute_maps[(source_context.type_().0.get() - 1) as usize];
331 if !source_attribute_bitmap.is_set(access_vector_rule.source_type().0.get() - 1) {
332 continue;
333 }
334 let target_attribute_bitmap: &ExtensibleBitmap<PS> =
335 &self.attribute_maps[(target_context.type_().0.get() - 1) as usize];
336 if !target_attribute_bitmap.is_set(access_vector_rule.target_type().0.get() - 1) {
337 continue;
338 }
339
340 if let Some(xperms) = access_vector_rule.extended_permissions() {
341 if access_vector_rule.is_allowxperm() {
344 explicit_allow.get_or_insert(XpermsBitmap::NONE);
345 }
346 let bitmap_if_prefix_matches = match xperms.xperms_type {
349 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES => (xperms.xperms_optional_prefix
350 == ioctl_prefix)
351 .then_some(&xperms.xperms_bitmap),
352 XPERMS_TYPE_IOCTL_PREFIXES => {
353 xperms.xperms_bitmap.contains(ioctl_prefix).then_some(&XpermsBitmap::ALL)
354 }
355 _ => unreachable!("invalid xperms_type in validated ExtendedPermissions"),
356 };
357 let Some(xperms_bitmap) = bitmap_if_prefix_matches else {
358 continue;
359 };
360 if access_vector_rule.is_allowxperm() {
361 (*explicit_allow.get_or_insert(XpermsBitmap::NONE)) |= xperms_bitmap;
362 }
363 if access_vector_rule.is_auditallowxperm() {
364 auditallow |= xperms_bitmap;
365 }
366 if access_vector_rule.is_dontauditxperm() {
367 auditdeny -= xperms_bitmap;
368 }
369 }
370 }
371 let allow = explicit_allow.unwrap_or(XpermsBitmap::ALL);
372 IoctlAccessDecision { allow, auditallow, auditdeny }
373 }
374
375 pub(super) fn compute_ioctl_access_decision_custom(
380 &self,
381 source_context: &SecurityContext,
382 target_context: &SecurityContext,
383 target_class_name: &str,
384 ioctl_prefix: u8,
385 ) -> IoctlAccessDecision {
386 if let Some(target_class) = find_class_by_name(self.classes(), target_class_name) {
387 self.compute_ioctl_access_decision(
388 source_context,
389 target_context,
390 target_class,
391 ioctl_prefix,
392 )
393 } else {
394 IoctlAccessDecision::ALLOW_ALL
395 }
396 }
397
398 pub(super) fn initial_context(&self, id: crate::InitialSid) -> &Context<PS> {
400 let id = le::U32::from(id as u32);
401 &self.initial_sids.data.iter().find(|initial| initial.id() == id).unwrap().context()
403 }
404
405 pub(super) fn user(&self, id: UserId) -> &User<PS> {
408 self.users.data.iter().find(|x| x.id() == id).unwrap()
409 }
410
411 pub(super) fn user_by_name(&self, name: &str) -> Option<&User<PS>> {
413 self.users.data.iter().find(|x| x.name_bytes() == name.as_bytes())
414 }
415
416 pub(super) fn role(&self, id: RoleId) -> &Role<PS> {
419 self.roles.data.iter().find(|x| x.id() == id).unwrap()
420 }
421
422 pub(super) fn role_by_name(&self, name: &str) -> Option<&Role<PS>> {
424 self.roles.data.iter().find(|x| x.name_bytes() == name.as_bytes())
425 }
426
427 pub(super) fn type_(&self, id: TypeId) -> &Type<PS> {
430 self.types.data.iter().find(|x| x.id() == id).unwrap()
431 }
432
433 pub(super) fn type_by_name(&self, name: &str) -> Option<&Type<PS>> {
435 self.types.data.iter().find(|x| x.name_bytes() == name.as_bytes())
436 }
437
438 pub(super) fn permissive_types(&self) -> &ExtensibleBitmap<PS> {
441 &self.permissive_map
442 }
443
444 pub(super) fn sensitivity(&self, id: SensitivityId) -> &Sensitivity<PS> {
447 self.sensitivities.data.iter().find(|x| x.id() == id).unwrap()
448 }
449
450 pub(super) fn sensitivity_by_name(&self, name: &str) -> Option<&Sensitivity<PS>> {
452 self.sensitivities.data.iter().find(|x| x.name_bytes() == name.as_bytes())
453 }
454
455 pub(super) fn category(&self, id: CategoryId) -> &Category<PS> {
458 self.categories.data.iter().find(|y| y.id() == id).unwrap()
459 }
460
461 pub(super) fn category_by_name(&self, name: &str) -> Option<&Category<PS>> {
463 self.categories.data.iter().find(|x| x.name_bytes() == name.as_bytes())
464 }
465
466 pub(super) fn classes(&self) -> &Classes<PS> {
467 &self.classes.data
468 }
469
470 pub(super) fn common_symbols(&self) -> &CommonSymbols<PS> {
471 &self.common_symbols.data
472 }
473
474 pub(super) fn conditional_booleans(&self) -> &Vec<ConditionalBoolean<PS>> {
475 &self.conditional_booleans.data
476 }
477
478 pub(super) fn fs_uses(&self) -> &FsUses<PS> {
479 &self.fs_uses.data
480 }
481
482 pub(super) fn generic_fs_contexts(&self) -> &GenericFsContexts<PS> {
483 &self.generic_fs_contexts.data
484 }
485
486 #[allow(dead_code)]
487 pub(super) fn role_allowlist(&self) -> &[RoleAllow] {
490 PS::deref_slice(&self.role_allowlist.data)
491 }
492
493 pub(super) fn role_transitions(&self) -> &[RoleTransition] {
494 PS::deref_slice(&self.role_transitions.data)
495 }
496
497 pub(super) fn range_transitions(&self) -> &RangeTransitions<PS> {
498 &self.range_transitions.data
499 }
500
501 pub(super) fn access_vector_rules(&self) -> &AccessVectorRules<PS> {
502 &self.access_vector_rules.data
503 }
504
505 pub(super) fn compute_filename_transition(
506 &self,
507 source_type: TypeId,
508 target_type: TypeId,
509 class: ClassId,
510 name: NullessByteStr<'_>,
511 ) -> Option<TypeId> {
512 match &self.filename_transition_list {
513 FilenameTransitionList::PolicyVersionGeq33(list) => {
514 let entry = list.data.iter().find(|transition| {
515 transition.target_type() == target_type
516 && transition.target_class() == class
517 && transition.name_bytes() == name.as_bytes()
518 })?;
519 entry
520 .outputs()
521 .iter()
522 .find(|entry| entry.has_source_type(source_type))
523 .map(|x| x.out_type())
524 }
525 FilenameTransitionList::PolicyVersionLeq32(list) => list
526 .data
527 .iter()
528 .find(|transition| {
529 transition.target_class() == class
530 && transition.target_type() == target_type
531 && transition.source_type() == source_type
532 && transition.name_bytes() == name.as_bytes()
533 })
534 .map(|x| x.out_type()),
535 }
536 }
537
538 fn validate_mls_range(
545 &self,
546 low_level: &MlsLevel<PS>,
547 high_level: &Option<MlsLevel<PS>>,
548 sensitivity_ids: &HashSet<SensitivityId>,
549 category_ids: &HashSet<CategoryId>,
550 ) -> Result<(), anyhow::Error> {
551 validate_id(sensitivity_ids, low_level.sensitivity(), "sensitivity")?;
552 for id in low_level.category_ids() {
553 validate_id(category_ids, id, "category")?;
554 }
555 if let Some(high) = high_level {
556 validate_id(sensitivity_ids, high.sensitivity(), "sensitivity")?;
557 for id in high.category_ids() {
558 validate_id(category_ids, id, "category")?;
559 }
560 if !high.dominates(low_level) {
561 return Err(ValidateError::InvalidMlsRange {
562 low: low_level.serialize(self).into(),
563 high: high.serialize(self).into(),
564 }
565 .into());
566 }
567 }
568 Ok(())
569 }
570}
571
572impl<PS: ParseStrategy> ParsedPolicy<PS>
573where
574 Self: Parse<PS>,
575{
576 pub(super) fn parse(bytes: PS) -> Result<(Self, PS::Input), anyhow::Error> {
579 let (policy, tail) =
580 <ParsedPolicy<PS> as Parse<PS>>::parse(bytes).map_err(Into::<anyhow::Error>::into)?;
581 let num_bytes = tail.len();
582 if num_bytes > 0 {
583 return Err(ParseError::TrailingBytes { num_bytes }.into());
584 }
585 Ok((policy, tail.into_inner()))
586 }
587}
588
589impl<PS: ParseStrategy> Parse<PS> for ParsedPolicy<PS>
591where
592 Signature<PS>: Parse<PS>,
593 ExtensibleBitmap<PS>: Parse<PS>,
594 SymbolList<PS, CommonSymbol<PS>>: Parse<PS>,
595 SymbolList<PS, Class<PS>>: Parse<PS>,
596 SymbolList<PS, Role<PS>>: Parse<PS>,
597 SymbolList<PS, Type<PS>>: Parse<PS>,
598 SymbolList<PS, User<PS>>: Parse<PS>,
599 SymbolList<PS, ConditionalBoolean<PS>>: Parse<PS>,
600 SymbolList<PS, Sensitivity<PS>>: Parse<PS>,
601 SymbolList<PS, Category<PS>>: Parse<PS>,
602 SimpleArray<PS, AccessVectorRules<PS>>: Parse<PS>,
603 SimpleArray<PS, ConditionalNodes<PS>>: Parse<PS>,
604 RoleTransitions<PS>: Parse<PS>,
605 RoleAllows<PS>: Parse<PS>,
606 SimpleArray<PS, FilenameTransitions<PS>>: Parse<PS>,
607 SimpleArray<PS, DeprecatedFilenameTransitions<PS>>: Parse<PS>,
608 SimpleArray<PS, InitialSids<PS>>: Parse<PS>,
609 SimpleArray<PS, NamedContextPairs<PS>>: Parse<PS>,
610 SimpleArray<PS, Ports<PS>>: Parse<PS>,
611 SimpleArray<PS, NamedContextPairs<PS>>: Parse<PS>,
612 SimpleArray<PS, Nodes<PS>>: Parse<PS>,
613 SimpleArray<PS, FsUses<PS>>: Parse<PS>,
614 SimpleArray<PS, IPv6Nodes<PS>>: Parse<PS>,
615 SimpleArray<PS, InfinitiBandPartitionKeys<PS>>: Parse<PS>,
616 SimpleArray<PS, InfinitiBandEndPorts<PS>>: Parse<PS>,
617 SimpleArray<PS, GenericFsContexts<PS>>: Parse<PS>,
618 SimpleArray<PS, RangeTransitions<PS>>: Parse<PS>,
619{
620 type Error = anyhow::Error;
622
623 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
625 let tail = bytes;
626
627 let (magic, tail) = PS::parse::<Magic>(tail).context("parsing magic")?;
628
629 let (signature, tail) = Signature::parse(tail)
630 .map_err(Into::<anyhow::Error>::into)
631 .context("parsing signature")?;
632
633 let (policy_version, tail) =
634 PS::parse::<PolicyVersion>(tail).context("parsing policy version")?;
635 let policy_version_value = PS::deref(&policy_version).policy_version();
636
637 let (config, tail) = Config::parse(tail)
638 .map_err(Into::<anyhow::Error>::into)
639 .context("parsing policy config")?;
640
641 let (counts, tail) =
642 PS::parse::<Counts>(tail).context("parsing high-level policy object counts")?;
643
644 let (policy_capabilities, tail) = ExtensibleBitmap::parse(tail)
645 .map_err(Into::<anyhow::Error>::into)
646 .context("parsing policy capabilities")?;
647
648 let (permissive_map, tail) = ExtensibleBitmap::parse(tail)
649 .map_err(Into::<anyhow::Error>::into)
650 .context("parsing permissive map")?;
651
652 let (common_symbols, tail) = SymbolList::<PS, CommonSymbol<PS>>::parse(tail)
653 .map_err(Into::<anyhow::Error>::into)
654 .context("parsing common symbols")?;
655
656 let (classes, tail) = SymbolList::<PS, Class<PS>>::parse(tail)
657 .map_err(Into::<anyhow::Error>::into)
658 .context("parsing classes")?;
659
660 let (roles, tail) = SymbolList::<PS, Role<PS>>::parse(tail)
661 .map_err(Into::<anyhow::Error>::into)
662 .context("parsing roles")?;
663
664 let (types, tail) = SymbolList::<PS, Type<PS>>::parse(tail)
665 .map_err(Into::<anyhow::Error>::into)
666 .context("parsing types")?;
667
668 let (users, tail) = SymbolList::<PS, User<PS>>::parse(tail)
669 .map_err(Into::<anyhow::Error>::into)
670 .context("parsing users")?;
671
672 let (conditional_booleans, tail) = SymbolList::<PS, ConditionalBoolean<PS>>::parse(tail)
673 .map_err(Into::<anyhow::Error>::into)
674 .context("parsing conditional booleans")?;
675
676 let (sensitivities, tail) = SymbolList::<PS, Sensitivity<PS>>::parse(tail)
677 .map_err(Into::<anyhow::Error>::into)
678 .context("parsing sensitivites")?;
679
680 let (categories, tail) = SymbolList::<PS, Category<PS>>::parse(tail)
681 .map_err(Into::<anyhow::Error>::into)
682 .context("parsing categories")?;
683
684 let (access_vector_rules, tail) = SimpleArray::<PS, AccessVectorRules<PS>>::parse(tail)
685 .map_err(Into::<anyhow::Error>::into)
686 .context("parsing access vector rules")?;
687
688 let (conditional_lists, tail) = SimpleArray::<PS, ConditionalNodes<PS>>::parse(tail)
689 .map_err(Into::<anyhow::Error>::into)
690 .context("parsing conditional lists")?;
691
692 let (role_transitions, tail) = RoleTransitions::<PS>::parse(tail)
693 .map_err(Into::<anyhow::Error>::into)
694 .context("parsing role transitions")?;
695
696 let (role_allowlist, tail) = RoleAllows::<PS>::parse(tail)
697 .map_err(Into::<anyhow::Error>::into)
698 .context("parsing role allow rules")?;
699
700 let (filename_transition_list, tail) = if policy_version_value >= 33 {
701 let (filename_transition_list, tail) =
702 SimpleArray::<PS, FilenameTransitions<PS>>::parse(tail)
703 .map_err(Into::<anyhow::Error>::into)
704 .context("parsing standard filename transitions")?;
705 (FilenameTransitionList::PolicyVersionGeq33(filename_transition_list), tail)
706 } else {
707 let (filename_transition_list, tail) =
708 SimpleArray::<PS, DeprecatedFilenameTransitions<PS>>::parse(tail)
709 .map_err(Into::<anyhow::Error>::into)
710 .context("parsing deprecated filename transitions")?;
711 (FilenameTransitionList::PolicyVersionLeq32(filename_transition_list), tail)
712 };
713
714 let (initial_sids, tail) = SimpleArray::<PS, InitialSids<PS>>::parse(tail)
715 .map_err(Into::<anyhow::Error>::into)
716 .context("parsing initial sids")?;
717
718 let (filesystems, tail) = SimpleArray::<PS, NamedContextPairs<PS>>::parse(tail)
719 .map_err(Into::<anyhow::Error>::into)
720 .context("parsing filesystem contexts")?;
721
722 let (ports, tail) = SimpleArray::<PS, Ports<PS>>::parse(tail)
723 .map_err(Into::<anyhow::Error>::into)
724 .context("parsing ports")?;
725
726 let (network_interfaces, tail) = SimpleArray::<PS, NamedContextPairs<PS>>::parse(tail)
727 .map_err(Into::<anyhow::Error>::into)
728 .context("parsing network interfaces")?;
729
730 let (nodes, tail) = SimpleArray::<PS, Nodes<PS>>::parse(tail)
731 .map_err(Into::<anyhow::Error>::into)
732 .context("parsing nodes")?;
733
734 let (fs_uses, tail) = SimpleArray::<PS, FsUses<PS>>::parse(tail)
735 .map_err(Into::<anyhow::Error>::into)
736 .context("parsing fs uses")?;
737
738 let (ipv6_nodes, tail) = SimpleArray::<PS, IPv6Nodes<PS>>::parse(tail)
739 .map_err(Into::<anyhow::Error>::into)
740 .context("parsing ipv6 nodes")?;
741
742 let (infinitiband_partition_keys, infinitiband_end_ports, tail) =
743 if policy_version_value >= MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY {
744 let (infinity_band_partition_keys, tail) =
745 SimpleArray::<PS, InfinitiBandPartitionKeys<PS>>::parse(tail)
746 .map_err(Into::<anyhow::Error>::into)
747 .context("parsing infiniti band partition keys")?;
748 let (infinitiband_end_ports, tail) =
749 SimpleArray::<PS, InfinitiBandEndPorts<PS>>::parse(tail)
750 .map_err(Into::<anyhow::Error>::into)
751 .context("parsing infiniti band end ports")?;
752 (Some(infinity_band_partition_keys), Some(infinitiband_end_ports), tail)
753 } else {
754 (None, None, tail)
755 };
756
757 let (generic_fs_contexts, tail) = SimpleArray::<PS, GenericFsContexts<PS>>::parse(tail)
758 .map_err(Into::<anyhow::Error>::into)
759 .context("parsing generic filesystem contexts")?;
760
761 let (range_transitions, tail) = SimpleArray::<PS, RangeTransitions<PS>>::parse(tail)
762 .map_err(Into::<anyhow::Error>::into)
763 .context("parsing range transitions")?;
764
765 let primary_names_count = PS::deref(&types.metadata).primary_names_count();
766 let mut attribute_maps = Vec::with_capacity(primary_names_count as usize);
767 let mut tail = tail;
768
769 for i in 0..primary_names_count {
770 let (item, next_tail) = ExtensibleBitmap::parse(tail)
771 .map_err(Into::<anyhow::Error>::into)
772 .with_context(|| format!("parsing {}th attribtue map", i))?;
773 attribute_maps.push(item);
774 tail = next_tail;
775 }
776 let tail = tail;
777 let attribute_maps = attribute_maps;
778
779 Ok((
780 Self {
781 magic,
782 signature,
783 policy_version,
784 config,
785 counts,
786 policy_capabilities,
787 permissive_map,
788 common_symbols,
789 classes,
790 roles,
791 types,
792 users,
793 conditional_booleans,
794 sensitivities,
795 categories,
796 access_vector_rules,
797 conditional_lists,
798 role_transitions,
799 role_allowlist,
800 filename_transition_list,
801 initial_sids,
802 filesystems,
803 ports,
804 network_interfaces,
805 nodes,
806 fs_uses,
807 ipv6_nodes,
808 infinitiband_partition_keys,
809 infinitiband_end_ports,
810 generic_fs_contexts,
811 range_transitions,
812 attribute_maps,
813 },
814 tail,
815 ))
816 }
817}
818
819impl<PS: ParseStrategy> Validate for ParsedPolicy<PS> {
820 type Error = anyhow::Error;
822
823 fn validate(&self) -> Result<(), Self::Error> {
824 PS::deref(&self.magic)
825 .validate()
826 .map_err(Into::<anyhow::Error>::into)
827 .context("validating magic")?;
828 self.signature
829 .validate()
830 .map_err(Into::<anyhow::Error>::into)
831 .context("validating signature")?;
832 PS::deref(&self.policy_version)
833 .validate()
834 .map_err(Into::<anyhow::Error>::into)
835 .context("validating policy_version")?;
836 self.config.validate().map_err(Into::<anyhow::Error>::into).context("validating config")?;
837 PS::deref(&self.counts)
838 .validate()
839 .map_err(Into::<anyhow::Error>::into)
840 .context("validating counts")?;
841 self.policy_capabilities
842 .validate()
843 .map_err(Into::<anyhow::Error>::into)
844 .context("validating policy_capabilities")?;
845 self.permissive_map
846 .validate()
847 .map_err(Into::<anyhow::Error>::into)
848 .context("validating permissive_map")?;
849 self.common_symbols
850 .validate()
851 .map_err(Into::<anyhow::Error>::into)
852 .context("validating common_symbols")?;
853 self.classes
854 .validate()
855 .map_err(Into::<anyhow::Error>::into)
856 .context("validating classes")?;
857 self.roles.validate().map_err(Into::<anyhow::Error>::into).context("validating roles")?;
858 self.types.validate().map_err(Into::<anyhow::Error>::into).context("validating types")?;
859 self.users.validate().map_err(Into::<anyhow::Error>::into).context("validating users")?;
860 self.conditional_booleans
861 .validate()
862 .map_err(Into::<anyhow::Error>::into)
863 .context("validating conditional_booleans")?;
864 self.sensitivities
865 .validate()
866 .map_err(Into::<anyhow::Error>::into)
867 .context("validating sensitivities")?;
868 self.categories
869 .validate()
870 .map_err(Into::<anyhow::Error>::into)
871 .context("validating categories")?;
872 self.access_vector_rules
873 .validate()
874 .map_err(Into::<anyhow::Error>::into)
875 .context("validating access_vector_rules")?;
876 self.conditional_lists
877 .validate()
878 .map_err(Into::<anyhow::Error>::into)
879 .context("validating conditional_lists")?;
880 self.role_transitions
881 .validate()
882 .map_err(Into::<anyhow::Error>::into)
883 .context("validating role_transitions")?;
884 self.role_allowlist
885 .validate()
886 .map_err(Into::<anyhow::Error>::into)
887 .context("validating role_allowlist")?;
888 self.filename_transition_list
889 .validate()
890 .map_err(Into::<anyhow::Error>::into)
891 .context("validating filename_transition_list")?;
892 self.initial_sids
893 .validate()
894 .map_err(Into::<anyhow::Error>::into)
895 .context("validating initial_sids")?;
896 self.filesystems
897 .validate()
898 .map_err(Into::<anyhow::Error>::into)
899 .context("validating filesystems")?;
900 self.ports.validate().map_err(Into::<anyhow::Error>::into).context("validating ports")?;
901 self.network_interfaces
902 .validate()
903 .map_err(Into::<anyhow::Error>::into)
904 .context("validating network_interfaces")?;
905 self.nodes.validate().map_err(Into::<anyhow::Error>::into).context("validating nodes")?;
906 self.fs_uses
907 .validate()
908 .map_err(Into::<anyhow::Error>::into)
909 .context("validating fs_uses")?;
910 self.ipv6_nodes
911 .validate()
912 .map_err(Into::<anyhow::Error>::into)
913 .context("validating ipv6 nodes")?;
914 self.infinitiband_partition_keys
915 .validate()
916 .map_err(Into::<anyhow::Error>::into)
917 .context("validating infinitiband_partition_keys")?;
918 self.infinitiband_end_ports
919 .validate()
920 .map_err(Into::<anyhow::Error>::into)
921 .context("validating infinitiband_end_ports")?;
922 self.generic_fs_contexts
923 .validate()
924 .map_err(Into::<anyhow::Error>::into)
925 .context("validating generic_fs_contexts")?;
926 self.range_transitions
927 .validate()
928 .map_err(Into::<anyhow::Error>::into)
929 .context("validating range_transitions")?;
930 self.attribute_maps
931 .validate()
932 .map_err(Into::<anyhow::Error>::into)
933 .context("validating attribute_maps")?;
934
935 let user_ids: HashSet<UserId> = self.users.data.iter().map(|x| x.id()).collect();
937 let role_ids: HashSet<RoleId> = self.roles.data.iter().map(|x| x.id()).collect();
938 let type_ids: HashSet<TypeId> = self.types.data.iter().map(|x| x.id()).collect();
939 let sensitivity_ids: HashSet<SensitivityId> =
940 self.sensitivities.data.iter().map(|x| x.id()).collect();
941 let category_ids: HashSet<CategoryId> =
942 self.categories.data.iter().map(|x| x.id()).collect();
943
944 for user in &self.users.data {
948 self.validate_mls_range(
949 user.mls_range().low(),
950 user.mls_range().high(),
951 &sensitivity_ids,
952 &category_ids,
953 )?;
954 }
955
956 for initial_sid in &self.initial_sids.data {
960 let context = initial_sid.context();
961 validate_id(&user_ids, context.user_id(), "user")?;
962 validate_id(&role_ids, context.role_id(), "role")?;
963 validate_id(&type_ids, context.type_id(), "type")?;
964 self.validate_mls_range(
965 context.low_level(),
966 context.high_level(),
967 &sensitivity_ids,
968 &category_ids,
969 )?;
970 }
971
972 for fs_use in &self.fs_uses.data {
976 let context = fs_use.context();
977 validate_id(&user_ids, context.user_id(), "user")?;
978 validate_id(&role_ids, context.role_id(), "role")?;
979 validate_id(&type_ids, context.type_id(), "type")?;
980 self.validate_mls_range(
981 context.low_level(),
982 context.high_level(),
983 &sensitivity_ids,
984 &category_ids,
985 )?;
986 }
987
988 for transition in PS::deref_slice(&self.role_transitions.data) {
990 validate_id(&role_ids, transition.new_role(), "new_role")?;
991 }
992 for allow in PS::deref_slice(&self.role_allowlist.data) {
993 validate_id(&role_ids, allow.new_role(), "new_role")?;
994 }
995
996 for access_vector_rule in &self.access_vector_rules.data {
998 if let Some(type_id) = access_vector_rule.new_type() {
999 validate_id(&type_ids, type_id, "new_type")?;
1000 }
1001 }
1002
1003 let initial_context = SecurityContext::new_from_policy_context(
1006 self.initial_context(crate::InitialSid::Kernel),
1007 );
1008 for class in self.classes() {
1009 for constraint in class.constraints() {
1010 constraint
1011 .constraint_expr()
1012 .evaluate(&initial_context, &initial_context)
1013 .map_err(Into::<anyhow::Error>::into)
1014 .context("validating constraints")?;
1015 }
1016 }
1017
1018 Ok(())
1022 }
1023}
1024
1025fn validate_id<IdType: Debug + Eq + Hash>(
1026 id_set: &HashSet<IdType>,
1027 id: IdType,
1028 debug_kind: &'static str,
1029) -> Result<(), anyhow::Error> {
1030 if !id_set.contains(&id) {
1031 return Err(ValidateError::UnknownId { kind: debug_kind, id: format!("{:?}", id) }.into());
1032 }
1033 Ok(())
1034}