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_by_name(&self, name: &str) -> Option<&Type> {
380 self.types.data.iter().find(|x| x.name_bytes() == name.as_bytes())
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.clone(), 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 cursor = PolicyCursor::new(data.clone());
557 let policy_size = data.len();
558 if MAXIMUM_POLICY_SIZE <= policy_size {
559 return Err(anyhow::Error::from(ParseError::UnsupportedlyLarge {
560 observed: policy_size,
561 limit: MAXIMUM_POLICY_SIZE,
562 }));
563 }
564 let (policy, tail) = parse_policy_internal(cursor, data)?;
565 let excess_bytes = policy_size - tail.offset() as usize;
566 if excess_bytes > 0 {
567 return Err(anyhow::Error::from(ParseError::TrailingBytes { num_bytes: excess_bytes }));
568 }
569 Ok(policy)
570 }
571}
572
573fn parse_policy_internal(
575 bytes: PolicyCursor,
576 data: PolicyData,
577) -> Result<(ParsedPolicy, PolicyCursor), anyhow::Error> {
578 let tail = bytes;
579
580 let (magic, tail) = PolicyCursor::parse::<Magic>(tail).context("parsing magic")?;
581
582 let (signature, tail) =
583 Signature::parse(tail).map_err(Into::<anyhow::Error>::into).context("parsing signature")?;
584
585 let (policy_version, tail) =
586 PolicyCursor::parse::<PolicyVersion>(tail).context("parsing policy version")?;
587 let policy_version_value = policy_version.policy_version();
588
589 let (config, tail) = Config::parse(tail)
590 .map_err(Into::<anyhow::Error>::into)
591 .context("parsing policy config")?;
592
593 let (counts, tail) =
594 PolicyCursor::parse::<Counts>(tail).context("parsing high-level policy object counts")?;
595
596 let (policy_capabilities, tail) = ExtensibleBitmap::parse(tail)
597 .map_err(Into::<anyhow::Error>::into)
598 .context("parsing policy capabilities")?;
599
600 let (permissive_map, tail) = ExtensibleBitmap::parse(tail)
601 .map_err(Into::<anyhow::Error>::into)
602 .context("parsing permissive map")?;
603
604 let (common_symbols, tail) = SymbolList::<CommonSymbol>::parse(tail)
605 .map_err(Into::<anyhow::Error>::into)
606 .context("parsing common symbols")?;
607
608 let (classes, tail) = SymbolList::<Class>::parse(tail)
609 .map_err(Into::<anyhow::Error>::into)
610 .context("parsing classes")?;
611
612 let (roles, tail) = SymbolList::<Role>::parse(tail)
613 .map_err(Into::<anyhow::Error>::into)
614 .context("parsing roles")?;
615
616 let (types, tail) = SymbolList::<Type>::parse(tail)
617 .map_err(Into::<anyhow::Error>::into)
618 .context("parsing types")?;
619
620 let (users, tail) = SymbolList::<User>::parse(tail)
621 .map_err(Into::<anyhow::Error>::into)
622 .context("parsing users")?;
623
624 let (conditional_booleans, tail) = SymbolList::<ConditionalBoolean>::parse(tail)
625 .map_err(Into::<anyhow::Error>::into)
626 .context("parsing conditional booleans")?;
627
628 let (sensitivities, tail) = SymbolList::<Sensitivity>::parse(tail)
629 .map_err(Into::<anyhow::Error>::into)
630 .context("parsing sensitivites")?;
631
632 let (categories, tail) = SymbolList::<Category>::parse(tail)
633 .map_err(Into::<anyhow::Error>::into)
634 .context("parsing categories")?;
635
636 let (access_vector_rules, tail) = HashedArrayView::<AccessVectorRule>::parse(tail)
637 .map_err(Into::<anyhow::Error>::into)
638 .context("parsing access vector rules")?;
639
640 let (conditional_lists, tail) = SimpleArray::<ConditionalNodes>::parse(tail)
641 .map_err(Into::<anyhow::Error>::into)
642 .context("parsing conditional lists")?;
643
644 let (role_transitions, tail) = RoleTransitions::parse(tail)
645 .map_err(Into::<anyhow::Error>::into)
646 .context("parsing role transitions")?;
647
648 let (role_allowlist, tail) = RoleAllows::parse(tail)
649 .map_err(Into::<anyhow::Error>::into)
650 .context("parsing role allow rules")?;
651
652 let (filename_transition_list, tail) = if policy_version_value >= 33 {
653 let (filename_transition_list, tail) = SimpleArray::<FilenameTransitions>::parse(tail)
654 .map_err(Into::<anyhow::Error>::into)
655 .context("parsing standard filename transitions")?;
656 (FilenameTransitionList::PolicyVersionGeq33(filename_transition_list), tail)
657 } else {
658 let (filename_transition_list, tail) =
659 SimpleArray::<DeprecatedFilenameTransitions>::parse(tail)
660 .map_err(Into::<anyhow::Error>::into)
661 .context("parsing deprecated filename transitions")?;
662 (FilenameTransitionList::PolicyVersionLeq32(filename_transition_list), tail)
663 };
664
665 let (initial_sids, tail) = SimpleArray::<InitialSids>::parse(tail)
666 .map_err(Into::<anyhow::Error>::into)
667 .context("parsing initial sids")?;
668
669 let (filesystems, tail) = SimpleArray::<NamedContextPairs>::parse(tail)
670 .map_err(Into::<anyhow::Error>::into)
671 .context("parsing filesystem contexts")?;
672
673 let (ports, tail) = SimpleArray::<Ports>::parse(tail)
674 .map_err(Into::<anyhow::Error>::into)
675 .context("parsing ports")?;
676
677 let (network_interfaces, tail) = SimpleArray::<NamedContextPairs>::parse(tail)
678 .map_err(Into::<anyhow::Error>::into)
679 .context("parsing network interfaces")?;
680
681 let (nodes, tail) = SimpleArray::<Nodes>::parse(tail)
682 .map_err(Into::<anyhow::Error>::into)
683 .context("parsing nodes")?;
684
685 let (fs_uses, tail) = SimpleArray::<FsUses>::parse(tail)
686 .map_err(Into::<anyhow::Error>::into)
687 .context("parsing fs uses")?;
688
689 let (ipv6_nodes, tail) = SimpleArray::<IPv6Nodes>::parse(tail)
690 .map_err(Into::<anyhow::Error>::into)
691 .context("parsing ipv6 nodes")?;
692
693 let (infinitiband_partition_keys, infinitiband_end_ports, tail) =
694 if policy_version_value >= MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY {
695 let (infinity_band_partition_keys, tail) =
696 SimpleArray::<InfinitiBandPartitionKeys>::parse(tail)
697 .map_err(Into::<anyhow::Error>::into)
698 .context("parsing infiniti band partition keys")?;
699 let (infinitiband_end_ports, tail) = SimpleArray::<InfinitiBandEndPorts>::parse(tail)
700 .map_err(Into::<anyhow::Error>::into)
701 .context("parsing infiniti band end ports")?;
702 (Some(infinity_band_partition_keys), Some(infinitiband_end_ports), tail)
703 } else {
704 (None, None, tail)
705 };
706
707 let (generic_fs_contexts, tail) = SimpleArray::<GenericFsContexts>::parse(tail)
708 .map_err(Into::<anyhow::Error>::into)
709 .context("parsing generic filesystem contexts")?;
710
711 let (range_transitions, tail) = SimpleArray::<RangeTransitions>::parse(tail)
712 .map_err(Into::<anyhow::Error>::into)
713 .context("parsing range transitions")?;
714
715 let primary_names_count = types.metadata.primary_names_count();
716 let mut attribute_maps = Vec::with_capacity(primary_names_count as usize);
717 let mut tail = tail;
718 for i in 0..primary_names_count {
719 let offset = U24::try_from(tail.offset()).expect("Policy offsets ought fit in U24!");
720 let (_, next_tail) = ExtensibleBitmap::parse(tail)
721 .map_err(Into::<anyhow::Error>::into)
722 .with_context(|| format!("parsing {}th attribute map", i))?;
723 attribute_maps.push(offset);
724 tail = next_tail;
725 }
726
727 Ok((
728 ParsedPolicy {
729 data,
730 magic,
731 signature,
732 policy_version,
733 config,
734 counts,
735 policy_capabilities,
736 permissive_map,
737 common_symbols,
738 classes,
739 roles,
740 types,
741 users,
742 conditional_booleans,
743 sensitivities,
744 categories,
745 access_vector_rules,
746 conditional_lists,
747 role_transitions,
748 role_allowlist,
749 filename_transition_list,
750 initial_sids,
751 filesystems,
752 ports,
753 network_interfaces,
754 nodes,
755 fs_uses,
756 ipv6_nodes,
757 infinitiband_partition_keys,
758 infinitiband_end_ports,
759 generic_fs_contexts,
760 range_transitions,
761 attribute_maps,
762 },
763 tail,
764 ))
765}
766
767impl ParsedPolicy {
768 pub fn validate(&self) -> Result<(), anyhow::Error> {
769 let mut context = PolicyValidationContext { data: self.data.clone() };
770
771 self.magic
772 .validate(&mut context)
773 .map_err(Into::<anyhow::Error>::into)
774 .context("validating magic")?;
775 self.signature
776 .validate(&mut context)
777 .map_err(Into::<anyhow::Error>::into)
778 .context("validating signature")?;
779 self.policy_version
780 .validate(&mut context)
781 .map_err(Into::<anyhow::Error>::into)
782 .context("validating policy_version")?;
783 self.config
784 .validate(&mut context)
785 .map_err(Into::<anyhow::Error>::into)
786 .context("validating config")?;
787 self.counts
788 .validate(&mut context)
789 .map_err(Into::<anyhow::Error>::into)
790 .context("validating counts")?;
791 self.policy_capabilities
792 .validate(&mut context)
793 .map_err(Into::<anyhow::Error>::into)
794 .context("validating policy_capabilities")?;
795 self.permissive_map
796 .validate(&mut context)
797 .map_err(Into::<anyhow::Error>::into)
798 .context("validating permissive_map")?;
799 self.common_symbols
800 .validate(&mut context)
801 .map_err(Into::<anyhow::Error>::into)
802 .context("validating common_symbols")?;
803 self.classes
804 .validate(&mut context)
805 .map_err(Into::<anyhow::Error>::into)
806 .context("validating classes")?;
807 self.roles
808 .validate(&mut context)
809 .map_err(Into::<anyhow::Error>::into)
810 .context("validating roles")?;
811 self.types
812 .validate(&mut context)
813 .map_err(Into::<anyhow::Error>::into)
814 .context("validating types")?;
815 self.users
816 .validate(&mut context)
817 .map_err(Into::<anyhow::Error>::into)
818 .context("validating users")?;
819 self.conditional_booleans
820 .validate(&mut context)
821 .map_err(Into::<anyhow::Error>::into)
822 .context("validating conditional_booleans")?;
823 self.sensitivities
824 .validate(&mut context)
825 .map_err(Into::<anyhow::Error>::into)
826 .context("validating sensitivities")?;
827 self.categories
828 .validate(&mut context)
829 .map_err(Into::<anyhow::Error>::into)
830 .context("validating categories")?;
831 self.access_vector_rules
832 .validate(&mut context)
833 .map_err(Into::<anyhow::Error>::into)
834 .context("validating access_vector_rules")?;
835 self.conditional_lists
836 .validate(&mut context)
837 .map_err(Into::<anyhow::Error>::into)
838 .context("validating conditional_lists")?;
839 self.role_transitions
840 .validate(&mut context)
841 .map_err(Into::<anyhow::Error>::into)
842 .context("validating role_transitions")?;
843 self.role_allowlist
844 .validate(&mut context)
845 .map_err(Into::<anyhow::Error>::into)
846 .context("validating role_allowlist")?;
847 self.filename_transition_list
848 .validate(&mut context)
849 .map_err(Into::<anyhow::Error>::into)
850 .context("validating filename_transition_list")?;
851 self.initial_sids
852 .validate(&mut context)
853 .map_err(Into::<anyhow::Error>::into)
854 .context("validating initial_sids")?;
855 self.filesystems
856 .validate(&mut context)
857 .map_err(Into::<anyhow::Error>::into)
858 .context("validating filesystems")?;
859 self.ports
860 .validate(&mut context)
861 .map_err(Into::<anyhow::Error>::into)
862 .context("validating ports")?;
863 self.network_interfaces
864 .validate(&mut context)
865 .map_err(Into::<anyhow::Error>::into)
866 .context("validating network_interfaces")?;
867 self.nodes
868 .validate(&mut context)
869 .map_err(Into::<anyhow::Error>::into)
870 .context("validating nodes")?;
871 self.fs_uses
872 .validate(&mut context)
873 .map_err(Into::<anyhow::Error>::into)
874 .context("validating fs_uses")?;
875 self.ipv6_nodes
876 .validate(&mut context)
877 .map_err(Into::<anyhow::Error>::into)
878 .context("validating ipv6 nodes")?;
879 self.infinitiband_partition_keys
880 .validate(&mut context)
881 .map_err(Into::<anyhow::Error>::into)
882 .context("validating infinitiband_partition_keys")?;
883 self.infinitiband_end_ports
884 .validate(&mut context)
885 .map_err(Into::<anyhow::Error>::into)
886 .context("validating infinitiband_end_ports")?;
887 self.generic_fs_contexts
888 .validate(&mut context)
889 .map_err(Into::<anyhow::Error>::into)
890 .context("validating generic_fs_contexts")?;
891 self.range_transitions
892 .validate(&mut context)
893 .map_err(Into::<anyhow::Error>::into)
894 .context("validating range_transitions")?;
895 for attribute_map_offset in &self.attribute_maps {
896 self.reparse_attribute_map(*attribute_map_offset)
897 .validate(&mut context)
898 .map_err(anyhow::Error::from)
899 .context("validating attribute_maps")?;
900 }
901
902 let user_ids: HashSet<UserId> = self.users.data.iter().map(|x| x.id()).collect();
904 let role_ids: HashSet<RoleId> = self.roles.data.iter().map(|x| x.id()).collect();
905 let class_ids: HashSet<ClassId> = self.classes.data.iter().map(|x| x.id()).collect();
906 let type_ids: HashSet<TypeId> = self.types.data.iter().map(|x| x.id()).collect();
907 let sensitivity_ids: HashSet<SensitivityId> =
908 self.sensitivities.data.iter().map(|x| x.id()).collect();
909 let category_ids: HashSet<CategoryId> =
910 self.categories.data.iter().map(|x| x.id()).collect();
911
912 for user in &self.users.data {
916 self.validate_mls_range(
917 user.mls_range().low(),
918 user.mls_range().high(),
919 &sensitivity_ids,
920 &category_ids,
921 )?;
922 }
923
924 for initial_sid in &self.initial_sids.data {
928 let context = initial_sid.context();
929 validate_id(&user_ids, context.user_id(), "user")?;
930 validate_id(&role_ids, context.role_id(), "role")?;
931 validate_id(&type_ids, context.type_id(), "type")?;
932 self.validate_mls_range(
933 context.low_level(),
934 context.high_level(),
935 &sensitivity_ids,
936 &category_ids,
937 )?;
938 }
939
940 for fs_use in &self.fs_uses.data {
944 let context = fs_use.context();
945 validate_id(&user_ids, context.user_id(), "user")?;
946 validate_id(&role_ids, context.role_id(), "role")?;
947 validate_id(&type_ids, context.type_id(), "type")?;
948 self.validate_mls_range(
949 context.low_level(),
950 context.high_level(),
951 &sensitivity_ids,
952 &category_ids,
953 )?;
954 }
955
956 for transition in &self.role_transitions.data {
958 validate_id(&role_ids, transition.current_role(), "current_role")?;
959 validate_id(&type_ids, transition.type_(), "type")?;
960 validate_id(&class_ids, transition.class(), "class")?;
961 validate_id(&role_ids, transition.new_role(), "new_role")?;
962 }
963 for allow in &self.role_allowlist.data {
964 validate_id(&role_ids, allow.source_role(), "source_role")?;
965 validate_id(&role_ids, allow.new_role(), "new_role")?;
966 }
967
968 for access_vector_rule_view in self.access_vector_rules.iter(&self.data) {
970 let access_vector_rule = access_vector_rule_view.parse(&self.data);
971 if let Some(type_id) = access_vector_rule.new_type() {
972 validate_id(&type_ids, type_id, "new_type")?;
973 }
974 }
975
976 let initial_context = SecurityContext::new_from_policy_context(
979 self.initial_context(crate::InitialSid::Kernel),
980 );
981 for class in self.classes() {
982 for constraint in class.constraints() {
983 constraint
984 .constraint_expr()
985 .evaluate(&initial_context, &initial_context)
986 .map_err(Into::<anyhow::Error>::into)
987 .context("validating constraints")?;
988 }
989 }
990
991 Ok(())
995 }
996}
997
998fn validate_id<IdType: Debug + Eq + Hash>(
999 id_set: &HashSet<IdType>,
1000 id: IdType,
1001 debug_kind: &'static str,
1002) -> Result<(), anyhow::Error> {
1003 if !id_set.contains(&id) {
1004 return Err(ValidateError::UnknownId { kind: debug_kind, id: format!("{:?}", id) }.into());
1005 }
1006 Ok(())
1007}