1use crate::policy::arrays::{
6 ACCESS_VECTOR_RULE_TYPE_ALLOW, ACCESS_VECTOR_RULE_TYPE_AUDITALLOW,
7 ACCESS_VECTOR_RULE_TYPE_DONTAUDIT, AccessVectorRuleMetadata, ExtendedPermissions,
8 XPERMS_TYPE_NLMSG,
9};
10use crate::{NullessByteStr, PolicyCap};
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 fn has_policycap(&self, policy_cap: PolicyCap) -> bool {
118 self.policy_capabilities.is_set(policy_cap as u32)
119 }
120
121 pub(super) fn compute_access_decision(
133 &self,
134 source_context: &SecurityContext,
135 target_context: &SecurityContext,
136 target_class: &Class,
137 ) -> AccessDecision {
138 let mut access_decision = self.compute_explicitly_allowed(
139 source_context.type_(),
140 target_context.type_(),
141 target_class,
142 );
143 access_decision.allow -=
144 self.compute_denied_by_constraints(source_context, target_context, target_class);
145 access_decision
146 }
147
148 pub(super) fn compute_explicitly_allowed(
153 &self,
154 source_type: TypeId,
155 target_type: TypeId,
156 target_class: &Class,
157 ) -> AccessDecision {
158 let target_class_id = target_class.id();
159
160 let mut computed_access_vector = AccessVector::NONE;
161 let mut computed_audit_allow = AccessVector::NONE;
162 let mut computed_audit_deny = AccessVector::ALL;
163
164 let source_attribute_bitmap: &ExtensibleBitmap =
165 &self.attribute_maps[(source_type.0.get() - 1) as usize];
166 let target_attribute_bitmap: &ExtensibleBitmap =
167 &self.attribute_maps[(target_type.0.get() - 1) as usize];
168
169 for source_span in source_attribute_bitmap.spans() {
170 for source_bit_index in source_span.low..=source_span.high {
171 let source_id = TypeId(NonZeroU32::new(source_bit_index + 1).unwrap());
172 for target_span in target_attribute_bitmap.spans() {
173 for target_bit_index in target_span.low..=target_span.high {
174 let target_id = TypeId(NonZeroU32::new(target_bit_index + 1).unwrap());
175
176 if let Some(allow_rule) = self.find_access_vector_rule(
177 source_id,
178 target_id,
179 target_class_id,
180 ACCESS_VECTOR_RULE_TYPE_ALLOW,
181 ) {
182 computed_access_vector |= allow_rule.access_vector().unwrap();
184 }
185 if let Some(auditallow_rule) = self.find_access_vector_rule(
186 source_id,
187 target_id,
188 target_class_id,
189 ACCESS_VECTOR_RULE_TYPE_AUDITALLOW,
190 ) {
191 computed_audit_allow |= auditallow_rule.access_vector().unwrap();
193 }
194 if let Some(dontaudit_rule) = self.find_access_vector_rule(
195 source_id,
196 target_id,
197 target_class_id,
198 ACCESS_VECTOR_RULE_TYPE_DONTAUDIT,
199 ) {
200 computed_audit_deny &= dontaudit_rule.access_vector().unwrap();
202 }
203 }
204 }
205 }
206 }
207
208 let mut flags = 0;
210 if self.permissive_types().is_set(source_type.0.get()) {
211 flags |= SELINUX_AVD_FLAGS_PERMISSIVE;
212 }
213 AccessDecision {
214 allow: computed_access_vector,
215 auditallow: computed_audit_allow,
216 auditdeny: computed_audit_deny,
217 flags,
218 todo_bug: None,
219 }
220 }
221
222 fn compute_denied_by_constraints(
224 &self,
225 source_context: &SecurityContext,
226 target_context: &SecurityContext,
227 target_class: &Class,
228 ) -> AccessVector {
229 let mut denied = AccessVector::NONE;
230 for constraint in target_class.constraints().iter() {
231 match constraint.constraint_expr().evaluate(source_context, target_context) {
232 Err(err) => {
233 unreachable!("validated constraint expression failed to evaluate: {:?}", err)
234 }
235 Ok(false) => denied |= constraint.access_vector(),
236 Ok(true) => {}
237 }
238 }
239 denied
240 }
241
242 pub(super) fn compute_xperms_access_decision(
245 &self,
246 xperms_kind: XpermsKind,
247 source_context: &SecurityContext,
248 target_context: &SecurityContext,
249 target_class: &Class,
250 xperms_prefix: u8,
251 ) -> XpermsAccessDecision {
252 let target_class_id = target_class.id();
253
254 let mut explicit_allow: Option<XpermsBitmap> = None;
255 let mut auditallow = XpermsBitmap::NONE;
256 let mut auditdeny = XpermsBitmap::ALL;
257
258 let xperms_types = match xperms_kind {
259 XpermsKind::Ioctl => {
260 [XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES, XPERMS_TYPE_IOCTL_PREFIXES].as_slice()
261 }
262 XpermsKind::Nlmsg => [XPERMS_TYPE_NLMSG].as_slice(),
263 };
264 let bitmap_if_prefix_matches =
265 |xperms_kind: &XpermsKind, xperms_prefix: u8, xperms: &ExtendedPermissions| {
266 match xperms_kind {
267 XpermsKind::Ioctl => match xperms.xperms_type {
268 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES => (xperms.xperms_optional_prefix
269 == xperms_prefix)
270 .then_some(xperms.xperms_bitmap),
271 XPERMS_TYPE_IOCTL_PREFIXES => xperms
272 .xperms_bitmap
273 .contains(xperms_prefix)
274 .then_some(XpermsBitmap::ALL),
275 _ => None,
276 },
277 XpermsKind::Nlmsg => match xperms.xperms_type {
278 XPERMS_TYPE_NLMSG => (xperms.xperms_optional_prefix == xperms_prefix)
279 .then_some(xperms.xperms_bitmap),
280 _ => None,
281 },
282 }
283 };
284
285 let source_attribute_bitmap: &ExtensibleBitmap =
286 &self.attribute_maps[(source_context.type_().0.get() - 1) as usize];
287 let target_attribute_bitmap: &ExtensibleBitmap =
288 &self.attribute_maps[(target_context.type_().0.get() - 1) as usize];
289
290 for access_vector_rule_view in self.access_vector_rules() {
291 let metadata = access_vector_rule_view.read_metadata(&self.data);
292
293 if !metadata.is_allowxperm()
294 && !metadata.is_auditallowxperm()
295 && !metadata.is_dontauditxperm()
296 {
297 continue;
298 }
299 if metadata.target_class() != target_class_id {
300 continue;
301 }
302 if !source_attribute_bitmap.is_set(metadata.source_type().0.get() - 1) {
303 continue;
304 }
305 if !target_attribute_bitmap.is_set(metadata.target_type().0.get() - 1) {
306 continue;
307 }
308
309 let access_control_rule = access_vector_rule_view.parse(&self.data);
310 if let Some(xperms) = access_control_rule.extended_permissions() {
311 if metadata.is_allowxperm() && xperms_types.contains(&xperms.xperms_type) {
315 explicit_allow.get_or_insert(XpermsBitmap::NONE);
316 }
317 let Some(ref xperms_bitmap) =
318 bitmap_if_prefix_matches(&xperms_kind, xperms_prefix, xperms)
319 else {
320 continue;
321 };
322 if metadata.is_allowxperm() {
323 (*explicit_allow.get_or_insert(XpermsBitmap::NONE)) |= xperms_bitmap;
324 }
325 if metadata.is_auditallowxperm() {
326 auditallow |= xperms_bitmap;
327 }
328 if metadata.is_dontauditxperm() {
329 auditdeny -= xperms_bitmap;
330 }
331 }
332 }
333 let allow = explicit_allow.unwrap_or(XpermsBitmap::ALL);
334 XpermsAccessDecision { allow, auditallow, auditdeny }
335 }
336
337 pub(super) fn initial_context(&self, id: crate::InitialSid) -> &Context {
339 let id = le::U32::from(id as u32);
340 &self.initial_sids.data.iter().find(|initial| initial.id() == id).unwrap().context()
342 }
343
344 pub(super) fn user(&self, id: UserId) -> &User {
347 self.users.data.iter().find(|x| x.id() == id).unwrap()
348 }
349
350 pub(super) fn user_by_name(&self, name: &str) -> Option<&User> {
352 self.users.data.iter().find(|x| x.name_bytes() == name.as_bytes())
353 }
354
355 pub(super) fn role(&self, id: RoleId) -> &Role {
358 self.roles.data.iter().find(|x| x.id() == id).unwrap()
359 }
360
361 pub(super) fn role_by_name(&self, name: &str) -> Option<&Role> {
363 self.roles.data.iter().find(|x| x.name_bytes() == name.as_bytes())
364 }
365
366 pub(super) fn type_(&self, id: TypeId) -> &Type {
369 self.types.data.iter().find(|x| x.id() == id).unwrap()
370 }
371
372 pub(super) fn type_by_name(&self, name: &str) -> Option<&Type> {
374 self.types.data.iter().find(|x| x.name_bytes() == name.as_bytes())
375 }
376
377 pub(super) fn permissive_types(&self) -> &ExtensibleBitmap {
380 &self.permissive_map
381 }
382
383 pub(super) fn sensitivity(&self, id: SensitivityId) -> &Sensitivity {
386 self.sensitivities.data.iter().find(|x| x.id() == id).unwrap()
387 }
388
389 pub(super) fn sensitivity_by_name(&self, name: &str) -> Option<&Sensitivity> {
391 self.sensitivities.data.iter().find(|x| x.name_bytes() == name.as_bytes())
392 }
393
394 pub(super) fn category(&self, id: CategoryId) -> &Category {
397 self.categories.data.iter().find(|y| y.id() == id).unwrap()
398 }
399
400 pub(super) fn category_by_name(&self, name: &str) -> Option<&Category> {
402 self.categories.data.iter().find(|x| x.name_bytes() == name.as_bytes())
403 }
404
405 pub(super) fn classes(&self) -> &Classes {
406 &self.classes.data
407 }
408
409 pub(super) fn common_symbols(&self) -> &CommonSymbols {
410 &self.common_symbols.data
411 }
412
413 pub(super) fn conditional_booleans(&self) -> &Vec<ConditionalBoolean> {
414 &self.conditional_booleans.data
415 }
416
417 pub(super) fn fs_uses(&self) -> &FsUses {
418 &self.fs_uses.data
419 }
420
421 pub(super) fn generic_fs_contexts(&self) -> &GenericFsContexts {
422 &self.generic_fs_contexts.data
423 }
424
425 pub(super) fn role_allowlist(&self) -> &[RoleAllow] {
426 &self.role_allowlist.data
427 }
428
429 pub(super) fn role_transitions(&self) -> &[RoleTransition] {
430 &self.role_transitions.data
431 }
432
433 pub(super) fn range_transitions(&self) -> &RangeTransitions {
434 &self.range_transitions.data
435 }
436
437 pub(super) fn access_vector_rules(&self) -> impl Iterator<Item = View<AccessVectorRule>> {
438 self.access_vector_rules.data().iter(&self.data)
439 }
440
441 pub(super) fn find_access_vector_rule(
442 &self,
443 source: TypeId,
444 target: TypeId,
445 class: ClassId,
446 rule_type: u16,
447 ) -> Option<AccessVectorRule> {
448 let query = AccessVectorRuleMetadata::for_query(source, target, class, rule_type);
449 self.access_vector_rules.find(query, &self.data)
450 }
451
452 #[cfg(test)]
453 pub(super) fn access_vector_rules_for_test(
454 &self,
455 ) -> impl Iterator<Item = AccessVectorRule> + use<'_> {
456 self.access_vector_rules().map(|view| view.parse(&self.data))
457 }
458
459 pub(super) fn compute_filename_transition(
460 &self,
461 source_type: TypeId,
462 target_type: TypeId,
463 class: ClassId,
464 name: NullessByteStr<'_>,
465 ) -> Option<TypeId> {
466 match &self.filename_transition_list {
467 FilenameTransitionList::PolicyVersionGeq33(list) => {
468 let entry = list.data.iter().find(|transition| {
469 transition.target_type() == target_type
470 && transition.target_class() == class
471 && transition.name_bytes() == name.as_bytes()
472 })?;
473 entry
474 .outputs()
475 .iter()
476 .find(|entry| entry.has_source_type(source_type))
477 .map(|x| x.out_type())
478 }
479 FilenameTransitionList::PolicyVersionLeq32(list) => list
480 .data
481 .iter()
482 .find(|transition| {
483 transition.target_class() == class
484 && transition.target_type() == target_type
485 && transition.source_type() == source_type
486 && transition.name_bytes() == name.as_bytes()
487 })
488 .map(|x| x.out_type()),
489 }
490 }
491
492 fn validate_mls_range(
499 &self,
500 low_level: &MlsLevel,
501 high_level: &Option<MlsLevel>,
502 sensitivity_ids: &HashSet<SensitivityId>,
503 category_ids: &HashSet<CategoryId>,
504 ) -> Result<(), anyhow::Error> {
505 validate_id(sensitivity_ids, low_level.sensitivity(), "sensitivity")?;
506 for id in low_level.category_ids() {
507 validate_id(category_ids, id, "category")?;
508 }
509 if let Some(high) = high_level {
510 validate_id(sensitivity_ids, high.sensitivity(), "sensitivity")?;
511 for id in high.category_ids() {
512 validate_id(category_ids, id, "category")?;
513 }
514 if !high.dominates(low_level) {
515 return Err(ValidateError::InvalidMlsRange {
516 low: low_level.serialize(self).into(),
517 high: high.serialize(self).into(),
518 }
519 .into());
520 }
521 }
522 Ok(())
523 }
524}
525
526impl ParsedPolicy {
527 pub(super) fn parse(data: PolicyData) -> Result<Self, anyhow::Error> {
530 let cursor = PolicyCursor::new(data.clone());
531 let (policy, tail) = parse_policy_internal(cursor, data)?;
532 let num_bytes = tail.len();
533 if num_bytes > 0 {
534 return Err(ParseError::TrailingBytes { num_bytes }.into());
535 }
536 Ok(policy)
537 }
538}
539
540fn parse_policy_internal(
542 bytes: PolicyCursor,
543 data: PolicyData,
544) -> Result<(ParsedPolicy, PolicyCursor), anyhow::Error> {
545 let tail = bytes;
546
547 let (magic, tail) = PolicyCursor::parse::<Magic>(tail).context("parsing magic")?;
548
549 let (signature, tail) =
550 Signature::parse(tail).map_err(Into::<anyhow::Error>::into).context("parsing signature")?;
551
552 let (policy_version, tail) =
553 PolicyCursor::parse::<PolicyVersion>(tail).context("parsing policy version")?;
554 let policy_version_value = policy_version.policy_version();
555
556 let (config, tail) = Config::parse(tail)
557 .map_err(Into::<anyhow::Error>::into)
558 .context("parsing policy config")?;
559
560 let (counts, tail) =
561 PolicyCursor::parse::<Counts>(tail).context("parsing high-level policy object counts")?;
562
563 let (policy_capabilities, tail) = ExtensibleBitmap::parse(tail)
564 .map_err(Into::<anyhow::Error>::into)
565 .context("parsing policy capabilities")?;
566
567 let (permissive_map, tail) = ExtensibleBitmap::parse(tail)
568 .map_err(Into::<anyhow::Error>::into)
569 .context("parsing permissive map")?;
570
571 let (common_symbols, tail) = SymbolList::<CommonSymbol>::parse(tail)
572 .map_err(Into::<anyhow::Error>::into)
573 .context("parsing common symbols")?;
574
575 let (classes, tail) = SymbolList::<Class>::parse(tail)
576 .map_err(Into::<anyhow::Error>::into)
577 .context("parsing classes")?;
578
579 let (roles, tail) = SymbolList::<Role>::parse(tail)
580 .map_err(Into::<anyhow::Error>::into)
581 .context("parsing roles")?;
582
583 let (types, tail) = SymbolList::<Type>::parse(tail)
584 .map_err(Into::<anyhow::Error>::into)
585 .context("parsing types")?;
586
587 let (users, tail) = SymbolList::<User>::parse(tail)
588 .map_err(Into::<anyhow::Error>::into)
589 .context("parsing users")?;
590
591 let (conditional_booleans, tail) = SymbolList::<ConditionalBoolean>::parse(tail)
592 .map_err(Into::<anyhow::Error>::into)
593 .context("parsing conditional booleans")?;
594
595 let (sensitivities, tail) = SymbolList::<Sensitivity>::parse(tail)
596 .map_err(Into::<anyhow::Error>::into)
597 .context("parsing sensitivites")?;
598
599 let (categories, tail) = SymbolList::<Category>::parse(tail)
600 .map_err(Into::<anyhow::Error>::into)
601 .context("parsing categories")?;
602
603 let (access_vector_rules, tail) = HashedArrayView::<le::U32, AccessVectorRule>::parse(tail)
604 .map_err(Into::<anyhow::Error>::into)
605 .context("parsing access vector rules")?;
606
607 let (conditional_lists, tail) = SimpleArray::<ConditionalNodes>::parse(tail)
608 .map_err(Into::<anyhow::Error>::into)
609 .context("parsing conditional lists")?;
610
611 let (role_transitions, tail) = RoleTransitions::parse(tail)
612 .map_err(Into::<anyhow::Error>::into)
613 .context("parsing role transitions")?;
614
615 let (role_allowlist, tail) = RoleAllows::parse(tail)
616 .map_err(Into::<anyhow::Error>::into)
617 .context("parsing role allow rules")?;
618
619 let (filename_transition_list, tail) = if policy_version_value >= 33 {
620 let (filename_transition_list, tail) = SimpleArray::<FilenameTransitions>::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::<DeprecatedFilenameTransitions>::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::<InitialSids>::parse(tail)
633 .map_err(Into::<anyhow::Error>::into)
634 .context("parsing initial sids")?;
635
636 let (filesystems, tail) = SimpleArray::<NamedContextPairs>::parse(tail)
637 .map_err(Into::<anyhow::Error>::into)
638 .context("parsing filesystem contexts")?;
639
640 let (ports, tail) = SimpleArray::<Ports>::parse(tail)
641 .map_err(Into::<anyhow::Error>::into)
642 .context("parsing ports")?;
643
644 let (network_interfaces, tail) = SimpleArray::<NamedContextPairs>::parse(tail)
645 .map_err(Into::<anyhow::Error>::into)
646 .context("parsing network interfaces")?;
647
648 let (nodes, tail) = SimpleArray::<Nodes>::parse(tail)
649 .map_err(Into::<anyhow::Error>::into)
650 .context("parsing nodes")?;
651
652 let (fs_uses, tail) = SimpleArray::<FsUses>::parse(tail)
653 .map_err(Into::<anyhow::Error>::into)
654 .context("parsing fs uses")?;
655
656 let (ipv6_nodes, tail) = SimpleArray::<IPv6Nodes>::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::<InfinitiBandPartitionKeys>::parse(tail)
664 .map_err(Into::<anyhow::Error>::into)
665 .context("parsing infiniti band partition keys")?;
666 let (infinitiband_end_ports, tail) = SimpleArray::<InfinitiBandEndPorts>::parse(tail)
667 .map_err(Into::<anyhow::Error>::into)
668 .context("parsing infiniti band end ports")?;
669 (Some(infinity_band_partition_keys), Some(infinitiband_end_ports), tail)
670 } else {
671 (None, None, tail)
672 };
673
674 let (generic_fs_contexts, tail) = SimpleArray::<GenericFsContexts>::parse(tail)
675 .map_err(Into::<anyhow::Error>::into)
676 .context("parsing generic filesystem contexts")?;
677
678 let (range_transitions, tail) = SimpleArray::<RangeTransitions>::parse(tail)
679 .map_err(Into::<anyhow::Error>::into)
680 .context("parsing range transitions")?;
681
682 let primary_names_count = types.metadata.primary_names_count();
683 let mut attribute_maps = Vec::with_capacity(primary_names_count as usize);
684 let mut tail = tail;
685
686 for i in 0..primary_names_count {
687 let (item, next_tail) = ExtensibleBitmap::parse(tail)
688 .map_err(Into::<anyhow::Error>::into)
689 .with_context(|| format!("parsing {}th attribute map", i))?;
690 attribute_maps.push(item);
691 tail = next_tail;
692 }
693 let tail = tail;
694 let attribute_maps = attribute_maps;
695
696 Ok((
697 ParsedPolicy {
698 data,
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
736impl ParsedPolicy {
737 pub fn validate(&self) -> Result<(), anyhow::Error> {
738 let mut context = PolicyValidationContext { data: self.data.clone() };
739
740 self.magic
741 .validate(&mut context)
742 .map_err(Into::<anyhow::Error>::into)
743 .context("validating magic")?;
744 self.signature
745 .validate(&mut context)
746 .map_err(Into::<anyhow::Error>::into)
747 .context("validating signature")?;
748 self.policy_version
749 .validate(&mut context)
750 .map_err(Into::<anyhow::Error>::into)
751 .context("validating policy_version")?;
752 self.config
753 .validate(&mut context)
754 .map_err(Into::<anyhow::Error>::into)
755 .context("validating config")?;
756 self.counts
757 .validate(&mut context)
758 .map_err(Into::<anyhow::Error>::into)
759 .context("validating counts")?;
760 self.policy_capabilities
761 .validate(&mut context)
762 .map_err(Into::<anyhow::Error>::into)
763 .context("validating policy_capabilities")?;
764 self.permissive_map
765 .validate(&mut context)
766 .map_err(Into::<anyhow::Error>::into)
767 .context("validating permissive_map")?;
768 self.common_symbols
769 .validate(&mut context)
770 .map_err(Into::<anyhow::Error>::into)
771 .context("validating common_symbols")?;
772 self.classes
773 .validate(&mut context)
774 .map_err(Into::<anyhow::Error>::into)
775 .context("validating classes")?;
776 self.roles
777 .validate(&mut context)
778 .map_err(Into::<anyhow::Error>::into)
779 .context("validating roles")?;
780 self.types
781 .validate(&mut context)
782 .map_err(Into::<anyhow::Error>::into)
783 .context("validating types")?;
784 self.users
785 .validate(&mut context)
786 .map_err(Into::<anyhow::Error>::into)
787 .context("validating users")?;
788 self.conditional_booleans
789 .validate(&mut context)
790 .map_err(Into::<anyhow::Error>::into)
791 .context("validating conditional_booleans")?;
792 self.sensitivities
793 .validate(&mut context)
794 .map_err(Into::<anyhow::Error>::into)
795 .context("validating sensitivities")?;
796 self.categories
797 .validate(&mut context)
798 .map_err(Into::<anyhow::Error>::into)
799 .context("validating categories")?;
800 self.access_vector_rules
801 .validate(&mut context)
802 .map_err(Into::<anyhow::Error>::into)
803 .context("validating access_vector_rules")?;
804 self.conditional_lists
805 .validate(&mut context)
806 .map_err(Into::<anyhow::Error>::into)
807 .context("validating conditional_lists")?;
808 self.role_transitions
809 .validate(&mut context)
810 .map_err(Into::<anyhow::Error>::into)
811 .context("validating role_transitions")?;
812 self.role_allowlist
813 .validate(&mut context)
814 .map_err(Into::<anyhow::Error>::into)
815 .context("validating role_allowlist")?;
816 self.filename_transition_list
817 .validate(&mut context)
818 .map_err(Into::<anyhow::Error>::into)
819 .context("validating filename_transition_list")?;
820 self.initial_sids
821 .validate(&mut context)
822 .map_err(Into::<anyhow::Error>::into)
823 .context("validating initial_sids")?;
824 self.filesystems
825 .validate(&mut context)
826 .map_err(Into::<anyhow::Error>::into)
827 .context("validating filesystems")?;
828 self.ports
829 .validate(&mut context)
830 .map_err(Into::<anyhow::Error>::into)
831 .context("validating ports")?;
832 self.network_interfaces
833 .validate(&mut context)
834 .map_err(Into::<anyhow::Error>::into)
835 .context("validating network_interfaces")?;
836 self.nodes
837 .validate(&mut context)
838 .map_err(Into::<anyhow::Error>::into)
839 .context("validating nodes")?;
840 self.fs_uses
841 .validate(&mut context)
842 .map_err(Into::<anyhow::Error>::into)
843 .context("validating fs_uses")?;
844 self.ipv6_nodes
845 .validate(&mut context)
846 .map_err(Into::<anyhow::Error>::into)
847 .context("validating ipv6 nodes")?;
848 self.infinitiband_partition_keys
849 .validate(&mut context)
850 .map_err(Into::<anyhow::Error>::into)
851 .context("validating infinitiband_partition_keys")?;
852 self.infinitiband_end_ports
853 .validate(&mut context)
854 .map_err(Into::<anyhow::Error>::into)
855 .context("validating infinitiband_end_ports")?;
856 self.generic_fs_contexts
857 .validate(&mut context)
858 .map_err(Into::<anyhow::Error>::into)
859 .context("validating generic_fs_contexts")?;
860 self.range_transitions
861 .validate(&mut context)
862 .map_err(Into::<anyhow::Error>::into)
863 .context("validating range_transitions")?;
864 self.attribute_maps
865 .validate(&mut context)
866 .map_err(Into::<anyhow::Error>::into)
867 .context("validating attribute_maps")?;
868
869 let user_ids: HashSet<UserId> = self.users.data.iter().map(|x| x.id()).collect();
871 let role_ids: HashSet<RoleId> = self.roles.data.iter().map(|x| x.id()).collect();
872 let class_ids: HashSet<ClassId> = self.classes.data.iter().map(|x| x.id()).collect();
873 let type_ids: HashSet<TypeId> = self.types.data.iter().map(|x| x.id()).collect();
874 let sensitivity_ids: HashSet<SensitivityId> =
875 self.sensitivities.data.iter().map(|x| x.id()).collect();
876 let category_ids: HashSet<CategoryId> =
877 self.categories.data.iter().map(|x| x.id()).collect();
878
879 for user in &self.users.data {
883 self.validate_mls_range(
884 user.mls_range().low(),
885 user.mls_range().high(),
886 &sensitivity_ids,
887 &category_ids,
888 )?;
889 }
890
891 for initial_sid in &self.initial_sids.data {
895 let context = initial_sid.context();
896 validate_id(&user_ids, context.user_id(), "user")?;
897 validate_id(&role_ids, context.role_id(), "role")?;
898 validate_id(&type_ids, context.type_id(), "type")?;
899 self.validate_mls_range(
900 context.low_level(),
901 context.high_level(),
902 &sensitivity_ids,
903 &category_ids,
904 )?;
905 }
906
907 for fs_use in &self.fs_uses.data {
911 let context = fs_use.context();
912 validate_id(&user_ids, context.user_id(), "user")?;
913 validate_id(&role_ids, context.role_id(), "role")?;
914 validate_id(&type_ids, context.type_id(), "type")?;
915 self.validate_mls_range(
916 context.low_level(),
917 context.high_level(),
918 &sensitivity_ids,
919 &category_ids,
920 )?;
921 }
922
923 for transition in &self.role_transitions.data {
925 validate_id(&role_ids, transition.current_role(), "current_role")?;
926 validate_id(&type_ids, transition.type_(), "type")?;
927 validate_id(&class_ids, transition.class(), "class")?;
928 validate_id(&role_ids, transition.new_role(), "new_role")?;
929 }
930 for allow in &self.role_allowlist.data {
931 validate_id(&role_ids, allow.source_role(), "source_role")?;
932 validate_id(&role_ids, allow.new_role(), "new_role")?;
933 }
934
935 for access_vector_rule_view in self.access_vector_rules() {
937 let access_vector_rule = access_vector_rule_view.parse(&self.data);
938 if let Some(type_id) = access_vector_rule.new_type() {
939 validate_id(&type_ids, type_id, "new_type")?;
940 }
941 }
942
943 let initial_context = SecurityContext::new_from_policy_context(
946 self.initial_context(crate::InitialSid::Kernel),
947 );
948 for class in self.classes() {
949 for constraint in class.constraints() {
950 constraint
951 .constraint_expr()
952 .evaluate(&initial_context, &initial_context)
953 .map_err(Into::<anyhow::Error>::into)
954 .context("validating constraints")?;
955 }
956 }
957
958 Ok(())
962 }
963}
964
965fn validate_id<IdType: Debug + Eq + Hash>(
966 id_set: &HashSet<IdType>,
967 id: IdType,
968 debug_kind: &'static str,
969) -> Result<(), anyhow::Error> {
970 if !id_set.contains(&id) {
971 return Err(ValidateError::UnknownId { kind: debug_kind, id: format!("{:?}", id) }.into());
972 }
973 Ok(())
974}