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