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, ConditionalNode, Context, DeprecatedFilenameTransition,
10 ExtendedPermissions, FilenameTransition, FilenameTransitionList, FsUse, GenericFsContext,
11 IPv6Node, InfinitiBandEndPort, InfinitiBandPartitionKey, InitialSid,
12 MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY, NamedContextPair, Node, Port,
13 RangeTransition, 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;
19
20use super::parser::{PolicyCursor, PolicyData};
21use super::security_context::SecurityContext;
22use super::symbols::{
23 Category, CategoryIndex, ConditionalBoolean, Role, Sensitivity, SymbolList, Type, TypeIndex,
24 User,
25};
26use super::view::{Hashable, HashedArrayView};
27use super::{
28 AccessDecision, AccessVector, CategoryId, ClassId, MlsLevel, Parse, PolicyValidationContext,
29 RoleId, SELINUX_AVD_FLAGS_PERMISSIVE, SensitivityId, TypeId, UserId, Validate,
30 XpermsAccessDecision, XpermsKind,
31};
32
33use crate::new_policy::traits::{HasPolicyId, PolicyId};
34use crate::new_policy::{Class, NewPolicy};
35use crate::policy::arrays::FsContext;
36use crate::policy::view::CustomKeyHashedView;
37use crate::{NullessByteStr, PolicyCap};
38use std::ops::Deref;
39use std::sync::Arc;
40
41use anyhow::Context as _;
42use itertools::Itertools;
43use std::collections::HashSet;
44use std::fmt::Debug;
45use std::hash::Hash;
46use std::iter::Iterator;
47use zerocopy::little_endian as le;
48
49const MAXIMUM_POLICY_SIZE: usize = 1 << 24;
51
52#[derive(Debug)]
54pub struct ParsedPolicy {
55 data: PolicyData,
57
58 new_policy: Arc<NewPolicy>,
60
61 roles: SymbolList<Role>,
63 types: TypeIndex,
65 users: SymbolList<User>,
67 conditional_booleans: SymbolList<ConditionalBoolean>,
69 sensitivities: SymbolList<Sensitivity>,
71 categories: CategoryIndex,
73 access_vector_rules: HashedArrayView<AccessVectorRule>,
75 conditional_lists: SimpleArray<ConditionalNode>,
76 role_transitions: RoleTransitions,
78 role_allowlist: RoleAllows,
80 filename_transition_list: FilenameTransitionList,
81 initial_sids: SimpleArray<InitialSid>,
82 filesystems: SimpleArray<NamedContextPair>,
83 ports: SimpleArray<Port>,
84 network_interfaces: SimpleArray<NamedContextPair>,
85 nodes: SimpleArray<Node>,
86 fs_uses: SimpleArray<FsUse>,
87 ipv6_nodes: SimpleArray<IPv6Node>,
88 infinitiband_partition_keys: Option<SimpleArray<InfinitiBandPartitionKey>>,
89 infinitiband_end_ports: Option<SimpleArray<InfinitiBandEndPort>>,
90 generic_fs_contexts: CustomKeyHashedView<GenericFsContext>,
93 range_transitions: SimpleArray<RangeTransition>,
94 attribute_maps: Vec<ExtensibleBitmap>,
96}
97
98impl Deref for ParsedPolicy {
99 type Target = NewPolicy;
100 fn deref(&self) -> &Self::Target {
101 &self.new_policy
102 }
103}
104
105impl ParsedPolicy {
106 pub fn has_policycap(&self, policy_cap: PolicyCap) -> bool {
108 self.new_policy.policy_capabilities().is_set(policy_cap as u32)
109 }
110
111 pub(super) fn compute_access_decision(
123 &self,
124 source_context: &SecurityContext,
125 target_context: &SecurityContext,
126 target_class: &Class,
127 ) -> AccessDecision {
128 let mut access_decision = self.compute_explicitly_allowed(
129 source_context.type_(),
130 target_context.type_(),
131 target_class,
132 );
133 access_decision.allow -=
134 self.compute_denied_by_constraints(source_context, target_context, target_class);
135 access_decision
136 }
137
138 pub(super) fn compute_explicitly_allowed(
143 &self,
144 source_type: TypeId,
145 target_type: TypeId,
146 target_class: &Class,
147 ) -> AccessDecision {
148 let target_class_id = target_class.id();
149
150 let mut computed_access_vector = AccessVector::NONE;
151 let mut computed_audit_allow = AccessVector::NONE;
152 let mut computed_audit_deny = AccessVector::ALL;
153
154 let source_attribute_bitmap: &ExtensibleBitmap =
155 &self.attribute_maps[(source_type.as_u32() - 1) as usize];
156 let target_attribute_bitmap: &ExtensibleBitmap =
157 &self.attribute_maps[(target_type.as_u32() - 1) as usize];
158
159 for (source_bit_index, target_bit_index) in Itertools::cartesian_product(
160 source_attribute_bitmap.indices_of_set_bits(),
161 target_attribute_bitmap.indices_of_set_bits(),
162 ) {
163 let source_id = TypeId::from_u32((source_bit_index + 1) as u32).unwrap();
164 let target_id = TypeId::from_u32((target_bit_index + 1) as u32).unwrap();
165
166 if let Some(allow_rule) = self.access_vector_rules_find(
167 source_id,
168 target_id,
169 target_class_id,
170 ACCESS_VECTOR_RULE_TYPE_ALLOW,
171 ) {
172 computed_access_vector |= allow_rule.access_vector().unwrap();
174 }
175 if let Some(auditallow_rule) = self.access_vector_rules_find(
176 source_id,
177 target_id,
178 target_class_id,
179 ACCESS_VECTOR_RULE_TYPE_AUDITALLOW,
180 ) {
181 computed_audit_allow |= auditallow_rule.access_vector().unwrap();
183 }
184 if let Some(dontaudit_rule) = self.access_vector_rules_find(
185 source_id,
186 target_id,
187 target_class_id,
188 ACCESS_VECTOR_RULE_TYPE_DONTAUDIT,
189 ) {
190 computed_audit_deny &= dontaudit_rule.access_vector().unwrap();
192 }
193 }
194
195 if let Some(parent) = self.type_(source_type).bounded_by() {
199 let access = if source_type == target_type {
202 self.compute_explicitly_allowed(parent, parent, target_class)
203 } else {
204 self.compute_explicitly_allowed(parent, target_type, target_class)
205 };
206 computed_access_vector &= access.allow;
207 }
208
209 let mut flags = 0;
210 if self.permissive_map().contains(source_type) {
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() {
231 match crate::policy::constraints::evaluate_constraint(
232 constraint.constraint_expr(),
233 source_context,
234 target_context,
235 ) {
236 Err(err) => {
237 unreachable!("validated constraint expression failed to evaluate: {:?}", err)
238 }
239 Ok(false) => denied |= constraint.access_vector(),
240 Ok(true) => {}
241 }
242 }
243 denied
244 }
245
246 pub(super) fn compute_xperms_access_decision(
249 &self,
250 xperms_kind: XpermsKind,
251 source_context: &SecurityContext,
252 target_context: &SecurityContext,
253 target_class: &Class,
254 xperms_prefix: u8,
255 ) -> XpermsAccessDecision {
256 let target_class_id = target_class.id();
257
258 let mut explicit_allow: Option<XpermsBitmap> = None;
259 let mut auditallow = XpermsBitmap::NONE;
260 let mut auditdeny = XpermsBitmap::ALL;
261
262 let xperms_types = match xperms_kind {
263 XpermsKind::Ioctl => {
264 [XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES, XPERMS_TYPE_IOCTL_PREFIXES].as_slice()
265 }
266 XpermsKind::Nlmsg => [XPERMS_TYPE_NLMSG].as_slice(),
267 };
268 let bitmap_if_prefix_matches =
269 |xperms_prefix: u8, xperms: &ExtendedPermissions| match xperms_kind {
270 XpermsKind::Ioctl => match xperms.xperms_type {
271 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES => (xperms.xperms_optional_prefix
272 == xperms_prefix)
273 .then_some(xperms.xperms_bitmap),
274 XPERMS_TYPE_IOCTL_PREFIXES => {
275 xperms.xperms_bitmap.contains(xperms_prefix).then_some(XpermsBitmap::ALL)
276 }
277 _ => None,
278 },
279 XpermsKind::Nlmsg => match xperms.xperms_type {
280 XPERMS_TYPE_NLMSG => (xperms.xperms_optional_prefix == xperms_prefix)
281 .then_some(xperms.xperms_bitmap),
282 _ => None,
283 },
284 };
285
286 let source_attribute_bitmap: &ExtensibleBitmap =
287 &self.attribute_maps[(source_context.type_().as_u32() - 1) as usize];
288 let target_attribute_bitmap: &ExtensibleBitmap =
289 &self.attribute_maps[(target_context.type_().as_u32() - 1) as usize];
290
291 for (source_bit_index, target_bit_index) in Itertools::cartesian_product(
292 source_attribute_bitmap.indices_of_set_bits(),
293 target_attribute_bitmap.indices_of_set_bits(),
294 ) {
295 let source_id = TypeId::from_u32((source_bit_index + 1) as u32).unwrap();
296 let target_id = TypeId::from_u32((target_bit_index + 1) as u32).unwrap();
297
298 for xperms_allow_rule in self.access_vector_rules_find_all(
299 source_id,
300 target_id,
301 target_class_id,
302 ACCESS_VECTOR_RULE_TYPE_ALLOWXPERM,
303 ) {
304 let xperms = xperms_allow_rule.extended_permissions().unwrap();
305
306 if xperms_types.contains(&xperms.xperms_type) {
310 explicit_allow.get_or_insert(XpermsBitmap::NONE);
311 }
312
313 if let Some(ref xperms_bitmap) = bitmap_if_prefix_matches(xperms_prefix, xperms) {
314 (*explicit_allow.get_or_insert(XpermsBitmap::NONE)) |= xperms_bitmap;
315 }
316 }
317
318 for xperms_auditallow_rule in self.access_vector_rules_find_all(
319 source_id,
320 target_id,
321 target_class_id,
322 ACCESS_VECTOR_RULE_TYPE_AUDITALLOWXPERM,
323 ) {
324 let xperms = xperms_auditallow_rule.extended_permissions().unwrap();
325 if let Some(ref xperms_bitmap) = bitmap_if_prefix_matches(xperms_prefix, xperms) {
326 auditallow |= xperms_bitmap;
327 }
328 }
329
330 for xperms_dontaudit_rule in self.access_vector_rules_find_all(
331 source_id,
332 target_id,
333 target_class_id,
334 ACCESS_VECTOR_RULE_TYPE_DONTAUDITXPERM,
335 ) {
336 let xperms = xperms_dontaudit_rule.extended_permissions().unwrap();
337 if let Some(ref xperms_bitmap) = bitmap_if_prefix_matches(xperms_prefix, xperms) {
338 auditdeny -= xperms_bitmap;
339 }
340 }
341 }
342 let allow = explicit_allow.unwrap_or(XpermsBitmap::ALL);
343 XpermsAccessDecision { allow, auditallow, auditdeny }
344 }
345
346 pub(super) fn initial_context(&self, mut id: crate::InitialSid) -> &Context {
348 if id == crate::InitialSid::Init && !self.has_policycap(PolicyCap::UserspaceInitialContext)
350 {
351 id = crate::InitialSid::Kernel
352 }
353
354 let id = le::U32::from(id as u32);
356 &self.initial_sids.data.iter().find(|initial| initial.id() == id).unwrap().context()
357 }
358
359 pub(super) fn user(&self, id: UserId) -> &User {
362 self.users.data.iter().find(|x| x.id() == id).unwrap()
363 }
364
365 pub(super) fn user_by_name(&self, name: &str) -> Option<&User> {
367 self.users.data.iter().find(|x| x.name_bytes() == name.as_bytes())
368 }
369
370 pub(super) fn role(&self, id: RoleId) -> &Role {
373 self.roles.data.iter().find(|x| x.id() == id).unwrap()
374 }
375
376 pub(super) fn role_by_name(&self, name: &str) -> Option<&Role> {
378 self.roles.data.iter().find(|x| x.name_bytes() == name.as_bytes())
379 }
380
381 pub(super) fn type_(&self, id: TypeId) -> Type {
384 self.types.type_by_type_id(id, &self.data)
385 }
386
387 pub(crate) fn type_id_by_name(&self, name: &str) -> Option<TypeId> {
389 self.types.type_id_by_name(name, &self.data)
390 }
391
392 pub(super) fn sensitivity(&self, id: SensitivityId) -> &Sensitivity {
395 self.sensitivities.data.iter().find(|x| x.id() == id).unwrap()
396 }
397
398 pub(super) fn sensitivity_by_name(&self, name: &str) -> Option<&Sensitivity> {
400 self.sensitivities.data.iter().find(|x| x.name_bytes() == name.as_bytes())
401 }
402
403 pub(super) fn category(&self, id: CategoryId) -> Category {
406 self.categories.category(&self.data, id)
407 }
408
409 pub(super) fn category_by_name(&self, name: &str) -> Option<Category> {
411 self.categories.category_by_name(&self.data, name)
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) -> &[FsUse] {
419 &self.fs_uses.data
420 }
421
422 pub(super) fn genfscon_find_all(&self, fs_type: &str) -> impl Iterator<Item = FsContext> {
423 let query = GenericFsContext::for_query(fs_type);
424 self.generic_fs_contexts.find_all(query, &self.data)
425 }
426
427 pub(super) fn role_allowlist(&self) -> &[RoleAllow] {
428 &self.role_allowlist.data
429 }
430
431 pub(super) fn role_transitions(&self) -> &[RoleTransition] {
432 &self.role_transitions.data
433 }
434
435 pub(super) fn range_transitions(&self) -> &[RangeTransition] {
436 &self.range_transitions.data
437 }
438
439 pub(super) fn access_vector_rules_find(
440 &self,
441 source: TypeId,
442 target: TypeId,
443 class: ClassId,
444 rule_type: u16,
445 ) -> Option<AccessVectorRule> {
446 let query = AccessVectorRuleMetadata::for_query(source, target, class, rule_type);
447 self.access_vector_rules.find(query, &self.data)
448 }
449
450 pub(super) fn access_vector_rules_find_all(
451 &self,
452 source: TypeId,
453 target: TypeId,
454 class: ClassId,
455 rule_type: u16,
456 ) -> impl Iterator<Item = AccessVectorRule> {
457 let query = AccessVectorRuleMetadata::for_query(source, target, class, rule_type);
458 self.access_vector_rules.find_all(query, &self.data)
459 }
460
461 #[cfg(test)]
462 pub(super) fn access_vector_rules_for_test(
463 &self,
464 ) -> impl Iterator<Item = AccessVectorRule> + use<'_> {
465 use super::arrays::testing::access_vector_rule_ordering;
466 use itertools::Itertools;
467
468 self.access_vector_rules
469 .iter(&self.data)
470 .map(|view| view.parse(&self.data))
471 .sorted_by(access_vector_rule_ordering)
472 }
473
474 pub(super) fn compute_filename_transition(
475 &self,
476 source_type: TypeId,
477 target_type: TypeId,
478 class: ClassId,
479 name: NullessByteStr<'_>,
480 ) -> Option<TypeId> {
481 match &self.filename_transition_list {
482 FilenameTransitionList::PolicyVersionGeq33(list) => {
483 let entry = list.data.iter().find(|transition| {
484 transition.target_type() == target_type
485 && transition.target_class() == class
486 && transition.name_bytes() == name.as_bytes()
487 })?;
488 entry
489 .outputs()
490 .iter()
491 .find(|entry| entry.has_source_type(source_type))
492 .map(|x| x.out_type())
493 }
494 FilenameTransitionList::PolicyVersionLeq32(list) => list
495 .data
496 .iter()
497 .find(|transition| {
498 transition.target_class() == class
499 && transition.target_type() == target_type
500 && transition.source_type() == source_type
501 && transition.name_bytes() == name.as_bytes()
502 })
503 .map(|x| x.out_type()),
504 }
505 }
506
507 fn validate_mls_range(
514 &self,
515 low_level: &MlsLevel,
516 high_level: &Option<MlsLevel>,
517 sensitivity_ids: &HashSet<SensitivityId>,
518 category_ids: &HashSet<CategoryId>,
519 ) -> Result<(), anyhow::Error> {
520 validate_id(sensitivity_ids, low_level.sensitivity(), "sensitivity")?;
521 for id in low_level.category_ids() {
522 validate_id(category_ids, id, "category")?;
523 }
524 if let Some(high) = high_level {
525 validate_id(sensitivity_ids, high.sensitivity(), "sensitivity")?;
526 for id in high.category_ids() {
527 validate_id(category_ids, id, "category")?;
528 }
529 if !high.dominates(low_level) {
530 return Err(ValidateError::InvalidMlsRange {
531 low: low_level.to_string(self).into(),
532 high: high.to_string(self).into(),
533 }
534 .into());
535 }
536 }
537 Ok(())
538 }
539
540 fn validate_context(
541 &self,
542 context: &Context,
543 user_ids: &HashSet<UserId>,
544 role_ids: &HashSet<RoleId>,
545 type_ids: &HashSet<TypeId>,
546 sensitivity_ids: &HashSet<SensitivityId>,
547 category_ids: &HashSet<CategoryId>,
548 ) -> Result<(), anyhow::Error> {
549 validate_id(user_ids, context.user_id(), "user")?;
550 validate_id(role_ids, context.role_id(), "role")?;
551 validate_id(type_ids, context.type_id(), "type")?;
552 self.validate_mls_range(
553 context.low_level(),
554 context.high_level(),
555 sensitivity_ids,
556 category_ids,
557 )?;
558 Ok(())
559 }
560}
561
562impl ParsedPolicy {
563 pub(super) fn parse(data: PolicyData) -> Result<Self, anyhow::Error> {
566 let policy_size = data.len();
567 if MAXIMUM_POLICY_SIZE <= policy_size {
568 return Err(anyhow::Error::from(ParseError::UnsupportedlyLarge {
569 observed: policy_size,
570 limit: MAXIMUM_POLICY_SIZE,
571 }));
572 }
573 let new_policy =
574 NewPolicy::parse(&data).map_err(|e| anyhow::anyhow!("new parser failed: {:?}", e))?;
575 new_policy.validate().context("validating new policy structure")?;
576
577 let rest_data = new_policy.rest_bytes();
578 let (policy, excess_bytes) = parse_policy_remaining(new_policy, rest_data)?;
579 if excess_bytes > 0 {
580 return Err(anyhow::Error::from(ParseError::TrailingBytes { num_bytes: excess_bytes }));
581 }
582 Ok(policy)
583 }
584}
585
586fn parse_policy_remaining(
588 new_policy: NewPolicy,
589 rest_data: PolicyData,
590) -> Result<(ParsedPolicy, usize), anyhow::Error> {
591 let tail = PolicyCursor::new(&rest_data);
592
593 let (roles, tail) = SymbolList::<Role>::parse(tail)
594 .map_err(Into::<anyhow::Error>::into)
595 .context("parsing roles")?;
596
597 let (types, tail) =
598 TypeIndex::parse(tail).map_err(anyhow::Error::from).context("parsing types")?;
599
600 let (users, tail) = SymbolList::<User>::parse(tail)
601 .map_err(Into::<anyhow::Error>::into)
602 .context("parsing users")?;
603
604 let (conditional_booleans, tail) = SymbolList::<ConditionalBoolean>::parse(tail)
605 .map_err(Into::<anyhow::Error>::into)
606 .context("parsing conditional booleans")?;
607
608 let (sensitivities, tail) = SymbolList::<Sensitivity>::parse(tail)
609 .map_err(Into::<anyhow::Error>::into)
610 .context("parsing sensitivites")?;
611
612 let (categories, tail) = CategoryIndex::parse(tail)
613 .map_err(Into::<anyhow::Error>::into)
614 .context("parsing categories")?;
615
616 let (access_vector_rules, tail) = HashedArrayView::<AccessVectorRule>::parse(tail)
617 .map_err(Into::<anyhow::Error>::into)
618 .context("parsing access vector rules")?;
619
620 let (conditional_lists, tail) = SimpleArray::<ConditionalNode>::parse(tail)
621 .map_err(Into::<anyhow::Error>::into)
622 .context("parsing conditional lists")?;
623
624 let (role_transitions, tail) = RoleTransitions::parse(tail)
625 .map_err(Into::<anyhow::Error>::into)
626 .context("parsing role transitions")?;
627
628 let (role_allowlist, tail) = RoleAllows::parse(tail)
629 .map_err(Into::<anyhow::Error>::into)
630 .context("parsing role allow rules")?;
631
632 let (filename_transition_list, tail) = if new_policy.policy_version() >= 33 {
633 let (filename_transition_list, tail) = SimpleArray::<FilenameTransition>::parse(tail)
634 .map_err(Into::<anyhow::Error>::into)
635 .context("parsing standard filename transitions")?;
636 (FilenameTransitionList::PolicyVersionGeq33(filename_transition_list), tail)
637 } else {
638 let (filename_transition_list, tail) =
639 SimpleArray::<DeprecatedFilenameTransition>::parse(tail)
640 .map_err(Into::<anyhow::Error>::into)
641 .context("parsing deprecated filename transitions")?;
642 (FilenameTransitionList::PolicyVersionLeq32(filename_transition_list), tail)
643 };
644
645 let (initial_sids, tail) = SimpleArray::<InitialSid>::parse(tail)
646 .map_err(Into::<anyhow::Error>::into)
647 .context("parsing initial sids")?;
648
649 let (filesystems, tail) = SimpleArray::<NamedContextPair>::parse(tail)
650 .map_err(Into::<anyhow::Error>::into)
651 .context("parsing filesystem contexts")?;
652
653 let (ports, tail) = SimpleArray::<Port>::parse(tail)
654 .map_err(Into::<anyhow::Error>::into)
655 .context("parsing ports")?;
656
657 let (network_interfaces, tail) = SimpleArray::<NamedContextPair>::parse(tail)
658 .map_err(Into::<anyhow::Error>::into)
659 .context("parsing network interfaces")?;
660
661 let (nodes, tail) = SimpleArray::<Node>::parse(tail)
662 .map_err(Into::<anyhow::Error>::into)
663 .context("parsing nodes")?;
664
665 let (fs_uses, tail) = SimpleArray::<FsUse>::parse(tail)
666 .map_err(Into::<anyhow::Error>::into)
667 .context("parsing fs uses")?;
668
669 let (ipv6_nodes, tail) = SimpleArray::<IPv6Node>::parse(tail)
670 .map_err(Into::<anyhow::Error>::into)
671 .context("parsing ipv6 nodes")?;
672
673 let (infinitiband_partition_keys, infinitiband_end_ports, tail) =
674 if new_policy.policy_version() >= MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY {
675 let (infinity_band_partition_keys, tail) =
676 SimpleArray::<InfinitiBandPartitionKey>::parse(tail)
677 .map_err(Into::<anyhow::Error>::into)
678 .context("parsing infiniti band partition keys")?;
679 let (infinitiband_end_ports, tail) = SimpleArray::<InfinitiBandEndPort>::parse(tail)
680 .map_err(Into::<anyhow::Error>::into)
681 .context("parsing infiniti band end ports")?;
682 (Some(infinity_band_partition_keys), Some(infinitiband_end_ports), tail)
683 } else {
684 (None, None, tail)
685 };
686
687 let (generic_fs_contexts, tail) = CustomKeyHashedView::<GenericFsContext>::parse(tail)
688 .map_err(Into::<anyhow::Error>::into)
689 .context("parsing generic filesystem contexts")?;
690
691 let (range_transitions, tail) = SimpleArray::<RangeTransition>::parse(tail)
692 .map_err(Into::<anyhow::Error>::into)
693 .context("parsing range transitions")?;
694
695 let primary_names_count = types.primary_names_count();
696 let mut attribute_maps = Vec::with_capacity(primary_names_count as usize);
697 let mut tail = tail;
698
699 for i in 0..primary_names_count {
700 let (item, next_tail) = ExtensibleBitmap::parse(tail)
701 .map_err(Into::<anyhow::Error>::into)
702 .with_context(|| format!("parsing {}th attribute map", i))?;
703 attribute_maps.push(item);
704 tail = next_tail;
705 }
706 let tail = tail;
707 let attribute_maps = attribute_maps;
708
709 let excess_bytes = rest_data.len() - tail.offset() as usize;
710
711 Ok((
712 ParsedPolicy {
713 data: rest_data,
714 new_policy: Arc::new(new_policy),
715 roles,
716 types,
717 users,
718 conditional_booleans,
719 sensitivities,
720 categories,
721 access_vector_rules,
722 conditional_lists,
723 role_transitions,
724 role_allowlist,
725 filename_transition_list,
726 initial_sids,
727 filesystems,
728 ports,
729 network_interfaces,
730 nodes,
731 fs_uses,
732 ipv6_nodes,
733 infinitiband_partition_keys,
734 infinitiband_end_ports,
735 generic_fs_contexts,
736 range_transitions,
737 attribute_maps,
738 },
739 excess_bytes,
740 ))
741}
742
743impl ParsedPolicy {
744 pub fn validate(&self) -> Result<(), anyhow::Error> {
745 let need_init_sid = self.has_policycap(PolicyCap::UserspaceInitialContext);
746 let context = PolicyValidationContext {
747 data: self.data.clone(),
748 need_init_sid,
749 new_policy: self.new_policy.clone(),
750 };
751
752 self.roles
753 .validate(&context)
754 .map_err(Into::<anyhow::Error>::into)
755 .context("validating roles")?;
756 self.types
757 .validate(&context)
758 .map_err(Into::<anyhow::Error>::into)
759 .context("validating types")?;
760 self.users
761 .validate(&context)
762 .map_err(Into::<anyhow::Error>::into)
763 .context("validating users")?;
764 self.conditional_booleans
765 .validate(&context)
766 .map_err(Into::<anyhow::Error>::into)
767 .context("validating conditional_booleans")?;
768 self.sensitivities
769 .validate(&context)
770 .map_err(Into::<anyhow::Error>::into)
771 .context("validating sensitivities")?;
772 self.categories
773 .validate(&context)
774 .map_err(Into::<anyhow::Error>::into)
775 .context("validating categories")?;
776 self.access_vector_rules
777 .validate(&context)
778 .map_err(Into::<anyhow::Error>::into)
779 .context("validating access_vector_rules")?;
780 self.conditional_lists
781 .validate(&context)
782 .map_err(Into::<anyhow::Error>::into)
783 .context("validating conditional_lists")?;
784 self.role_transitions
785 .validate(&context)
786 .map_err(Into::<anyhow::Error>::into)
787 .context("validating role_transitions")?;
788 self.role_allowlist
789 .validate(&context)
790 .map_err(Into::<anyhow::Error>::into)
791 .context("validating role_allowlist")?;
792 self.filename_transition_list
793 .validate(&context)
794 .map_err(Into::<anyhow::Error>::into)
795 .context("validating filename_transition_list")?;
796 self.initial_sids
797 .validate(&context)
798 .map_err(Into::<anyhow::Error>::into)
799 .context("validating initial_sids")?;
800 self.filesystems
801 .validate(&context)
802 .map_err(Into::<anyhow::Error>::into)
803 .context("validating filesystems")?;
804 self.ports
805 .validate(&context)
806 .map_err(Into::<anyhow::Error>::into)
807 .context("validating ports")?;
808 self.network_interfaces
809 .validate(&context)
810 .map_err(Into::<anyhow::Error>::into)
811 .context("validating network_interfaces")?;
812 self.nodes
813 .validate(&context)
814 .map_err(Into::<anyhow::Error>::into)
815 .context("validating nodes")?;
816 self.fs_uses
817 .validate(&context)
818 .map_err(Into::<anyhow::Error>::into)
819 .context("validating fs_uses")?;
820 self.ipv6_nodes
821 .validate(&context)
822 .map_err(Into::<anyhow::Error>::into)
823 .context("validating ipv6 nodes")?;
824 self.infinitiband_partition_keys
825 .validate(&context)
826 .map_err(Into::<anyhow::Error>::into)
827 .context("validating infinitiband_partition_keys")?;
828 self.infinitiband_end_ports
829 .validate(&context)
830 .map_err(Into::<anyhow::Error>::into)
831 .context("validating infinitiband_end_ports")?;
832 self.generic_fs_contexts
833 .validate(&context)
834 .map_err(Into::<anyhow::Error>::into)
835 .context("validating generic_fs_contexts")?;
836 self.range_transitions
837 .validate(&context)
838 .map_err(Into::<anyhow::Error>::into)
839 .context("validating range_transitions")?;
840 self.attribute_maps
841 .validate(&context)
842 .map_err(Into::<anyhow::Error>::into)
843 .context("validating attribute_maps")?;
844
845 let user_ids: HashSet<UserId> = self.users.data.iter().map(|x| x.id()).collect();
847 let role_ids: HashSet<RoleId> = self.roles.data.iter().map(|x| x.id()).collect();
848 let class_ids: HashSet<ClassId> = self.classes().iter().map(|x| x.id()).collect();
849 let type_ids: HashSet<TypeId> = self.types.all_type_ids().collect();
850 let sensitivity_ids: HashSet<SensitivityId> =
851 self.sensitivities.data.iter().map(|x| x.id()).collect();
852 let category_ids: HashSet<CategoryId> =
853 self.categories.categories(&self.data).map(|x| x.id()).collect();
854
855 for user in &self.users.data {
859 self.validate_mls_range(
860 user.mls_range().low(),
861 user.mls_range().high(),
862 &sensitivity_ids,
863 &category_ids,
864 )?;
865 }
866
867 for initial_sid in &self.initial_sids.data {
871 self.validate_context(
872 initial_sid.context(),
873 &user_ids,
874 &role_ids,
875 &type_ids,
876 &sensitivity_ids,
877 &category_ids,
878 )?;
879 }
880
881 for fs_use in &self.fs_uses.data {
885 self.validate_context(
886 fs_use.context(),
887 &user_ids,
888 &role_ids,
889 &type_ids,
890 &sensitivity_ids,
891 &category_ids,
892 )?;
893 }
894
895 for entry in self.generic_fs_contexts.iter(&self.data) {
899 let entry = entry?;
900 for fs_context_view in entry.values().data().iter(&self.data) {
901 let fs_context = fs_context_view.parse(&self.data);
902 self.validate_context(
903 fs_context.context(),
904 &user_ids,
905 &role_ids,
906 &type_ids,
907 &sensitivity_ids,
908 &category_ids,
909 )?;
910 }
911 }
912
913 for transition in &self.role_transitions.data {
915 validate_id(&role_ids, transition.current_role(), "current_role")?;
916 validate_id(&type_ids, transition.type_(), "type")?;
917 validate_id(&class_ids, transition.class(), "class")?;
918 validate_id(&role_ids, transition.new_role(), "new_role")?;
919 }
920 for allow in &self.role_allowlist.data {
921 validate_id(&role_ids, allow.source_role(), "source_role")?;
922 validate_id(&role_ids, allow.new_role(), "new_role")?;
923 }
924
925 for access_vector_rule_view in self.access_vector_rules.iter(&self.data) {
927 let access_vector_rule = access_vector_rule_view.parse(&self.data);
928 if let Some(type_id) = access_vector_rule.new_type() {
929 validate_id(&type_ids, type_id, "new_type")?;
930 }
931 }
932
933 let initial_context = SecurityContext::new_from_policy_context(
936 self.initial_context(crate::InitialSid::Kernel),
937 );
938 for class in self.classes().iter() {
939 for constraint in class.constraints() {
940 crate::policy::constraints::evaluate_constraint(
941 constraint.constraint_expr(),
942 &initial_context,
943 &initial_context,
944 )
945 .map_err(Into::<anyhow::Error>::into)
946 .context("validating constraints")?;
947 }
948 }
949
950 Ok(())
954 }
955}
956
957fn validate_id<IdType: Debug + Eq + Hash>(
958 id_set: &HashSet<IdType>,
959 id: IdType,
960 debug_kind: &'static str,
961) -> Result<(), anyhow::Error> {
962 if !id_set.contains(&id) {
963 return Err(ValidateError::UnknownId { kind: debug_kind, id: format!("{:?}", id) }.into());
964 }
965 Ok(())
966}