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