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