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 #[allow(dead_code)]
405 pub(super) fn role_allowlist(&self) -> &[RoleAllow] {
408 PS::deref_slice(&self.role_allowlist.data)
409 }
410
411 pub(super) fn role_transitions(&self) -> &[RoleTransition] {
412 PS::deref_slice(&self.role_transitions.data)
413 }
414
415 pub(super) fn range_transitions(&self) -> &RangeTransitions<PS> {
416 &self.range_transitions.data
417 }
418
419 pub(super) fn access_vector_rules(&self) -> &AccessVectorRules<PS> {
420 &self.access_vector_rules.data
421 }
422
423 pub(super) fn compute_filename_transition(
424 &self,
425 source_type: TypeId,
426 target_type: TypeId,
427 class: ClassId,
428 name: NullessByteStr<'_>,
429 ) -> Option<TypeId> {
430 match &self.filename_transition_list {
431 FilenameTransitionList::PolicyVersionGeq33(list) => {
432 let entry = list.data.iter().find(|transition| {
433 transition.target_type() == target_type
434 && transition.target_class() == class
435 && transition.name_bytes() == name.as_bytes()
436 })?;
437 entry
438 .outputs()
439 .iter()
440 .find(|entry| entry.has_source_type(source_type))
441 .map(|x| x.out_type())
442 }
443 FilenameTransitionList::PolicyVersionLeq32(list) => list
444 .data
445 .iter()
446 .find(|transition| {
447 transition.target_class() == class
448 && transition.target_type() == target_type
449 && transition.source_type() == source_type
450 && transition.name_bytes() == name.as_bytes()
451 })
452 .map(|x| x.out_type()),
453 }
454 }
455
456 fn validate_mls_range(
463 &self,
464 low_level: &MlsLevel<PS>,
465 high_level: &Option<MlsLevel<PS>>,
466 sensitivity_ids: &HashSet<SensitivityId>,
467 category_ids: &HashSet<CategoryId>,
468 ) -> Result<(), anyhow::Error> {
469 validate_id(sensitivity_ids, low_level.sensitivity(), "sensitivity")?;
470 for id in low_level.category_ids() {
471 validate_id(category_ids, id, "category")?;
472 }
473 if let Some(high) = high_level {
474 validate_id(sensitivity_ids, high.sensitivity(), "sensitivity")?;
475 for id in high.category_ids() {
476 validate_id(category_ids, id, "category")?;
477 }
478 if !high.dominates(low_level) {
479 return Err(ValidateError::InvalidMlsRange {
480 low: low_level.serialize(self).into(),
481 high: high.serialize(self).into(),
482 }
483 .into());
484 }
485 }
486 Ok(())
487 }
488}
489
490impl<PS: ParseStrategy> ParsedPolicy<PS>
491where
492 Self: Parse<PS>,
493{
494 pub(super) fn parse(bytes: PS) -> Result<(Self, PS::Input), anyhow::Error> {
497 let (policy, tail) =
498 <ParsedPolicy<PS> as Parse<PS>>::parse(bytes).map_err(Into::<anyhow::Error>::into)?;
499 let num_bytes = tail.len();
500 if num_bytes > 0 {
501 return Err(ParseError::TrailingBytes { num_bytes }.into());
502 }
503 Ok((policy, tail.into_inner()))
504 }
505}
506
507impl<PS: ParseStrategy> Parse<PS> for ParsedPolicy<PS>
509where
510 Signature<PS>: Parse<PS>,
511 ExtensibleBitmap<PS>: Parse<PS>,
512 SymbolList<PS, CommonSymbol<PS>>: Parse<PS>,
513 SymbolList<PS, Class<PS>>: Parse<PS>,
514 SymbolList<PS, Role<PS>>: Parse<PS>,
515 SymbolList<PS, Type<PS>>: Parse<PS>,
516 SymbolList<PS, User<PS>>: Parse<PS>,
517 SymbolList<PS, ConditionalBoolean<PS>>: Parse<PS>,
518 SymbolList<PS, Sensitivity<PS>>: Parse<PS>,
519 SymbolList<PS, Category<PS>>: Parse<PS>,
520 SimpleArray<PS, AccessVectorRules<PS>>: Parse<PS>,
521 SimpleArray<PS, ConditionalNodes<PS>>: Parse<PS>,
522 RoleTransitions<PS>: Parse<PS>,
523 RoleAllows<PS>: Parse<PS>,
524 SimpleArray<PS, FilenameTransitions<PS>>: Parse<PS>,
525 SimpleArray<PS, DeprecatedFilenameTransitions<PS>>: Parse<PS>,
526 SimpleArray<PS, InitialSids<PS>>: Parse<PS>,
527 SimpleArray<PS, NamedContextPairs<PS>>: Parse<PS>,
528 SimpleArray<PS, Ports<PS>>: Parse<PS>,
529 SimpleArray<PS, NamedContextPairs<PS>>: Parse<PS>,
530 SimpleArray<PS, Nodes<PS>>: Parse<PS>,
531 SimpleArray<PS, FsUses<PS>>: Parse<PS>,
532 SimpleArray<PS, IPv6Nodes<PS>>: Parse<PS>,
533 SimpleArray<PS, InfinitiBandPartitionKeys<PS>>: Parse<PS>,
534 SimpleArray<PS, InfinitiBandEndPorts<PS>>: Parse<PS>,
535 SimpleArray<PS, GenericFsContexts<PS>>: Parse<PS>,
536 SimpleArray<PS, RangeTransitions<PS>>: Parse<PS>,
537{
538 type Error = anyhow::Error;
540
541 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
543 let tail = bytes;
544
545 let (magic, tail) = PS::parse::<Magic>(tail).context("parsing magic")?;
546
547 let (signature, tail) = Signature::parse(tail)
548 .map_err(Into::<anyhow::Error>::into)
549 .context("parsing signature")?;
550
551 let (policy_version, tail) =
552 PS::parse::<PolicyVersion>(tail).context("parsing policy version")?;
553 let policy_version_value = PS::deref(&policy_version).policy_version();
554
555 let (config, tail) = Config::parse(tail)
556 .map_err(Into::<anyhow::Error>::into)
557 .context("parsing policy config")?;
558
559 let (counts, tail) =
560 PS::parse::<Counts>(tail).context("parsing high-level policy object counts")?;
561
562 let (policy_capabilities, tail) = ExtensibleBitmap::parse(tail)
563 .map_err(Into::<anyhow::Error>::into)
564 .context("parsing policy capabilities")?;
565
566 let (permissive_map, tail) = ExtensibleBitmap::parse(tail)
567 .map_err(Into::<anyhow::Error>::into)
568 .context("parsing permissive map")?;
569
570 let (common_symbols, tail) = SymbolList::<PS, CommonSymbol<PS>>::parse(tail)
571 .map_err(Into::<anyhow::Error>::into)
572 .context("parsing common symbols")?;
573
574 let (classes, tail) = SymbolList::<PS, Class<PS>>::parse(tail)
575 .map_err(Into::<anyhow::Error>::into)
576 .context("parsing classes")?;
577
578 let (roles, tail) = SymbolList::<PS, Role<PS>>::parse(tail)
579 .map_err(Into::<anyhow::Error>::into)
580 .context("parsing roles")?;
581
582 let (types, tail) = SymbolList::<PS, Type<PS>>::parse(tail)
583 .map_err(Into::<anyhow::Error>::into)
584 .context("parsing types")?;
585
586 let (users, tail) = SymbolList::<PS, User<PS>>::parse(tail)
587 .map_err(Into::<anyhow::Error>::into)
588 .context("parsing users")?;
589
590 let (conditional_booleans, tail) = SymbolList::<PS, ConditionalBoolean<PS>>::parse(tail)
591 .map_err(Into::<anyhow::Error>::into)
592 .context("parsing conditional booleans")?;
593
594 let (sensitivities, tail) = SymbolList::<PS, Sensitivity<PS>>::parse(tail)
595 .map_err(Into::<anyhow::Error>::into)
596 .context("parsing sensitivites")?;
597
598 let (categories, tail) = SymbolList::<PS, Category<PS>>::parse(tail)
599 .map_err(Into::<anyhow::Error>::into)
600 .context("parsing categories")?;
601
602 let (access_vector_rules, tail) = SimpleArray::<PS, AccessVectorRules<PS>>::parse(tail)
603 .map_err(Into::<anyhow::Error>::into)
604 .context("parsing access vector rules")?;
605
606 let (conditional_lists, tail) = SimpleArray::<PS, ConditionalNodes<PS>>::parse(tail)
607 .map_err(Into::<anyhow::Error>::into)
608 .context("parsing conditional lists")?;
609
610 let (role_transitions, tail) = RoleTransitions::<PS>::parse(tail)
611 .map_err(Into::<anyhow::Error>::into)
612 .context("parsing role transitions")?;
613
614 let (role_allowlist, tail) = RoleAllows::<PS>::parse(tail)
615 .map_err(Into::<anyhow::Error>::into)
616 .context("parsing role allow rules")?;
617
618 let (filename_transition_list, tail) = if policy_version_value >= 33 {
619 let (filename_transition_list, tail) =
620 SimpleArray::<PS, FilenameTransitions<PS>>::parse(tail)
621 .map_err(Into::<anyhow::Error>::into)
622 .context("parsing standard filename transitions")?;
623 (FilenameTransitionList::PolicyVersionGeq33(filename_transition_list), tail)
624 } else {
625 let (filename_transition_list, tail) =
626 SimpleArray::<PS, DeprecatedFilenameTransitions<PS>>::parse(tail)
627 .map_err(Into::<anyhow::Error>::into)
628 .context("parsing deprecated filename transitions")?;
629 (FilenameTransitionList::PolicyVersionLeq32(filename_transition_list), tail)
630 };
631
632 let (initial_sids, tail) = SimpleArray::<PS, InitialSids<PS>>::parse(tail)
633 .map_err(Into::<anyhow::Error>::into)
634 .context("parsing initial sids")?;
635
636 let (filesystems, tail) = SimpleArray::<PS, NamedContextPairs<PS>>::parse(tail)
637 .map_err(Into::<anyhow::Error>::into)
638 .context("parsing filesystem contexts")?;
639
640 let (ports, tail) = SimpleArray::<PS, Ports<PS>>::parse(tail)
641 .map_err(Into::<anyhow::Error>::into)
642 .context("parsing ports")?;
643
644 let (network_interfaces, tail) = SimpleArray::<PS, NamedContextPairs<PS>>::parse(tail)
645 .map_err(Into::<anyhow::Error>::into)
646 .context("parsing network interfaces")?;
647
648 let (nodes, tail) = SimpleArray::<PS, Nodes<PS>>::parse(tail)
649 .map_err(Into::<anyhow::Error>::into)
650 .context("parsing nodes")?;
651
652 let (fs_uses, tail) = SimpleArray::<PS, FsUses<PS>>::parse(tail)
653 .map_err(Into::<anyhow::Error>::into)
654 .context("parsing fs uses")?;
655
656 let (ipv6_nodes, tail) = SimpleArray::<PS, IPv6Nodes<PS>>::parse(tail)
657 .map_err(Into::<anyhow::Error>::into)
658 .context("parsing ipv6 nodes")?;
659
660 let (infinitiband_partition_keys, infinitiband_end_ports, tail) =
661 if policy_version_value >= MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY {
662 let (infinity_band_partition_keys, tail) =
663 SimpleArray::<PS, InfinitiBandPartitionKeys<PS>>::parse(tail)
664 .map_err(Into::<anyhow::Error>::into)
665 .context("parsing infiniti band partition keys")?;
666 let (infinitiband_end_ports, tail) =
667 SimpleArray::<PS, InfinitiBandEndPorts<PS>>::parse(tail)
668 .map_err(Into::<anyhow::Error>::into)
669 .context("parsing infiniti band end ports")?;
670 (Some(infinity_band_partition_keys), Some(infinitiband_end_ports), tail)
671 } else {
672 (None, None, tail)
673 };
674
675 let (generic_fs_contexts, tail) = SimpleArray::<PS, GenericFsContexts<PS>>::parse(tail)
676 .map_err(Into::<anyhow::Error>::into)
677 .context("parsing generic filesystem contexts")?;
678
679 let (range_transitions, tail) = SimpleArray::<PS, RangeTransitions<PS>>::parse(tail)
680 .map_err(Into::<anyhow::Error>::into)
681 .context("parsing range transitions")?;
682
683 let primary_names_count = PS::deref(&types.metadata).primary_names_count();
684 let mut attribute_maps = Vec::with_capacity(primary_names_count as usize);
685 let mut tail = tail;
686
687 for i in 0..primary_names_count {
688 let (item, next_tail) = ExtensibleBitmap::parse(tail)
689 .map_err(Into::<anyhow::Error>::into)
690 .with_context(|| format!("parsing {}th attribtue map", i))?;
691 attribute_maps.push(item);
692 tail = next_tail;
693 }
694 let tail = tail;
695 let attribute_maps = attribute_maps;
696
697 Ok((
698 Self {
699 magic,
700 signature,
701 policy_version,
702 config,
703 counts,
704 policy_capabilities,
705 permissive_map,
706 common_symbols,
707 classes,
708 roles,
709 types,
710 users,
711 conditional_booleans,
712 sensitivities,
713 categories,
714 access_vector_rules,
715 conditional_lists,
716 role_transitions,
717 role_allowlist,
718 filename_transition_list,
719 initial_sids,
720 filesystems,
721 ports,
722 network_interfaces,
723 nodes,
724 fs_uses,
725 ipv6_nodes,
726 infinitiband_partition_keys,
727 infinitiband_end_ports,
728 generic_fs_contexts,
729 range_transitions,
730 attribute_maps,
731 },
732 tail,
733 ))
734 }
735}
736
737impl<PS: ParseStrategy> Validate for ParsedPolicy<PS> {
738 type Error = anyhow::Error;
740
741 fn validate(&self) -> Result<(), Self::Error> {
742 PS::deref(&self.magic)
743 .validate()
744 .map_err(Into::<anyhow::Error>::into)
745 .context("validating magic")?;
746 self.signature
747 .validate()
748 .map_err(Into::<anyhow::Error>::into)
749 .context("validating signature")?;
750 PS::deref(&self.policy_version)
751 .validate()
752 .map_err(Into::<anyhow::Error>::into)
753 .context("validating policy_version")?;
754 self.config.validate().map_err(Into::<anyhow::Error>::into).context("validating config")?;
755 PS::deref(&self.counts)
756 .validate()
757 .map_err(Into::<anyhow::Error>::into)
758 .context("validating counts")?;
759 self.policy_capabilities
760 .validate()
761 .map_err(Into::<anyhow::Error>::into)
762 .context("validating policy_capabilities")?;
763 self.permissive_map
764 .validate()
765 .map_err(Into::<anyhow::Error>::into)
766 .context("validating permissive_map")?;
767 self.common_symbols
768 .validate()
769 .map_err(Into::<anyhow::Error>::into)
770 .context("validating common_symbols")?;
771 self.classes
772 .validate()
773 .map_err(Into::<anyhow::Error>::into)
774 .context("validating classes")?;
775 self.roles.validate().map_err(Into::<anyhow::Error>::into).context("validating roles")?;
776 self.types.validate().map_err(Into::<anyhow::Error>::into).context("validating types")?;
777 self.users.validate().map_err(Into::<anyhow::Error>::into).context("validating users")?;
778 self.conditional_booleans
779 .validate()
780 .map_err(Into::<anyhow::Error>::into)
781 .context("validating conditional_booleans")?;
782 self.sensitivities
783 .validate()
784 .map_err(Into::<anyhow::Error>::into)
785 .context("validating sensitivities")?;
786 self.categories
787 .validate()
788 .map_err(Into::<anyhow::Error>::into)
789 .context("validating categories")?;
790 self.access_vector_rules
791 .validate()
792 .map_err(Into::<anyhow::Error>::into)
793 .context("validating access_vector_rules")?;
794 self.conditional_lists
795 .validate()
796 .map_err(Into::<anyhow::Error>::into)
797 .context("validating conditional_lists")?;
798 self.role_transitions
799 .validate()
800 .map_err(Into::<anyhow::Error>::into)
801 .context("validating role_transitions")?;
802 self.role_allowlist
803 .validate()
804 .map_err(Into::<anyhow::Error>::into)
805 .context("validating role_allowlist")?;
806 self.filename_transition_list
807 .validate()
808 .map_err(Into::<anyhow::Error>::into)
809 .context("validating filename_transition_list")?;
810 self.initial_sids
811 .validate()
812 .map_err(Into::<anyhow::Error>::into)
813 .context("validating initial_sids")?;
814 self.filesystems
815 .validate()
816 .map_err(Into::<anyhow::Error>::into)
817 .context("validating filesystems")?;
818 self.ports.validate().map_err(Into::<anyhow::Error>::into).context("validating ports")?;
819 self.network_interfaces
820 .validate()
821 .map_err(Into::<anyhow::Error>::into)
822 .context("validating network_interfaces")?;
823 self.nodes.validate().map_err(Into::<anyhow::Error>::into).context("validating nodes")?;
824 self.fs_uses
825 .validate()
826 .map_err(Into::<anyhow::Error>::into)
827 .context("validating fs_uses")?;
828 self.ipv6_nodes
829 .validate()
830 .map_err(Into::<anyhow::Error>::into)
831 .context("validating ipv6 nodes")?;
832 self.infinitiband_partition_keys
833 .validate()
834 .map_err(Into::<anyhow::Error>::into)
835 .context("validating infinitiband_partition_keys")?;
836 self.infinitiband_end_ports
837 .validate()
838 .map_err(Into::<anyhow::Error>::into)
839 .context("validating infinitiband_end_ports")?;
840 self.generic_fs_contexts
841 .validate()
842 .map_err(Into::<anyhow::Error>::into)
843 .context("validating generic_fs_contexts")?;
844 self.range_transitions
845 .validate()
846 .map_err(Into::<anyhow::Error>::into)
847 .context("validating range_transitions")?;
848 self.attribute_maps
849 .validate()
850 .map_err(Into::<anyhow::Error>::into)
851 .context("validating attribute_maps")?;
852
853 let user_ids: HashSet<UserId> = self.users.data.iter().map(|x| x.id()).collect();
855 let role_ids: HashSet<RoleId> = self.roles.data.iter().map(|x| x.id()).collect();
856 let type_ids: HashSet<TypeId> = self.types.data.iter().map(|x| x.id()).collect();
857 let sensitivity_ids: HashSet<SensitivityId> =
858 self.sensitivities.data.iter().map(|x| x.id()).collect();
859 let category_ids: HashSet<CategoryId> =
860 self.categories.data.iter().map(|x| x.id()).collect();
861
862 for user in &self.users.data {
866 self.validate_mls_range(
867 user.mls_range().low(),
868 user.mls_range().high(),
869 &sensitivity_ids,
870 &category_ids,
871 )?;
872 }
873
874 for initial_sid in &self.initial_sids.data {
878 let context = initial_sid.context();
879 validate_id(&user_ids, context.user_id(), "user")?;
880 validate_id(&role_ids, context.role_id(), "role")?;
881 validate_id(&type_ids, context.type_id(), "type")?;
882 self.validate_mls_range(
883 context.low_level(),
884 context.high_level(),
885 &sensitivity_ids,
886 &category_ids,
887 )?;
888 }
889
890 for fs_use in &self.fs_uses.data {
894 let context = fs_use.context();
895 validate_id(&user_ids, context.user_id(), "user")?;
896 validate_id(&role_ids, context.role_id(), "role")?;
897 validate_id(&type_ids, context.type_id(), "type")?;
898 self.validate_mls_range(
899 context.low_level(),
900 context.high_level(),
901 &sensitivity_ids,
902 &category_ids,
903 )?;
904 }
905
906 for transition in PS::deref_slice(&self.role_transitions.data) {
908 validate_id(&role_ids, transition.new_role(), "new_role")?;
909 }
910 for allow in PS::deref_slice(&self.role_allowlist.data) {
911 validate_id(&role_ids, allow.new_role(), "new_role")?;
912 }
913
914 for access_vector_rule in &self.access_vector_rules.data {
916 if let Some(type_id) = access_vector_rule.new_type() {
917 validate_id(&type_ids, type_id, "new_type")?;
918 }
919 }
920
921 let initial_context = SecurityContext::new_from_policy_context(
924 self.initial_context(crate::InitialSid::Kernel),
925 );
926 for class in self.classes() {
927 for constraint in class.constraints() {
928 constraint
929 .constraint_expr()
930 .evaluate(&initial_context, &initial_context)
931 .map_err(Into::<anyhow::Error>::into)
932 .context("validating constraints")?;
933 }
934 }
935
936 Ok(())
940 }
941}
942
943fn validate_id<IdType: Debug + Eq + Hash>(
944 id_set: &HashSet<IdType>,
945 id: IdType,
946 debug_kind: &'static str,
947) -> Result<(), anyhow::Error> {
948 if !id_set.contains(&id) {
949 return Err(ValidateError::UnknownId { kind: debug_kind, id: format!("{:?}", id) }.into());
950 }
951 Ok(())
952}