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::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, id: crate::InitialSid) -> &Context {
358 let id = le::U32::from(id as u32);
359 &self.initial_sids.data.iter().find(|initial| initial.id() == id).unwrap().context()
361 }
362
363 pub(super) fn user(&self, id: UserId) -> &User {
366 self.users.data.iter().find(|x| x.id() == id).unwrap()
367 }
368
369 pub(super) fn user_by_name(&self, name: &str) -> Option<&User> {
371 self.users.data.iter().find(|x| x.name_bytes() == name.as_bytes())
372 }
373
374 pub(super) fn role(&self, id: RoleId) -> &Role {
377 self.roles.data.iter().find(|x| x.id() == id).unwrap()
378 }
379
380 pub(super) fn role_by_name(&self, name: &str) -> Option<&Role> {
382 self.roles.data.iter().find(|x| x.name_bytes() == name.as_bytes())
383 }
384
385 pub(super) fn type_(&self, id: TypeId) -> Type {
388 self.types.type_by_type_id(id, &self.data)
389 }
390
391 pub(super) fn type_id_by_name(&self, name: &str) -> Option<TypeId> {
393 self.types.type_id_by_name(name, &self.data)
394 }
395
396 pub(super) fn permissive_types(&self) -> &ExtensibleBitmap {
399 &self.permissive_map
400 }
401
402 pub(super) fn sensitivity(&self, id: SensitivityId) -> &Sensitivity {
405 self.sensitivities.data.iter().find(|x| x.id() == id).unwrap()
406 }
407
408 pub(super) fn sensitivity_by_name(&self, name: &str) -> Option<&Sensitivity> {
410 self.sensitivities.data.iter().find(|x| x.name_bytes() == name.as_bytes())
411 }
412
413 pub(super) fn category(&self, id: CategoryId) -> Category {
416 self.categories.category(&self.data, id)
417 }
418
419 pub(super) fn category_by_name(&self, name: &str) -> Option<Category> {
421 self.categories.categories(&self.data).find(|x| x.name_bytes() == name.as_bytes())
422 }
423
424 pub(super) fn class(&self, class_id: ClassId) -> Option<Class> {
425 self.classes.class(&self.data, class_id)
426 }
427
428 pub(super) fn classes(&self) -> Classes {
429 self.classes.classes(&self.data)
430 }
431
432 pub(super) fn common_symbols(&self) -> &CommonSymbols {
433 &self.common_symbols.data
434 }
435
436 pub(super) fn conditional_booleans(&self) -> &Vec<ConditionalBoolean> {
437 &self.conditional_booleans.data
438 }
439
440 pub(super) fn fs_uses(&self) -> &[FsUse] {
441 &self.fs_uses.data
442 }
443
444 pub(super) fn genfscon_find_all(&self, fs_type: &str) -> impl Iterator<Item = FsContext> {
445 let query = GenericFsContext::for_query(fs_type);
446 self.generic_fs_contexts.find_all(query, &self.data)
447 }
448
449 pub(super) fn role_allowlist(&self) -> &[RoleAllow] {
450 &self.role_allowlist.data
451 }
452
453 pub(super) fn role_transitions(&self) -> &[RoleTransition] {
454 &self.role_transitions.data
455 }
456
457 pub(super) fn range_transitions(&self) -> &[RangeTransition] {
458 &self.range_transitions.data
459 }
460
461 pub(super) fn access_vector_rules_find(
462 &self,
463 source: TypeId,
464 target: TypeId,
465 class: ClassId,
466 rule_type: u16,
467 ) -> Option<AccessVectorRule> {
468 let query = AccessVectorRuleMetadata::for_query(source, target, class, rule_type);
469 self.access_vector_rules.find(query, &self.data)
470 }
471
472 pub(super) fn access_vector_rules_find_all(
473 &self,
474 source: TypeId,
475 target: TypeId,
476 class: ClassId,
477 rule_type: u16,
478 ) -> impl Iterator<Item = AccessVectorRule> {
479 let query = AccessVectorRuleMetadata::for_query(source, target, class, rule_type);
480 self.access_vector_rules.find_all(query, &self.data)
481 }
482
483 #[cfg(test)]
484 pub(super) fn access_vector_rules_for_test(
485 &self,
486 ) -> impl Iterator<Item = AccessVectorRule> + use<'_> {
487 use super::arrays::testing::access_vector_rule_ordering;
488 use itertools::Itertools;
489
490 self.access_vector_rules
491 .iter(&self.data)
492 .map(|view| view.parse(&self.data))
493 .sorted_by(access_vector_rule_ordering)
494 }
495
496 pub(super) fn compute_filename_transition(
497 &self,
498 source_type: TypeId,
499 target_type: TypeId,
500 class: ClassId,
501 name: NullessByteStr<'_>,
502 ) -> Option<TypeId> {
503 match &self.filename_transition_list {
504 FilenameTransitionList::PolicyVersionGeq33(list) => {
505 let entry = list.data.iter().find(|transition| {
506 transition.target_type() == target_type
507 && transition.target_class() == class
508 && transition.name_bytes() == name.as_bytes()
509 })?;
510 entry
511 .outputs()
512 .iter()
513 .find(|entry| entry.has_source_type(source_type))
514 .map(|x| x.out_type())
515 }
516 FilenameTransitionList::PolicyVersionLeq32(list) => list
517 .data
518 .iter()
519 .find(|transition| {
520 transition.target_class() == class
521 && transition.target_type() == target_type
522 && transition.source_type() == source_type
523 && transition.name_bytes() == name.as_bytes()
524 })
525 .map(|x| x.out_type()),
526 }
527 }
528
529 fn validate_mls_range(
536 &self,
537 low_level: &MlsLevel,
538 high_level: &Option<MlsLevel>,
539 sensitivity_ids: &HashSet<SensitivityId>,
540 category_ids: &HashSet<CategoryId>,
541 ) -> Result<(), anyhow::Error> {
542 validate_id(sensitivity_ids, low_level.sensitivity(), "sensitivity")?;
543 for id in low_level.category_ids() {
544 validate_id(category_ids, id, "category")?;
545 }
546 if let Some(high) = high_level {
547 validate_id(sensitivity_ids, high.sensitivity(), "sensitivity")?;
548 for id in high.category_ids() {
549 validate_id(category_ids, id, "category")?;
550 }
551 if !high.dominates(low_level) {
552 return Err(ValidateError::InvalidMlsRange {
553 low: low_level.serialize(self).into(),
554 high: high.serialize(self).into(),
555 }
556 .into());
557 }
558 }
559 Ok(())
560 }
561}
562
563impl ParsedPolicy {
564 pub(super) fn parse(data: PolicyData) -> Result<Self, anyhow::Error> {
567 let policy_size = data.len();
568 if MAXIMUM_POLICY_SIZE <= policy_size {
569 return Err(anyhow::Error::from(ParseError::UnsupportedlyLarge {
570 observed: policy_size,
571 limit: MAXIMUM_POLICY_SIZE,
572 }));
573 }
574 let (policy, excess_bytes) = parse_policy_internal(data)?;
575 if excess_bytes > 0 {
576 return Err(anyhow::Error::from(ParseError::TrailingBytes { num_bytes: excess_bytes }));
577 }
578 Ok(policy)
579 }
580}
581
582fn parse_policy_internal<'a>(data: PolicyData) -> Result<(ParsedPolicy, usize), anyhow::Error> {
584 let tail = PolicyCursor::new(&data);
585
586 let (magic, tail) = PolicyCursor::parse::<Magic>(tail).context("parsing magic")?;
587
588 let (signature, tail) =
589 Signature::parse(tail).map_err(Into::<anyhow::Error>::into).context("parsing signature")?;
590
591 let (policy_version, tail) =
592 PolicyCursor::parse::<PolicyVersion>(tail).context("parsing policy version")?;
593 let policy_version_value = policy_version.policy_version();
594
595 let (config, tail) = Config::parse(tail)
596 .map_err(Into::<anyhow::Error>::into)
597 .context("parsing policy config")?;
598
599 let (counts, tail) =
600 PolicyCursor::parse::<Counts>(tail).context("parsing high-level policy object counts")?;
601
602 let (policy_capabilities, tail) = ExtensibleBitmap::parse(tail)
603 .map_err(Into::<anyhow::Error>::into)
604 .context("parsing policy capabilities")?;
605
606 let (permissive_map, tail) = ExtensibleBitmap::parse(tail)
607 .map_err(Into::<anyhow::Error>::into)
608 .context("parsing permissive map")?;
609
610 let (common_symbols, tail) = SymbolList::<CommonSymbol>::parse(tail)
611 .map_err(Into::<anyhow::Error>::into)
612 .context("parsing common symbols")?;
613
614 let (classes, tail) =
615 ClassIndex::parse(tail).map_err(anyhow::Error::from).context("parsing classes")?;
616
617 let (roles, tail) = SymbolList::<Role>::parse(tail)
618 .map_err(Into::<anyhow::Error>::into)
619 .context("parsing roles")?;
620
621 let (types, tail) =
622 TypeIndex::parse(tail).map_err(anyhow::Error::from).context("parsing types")?;
623
624 let (users, tail) = SymbolList::<User>::parse(tail)
625 .map_err(Into::<anyhow::Error>::into)
626 .context("parsing users")?;
627
628 let (conditional_booleans, tail) = SymbolList::<ConditionalBoolean>::parse(tail)
629 .map_err(Into::<anyhow::Error>::into)
630 .context("parsing conditional booleans")?;
631
632 let (sensitivities, tail) = SymbolList::<Sensitivity>::parse(tail)
633 .map_err(Into::<anyhow::Error>::into)
634 .context("parsing sensitivites")?;
635
636 let (categories, tail) = CategoryIndex::parse(tail)
637 .map_err(Into::<anyhow::Error>::into)
638 .context("parsing categories")?;
639
640 let (access_vector_rules, tail) = HashedArrayView::<AccessVectorRule>::parse(tail)
641 .map_err(Into::<anyhow::Error>::into)
642 .context("parsing access vector rules")?;
643
644 let (conditional_lists, tail) = SimpleArray::<ConditionalNode>::parse(tail)
645 .map_err(Into::<anyhow::Error>::into)
646 .context("parsing conditional lists")?;
647
648 let (role_transitions, tail) = RoleTransitions::parse(tail)
649 .map_err(Into::<anyhow::Error>::into)
650 .context("parsing role transitions")?;
651
652 let (role_allowlist, tail) = RoleAllows::parse(tail)
653 .map_err(Into::<anyhow::Error>::into)
654 .context("parsing role allow rules")?;
655
656 let (filename_transition_list, tail) = if policy_version_value >= 33 {
657 let (filename_transition_list, tail) = SimpleArray::<FilenameTransition>::parse(tail)
658 .map_err(Into::<anyhow::Error>::into)
659 .context("parsing standard filename transitions")?;
660 (FilenameTransitionList::PolicyVersionGeq33(filename_transition_list), tail)
661 } else {
662 let (filename_transition_list, tail) =
663 SimpleArray::<DeprecatedFilenameTransition>::parse(tail)
664 .map_err(Into::<anyhow::Error>::into)
665 .context("parsing deprecated filename transitions")?;
666 (FilenameTransitionList::PolicyVersionLeq32(filename_transition_list), tail)
667 };
668
669 let (initial_sids, tail) = SimpleArray::<InitialSid>::parse(tail)
670 .map_err(Into::<anyhow::Error>::into)
671 .context("parsing initial sids")?;
672
673 let (filesystems, tail) = SimpleArray::<NamedContextPair>::parse(tail)
674 .map_err(Into::<anyhow::Error>::into)
675 .context("parsing filesystem contexts")?;
676
677 let (ports, tail) = SimpleArray::<Port>::parse(tail)
678 .map_err(Into::<anyhow::Error>::into)
679 .context("parsing ports")?;
680
681 let (network_interfaces, tail) = SimpleArray::<NamedContextPair>::parse(tail)
682 .map_err(Into::<anyhow::Error>::into)
683 .context("parsing network interfaces")?;
684
685 let (nodes, tail) = SimpleArray::<Node>::parse(tail)
686 .map_err(Into::<anyhow::Error>::into)
687 .context("parsing nodes")?;
688
689 let (fs_uses, tail) = SimpleArray::<FsUse>::parse(tail)
690 .map_err(Into::<anyhow::Error>::into)
691 .context("parsing fs uses")?;
692
693 let (ipv6_nodes, tail) = SimpleArray::<IPv6Node>::parse(tail)
694 .map_err(Into::<anyhow::Error>::into)
695 .context("parsing ipv6 nodes")?;
696
697 let (infinitiband_partition_keys, infinitiband_end_ports, tail) =
698 if policy_version_value >= MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY {
699 let (infinity_band_partition_keys, tail) =
700 SimpleArray::<InfinitiBandPartitionKey>::parse(tail)
701 .map_err(Into::<anyhow::Error>::into)
702 .context("parsing infiniti band partition keys")?;
703 let (infinitiband_end_ports, tail) = SimpleArray::<InfinitiBandEndPort>::parse(tail)
704 .map_err(Into::<anyhow::Error>::into)
705 .context("parsing infiniti band end ports")?;
706 (Some(infinity_band_partition_keys), Some(infinitiband_end_ports), tail)
707 } else {
708 (None, None, tail)
709 };
710
711 let (generic_fs_contexts, tail) = CustomKeyHashedView::<GenericFsContext>::parse(tail)
712 .map_err(Into::<anyhow::Error>::into)
713 .context("parsing generic filesystem contexts")?;
714
715 let (range_transitions, tail) = SimpleArray::<RangeTransition>::parse(tail)
716 .map_err(Into::<anyhow::Error>::into)
717 .context("parsing range transitions")?;
718
719 let primary_names_count = types.primary_names_count();
720 let mut attribute_maps = Vec::with_capacity(primary_names_count as usize);
721 let mut tail = tail;
722
723 for i in 0..primary_names_count {
724 let (item, next_tail) = ExtensibleBitmap::parse(tail)
725 .map_err(Into::<anyhow::Error>::into)
726 .with_context(|| format!("parsing {}th attribute map", i))?;
727 attribute_maps.push(item);
728 tail = next_tail;
729 }
730 let tail = tail;
731 let attribute_maps = attribute_maps;
732
733 let excess_bytes = data.len() - tail.offset() as usize;
734
735 Ok((
736 ParsedPolicy {
737 data,
738 magic,
739 signature,
740 policy_version,
741 config,
742 counts,
743 policy_capabilities,
744 permissive_map,
745 common_symbols,
746 classes,
747 roles,
748 types,
749 users,
750 conditional_booleans,
751 sensitivities,
752 categories,
753 access_vector_rules,
754 conditional_lists,
755 role_transitions,
756 role_allowlist,
757 filename_transition_list,
758 initial_sids,
759 filesystems,
760 ports,
761 network_interfaces,
762 nodes,
763 fs_uses,
764 ipv6_nodes,
765 infinitiband_partition_keys,
766 infinitiband_end_ports,
767 generic_fs_contexts,
768 range_transitions,
769 attribute_maps,
770 },
771 excess_bytes,
772 ))
773}
774
775impl ParsedPolicy {
776 pub fn validate(&self) -> Result<(), anyhow::Error> {
777 let context = PolicyValidationContext { data: self.data.clone() };
778
779 self.magic
780 .validate(&context)
781 .map_err(Into::<anyhow::Error>::into)
782 .context("validating magic")?;
783 self.signature
784 .validate(&context)
785 .map_err(Into::<anyhow::Error>::into)
786 .context("validating signature")?;
787 self.policy_version
788 .validate(&context)
789 .map_err(Into::<anyhow::Error>::into)
790 .context("validating policy_version")?;
791 self.config
792 .validate(&context)
793 .map_err(Into::<anyhow::Error>::into)
794 .context("validating config")?;
795 self.counts
796 .validate(&context)
797 .map_err(Into::<anyhow::Error>::into)
798 .context("validating counts")?;
799 self.policy_capabilities
800 .validate(&context)
801 .map_err(Into::<anyhow::Error>::into)
802 .context("validating policy_capabilities")?;
803 self.permissive_map
804 .validate(&context)
805 .map_err(Into::<anyhow::Error>::into)
806 .context("validating permissive_map")?;
807 self.common_symbols
808 .validate(&context)
809 .map_err(Into::<anyhow::Error>::into)
810 .context("validating common_symbols")?;
811 self.classes
812 .validate(&context)
813 .map_err(Into::<anyhow::Error>::into)
814 .context("validating classes")?;
815 self.roles
816 .validate(&context)
817 .map_err(Into::<anyhow::Error>::into)
818 .context("validating roles")?;
819 self.types
820 .validate(&context)
821 .map_err(Into::<anyhow::Error>::into)
822 .context("validating types")?;
823 self.users
824 .validate(&context)
825 .map_err(Into::<anyhow::Error>::into)
826 .context("validating users")?;
827 self.conditional_booleans
828 .validate(&context)
829 .map_err(Into::<anyhow::Error>::into)
830 .context("validating conditional_booleans")?;
831 self.sensitivities
832 .validate(&context)
833 .map_err(Into::<anyhow::Error>::into)
834 .context("validating sensitivities")?;
835 self.categories
836 .validate(&context)
837 .map_err(Into::<anyhow::Error>::into)
838 .context("validating categories")?;
839 self.access_vector_rules
840 .validate(&context)
841 .map_err(Into::<anyhow::Error>::into)
842 .context("validating access_vector_rules")?;
843 self.conditional_lists
844 .validate(&context)
845 .map_err(Into::<anyhow::Error>::into)
846 .context("validating conditional_lists")?;
847 self.role_transitions
848 .validate(&context)
849 .map_err(Into::<anyhow::Error>::into)
850 .context("validating role_transitions")?;
851 self.role_allowlist
852 .validate(&context)
853 .map_err(Into::<anyhow::Error>::into)
854 .context("validating role_allowlist")?;
855 self.filename_transition_list
856 .validate(&context)
857 .map_err(Into::<anyhow::Error>::into)
858 .context("validating filename_transition_list")?;
859 self.initial_sids
860 .validate(&context)
861 .map_err(Into::<anyhow::Error>::into)
862 .context("validating initial_sids")?;
863 self.filesystems
864 .validate(&context)
865 .map_err(Into::<anyhow::Error>::into)
866 .context("validating filesystems")?;
867 self.ports
868 .validate(&context)
869 .map_err(Into::<anyhow::Error>::into)
870 .context("validating ports")?;
871 self.network_interfaces
872 .validate(&context)
873 .map_err(Into::<anyhow::Error>::into)
874 .context("validating network_interfaces")?;
875 self.nodes
876 .validate(&context)
877 .map_err(Into::<anyhow::Error>::into)
878 .context("validating nodes")?;
879 self.fs_uses
880 .validate(&context)
881 .map_err(Into::<anyhow::Error>::into)
882 .context("validating fs_uses")?;
883 self.ipv6_nodes
884 .validate(&context)
885 .map_err(Into::<anyhow::Error>::into)
886 .context("validating ipv6 nodes")?;
887 self.infinitiband_partition_keys
888 .validate(&context)
889 .map_err(Into::<anyhow::Error>::into)
890 .context("validating infinitiband_partition_keys")?;
891 self.infinitiband_end_ports
892 .validate(&context)
893 .map_err(Into::<anyhow::Error>::into)
894 .context("validating infinitiband_end_ports")?;
895 self.generic_fs_contexts
896 .validate(&context)
897 .map_err(Into::<anyhow::Error>::into)
898 .context("validating generic_fs_contexts")?;
899 self.range_transitions
900 .validate(&context)
901 .map_err(Into::<anyhow::Error>::into)
902 .context("validating range_transitions")?;
903 self.attribute_maps
904 .validate(&context)
905 .map_err(Into::<anyhow::Error>::into)
906 .context("validating attribute_maps")?;
907
908 let user_ids: HashSet<UserId> = self.users.data.iter().map(|x| x.id()).collect();
910 let role_ids: HashSet<RoleId> = self.roles.data.iter().map(|x| x.id()).collect();
911 let class_ids: HashSet<ClassId> =
912 self.classes.classes(&self.data).iter().map(|x| x.id()).collect();
913 let type_ids: HashSet<TypeId> = self.types.all_type_ids().collect();
914 let sensitivity_ids: HashSet<SensitivityId> =
915 self.sensitivities.data.iter().map(|x| x.id()).collect();
916 let category_ids: HashSet<CategoryId> =
917 self.categories.categories(&self.data).map(|x| x.id()).collect();
918
919 for user in &self.users.data {
923 self.validate_mls_range(
924 user.mls_range().low(),
925 user.mls_range().high(),
926 &sensitivity_ids,
927 &category_ids,
928 )?;
929 }
930
931 for initial_sid in &self.initial_sids.data {
935 let context = initial_sid.context();
936 validate_id(&user_ids, context.user_id(), "user")?;
937 validate_id(&role_ids, context.role_id(), "role")?;
938 validate_id(&type_ids, context.type_id(), "type")?;
939 self.validate_mls_range(
940 context.low_level(),
941 context.high_level(),
942 &sensitivity_ids,
943 &category_ids,
944 )?;
945 }
946
947 for fs_use in &self.fs_uses.data {
951 let context = fs_use.context();
952 validate_id(&user_ids, context.user_id(), "user")?;
953 validate_id(&role_ids, context.role_id(), "role")?;
954 validate_id(&type_ids, context.type_id(), "type")?;
955 self.validate_mls_range(
956 context.low_level(),
957 context.high_level(),
958 &sensitivity_ids,
959 &category_ids,
960 )?;
961 }
962
963 for transition in &self.role_transitions.data {
965 validate_id(&role_ids, transition.current_role(), "current_role")?;
966 validate_id(&type_ids, transition.type_(), "type")?;
967 validate_id(&class_ids, transition.class(), "class")?;
968 validate_id(&role_ids, transition.new_role(), "new_role")?;
969 }
970 for allow in &self.role_allowlist.data {
971 validate_id(&role_ids, allow.source_role(), "source_role")?;
972 validate_id(&role_ids, allow.new_role(), "new_role")?;
973 }
974
975 for access_vector_rule_view in self.access_vector_rules.iter(&self.data) {
977 let access_vector_rule = access_vector_rule_view.parse(&self.data);
978 if let Some(type_id) = access_vector_rule.new_type() {
979 validate_id(&type_ids, type_id, "new_type")?;
980 }
981 }
982
983 let initial_context = SecurityContext::new_from_policy_context(
986 self.initial_context(crate::InitialSid::Kernel),
987 );
988 for class in self.classes.classes(&self.data) {
989 for constraint in class.constraints() {
990 constraint
991 .constraint_expr()
992 .evaluate(&initial_context, &initial_context)
993 .map_err(Into::<anyhow::Error>::into)
994 .context("validating constraints")?;
995 }
996 }
997
998 Ok(())
1002 }
1003}
1004
1005fn validate_id<IdType: Debug + Eq + Hash>(
1006 id_set: &HashSet<IdType>,
1007 id: IdType,
1008 debug_kind: &'static str,
1009) -> Result<(), anyhow::Error> {
1010 if !id_set.contains(&id) {
1011 return Err(ValidateError::UnknownId { kind: debug_kind, id: format!("{:?}", id) }.into());
1012 }
1013 Ok(())
1014}