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 Category, Class, Classes, CommonSymbol, CommonSymbols, ConditionalBoolean, MlsLevel, Role,
22 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_explicitly_allowed(
136 &self,
137 source_type: TypeId,
138 target_type: TypeId,
139 target_class: &Class<PS>,
140 ) -> AccessDecision {
141 let target_class_id = target_class.id();
142
143 let mut computed_access_vector = AccessVector::NONE;
144 let mut computed_audit_allow = AccessVector::NONE;
145 let mut computed_audit_deny = AccessVector::ALL;
146
147 for access_vector_rule in self.access_vector_rules.data.iter() {
148 if !access_vector_rule.is_allow()
155 && !access_vector_rule.is_auditallow()
156 && !access_vector_rule.is_dontaudit()
157 {
158 continue;
159 }
160
161 if access_vector_rule.target_class() != target_class_id {
164 continue;
165 }
166
167 let source_attribute_bitmap: &ExtensibleBitmap<PS> =
175 &self.attribute_maps[(source_type.0.get() - 1) as usize];
176 if !source_attribute_bitmap.is_set(access_vector_rule.source_type().0.get() - 1) {
177 continue;
178 }
179
180 let target_attribute_bitmap: &ExtensibleBitmap<PS> =
183 &self.attribute_maps[(target_type.0.get() - 1) as usize];
184 if !target_attribute_bitmap.is_set(access_vector_rule.target_type().0.get() - 1) {
185 continue;
186 }
187
188 if let Some(access_vector) = access_vector_rule.access_vector() {
191 if access_vector_rule.is_allow() {
192 computed_access_vector |= access_vector;
194 } else if access_vector_rule.is_auditallow() {
195 computed_audit_allow |= access_vector;
197 } else if access_vector_rule.is_dontaudit() {
198 computed_audit_deny &= access_vector;
200 }
201 }
202 }
203
204 let mut flags = 0;
206 if self.permissive_types().is_set(source_type.0.get()) {
207 flags |= SELINUX_AVD_FLAGS_PERMISSIVE;
208 }
209 AccessDecision {
210 allow: computed_access_vector,
211 auditallow: computed_audit_allow,
212 auditdeny: computed_audit_deny,
213 flags,
214 todo_bug: None,
215 }
216 }
217
218 fn compute_denied_by_constraints(
220 &self,
221 source_context: &SecurityContext,
222 target_context: &SecurityContext,
223 target_class: &Class<PS>,
224 ) -> AccessVector {
225 let mut denied = AccessVector::NONE;
226 for constraint in target_class.constraints().iter() {
227 match constraint.constraint_expr().evaluate(source_context, target_context) {
228 Err(err) => {
229 unreachable!("validated constraint expression failed to evaluate: {:?}", err)
230 }
231 Ok(false) => denied |= constraint.access_vector(),
232 Ok(true) => {}
233 }
234 }
235 denied
236 }
237
238 pub(super) fn compute_ioctl_access_decision(
248 &self,
249 source_context: &SecurityContext,
250 target_context: &SecurityContext,
251 target_class: &Class<PS>,
252 ioctl_prefix: u8,
253 ) -> IoctlAccessDecision {
254 let target_class_id = target_class.id();
255
256 let mut explicit_allow: Option<XpermsBitmap> = None;
257 let mut auditallow = XpermsBitmap::NONE;
258 let mut auditdeny = XpermsBitmap::ALL;
259
260 for access_vector_rule in self.access_vector_rules.data.iter() {
261 if !access_vector_rule.is_allowxperm()
262 && !access_vector_rule.is_auditallowxperm()
263 && !access_vector_rule.is_dontauditxperm()
264 {
265 continue;
266 }
267 if access_vector_rule.target_class() != target_class_id {
268 continue;
269 }
270 let source_attribute_bitmap: &ExtensibleBitmap<PS> =
271 &self.attribute_maps[(source_context.type_().0.get() - 1) as usize];
272 if !source_attribute_bitmap.is_set(access_vector_rule.source_type().0.get() - 1) {
273 continue;
274 }
275 let target_attribute_bitmap: &ExtensibleBitmap<PS> =
276 &self.attribute_maps[(target_context.type_().0.get() - 1) as usize];
277 if !target_attribute_bitmap.is_set(access_vector_rule.target_type().0.get() - 1) {
278 continue;
279 }
280
281 if let Some(xperms) = access_vector_rule.extended_permissions() {
282 if access_vector_rule.is_allowxperm() {
285 explicit_allow.get_or_insert(XpermsBitmap::NONE);
286 }
287 let bitmap_if_prefix_matches = match xperms.xperms_type {
290 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES => (xperms.xperms_optional_prefix
291 == ioctl_prefix)
292 .then_some(&xperms.xperms_bitmap),
293 XPERMS_TYPE_IOCTL_PREFIXES => {
294 xperms.xperms_bitmap.contains(ioctl_prefix).then_some(&XpermsBitmap::ALL)
295 }
296 _ => unreachable!("invalid xperms_type in validated ExtendedPermissions"),
297 };
298 let Some(xperms_bitmap) = bitmap_if_prefix_matches else {
299 continue;
300 };
301 if access_vector_rule.is_allowxperm() {
302 (*explicit_allow.get_or_insert(XpermsBitmap::NONE)) |= xperms_bitmap;
303 }
304 if access_vector_rule.is_auditallowxperm() {
305 auditallow |= xperms_bitmap;
306 }
307 if access_vector_rule.is_dontauditxperm() {
308 auditdeny -= xperms_bitmap;
309 }
310 }
311 }
312 let allow = explicit_allow.unwrap_or(XpermsBitmap::ALL);
313 IoctlAccessDecision { allow, auditallow, auditdeny }
314 }
315
316 pub(super) fn initial_context(&self, id: crate::InitialSid) -> &Context<PS> {
318 let id = le::U32::from(id as u32);
319 &self.initial_sids.data.iter().find(|initial| initial.id() == id).unwrap().context()
321 }
322
323 pub(super) fn user(&self, id: UserId) -> &User<PS> {
326 self.users.data.iter().find(|x| x.id() == id).unwrap()
327 }
328
329 pub(super) fn user_by_name(&self, name: &str) -> Option<&User<PS>> {
331 self.users.data.iter().find(|x| x.name_bytes() == name.as_bytes())
332 }
333
334 pub(super) fn role(&self, id: RoleId) -> &Role<PS> {
337 self.roles.data.iter().find(|x| x.id() == id).unwrap()
338 }
339
340 pub(super) fn role_by_name(&self, name: &str) -> Option<&Role<PS>> {
342 self.roles.data.iter().find(|x| x.name_bytes() == name.as_bytes())
343 }
344
345 pub(super) fn type_(&self, id: TypeId) -> &Type<PS> {
348 self.types.data.iter().find(|x| x.id() == id).unwrap()
349 }
350
351 pub(super) fn type_by_name(&self, name: &str) -> Option<&Type<PS>> {
353 self.types.data.iter().find(|x| x.name_bytes() == name.as_bytes())
354 }
355
356 pub(super) fn permissive_types(&self) -> &ExtensibleBitmap<PS> {
359 &self.permissive_map
360 }
361
362 pub(super) fn sensitivity(&self, id: SensitivityId) -> &Sensitivity<PS> {
365 self.sensitivities.data.iter().find(|x| x.id() == id).unwrap()
366 }
367
368 pub(super) fn sensitivity_by_name(&self, name: &str) -> Option<&Sensitivity<PS>> {
370 self.sensitivities.data.iter().find(|x| x.name_bytes() == name.as_bytes())
371 }
372
373 pub(super) fn category(&self, id: CategoryId) -> &Category<PS> {
376 self.categories.data.iter().find(|y| y.id() == id).unwrap()
377 }
378
379 pub(super) fn category_by_name(&self, name: &str) -> Option<&Category<PS>> {
381 self.categories.data.iter().find(|x| x.name_bytes() == name.as_bytes())
382 }
383
384 pub(super) fn classes(&self) -> &Classes<PS> {
385 &self.classes.data
386 }
387
388 pub(super) fn common_symbols(&self) -> &CommonSymbols<PS> {
389 &self.common_symbols.data
390 }
391
392 pub(super) fn conditional_booleans(&self) -> &Vec<ConditionalBoolean<PS>> {
393 &self.conditional_booleans.data
394 }
395
396 pub(super) fn fs_uses(&self) -> &FsUses<PS> {
397 &self.fs_uses.data
398 }
399
400 pub(super) fn generic_fs_contexts(&self) -> &GenericFsContexts<PS> {
401 &self.generic_fs_contexts.data
402 }
403
404 pub(super) fn role_allowlist(&self) -> &[RoleAllow] {
405 PS::deref_slice(&self.role_allowlist.data)
406 }
407
408 pub(super) fn role_transitions(&self) -> &[RoleTransition] {
409 PS::deref_slice(&self.role_transitions.data)
410 }
411
412 pub(super) fn range_transitions(&self) -> &RangeTransitions<PS> {
413 &self.range_transitions.data
414 }
415
416 pub(super) fn access_vector_rules(&self) -> &AccessVectorRules<PS> {
417 &self.access_vector_rules.data
418 }
419
420 pub(super) fn compute_filename_transition(
421 &self,
422 source_type: TypeId,
423 target_type: TypeId,
424 class: ClassId,
425 name: NullessByteStr<'_>,
426 ) -> Option<TypeId> {
427 match &self.filename_transition_list {
428 FilenameTransitionList::PolicyVersionGeq33(list) => {
429 let entry = list.data.iter().find(|transition| {
430 transition.target_type() == target_type
431 && transition.target_class() == class
432 && transition.name_bytes() == name.as_bytes()
433 })?;
434 entry
435 .outputs()
436 .iter()
437 .find(|entry| entry.has_source_type(source_type))
438 .map(|x| x.out_type())
439 }
440 FilenameTransitionList::PolicyVersionLeq32(list) => list
441 .data
442 .iter()
443 .find(|transition| {
444 transition.target_class() == class
445 && transition.target_type() == target_type
446 && transition.source_type() == source_type
447 && transition.name_bytes() == name.as_bytes()
448 })
449 .map(|x| x.out_type()),
450 }
451 }
452
453 fn validate_mls_range(
460 &self,
461 low_level: &MlsLevel<PS>,
462 high_level: &Option<MlsLevel<PS>>,
463 sensitivity_ids: &HashSet<SensitivityId>,
464 category_ids: &HashSet<CategoryId>,
465 ) -> Result<(), anyhow::Error> {
466 validate_id(sensitivity_ids, low_level.sensitivity(), "sensitivity")?;
467 for id in low_level.category_ids() {
468 validate_id(category_ids, id, "category")?;
469 }
470 if let Some(high) = high_level {
471 validate_id(sensitivity_ids, high.sensitivity(), "sensitivity")?;
472 for id in high.category_ids() {
473 validate_id(category_ids, id, "category")?;
474 }
475 if !high.dominates(low_level) {
476 return Err(ValidateError::InvalidMlsRange {
477 low: low_level.serialize(self).into(),
478 high: high.serialize(self).into(),
479 }
480 .into());
481 }
482 }
483 Ok(())
484 }
485}
486
487impl<PS: ParseStrategy> ParsedPolicy<PS>
488where
489 Self: Parse<PS>,
490{
491 pub(super) fn parse(bytes: PS) -> Result<(Self, PS::Input), anyhow::Error> {
494 let (policy, tail) =
495 <ParsedPolicy<PS> as Parse<PS>>::parse(bytes).map_err(Into::<anyhow::Error>::into)?;
496 let num_bytes = tail.len();
497 if num_bytes > 0 {
498 return Err(ParseError::TrailingBytes { num_bytes }.into());
499 }
500 Ok((policy, tail.into_inner()))
501 }
502}
503
504impl<PS: ParseStrategy> Parse<PS> for ParsedPolicy<PS>
506where
507 Signature<PS>: Parse<PS>,
508 ExtensibleBitmap<PS>: Parse<PS>,
509 SymbolList<PS, CommonSymbol<PS>>: Parse<PS>,
510 SymbolList<PS, Class<PS>>: Parse<PS>,
511 SymbolList<PS, Role<PS>>: Parse<PS>,
512 SymbolList<PS, Type<PS>>: Parse<PS>,
513 SymbolList<PS, User<PS>>: Parse<PS>,
514 SymbolList<PS, ConditionalBoolean<PS>>: Parse<PS>,
515 SymbolList<PS, Sensitivity<PS>>: Parse<PS>,
516 SymbolList<PS, Category<PS>>: Parse<PS>,
517 SimpleArray<PS, AccessVectorRules<PS>>: Parse<PS>,
518 SimpleArray<PS, ConditionalNodes<PS>>: Parse<PS>,
519 RoleTransitions<PS>: Parse<PS>,
520 RoleAllows<PS>: Parse<PS>,
521 SimpleArray<PS, FilenameTransitions<PS>>: Parse<PS>,
522 SimpleArray<PS, DeprecatedFilenameTransitions<PS>>: Parse<PS>,
523 SimpleArray<PS, InitialSids<PS>>: Parse<PS>,
524 SimpleArray<PS, NamedContextPairs<PS>>: Parse<PS>,
525 SimpleArray<PS, Ports<PS>>: Parse<PS>,
526 SimpleArray<PS, NamedContextPairs<PS>>: Parse<PS>,
527 SimpleArray<PS, Nodes<PS>>: Parse<PS>,
528 SimpleArray<PS, FsUses<PS>>: Parse<PS>,
529 SimpleArray<PS, IPv6Nodes<PS>>: Parse<PS>,
530 SimpleArray<PS, InfinitiBandPartitionKeys<PS>>: Parse<PS>,
531 SimpleArray<PS, InfinitiBandEndPorts<PS>>: Parse<PS>,
532 SimpleArray<PS, GenericFsContexts<PS>>: Parse<PS>,
533 SimpleArray<PS, RangeTransitions<PS>>: Parse<PS>,
534{
535 type Error = anyhow::Error;
537
538 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
540 let tail = bytes;
541
542 let (magic, tail) = PS::parse::<Magic>(tail).context("parsing magic")?;
543
544 let (signature, tail) = Signature::parse(tail)
545 .map_err(Into::<anyhow::Error>::into)
546 .context("parsing signature")?;
547
548 let (policy_version, tail) =
549 PS::parse::<PolicyVersion>(tail).context("parsing policy version")?;
550 let policy_version_value = PS::deref(&policy_version).policy_version();
551
552 let (config, tail) = Config::parse(tail)
553 .map_err(Into::<anyhow::Error>::into)
554 .context("parsing policy config")?;
555
556 let (counts, tail) =
557 PS::parse::<Counts>(tail).context("parsing high-level policy object counts")?;
558
559 let (policy_capabilities, tail) = ExtensibleBitmap::parse(tail)
560 .map_err(Into::<anyhow::Error>::into)
561 .context("parsing policy capabilities")?;
562
563 let (permissive_map, tail) = ExtensibleBitmap::parse(tail)
564 .map_err(Into::<anyhow::Error>::into)
565 .context("parsing permissive map")?;
566
567 let (common_symbols, tail) = SymbolList::<PS, CommonSymbol<PS>>::parse(tail)
568 .map_err(Into::<anyhow::Error>::into)
569 .context("parsing common symbols")?;
570
571 let (classes, tail) = SymbolList::<PS, Class<PS>>::parse(tail)
572 .map_err(Into::<anyhow::Error>::into)
573 .context("parsing classes")?;
574
575 let (roles, tail) = SymbolList::<PS, Role<PS>>::parse(tail)
576 .map_err(Into::<anyhow::Error>::into)
577 .context("parsing roles")?;
578
579 let (types, tail) = SymbolList::<PS, Type<PS>>::parse(tail)
580 .map_err(Into::<anyhow::Error>::into)
581 .context("parsing types")?;
582
583 let (users, tail) = SymbolList::<PS, User<PS>>::parse(tail)
584 .map_err(Into::<anyhow::Error>::into)
585 .context("parsing users")?;
586
587 let (conditional_booleans, tail) = SymbolList::<PS, ConditionalBoolean<PS>>::parse(tail)
588 .map_err(Into::<anyhow::Error>::into)
589 .context("parsing conditional booleans")?;
590
591 let (sensitivities, tail) = SymbolList::<PS, Sensitivity<PS>>::parse(tail)
592 .map_err(Into::<anyhow::Error>::into)
593 .context("parsing sensitivites")?;
594
595 let (categories, tail) = SymbolList::<PS, Category<PS>>::parse(tail)
596 .map_err(Into::<anyhow::Error>::into)
597 .context("parsing categories")?;
598
599 let (access_vector_rules, tail) = SimpleArray::<PS, AccessVectorRules<PS>>::parse(tail)
600 .map_err(Into::<anyhow::Error>::into)
601 .context("parsing access vector rules")?;
602
603 let (conditional_lists, tail) = SimpleArray::<PS, ConditionalNodes<PS>>::parse(tail)
604 .map_err(Into::<anyhow::Error>::into)
605 .context("parsing conditional lists")?;
606
607 let (role_transitions, tail) = RoleTransitions::<PS>::parse(tail)
608 .map_err(Into::<anyhow::Error>::into)
609 .context("parsing role transitions")?;
610
611 let (role_allowlist, tail) = RoleAllows::<PS>::parse(tail)
612 .map_err(Into::<anyhow::Error>::into)
613 .context("parsing role allow rules")?;
614
615 let (filename_transition_list, tail) = if policy_version_value >= 33 {
616 let (filename_transition_list, tail) =
617 SimpleArray::<PS, FilenameTransitions<PS>>::parse(tail)
618 .map_err(Into::<anyhow::Error>::into)
619 .context("parsing standard filename transitions")?;
620 (FilenameTransitionList::PolicyVersionGeq33(filename_transition_list), tail)
621 } else {
622 let (filename_transition_list, tail) =
623 SimpleArray::<PS, DeprecatedFilenameTransitions<PS>>::parse(tail)
624 .map_err(Into::<anyhow::Error>::into)
625 .context("parsing deprecated filename transitions")?;
626 (FilenameTransitionList::PolicyVersionLeq32(filename_transition_list), tail)
627 };
628
629 let (initial_sids, tail) = SimpleArray::<PS, InitialSids<PS>>::parse(tail)
630 .map_err(Into::<anyhow::Error>::into)
631 .context("parsing initial sids")?;
632
633 let (filesystems, tail) = SimpleArray::<PS, NamedContextPairs<PS>>::parse(tail)
634 .map_err(Into::<anyhow::Error>::into)
635 .context("parsing filesystem contexts")?;
636
637 let (ports, tail) = SimpleArray::<PS, Ports<PS>>::parse(tail)
638 .map_err(Into::<anyhow::Error>::into)
639 .context("parsing ports")?;
640
641 let (network_interfaces, tail) = SimpleArray::<PS, NamedContextPairs<PS>>::parse(tail)
642 .map_err(Into::<anyhow::Error>::into)
643 .context("parsing network interfaces")?;
644
645 let (nodes, tail) = SimpleArray::<PS, Nodes<PS>>::parse(tail)
646 .map_err(Into::<anyhow::Error>::into)
647 .context("parsing nodes")?;
648
649 let (fs_uses, tail) = SimpleArray::<PS, FsUses<PS>>::parse(tail)
650 .map_err(Into::<anyhow::Error>::into)
651 .context("parsing fs uses")?;
652
653 let (ipv6_nodes, tail) = SimpleArray::<PS, IPv6Nodes<PS>>::parse(tail)
654 .map_err(Into::<anyhow::Error>::into)
655 .context("parsing ipv6 nodes")?;
656
657 let (infinitiband_partition_keys, infinitiband_end_ports, tail) =
658 if policy_version_value >= MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY {
659 let (infinity_band_partition_keys, tail) =
660 SimpleArray::<PS, InfinitiBandPartitionKeys<PS>>::parse(tail)
661 .map_err(Into::<anyhow::Error>::into)
662 .context("parsing infiniti band partition keys")?;
663 let (infinitiband_end_ports, tail) =
664 SimpleArray::<PS, InfinitiBandEndPorts<PS>>::parse(tail)
665 .map_err(Into::<anyhow::Error>::into)
666 .context("parsing infiniti band end ports")?;
667 (Some(infinity_band_partition_keys), Some(infinitiband_end_ports), tail)
668 } else {
669 (None, None, tail)
670 };
671
672 let (generic_fs_contexts, tail) = SimpleArray::<PS, GenericFsContexts<PS>>::parse(tail)
673 .map_err(Into::<anyhow::Error>::into)
674 .context("parsing generic filesystem contexts")?;
675
676 let (range_transitions, tail) = SimpleArray::<PS, RangeTransitions<PS>>::parse(tail)
677 .map_err(Into::<anyhow::Error>::into)
678 .context("parsing range transitions")?;
679
680 let primary_names_count = PS::deref(&types.metadata).primary_names_count();
681 let mut attribute_maps = Vec::with_capacity(primary_names_count as usize);
682 let mut tail = tail;
683
684 for i in 0..primary_names_count {
685 let (item, next_tail) = ExtensibleBitmap::parse(tail)
686 .map_err(Into::<anyhow::Error>::into)
687 .with_context(|| format!("parsing {}th attribtue map", i))?;
688 attribute_maps.push(item);
689 tail = next_tail;
690 }
691 let tail = tail;
692 let attribute_maps = attribute_maps;
693
694 Ok((
695 Self {
696 magic,
697 signature,
698 policy_version,
699 config,
700 counts,
701 policy_capabilities,
702 permissive_map,
703 common_symbols,
704 classes,
705 roles,
706 types,
707 users,
708 conditional_booleans,
709 sensitivities,
710 categories,
711 access_vector_rules,
712 conditional_lists,
713 role_transitions,
714 role_allowlist,
715 filename_transition_list,
716 initial_sids,
717 filesystems,
718 ports,
719 network_interfaces,
720 nodes,
721 fs_uses,
722 ipv6_nodes,
723 infinitiband_partition_keys,
724 infinitiband_end_ports,
725 generic_fs_contexts,
726 range_transitions,
727 attribute_maps,
728 },
729 tail,
730 ))
731 }
732}
733
734impl<PS: ParseStrategy> Validate for ParsedPolicy<PS> {
735 type Error = anyhow::Error;
737
738 fn validate(&self) -> Result<(), Self::Error> {
739 PS::deref(&self.magic)
740 .validate()
741 .map_err(Into::<anyhow::Error>::into)
742 .context("validating magic")?;
743 self.signature
744 .validate()
745 .map_err(Into::<anyhow::Error>::into)
746 .context("validating signature")?;
747 PS::deref(&self.policy_version)
748 .validate()
749 .map_err(Into::<anyhow::Error>::into)
750 .context("validating policy_version")?;
751 self.config.validate().map_err(Into::<anyhow::Error>::into).context("validating config")?;
752 PS::deref(&self.counts)
753 .validate()
754 .map_err(Into::<anyhow::Error>::into)
755 .context("validating counts")?;
756 self.policy_capabilities
757 .validate()
758 .map_err(Into::<anyhow::Error>::into)
759 .context("validating policy_capabilities")?;
760 self.permissive_map
761 .validate()
762 .map_err(Into::<anyhow::Error>::into)
763 .context("validating permissive_map")?;
764 self.common_symbols
765 .validate()
766 .map_err(Into::<anyhow::Error>::into)
767 .context("validating common_symbols")?;
768 self.classes
769 .validate()
770 .map_err(Into::<anyhow::Error>::into)
771 .context("validating classes")?;
772 self.roles.validate().map_err(Into::<anyhow::Error>::into).context("validating roles")?;
773 self.types.validate().map_err(Into::<anyhow::Error>::into).context("validating types")?;
774 self.users.validate().map_err(Into::<anyhow::Error>::into).context("validating users")?;
775 self.conditional_booleans
776 .validate()
777 .map_err(Into::<anyhow::Error>::into)
778 .context("validating conditional_booleans")?;
779 self.sensitivities
780 .validate()
781 .map_err(Into::<anyhow::Error>::into)
782 .context("validating sensitivities")?;
783 self.categories
784 .validate()
785 .map_err(Into::<anyhow::Error>::into)
786 .context("validating categories")?;
787 self.access_vector_rules
788 .validate()
789 .map_err(Into::<anyhow::Error>::into)
790 .context("validating access_vector_rules")?;
791 self.conditional_lists
792 .validate()
793 .map_err(Into::<anyhow::Error>::into)
794 .context("validating conditional_lists")?;
795 self.role_transitions
796 .validate()
797 .map_err(Into::<anyhow::Error>::into)
798 .context("validating role_transitions")?;
799 self.role_allowlist
800 .validate()
801 .map_err(Into::<anyhow::Error>::into)
802 .context("validating role_allowlist")?;
803 self.filename_transition_list
804 .validate()
805 .map_err(Into::<anyhow::Error>::into)
806 .context("validating filename_transition_list")?;
807 self.initial_sids
808 .validate()
809 .map_err(Into::<anyhow::Error>::into)
810 .context("validating initial_sids")?;
811 self.filesystems
812 .validate()
813 .map_err(Into::<anyhow::Error>::into)
814 .context("validating filesystems")?;
815 self.ports.validate().map_err(Into::<anyhow::Error>::into).context("validating ports")?;
816 self.network_interfaces
817 .validate()
818 .map_err(Into::<anyhow::Error>::into)
819 .context("validating network_interfaces")?;
820 self.nodes.validate().map_err(Into::<anyhow::Error>::into).context("validating nodes")?;
821 self.fs_uses
822 .validate()
823 .map_err(Into::<anyhow::Error>::into)
824 .context("validating fs_uses")?;
825 self.ipv6_nodes
826 .validate()
827 .map_err(Into::<anyhow::Error>::into)
828 .context("validating ipv6 nodes")?;
829 self.infinitiband_partition_keys
830 .validate()
831 .map_err(Into::<anyhow::Error>::into)
832 .context("validating infinitiband_partition_keys")?;
833 self.infinitiband_end_ports
834 .validate()
835 .map_err(Into::<anyhow::Error>::into)
836 .context("validating infinitiband_end_ports")?;
837 self.generic_fs_contexts
838 .validate()
839 .map_err(Into::<anyhow::Error>::into)
840 .context("validating generic_fs_contexts")?;
841 self.range_transitions
842 .validate()
843 .map_err(Into::<anyhow::Error>::into)
844 .context("validating range_transitions")?;
845 self.attribute_maps
846 .validate()
847 .map_err(Into::<anyhow::Error>::into)
848 .context("validating attribute_maps")?;
849
850 let user_ids: HashSet<UserId> = self.users.data.iter().map(|x| x.id()).collect();
852 let role_ids: HashSet<RoleId> = self.roles.data.iter().map(|x| x.id()).collect();
853 let class_ids: HashSet<ClassId> = self.classes.data.iter().map(|x| x.id()).collect();
854 let type_ids: HashSet<TypeId> = self.types.data.iter().map(|x| x.id()).collect();
855 let sensitivity_ids: HashSet<SensitivityId> =
856 self.sensitivities.data.iter().map(|x| x.id()).collect();
857 let category_ids: HashSet<CategoryId> =
858 self.categories.data.iter().map(|x| x.id()).collect();
859
860 for user in &self.users.data {
864 self.validate_mls_range(
865 user.mls_range().low(),
866 user.mls_range().high(),
867 &sensitivity_ids,
868 &category_ids,
869 )?;
870 }
871
872 for initial_sid in &self.initial_sids.data {
876 let context = initial_sid.context();
877 validate_id(&user_ids, context.user_id(), "user")?;
878 validate_id(&role_ids, context.role_id(), "role")?;
879 validate_id(&type_ids, context.type_id(), "type")?;
880 self.validate_mls_range(
881 context.low_level(),
882 context.high_level(),
883 &sensitivity_ids,
884 &category_ids,
885 )?;
886 }
887
888 for fs_use in &self.fs_uses.data {
892 let context = fs_use.context();
893 validate_id(&user_ids, context.user_id(), "user")?;
894 validate_id(&role_ids, context.role_id(), "role")?;
895 validate_id(&type_ids, context.type_id(), "type")?;
896 self.validate_mls_range(
897 context.low_level(),
898 context.high_level(),
899 &sensitivity_ids,
900 &category_ids,
901 )?;
902 }
903
904 for transition in PS::deref_slice(&self.role_transitions.data) {
906 validate_id(&role_ids, transition.current_role(), "current_role")?;
907 validate_id(&type_ids, transition.type_(), "type")?;
908 validate_id(&class_ids, transition.class(), "class")?;
909 validate_id(&role_ids, transition.new_role(), "new_role")?;
910 }
911 for allow in PS::deref_slice(&self.role_allowlist.data) {
912 validate_id(&role_ids, allow.source_role(), "source_role")?;
913 validate_id(&role_ids, allow.new_role(), "new_role")?;
914 }
915
916 for access_vector_rule in &self.access_vector_rules.data {
918 if let Some(type_id) = access_vector_rule.new_type() {
919 validate_id(&type_ids, type_id, "new_type")?;
920 }
921 }
922
923 let initial_context = SecurityContext::new_from_policy_context(
926 self.initial_context(crate::InitialSid::Kernel),
927 );
928 for class in self.classes() {
929 for constraint in class.constraints() {
930 constraint
931 .constraint_expr()
932 .evaluate(&initial_context, &initial_context)
933 .map_err(Into::<anyhow::Error>::into)
934 .context("validating constraints")?;
935 }
936 }
937
938 Ok(())
942 }
943}
944
945fn validate_id<IdType: Debug + Eq + Hash>(
946 id_set: &HashSet<IdType>,
947 id: IdType,
948 debug_kind: &'static str,
949) -> Result<(), anyhow::Error> {
950 if !id_set.contains(&id) {
951 return Err(ValidateError::UnknownId { kind: debug_kind, id: format!("{:?}", id) }.into());
952 }
953 Ok(())
954}