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