1pub mod arrays;
6pub mod error;
7pub mod index;
8pub mod metadata;
9pub mod parsed_policy;
10pub mod parser;
11pub mod view;
12
13mod constraints;
14mod extensible_bitmap;
15mod security_context;
16
17pub use crate::new_policy::{
18 AccessDecision, AccessVectorRules, SELINUX_AVD_FLAGS_PERMISSIVE, XpermsBitmap,
19};
20pub use arrays::FsUseType;
21pub use index::FsUseLabelAndType;
22pub use parser::PolicyCursor;
23pub use security_context::{SecurityContext, SecurityContextError};
24
25use crate::new_policy::traits::Serialize as _;
26pub use crate::new_policy::traits::{HasName, HasPolicyId, PolicyId};
27pub use crate::new_policy::{
28 AccessVector, CategoryId, ClassId, HandleUnknown, MlsLevel, MlsRange, POLICYDB_VERSION_MAX,
29 PermissionId, RoleId, SensitivityId, TypeId, User, UserId,
30};
31use crate::{ClassPermission, KernelClass, NullessByteStr, ObjectClass, new_policy as new};
32use index::PolicyIndex;
33use parsed_policy::ParsedPolicy;
34use parser::PolicyData;
35
36use anyhow::Context as _;
37use std::fmt::Debug;
38use std::num::NonZeroU32;
39use std::ops::Deref;
40
41use std::sync::Arc;
42use zerocopy::{
43 FromBytes, Immutable, KnownLayout, Ref, SplitByteSlice, Unaligned, little_endian as le,
44};
45
46impl<T, Tag> Parse for crate::new_policy::IdType<T, Tag>
47where
48 crate::new_policy::IdType<T, Tag>: crate::new_policy::traits::PolicyId,
49{
50 type Error = error::ParseError;
51
52 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
53 let (id_val, tail) = PolicyCursor::parse::<le::U32>(bytes)?;
54 let id = Self::try_from(id_val.get())
55 .map_err(|_| error::ParseError::InvalidId { value: id_val.get() })?;
56 Ok((id, tail))
57 }
58}
59
60impl<T, Tag> Validate for crate::new_policy::IdType<T, Tag>
61where
62 crate::new_policy::IdType<T, Tag>: crate::new_policy::traits::PolicyId,
63{
64 type Error = anyhow::Error;
65
66 fn validate(&self, _context: &PolicyValidationContext) -> Result<(), Self::Error> {
67 Ok(())
68 }
69}
70
71#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
77pub enum XpermsKind {
78 Ioctl,
79 Nlmsg,
80}
81
82#[derive(Debug, Clone, PartialEq)]
87pub struct XpermsAccessDecision {
88 pub allow: XpermsBitmap,
89 pub auditallow: XpermsBitmap,
90 pub auditdeny: XpermsBitmap,
91}
92
93impl XpermsAccessDecision {
94 pub const DENY_ALL: Self = Self {
95 allow: XpermsBitmap::NONE,
96 auditallow: XpermsBitmap::NONE,
97 auditdeny: XpermsBitmap::ALL,
98 };
99 pub const ALLOW_ALL: Self = Self {
100 allow: XpermsBitmap::ALL,
101 auditallow: XpermsBitmap::NONE,
102 auditdeny: XpermsBitmap::ALL,
103 };
104}
105
106pub fn parse_policy_by_value(binary_policy: Vec<u8>) -> Result<Unvalidated, anyhow::Error> {
115 let policy_data: PolicyData = Arc::from(binary_policy);
116 let policy = ParsedPolicy::parse(policy_data).context("parsing policy")?;
117 Ok(Unvalidated(policy))
118}
119
120#[derive(Debug)]
121pub struct Policy(PolicyIndex);
122
123impl Deref for Policy {
124 type Target = PolicyIndex;
125
126 fn deref(&self) -> &Self::Target {
127 &self.0
128 }
129}
130
131impl Policy {
132 pub fn serialize(&self) -> PolicyData {
134 let mut bytes = Vec::new();
135 self.0.serialize(&mut bytes).expect("serialization of new_policy should succeed");
136 std::sync::Arc::from(bytes)
137 }
138
139 pub fn conditional_booleans<'a>(&'a self) -> Vec<(&'a [u8], bool)> {
140 self.0
141 .conditional_booleans()
142 .iter()
143 .map(|boolean| (boolean.name(), boolean.active()))
144 .collect()
145 }
146
147 pub fn find_class_permissions_by_name(
152 &self,
153 class_name: &str,
154 ) -> Result<Vec<(PermissionId, Vec<u8>)>, ()> {
155 let classes = self.classes();
156 let class = classes.get_by_name(class_name.as_bytes()).ok_or(())?;
157 let owned_permissions = class.permissions();
158
159 let mut result: Vec<_> = owned_permissions
160 .iter()
161 .map(|permission| (permission.id(), permission.name().to_vec()))
162 .collect();
163
164 if class.common_name().is_empty() {
166 return Ok(result);
167 }
168
169 let common_symbol_permissions =
170 self.common_symbols().get_by_name(class.common_name()).ok_or(())?.permissions();
171
172 result.append(
173 &mut common_symbol_permissions
174 .iter()
175 .map(|permission| (permission.id(), permission.name().to_vec()))
176 .collect(),
177 );
178
179 Ok(result)
180 }
181
182 pub fn fs_use_label_and_type(&self, fs_type: NullessByteStr<'_>) -> Option<FsUseLabelAndType> {
185 self.0.fs_use_label_and_type(fs_type)
186 }
187
188 pub fn genfscon_label_for_fs_and_path(
191 &self,
192 fs_type: NullessByteStr<'_>,
193 node_path: NullessByteStr<'_>,
194 class_id: Option<KernelClass>,
195 ) -> Option<SecurityContext> {
196 self.0.genfscon_label_for_fs_and_path(fs_type, node_path, class_id)
197 }
198
199 pub fn initial_context(&self, id: crate::InitialSid) -> security_context::SecurityContext {
202 self.0.initial_context(id)
203 }
204
205 pub fn parse_security_context(
207 &self,
208 security_context: NullessByteStr<'_>,
209 ) -> Result<security_context::SecurityContext, security_context::SecurityContextError> {
210 security_context::SecurityContext::from_string(&self.0, security_context)
211 }
212
213 pub fn validate_security_context(
215 &self,
216 security_context: &SecurityContext,
217 ) -> Result<(), SecurityContextError> {
218 security_context.validate(&self.0)
219 }
220
221 pub fn serialize_security_context(&self, security_context: &SecurityContext) -> Vec<u8> {
223 security_context.to_string(&self.0)
224 }
225
226 pub fn compute_create_context_with_name(
234 &self,
235 source: &SecurityContext,
236 target: &SecurityContext,
237 class: impl Into<ObjectClass>,
238 name: NullessByteStr<'_>,
239 ) -> Option<SecurityContext> {
240 self.0.compute_create_context_with_name(source, target, class.into(), name)
241 }
242
243 pub fn compute_create_context(
261 &self,
262 source: &SecurityContext,
263 target: &SecurityContext,
264 class: impl Into<ObjectClass>,
265 ) -> SecurityContext {
266 self.0.compute_create_context(source, target, class.into())
267 }
268
269 pub fn compute_access_decision(
279 &self,
280 source_context: &SecurityContext,
281 target_context: &SecurityContext,
282 object_class: impl Into<ObjectClass>,
283 ) -> AccessDecision {
284 if let Some(target_class) = self.0.class(object_class.into()) {
285 self.0.compute_access_decision(source_context, target_context, &target_class)
286 } else {
287 let mut decision = AccessDecision::allow(AccessVector::NONE);
288 if self.is_permissive(source_context.type_()) {
289 decision.flags |= SELINUX_AVD_FLAGS_PERMISSIVE;
290 }
291 decision
292 }
293 }
294
295 pub fn compute_xperms_access_decision(
299 &self,
300 xperms_kind: XpermsKind,
301 source_context: &SecurityContext,
302 target_context: &SecurityContext,
303 object_class: impl Into<ObjectClass>,
304 xperms_prefix: u8,
305 ) -> XpermsAccessDecision {
306 if let Some(target_class) = self.0.class(object_class.into()) {
307 self.0.compute_xperms_access_decision(
308 xperms_kind,
309 source_context,
310 target_context,
311 &target_class,
312 xperms_prefix,
313 )
314 } else {
315 XpermsAccessDecision::DENY_ALL
316 }
317 }
318
319 pub fn is_bounded_by(&self, bounded_type: TypeId, parent_type: TypeId) -> bool {
320 self.0.types().get_by_id(bounded_type).unwrap().bounded_by() == Some(parent_type)
321 }
322
323 pub fn is_permissive(&self, type_: TypeId) -> bool {
325 self.0.permissive_map().contains(type_)
326 }
327}
328
329impl AccessVectorComputer for Policy {
330 fn access_decision_to_kernel_access_decision(
331 &self,
332 class: KernelClass,
333 av: AccessDecision,
334 ) -> KernelAccessDecision {
335 let mut kernel_allow;
336 let mut kernel_audit;
337 if self.0.handle_unknown() == HandleUnknown::Allow {
340 kernel_allow = 0xffffffffu32;
342 kernel_audit = 0u32;
343 } else {
344 kernel_allow = 0u32;
346 kernel_audit = 0xffffffffu32;
347 }
348
349 let decision_allow = av.allow;
350 let decision_audit = (av.allow & av.auditallow) | (!av.allow & av.auditdeny);
351 for permission in class.permissions() {
352 if let Some(permission_access_vector) =
353 self.0.kernel_permission_to_access_vector(permission.clone())
354 {
355 let bit = 1 << permission.id();
358 let allow = decision_allow & permission_access_vector == permission_access_vector;
359 let audit = decision_audit & permission_access_vector == permission_access_vector;
360 kernel_allow = (kernel_allow & !bit) | ((allow as u32) << permission.id());
361 kernel_audit = (kernel_audit & !bit) | ((audit as u32) << permission.id());
362 }
363 }
364 KernelAccessDecision {
365 allow: AccessVector::from(kernel_allow),
366 audit: AccessVector::from(kernel_audit),
367 flags: av.flags,
368 todo_bug: av.todo_bug,
369 }
370 }
371}
372
373pub struct Unvalidated(ParsedPolicy);
375
376impl Unvalidated {
377 pub fn validate(self) -> Result<Policy, anyhow::Error> {
378 self.0.validate().context("validating parsed policy")?;
379 let index = PolicyIndex::new(self.0).context("building index")?;
380 Ok(Policy(index))
381 }
382}
383
384#[derive(Clone, Copy, Debug, PartialEq, Eq)]
385pub struct KernelAccessDecision {
386 pub allow: AccessVector,
387 pub audit: AccessVector,
388 pub flags: u32,
389 pub todo_bug: Option<NonZeroU32>,
390}
391
392pub trait AccessVectorComputer {
395 fn access_decision_to_kernel_access_decision(
402 &self,
403 class: KernelClass,
404 av: AccessDecision,
405 ) -> KernelAccessDecision;
406}
407
408pub trait Parse: Sized {
410 type Error: Into<anyhow::Error>;
413
414 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error>;
417}
418
419pub(super) struct PolicyValidationContext {
421 pub(super) data: PolicyData,
423
424 pub(super) need_init_sid: bool,
426
427 pub(super) new_policy: Arc<new::NewPolicy>,
429}
430
431pub(super) trait Validate {
433 type Error: Into<anyhow::Error>;
436
437 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error>;
439}
440
441pub(super) trait ValidateArray<M, D> {
442 type Error: Into<anyhow::Error>;
445
446 fn validate_array(
448 context: &PolicyValidationContext,
449 metadata: &M,
450 items: &[D],
451 ) -> Result<(), Self::Error>;
452}
453
454pub(super) trait Counted {
456 fn count(&self) -> u32;
458}
459
460impl<T: Validate> Validate for Option<T> {
461 type Error = <T as Validate>::Error;
462
463 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
464 match self {
465 Some(value) => value.validate(context),
466 None => Ok(()),
467 }
468 }
469}
470
471impl<T: Validate> Validate for Vec<T> {
472 type Error = <T as Validate>::Error;
473
474 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
475 for item in self {
476 item.validate(context)?;
477 }
478 Ok(())
479 }
480}
481
482impl Validate for le::U32 {
483 type Error = anyhow::Error;
484
485 fn validate(&self, _context: &PolicyValidationContext) -> Result<(), Self::Error> {
488 Ok(())
489 }
490}
491
492impl Validate for u8 {
493 type Error = anyhow::Error;
494
495 fn validate(&self, _context: &PolicyValidationContext) -> Result<(), Self::Error> {
498 Ok(())
499 }
500}
501
502impl<B: SplitByteSlice, T: Validate + FromBytes + KnownLayout + Immutable> Validate for Ref<B, T> {
503 type Error = <T as Validate>::Error;
504
505 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
506 self.deref().validate(context)
507 }
508}
509
510impl<B: SplitByteSlice, T: Counted + FromBytes + KnownLayout + Immutable> Counted for Ref<B, T> {
511 fn count(&self) -> u32 {
512 self.deref().count()
513 }
514}
515
516#[derive(Clone, Debug, PartialEq)]
518struct Array<M, T> {
519 metadata: M,
520 data: Vec<T>,
521}
522
523impl<M: Counted + Parse, T: Parse> Parse for Array<M, T> {
524 type Error = anyhow::Error;
527
528 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
530 let tail = bytes;
531
532 let (metadata, tail) = M::parse(tail).map_err(Into::<anyhow::Error>::into)?;
533
534 let count = metadata.count() as usize;
535 let mut data = Vec::with_capacity(count);
536 let mut cur_tail = tail;
537 for _ in 0..count {
538 let (item, next_tail) = T::parse(cur_tail).map_err(Into::<anyhow::Error>::into)?;
539 data.push(item);
540 cur_tail = next_tail;
541 }
542 let tail = cur_tail;
543
544 let array = Self { metadata, data };
545
546 Ok((array, tail))
547 }
548}
549
550impl<T: Clone + Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned> Parse for T {
551 type Error = anyhow::Error;
552
553 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
554 bytes.parse::<T>().map_err(anyhow::Error::from)
555 }
556}
557
558macro_rules! array_type {
562 ($type_name:ident, $metadata_type:ty, $data_type:ty, $metadata_type_name:expr, $data_type_name:expr) => {
563 #[doc = "An [`Array`] with [`"]
564 #[doc = $metadata_type_name]
565 #[doc = "`] metadata and [`"]
566 #[doc = $data_type_name]
567 #[doc = "`] data items."]
568 #[derive(Debug, PartialEq)]
569 pub(super) struct $type_name(super::Array<$metadata_type, $data_type>);
570
571 impl std::ops::Deref for $type_name {
572 type Target = super::Array<$metadata_type, $data_type>;
573
574 fn deref(&self) -> &Self::Target {
575 &self.0
576 }
577 }
578
579 impl super::Parse for $type_name
580 where
581 super::Array<$metadata_type, $data_type>: super::Parse,
582 {
583 type Error = <Array<$metadata_type, $data_type> as super::Parse>::Error;
584
585 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
586 let (array, tail) = Array::<$metadata_type, $data_type>::parse(bytes)?;
587 Ok((Self(array), tail))
588 }
589 }
590 };
591
592 ($type_name:ident, $metadata_type:ty, $data_type:ty) => {
593 array_type!(
594 $type_name,
595 $metadata_type,
596 $data_type,
597 stringify!($metadata_type),
598 stringify!($data_type)
599 );
600 };
601}
602
603pub(super) use array_type;
604
605macro_rules! array_type_validate_deref_both {
606 ($type_name:ident) => {
607 impl Validate for $type_name {
608 type Error = anyhow::Error;
609
610 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
611 let metadata = &self.metadata;
612 metadata.validate(context)?;
613
614 self.data.validate(context).map_err(Into::<anyhow::Error>::into)?;
615
616 Self::validate_array(context, metadata, &self.data)
617 .map_err(Into::<anyhow::Error>::into)
618 }
619 }
620 };
621}
622
623pub(super) use array_type_validate_deref_both;
624
625#[cfg(test)]
626pub(super) mod testing {
627 use super::error::ParseError;
628
629 pub(super) fn as_parse_error(error: anyhow::Error) -> ParseError {
631 error.downcast::<ParseError>().expect("parse error")
632 }
633}
634
635#[cfg(test)]
636pub(super) mod tests {
637 use super::security_context::SecurityContext;
638 use super::{
639 AccessVector, ClassId, HandleUnknown, Policy, TypeId, XpermsAccessDecision, XpermsBitmap,
640 XpermsKind, parse_policy_by_value,
641 };
642 use crate::new_policy::traits::HasPolicyId;
643 use crate::{FileClass, InitialSid, KernelClass};
644
645 use anyhow::Context as _;
646 use serde::Deserialize;
647 use std::ops::Deref;
648
649 fn is_explicitly_allowed(
657 policy: &Policy,
658 source_type: TypeId,
659 target_type: TypeId,
660 target_class: &str,
661 permission: &str,
662 ) -> bool {
663 let classes = policy.classes();
664 let class = classes.get_by_name(target_class.as_bytes()).expect("class not found");
665 let class_permissions = policy
666 .find_class_permissions_by_name(target_class)
667 .expect("class permissions not found");
668 let (permission_id, _) = class_permissions
669 .iter()
670 .find(|(_, name)| permission.as_bytes() == name)
671 .expect("permission not found");
672 let permission_bit = AccessVector::from(*permission_id);
673 let access_decision = policy.0.compute_explicitly_allowed(source_type, target_type, class);
674 permission_bit == access_decision.allow & permission_bit
675 }
676
677 #[derive(Debug, Deserialize)]
678 struct Expectations {
679 expected_policy_version: u32,
680 expected_handle_unknown: LocalHandleUnknown,
681 }
682
683 #[derive(Debug, Deserialize, PartialEq)]
684 #[serde(rename_all = "snake_case")]
685 enum LocalHandleUnknown {
686 Deny,
687 Reject,
688 Allow,
689 }
690
691 impl PartialEq<HandleUnknown> for LocalHandleUnknown {
692 fn eq(&self, other: &HandleUnknown) -> bool {
693 match self {
694 LocalHandleUnknown::Deny => *other == HandleUnknown::Deny,
695 LocalHandleUnknown::Reject => *other == HandleUnknown::Reject,
696 LocalHandleUnknown::Allow => *other == HandleUnknown::Allow,
697 }
698 }
699 }
700
701 fn xperms_bitmap_from_elements(elements: &[u8]) -> XpermsBitmap {
704 let mut bitmap = [0u64; 4];
705 for element in elements {
706 let block_index = (*element as usize) / 64;
707 let bit_index = (*element as usize) % 64;
708 bitmap[block_index] |= 1u64 << bit_index;
709 }
710 XpermsBitmap::new(bitmap)
711 }
712
713 #[test]
714 fn known_policies() {
715 let policies_and_expectations = [
716 [
717 b"testdata/policies/emulator".to_vec(),
718 include_bytes!("../../testdata/policies/emulator").to_vec(),
719 include_bytes!("../../testdata/expectations/emulator").to_vec(),
720 ],
721 [
722 b"testdata/policies/selinux_testsuite".to_vec(),
723 include_bytes!("../../testdata/policies/selinux_testsuite").to_vec(),
724 include_bytes!("../../testdata/expectations/selinux_testsuite").to_vec(),
725 ],
726 ];
727
728 for [policy_path, policy_bytes, expectations_bytes] in policies_and_expectations {
729 let expectations = serde_json5::from_reader::<_, Expectations>(
730 &mut std::io::Cursor::new(expectations_bytes),
731 )
732 .expect("deserialize expectations");
733
734 let unvalidated_policy =
737 parse_policy_by_value(policy_bytes.clone()).expect("parse policy");
738
739 let policy = unvalidated_policy
740 .validate()
741 .with_context(|| {
742 format!(
743 "policy path: {:?}",
744 std::str::from_utf8(policy_path.as_slice()).unwrap()
745 )
746 })
747 .expect("validate policy");
748
749 assert_eq!(expectations.expected_policy_version, policy.policy_version());
750 assert_eq!(expectations.expected_handle_unknown, policy.handle_unknown());
751
752 let binary_policy = policy.serialize();
754 assert_eq!(&policy_bytes, binary_policy.deref());
755 }
756 }
757
758 #[test]
759 fn policy_lookup() {
760 let policy_bytes = include_bytes!("../../testdata/policies/selinux_testsuite");
761 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
762 let policy = policy.validate().expect("validate selinux testsuite policy");
763
764 let unconfined_t = policy.types().get_by_name(b"unconfined_t").expect("look up type").id();
765
766 assert!(is_explicitly_allowed(&policy, unconfined_t, unconfined_t, "process", "fork",));
767 }
768
769 #[test]
770 fn initial_contexts() {
771 let policy_bytes =
772 include_bytes!("../../testdata/micro_policies/multiple_levels_and_categories_policy");
773 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
774 let policy = policy.validate().expect("validate policy");
775
776 let kernel_context = policy.initial_context(InitialSid::Kernel);
777 assert_eq!(
778 policy.serialize_security_context(&kernel_context),
779 b"user0:object_r:type0:s0:c0-s1:c0.c2,c4"
780 )
781 }
782
783 #[test]
784 fn explicit_allow_type_type() {
785 let policy_bytes =
786 include_bytes!("../../testdata/micro_policies/allow_a_t_b_t_class0_perm0_policy");
787 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
788 let policy = policy.validate().expect("validate policy");
789
790 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
791 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
792
793 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
794 }
795
796 #[test]
797 fn no_explicit_allow_type_type() {
798 let policy_bytes =
799 include_bytes!("../../testdata/micro_policies/no_allow_a_t_b_t_class0_perm0_policy");
800 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
801 let policy = policy.validate().expect("validate policy");
802
803 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
804 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
805
806 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
807 }
808
809 #[test]
810 fn explicit_allow_type_attr() {
811 let policy_bytes =
812 include_bytes!("../../testdata/micro_policies/allow_a_t_b_attr_class0_perm0_policy");
813 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
814 let policy = policy.validate().expect("validate policy");
815
816 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
817 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
818
819 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
820 }
821
822 #[test]
823 fn no_explicit_allow_type_attr() {
824 let policy_bytes =
825 include_bytes!("../../testdata/micro_policies/no_allow_a_t_b_attr_class0_perm0_policy");
826 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
827 let policy = policy.validate().expect("validate policy");
828
829 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
830 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
831
832 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
833 }
834
835 #[test]
836 fn explicit_allow_attr_attr() {
837 let policy_bytes =
838 include_bytes!("../../testdata/micro_policies/allow_a_attr_b_attr_class0_perm0_policy");
839 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
840 let policy = policy.validate().expect("validate policy");
841
842 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
843 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
844
845 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
846 }
847
848 #[test]
849 fn no_explicit_allow_attr_attr() {
850 let policy_bytes = include_bytes!(
851 "../../testdata/micro_policies/no_allow_a_attr_b_attr_class0_perm0_policy"
852 );
853 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
854 let policy = policy.validate().expect("validate policy");
855
856 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
857 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
858
859 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
860 }
861
862 #[test]
863 fn compute_explicitly_allowed_multiple_attributes() {
864 let policy_bytes = include_bytes!(
865 "../../testdata/micro_policies/allow_a_t_a1_attr_class0_perm0_a2_attr_class0_perm1_policy"
866 );
867 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
868 let policy = policy.validate().expect("validate policy");
869
870 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
871
872 let classes = policy.classes();
873 let class = classes.get_by_name(b"class0").expect("class not found");
874 let raw_access_vector = policy.0.compute_explicitly_allowed(a_t, a_t, class).allow.value();
875
876 assert_eq!(2, raw_access_vector.count_ones());
881 }
882
883 #[test]
884 fn compute_access_decision_with_constraints() {
885 let policy_bytes =
886 include_bytes!("../../testdata/micro_policies/allow_with_constraints_policy");
887 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
888 let policy = policy.validate().expect("validate policy");
889
890 let source_context: SecurityContext = policy
891 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
892 .expect("create source security context");
893
894 let target_context_satisfied: SecurityContext = source_context.clone();
895 let decision_satisfied = policy.compute_access_decision(
896 &source_context,
897 &target_context_satisfied,
898 KernelClass::File,
899 );
900 assert_eq!(decision_satisfied.allow, AccessVector::from(7));
904
905 let target_context_unsatisfied: SecurityContext = policy
906 .parse_security_context(b"user1:object_r:type0:s0:c0-s0:c0".into())
907 .expect("create target security context failing some constraints");
908 let decision_unsatisfied = policy.compute_access_decision(
909 &source_context,
910 &target_context_unsatisfied,
911 KernelClass::File,
912 );
913 assert_eq!(decision_unsatisfied.allow, AccessVector::from(4));
916 }
917
918 #[test]
919 fn compute_ioctl_access_decision_explicitly_allowed() {
920 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
921 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
922 let policy = policy.validate().expect("validate policy");
923
924 let source_context: SecurityContext = policy
925 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
926 .expect("create source security context");
927 let target_context_matched: SecurityContext = source_context.clone();
928
929 let decision_single = policy.compute_xperms_access_decision(
947 XpermsKind::Ioctl,
948 &source_context,
949 &target_context_matched,
950 KernelClass::File,
951 0xab,
952 );
953
954 let mut expected_auditdeny =
955 xperms_bitmap_from_elements((0x0..=0xff).collect::<Vec<_>>().as_slice());
956 expected_auditdeny -= xperms_bitmap_from_elements(&[0xcd, 0xef]);
957
958 let expected_decision_single = XpermsAccessDecision {
959 allow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
960 auditallow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
961 auditdeny: expected_auditdeny,
962 };
963 assert_eq!(decision_single, expected_decision_single);
964
965 let decision_range = policy.compute_xperms_access_decision(
966 XpermsKind::Ioctl,
967 &source_context,
968 &target_context_matched,
969 KernelClass::File,
970 0x10,
971 );
972 let expected_decision_range = XpermsAccessDecision {
973 allow: XpermsBitmap::ALL,
974 auditallow: XpermsBitmap::ALL,
975 auditdeny: XpermsBitmap::NONE,
976 };
977 assert_eq!(decision_range, expected_decision_range);
978 }
979
980 #[test]
981 fn compute_ioctl_access_decision_denied() {
982 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
983 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
984 let class_id = unvalidated
985 .0
986 .classes()
987 .get_by_name(b"class_one_ioctl")
988 .expect("look up class_one_ioctl")
989 .id();
990 let policy = unvalidated.validate().expect("validate policy");
991 let source_context: SecurityContext = policy
992 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
993 .expect("create source security context");
994 let target_context_matched: SecurityContext = source_context.clone();
995
996 let decision_single = policy.compute_xperms_access_decision(
1000 XpermsKind::Ioctl,
1001 &source_context,
1002 &target_context_matched,
1003 class_id,
1004 0xdb,
1005 );
1006
1007 let expected_decision = XpermsAccessDecision {
1008 allow: XpermsBitmap::NONE,
1009 auditallow: XpermsBitmap::NONE,
1010 auditdeny: XpermsBitmap::ALL,
1011 };
1012 assert_eq!(decision_single, expected_decision);
1013 }
1014
1015 #[test]
1016 fn compute_ioctl_access_decision_unmatched() {
1017 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1018 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1019 let policy = policy.validate().expect("validate policy");
1020
1021 let source_context: SecurityContext = policy
1022 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1023 .expect("create source security context");
1024
1025 let target_context_unmatched: SecurityContext = policy
1027 .parse_security_context(b"user0:object_r:type1:s0-s0".into())
1028 .expect("create source security context");
1029
1030 for prefix in 0x0..=0xff {
1031 let decision = policy.compute_xperms_access_decision(
1032 XpermsKind::Ioctl,
1033 &source_context,
1034 &target_context_unmatched,
1035 KernelClass::File,
1036 prefix,
1037 );
1038 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1039 }
1040 }
1041
1042 #[test]
1043 fn compute_ioctl_earlier_redundant_prefixful_not_coalesced_into_prefixless() {
1044 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1045 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1046 let class_id = unvalidated
1047 .0
1048 .classes()
1049 .get_by_name(b"class_earlier_redundant_prefixful_not_coalesced_into_prefixless")
1050 .expect("look up class_earlier_redundant_prefixful_not_coalesced_into_prefixless")
1051 .id();
1052 let policy = unvalidated.validate().expect("validate policy");
1053 let source_context: SecurityContext = policy
1054 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1055 .expect("create source security context");
1056 let target_context_matched: SecurityContext = source_context.clone();
1057
1058 let decision = policy.compute_xperms_access_decision(
1063 XpermsKind::Ioctl,
1064 &source_context,
1065 &target_context_matched,
1066 class_id,
1067 0x7f,
1068 );
1069 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1070 let decision = policy.compute_xperms_access_decision(
1071 XpermsKind::Ioctl,
1072 &source_context,
1073 &target_context_matched,
1074 class_id,
1075 0x80,
1076 );
1077 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1078 let decision = policy.compute_xperms_access_decision(
1079 XpermsKind::Ioctl,
1080 &source_context,
1081 &target_context_matched,
1082 class_id,
1083 0x81,
1084 );
1085 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1086 }
1087
1088 #[test]
1089 fn compute_ioctl_later_redundant_prefixful_not_coalesced_into_prefixless() {
1090 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1091 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1092 let class_id = unvalidated
1093 .0
1094 .classes()
1095 .get_by_name(b"class_later_redundant_prefixful_not_coalesced_into_prefixless")
1096 .expect("look up class_later_redundant_prefixful_not_coalesced_into_prefixless")
1097 .id();
1098 let policy = unvalidated.validate().expect("validate policy");
1099 let source_context: SecurityContext = policy
1100 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1101 .expect("create source security context");
1102 let target_context_matched: SecurityContext = source_context.clone();
1103
1104 let decision = policy.compute_xperms_access_decision(
1109 XpermsKind::Ioctl,
1110 &source_context,
1111 &target_context_matched,
1112 class_id,
1113 0x8f,
1114 );
1115 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1116 let decision = policy.compute_xperms_access_decision(
1117 XpermsKind::Ioctl,
1118 &source_context,
1119 &target_context_matched,
1120 class_id,
1121 0x90,
1122 );
1123 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1124 let decision = policy.compute_xperms_access_decision(
1125 XpermsKind::Ioctl,
1126 &source_context,
1127 &target_context_matched,
1128 class_id,
1129 0x91,
1130 );
1131 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1132 }
1133
1134 #[test]
1135 fn compute_ioctl_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless() {
1136 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1137 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1138 let class_id = unvalidated
1139 .0
1140 .classes()
1141 .get_by_name(
1142 b"class_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless",
1143 )
1144 .expect(
1145 "look up class_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless",
1146 )
1147 .id();
1148 let policy = unvalidated.validate().expect("validate policy");
1149 let source_context: SecurityContext = policy
1150 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1151 .expect("create source security context");
1152 let target_context_matched: SecurityContext = source_context.clone();
1153
1154 let decision = policy.compute_xperms_access_decision(
1160 XpermsKind::Ioctl,
1161 &source_context,
1162 &target_context_matched,
1163 class_id,
1164 0x9f,
1165 );
1166 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1167 let decision = policy.compute_xperms_access_decision(
1168 XpermsKind::Ioctl,
1169 &source_context,
1170 &target_context_matched,
1171 class_id,
1172 0xa0,
1173 );
1174 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1175 let decision = policy.compute_xperms_access_decision(
1176 XpermsKind::Ioctl,
1177 &source_context,
1178 &target_context_matched,
1179 class_id,
1180 0xa1,
1181 );
1182 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1183 }
1184
1185 #[test]
1186 fn compute_ioctl_prefixfuls_that_coalesce_to_prefixless() {
1187 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1188 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1189 let class_id: ClassId = unvalidated
1190 .0
1191 .classes()
1192 .get_by_name(b"class_prefixfuls_that_coalesce_to_prefixless")
1193 .expect("look up class_prefixfuls_that_coalesce_to_prefixless")
1194 .id();
1195 let policy = unvalidated.validate().expect("validate policy");
1196 let source_context: SecurityContext = policy
1197 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1198 .expect("create source security context");
1199 let target_context_matched: SecurityContext = source_context.clone();
1200
1201 let decision = policy.compute_xperms_access_decision(
1207 XpermsKind::Ioctl,
1208 &source_context,
1209 &target_context_matched,
1210 class_id,
1211 0xaf,
1212 );
1213 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1214 let decision = policy.compute_xperms_access_decision(
1215 XpermsKind::Ioctl,
1216 &source_context,
1217 &target_context_matched,
1218 class_id,
1219 0xb0,
1220 );
1221 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1222 let decision = policy.compute_xperms_access_decision(
1223 XpermsKind::Ioctl,
1224 &source_context,
1225 &target_context_matched,
1226 class_id,
1227 0xb1,
1228 );
1229 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1230 }
1231
1232 #[test]
1233 fn compute_ioctl_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless() {
1234 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1235 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1236 let class_id = unvalidated
1237 .0
1238 .classes()
1239 .get_by_name(b"class_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless")
1240 .expect("look up class_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless")
1241 .id();
1242 let policy = unvalidated.validate().expect("validate policy");
1243 let source_context: SecurityContext = policy
1244 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1245 .expect("create source security context");
1246 let target_context_matched: SecurityContext = source_context.clone();
1247
1248 let decision = policy.compute_xperms_access_decision(
1255 XpermsKind::Ioctl,
1256 &source_context,
1257 &target_context_matched,
1258 class_id,
1259 0xbf,
1260 );
1261 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1262 let decision = policy.compute_xperms_access_decision(
1263 XpermsKind::Ioctl,
1264 &source_context,
1265 &target_context_matched,
1266 class_id,
1267 0xc0,
1268 );
1269 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1270 let decision = policy.compute_xperms_access_decision(
1271 XpermsKind::Ioctl,
1272 &source_context,
1273 &target_context_matched,
1274 class_id,
1275 0xc1,
1276 );
1277 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1278 let decision = policy.compute_xperms_access_decision(
1279 XpermsKind::Ioctl,
1280 &source_context,
1281 &target_context_matched,
1282 class_id,
1283 0xc2,
1284 );
1285 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1286 }
1287
1288 #[test]
1289 fn compute_ioctl_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless() {
1290 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1291 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1292 let class_id = unvalidated
1293 .0
1294 .classes()
1295 .get_by_name(b"class_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless")
1296 .expect("look up class_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless")
1297 .id();
1298 let policy = unvalidated.validate().expect("validate policy");
1299 let source_context: SecurityContext = policy
1300 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1301 .expect("create source security context");
1302 let target_context_matched: SecurityContext = source_context.clone();
1303
1304 let decision = policy.compute_xperms_access_decision(
1311 XpermsKind::Ioctl,
1312 &source_context,
1313 &target_context_matched,
1314 class_id,
1315 0xd5,
1316 );
1317 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1318 let decision = policy.compute_xperms_access_decision(
1319 XpermsKind::Ioctl,
1320 &source_context,
1321 &target_context_matched,
1322 class_id,
1323 0xd6,
1324 );
1325 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1326 let decision = policy.compute_xperms_access_decision(
1327 XpermsKind::Ioctl,
1328 &source_context,
1329 &target_context_matched,
1330 class_id,
1331 0xd7,
1332 );
1333 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1334 let decision = policy.compute_xperms_access_decision(
1335 XpermsKind::Ioctl,
1336 &source_context,
1337 &target_context_matched,
1338 class_id,
1339 0xd8,
1340 );
1341 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1342 }
1343
1344 #[test]
1355 fn compute_ioctl_ridiculous_permission_ordering() {
1356 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1357 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1358 let class_id = unvalidated
1359 .0
1360 .classes()
1361 .get_by_name(b"class_ridiculous_permission_ordering")
1362 .expect("look up class_ridiculous_permission_ordering")
1363 .id();
1364 let policy = unvalidated.validate().expect("validate policy");
1365 let source_context: SecurityContext = policy
1366 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1367 .expect("create source security context");
1368 let target_context_matched: SecurityContext = source_context.clone();
1369
1370 let decision = policy.compute_xperms_access_decision(
1375 XpermsKind::Ioctl,
1376 &source_context,
1377 &target_context_matched,
1378 class_id,
1379 0x00,
1380 );
1381 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1382 let decision = policy.compute_xperms_access_decision(
1383 XpermsKind::Ioctl,
1384 &source_context,
1385 &target_context_matched,
1386 class_id,
1387 0x01,
1388 );
1389 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1390 let decision = policy.compute_xperms_access_decision(
1391 XpermsKind::Ioctl,
1392 &source_context,
1393 &target_context_matched,
1394 class_id,
1395 0xbf,
1396 );
1397 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1398 let decision = policy.compute_xperms_access_decision(
1399 XpermsKind::Ioctl,
1400 &source_context,
1401 &target_context_matched,
1402 class_id,
1403 0xc0,
1404 );
1405 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1406 let decision = policy.compute_xperms_access_decision(
1407 XpermsKind::Ioctl,
1408 &source_context,
1409 &target_context_matched,
1410 class_id,
1411 0xce,
1412 );
1413 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1414 let decision = policy.compute_xperms_access_decision(
1415 XpermsKind::Ioctl,
1416 &source_context,
1417 &target_context_matched,
1418 class_id,
1419 0xcf,
1420 );
1421 assert_eq!(
1422 decision,
1423 XpermsAccessDecision {
1424 allow: xperms_bitmap_from_elements((0x0..=0xf2).collect::<Vec<_>>().as_slice()),
1425 auditallow: XpermsBitmap::NONE,
1426 auditdeny: XpermsBitmap::ALL,
1427 }
1428 );
1429 let decision = policy.compute_xperms_access_decision(
1430 XpermsKind::Ioctl,
1431 &source_context,
1432 &target_context_matched,
1433 class_id,
1434 0xd0,
1435 );
1436 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1437 let decision = policy.compute_xperms_access_decision(
1438 XpermsKind::Ioctl,
1439 &source_context,
1440 &target_context_matched,
1441 class_id,
1442 0xe9,
1443 );
1444 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1445 let decision = policy.compute_xperms_access_decision(
1446 XpermsKind::Ioctl,
1447 &source_context,
1448 &target_context_matched,
1449 class_id,
1450 0xf0,
1451 );
1452 assert_eq!(
1453 decision,
1454 XpermsAccessDecision {
1455 allow: xperms_bitmap_from_elements(&[0x01]),
1456 auditallow: XpermsBitmap::NONE,
1457 auditdeny: XpermsBitmap::ALL,
1458 }
1459 );
1460 let decision = policy.compute_xperms_access_decision(
1461 XpermsKind::Ioctl,
1462 &source_context,
1463 &target_context_matched,
1464 class_id,
1465 0xf1,
1466 );
1467 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1468 let decision = policy.compute_xperms_access_decision(
1469 XpermsKind::Ioctl,
1470 &source_context,
1471 &target_context_matched,
1472 class_id,
1473 0xfc,
1474 );
1475 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1476 let decision = policy.compute_xperms_access_decision(
1477 XpermsKind::Ioctl,
1478 &source_context,
1479 &target_context_matched,
1480 class_id,
1481 0xfd,
1482 );
1483 assert_eq!(
1484 decision,
1485 XpermsAccessDecision {
1486 allow: xperms_bitmap_from_elements((0xfa..=0xfd).collect::<Vec<_>>().as_slice()),
1487 auditallow: XpermsBitmap::NONE,
1488 auditdeny: XpermsBitmap::ALL,
1489 }
1490 );
1491 let decision = policy.compute_xperms_access_decision(
1492 XpermsKind::Ioctl,
1493 &source_context,
1494 &target_context_matched,
1495 class_id,
1496 0xfe,
1497 );
1498 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1499 }
1500
1501 #[test]
1502 fn compute_nlmsg_access_decision_explicitly_allowed() {
1503 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1504 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1505 let policy = policy.validate().expect("validate policy");
1506
1507 let source_context: SecurityContext = policy
1508 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1509 .expect("create source security context");
1510 let target_context_matched: SecurityContext = source_context.clone();
1511
1512 let decision_single = policy.compute_xperms_access_decision(
1530 XpermsKind::Nlmsg,
1531 &source_context,
1532 &target_context_matched,
1533 KernelClass::NetlinkRouteSocket,
1534 0xab,
1535 );
1536
1537 let mut expected_auditdeny =
1538 xperms_bitmap_from_elements((0x0..=0xff).collect::<Vec<_>>().as_slice());
1539 expected_auditdeny -= xperms_bitmap_from_elements(&[0xcd, 0xef]);
1540
1541 let expected_decision_single = XpermsAccessDecision {
1542 allow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
1543 auditallow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
1544 auditdeny: expected_auditdeny,
1545 };
1546 assert_eq!(decision_single, expected_decision_single);
1547
1548 let decision_range = policy.compute_xperms_access_decision(
1549 XpermsKind::Nlmsg,
1550 &source_context,
1551 &target_context_matched,
1552 KernelClass::NetlinkRouteSocket,
1553 0x10,
1554 );
1555 let expected_decision_range = XpermsAccessDecision {
1556 allow: XpermsBitmap::ALL,
1557 auditallow: XpermsBitmap::ALL,
1558 auditdeny: XpermsBitmap::NONE,
1559 };
1560 assert_eq!(decision_range, expected_decision_range);
1561 }
1562
1563 #[test]
1564 fn compute_nlmsg_access_decision_unmatched() {
1565 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1566 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1567 let policy = policy.validate().expect("validate policy");
1568
1569 let source_context: SecurityContext = policy
1570 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1571 .expect("create source security context");
1572
1573 let target_context_unmatched: SecurityContext = policy
1575 .parse_security_context(b"user0:object_r:type1:s0-s0".into())
1576 .expect("create source security context");
1577
1578 for prefix in 0x0..=0xff {
1579 let decision = policy.compute_xperms_access_decision(
1580 XpermsKind::Nlmsg,
1581 &source_context,
1582 &target_context_unmatched,
1583 KernelClass::NetlinkRouteSocket,
1584 prefix,
1585 );
1586 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1587 }
1588 }
1589
1590 #[test]
1591 fn compute_ioctl_grant_does_not_cause_nlmsg_deny() {
1592 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1593 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1594 let class_id = unvalidated
1595 .0
1596 .classes()
1597 .get_by_name(b"class_ioctl_grant_does_not_cause_nlmsg_deny")
1598 .expect("look up class_ioctl_grant_does_not_cause_nlmsg_deny")
1599 .id();
1600 let policy = unvalidated.validate().expect("validate policy");
1601 let source_context: SecurityContext = policy
1602 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1603 .expect("create source security context");
1604 let target_context_matched: SecurityContext = source_context.clone();
1605
1606 let ioctl_decision = policy.compute_xperms_access_decision(
1610 XpermsKind::Ioctl,
1611 &source_context,
1612 &target_context_matched,
1613 class_id,
1614 0x00,
1615 );
1616 assert_eq!(
1617 ioctl_decision,
1618 XpermsAccessDecision {
1619 allow: xperms_bitmap_from_elements(&[0x0002]),
1620 auditallow: XpermsBitmap::NONE,
1621 auditdeny: XpermsBitmap::ALL,
1622 }
1623 );
1624 let nlmsg_decision = policy.compute_xperms_access_decision(
1625 XpermsKind::Nlmsg,
1626 &source_context,
1627 &target_context_matched,
1628 class_id,
1629 0x00,
1630 );
1631 assert_eq!(nlmsg_decision, XpermsAccessDecision::ALLOW_ALL);
1632 }
1633
1634 #[test]
1635 fn compute_nlmsg_grant_does_not_cause_ioctl_deny() {
1636 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1637 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1638 let class_id = unvalidated
1639 .0
1640 .classes()
1641 .get_by_name(b"class_nlmsg_grant_does_not_cause_ioctl_deny")
1642 .expect("look up class_nlmsg_grant_does_not_cause_ioctl_deny")
1643 .id();
1644 let policy = unvalidated.validate().expect("validate policy");
1645 let source_context: SecurityContext = policy
1646 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1647 .expect("create source security context");
1648 let target_context_matched: SecurityContext = source_context.clone();
1649
1650 let nlmsg_decision = policy.compute_xperms_access_decision(
1654 XpermsKind::Nlmsg,
1655 &source_context,
1656 &target_context_matched,
1657 class_id,
1658 0x00,
1659 );
1660 assert_eq!(
1661 nlmsg_decision,
1662 XpermsAccessDecision {
1663 allow: xperms_bitmap_from_elements(&[0x0003]),
1664 auditallow: XpermsBitmap::NONE,
1665 auditdeny: XpermsBitmap::ALL,
1666 }
1667 );
1668 let ioctl_decision = policy.compute_xperms_access_decision(
1669 XpermsKind::Ioctl,
1670 &source_context,
1671 &target_context_matched,
1672 class_id,
1673 0x00,
1674 );
1675 assert_eq!(ioctl_decision, XpermsAccessDecision::ALLOW_ALL);
1676 }
1677
1678 #[test]
1679 fn compute_create_context_minimal() {
1680 let policy_bytes =
1681 include_bytes!("../../testdata/composite_policies/compiled/minimal_policy");
1682 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1683 let policy = policy.validate().expect("validate policy");
1684 let source = policy
1685 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1686 .expect("valid source security context");
1687 let target = policy
1688 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1689 .expect("valid target security context");
1690
1691 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1692 let expected: SecurityContext = policy
1693 .parse_security_context(b"source_u:object_r:target_t:s0:c0".into())
1694 .expect("valid expected security context");
1695
1696 assert_eq!(expected, actual);
1697 }
1698
1699 #[test]
1700 fn new_security_context_minimal() {
1701 let policy_bytes =
1702 include_bytes!("../../testdata/composite_policies/compiled/minimal_policy");
1703 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1704 let policy = policy.validate().expect("validate policy");
1705 let source = policy
1706 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1707 .expect("valid source security context");
1708 let target = policy
1709 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1710 .expect("valid target security context");
1711
1712 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
1713
1714 assert_eq!(source, actual);
1715 }
1716
1717 #[test]
1718 fn compute_create_context_class_defaults() {
1719 let policy_bytes =
1720 include_bytes!("../../testdata/composite_policies/compiled/class_defaults_policy");
1721 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1722 let policy = policy.validate().expect("validate policy");
1723 let source = policy
1724 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1725 .expect("valid source security context");
1726 let target = policy
1727 .parse_security_context(b"target_u:target_r:target_t:s1:c0-s1:c0.c1".into())
1728 .expect("valid target security context");
1729
1730 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1731 let expected: SecurityContext = policy
1732 .parse_security_context(b"target_u:source_r:source_t:s1:c0-s1:c0.c1".into())
1733 .expect("valid expected security context");
1734
1735 assert_eq!(expected, actual);
1736 }
1737
1738 #[test]
1739 fn new_security_context_class_defaults() {
1740 let policy_bytes =
1741 include_bytes!("../../testdata/composite_policies/compiled/class_defaults_policy");
1742 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1743 let policy = policy.validate().expect("validate policy");
1744 let source = policy
1745 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1746 .expect("valid source security context");
1747 let target = policy
1748 .parse_security_context(b"target_u:target_r:target_t:s1:c0-s1:c0.c1".into())
1749 .expect("valid target security context");
1750
1751 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
1752 let expected: SecurityContext = policy
1753 .parse_security_context(b"target_u:source_r:source_t:s1:c0-s1:c0.c1".into())
1754 .expect("valid expected security context");
1755
1756 assert_eq!(expected, actual);
1757 }
1758
1759 #[test]
1760 fn compute_create_context_role_transition() {
1761 let policy_bytes =
1762 include_bytes!("../../testdata/composite_policies/compiled/role_transition_policy");
1763 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1764 let policy = policy.validate().expect("validate policy");
1765 let source = policy
1766 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1767 .expect("valid source security context");
1768 let target = policy
1769 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1770 .expect("valid target security context");
1771
1772 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1773 let expected: SecurityContext = policy
1774 .parse_security_context(b"source_u:transition_r:target_t:s0:c0".into())
1775 .expect("valid expected security context");
1776
1777 assert_eq!(expected, actual);
1778 }
1779
1780 #[test]
1781 fn new_security_context_role_transition() {
1782 let policy_bytes =
1783 include_bytes!("../../testdata/composite_policies/compiled/role_transition_policy");
1784 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1785 let policy = policy.validate().expect("validate policy");
1786 let source = policy
1787 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1788 .expect("valid source security context");
1789 let target = policy
1790 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1791 .expect("valid target security context");
1792
1793 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
1794 let expected: SecurityContext = policy
1795 .parse_security_context(b"source_u:transition_r:source_t:s0:c0-s2:c0.c1".into())
1796 .expect("valid expected security context");
1797
1798 assert_eq!(expected, actual);
1799 }
1800
1801 #[test]
1802 #[ignore]
1804 fn compute_create_context_role_transition_not_allowed() {
1805 let policy_bytes = include_bytes!(
1806 "../../testdata/composite_policies/compiled/role_transition_not_allowed_policy"
1807 );
1808 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1809 let policy = policy.validate().expect("validate policy");
1810 let source = policy
1811 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1812 .expect("valid source security context");
1813 let target = policy
1814 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1815 .expect("valid target security context");
1816
1817 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1818
1819 assert!(policy.validate_security_context(&actual).is_err());
1821 }
1822
1823 #[test]
1824 fn compute_create_context_type_transition() {
1825 let policy_bytes =
1826 include_bytes!("../../testdata/composite_policies/compiled/type_transition_policy");
1827 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1828 let policy = policy.validate().expect("validate policy");
1829 let source = policy
1830 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1831 .expect("valid source security context");
1832 let target = policy
1833 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1834 .expect("valid target security context");
1835
1836 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1837 let expected: SecurityContext = policy
1838 .parse_security_context(b"source_u:object_r:transition_t:s0:c0".into())
1839 .expect("valid expected security context");
1840
1841 assert_eq!(expected, actual);
1842 }
1843
1844 #[test]
1845 fn new_security_context_type_transition() {
1846 let policy_bytes =
1847 include_bytes!("../../testdata/composite_policies/compiled/type_transition_policy");
1848 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1849 let policy = policy.validate().expect("validate policy");
1850 let source = policy
1851 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1852 .expect("valid source security context");
1853 let target = policy
1854 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1855 .expect("valid target security context");
1856
1857 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
1858 let expected: SecurityContext = policy
1859 .parse_security_context(b"source_u:source_r:transition_t:s0:c0-s2:c0.c1".into())
1860 .expect("valid expected security context");
1861
1862 assert_eq!(expected, actual);
1863 }
1864
1865 #[test]
1866 fn compute_create_context_range_transition() {
1867 let policy_bytes =
1868 include_bytes!("../../testdata/composite_policies/compiled/range_transition_policy");
1869 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1870 let policy = policy.validate().expect("validate policy");
1871 let source = policy
1872 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1873 .expect("valid source security context");
1874 let target = policy
1875 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1876 .expect("valid target security context");
1877
1878 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1879 let expected: SecurityContext = policy
1880 .parse_security_context(b"source_u:object_r:target_t:s1:c1-s2:c1.c2".into())
1881 .expect("valid expected security context");
1882
1883 assert_eq!(expected, actual);
1884 }
1885
1886 #[test]
1887 fn new_security_context_range_transition() {
1888 let policy_bytes =
1889 include_bytes!("../../testdata/composite_policies/compiled/range_transition_policy");
1890 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1891 let policy = policy.validate().expect("validate policy");
1892 let source = policy
1893 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1894 .expect("valid source security context");
1895 let target = policy
1896 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1897 .expect("valid target security context");
1898
1899 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
1900 let expected: SecurityContext = policy
1901 .parse_security_context(b"source_u:source_r:source_t:s1:c1-s2:c1.c2".into())
1902 .expect("valid expected security context");
1903
1904 assert_eq!(expected, actual);
1905 }
1906
1907 #[test]
1908 fn access_vector_formats() {
1909 assert_eq!(format!("{:x}", AccessVector::NONE), "0");
1910 assert_eq!(format!("{:x}", AccessVector::ALL), "ffffffff");
1911 assert_eq!(format!("{:?}", AccessVector::NONE), "AccessVector(00000000)");
1912 assert_eq!(format!("{:?}", AccessVector::ALL), "AccessVector(ffffffff)");
1913 }
1914
1915 #[test]
1916 fn policy_genfscon_root_path() {
1917 let policy_bytes =
1918 include_bytes!("../../testdata/composite_policies/compiled/genfscon_policy");
1919 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1920 let policy = policy.validate().expect("validate selinux policy");
1921
1922 {
1923 let context = policy.genfscon_label_for_fs_and_path(
1924 "fs_with_path_rules".into(),
1925 "/".into(),
1926 None,
1927 );
1928 assert_eq!(
1929 policy.serialize_security_context(&context.unwrap()),
1930 b"system_u:object_r:fs_with_path_rules_t:s0"
1931 )
1932 }
1933 {
1934 let context = policy.genfscon_label_for_fs_and_path(
1935 "fs_2_with_path_rules".into(),
1936 "/".into(),
1937 None,
1938 );
1939 assert_eq!(
1940 policy.serialize_security_context(&context.unwrap()),
1941 b"system_u:object_r:fs_2_with_path_rules_t:s0"
1942 )
1943 }
1944 }
1945
1946 #[test]
1947 fn policy_genfscon_subpaths() {
1948 let policy_bytes =
1949 include_bytes!("../../testdata/composite_policies/compiled/genfscon_policy");
1950 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1951 let policy = policy.validate().expect("validate selinux policy");
1952
1953 let path_label_expectations = [
1954 ("/a1/", "system_u:object_r:fs_with_path_rules_a1_t:s0"),
1958 ("/a1/b", "system_u:object_r:fs_with_path_rules_a1_t:s0"),
1959 ("/a1/b/c", "system_u:object_r:fs_with_path_rules_a1_b_c_t:s0"),
1960 ("/a2/", "system_u:object_r:fs_with_path_rules_t:s0"),
1963 ("/a2/b/c/d", "system_u:object_r:fs_with_path_rules_a2_b_t:s0"),
1964 ("/a3/b/c/d", "system_u:object_r:fs_with_path_rules_a3_t:s0"),
1967 ];
1968 for (path, expected_label) in path_label_expectations {
1969 let context = policy.genfscon_label_for_fs_and_path(
1970 "fs_with_path_rules".into(),
1971 path.into(),
1972 None,
1973 );
1974 assert_eq!(
1975 policy.serialize_security_context(&context.unwrap()),
1976 expected_label.as_bytes()
1977 )
1978 }
1979 }
1980
1981 #[test]
1982 fn policy_genfscon_mixed_order() {
1983 let policy_bytes =
1984 include_bytes!("../../testdata/composite_policies/compiled/genfscon_policy");
1985 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1986 let policy = policy.validate().expect("validate selinux policy");
1987
1988 let path_label_expectations = [
1989 ("/", "system_u:object_r:fs_mixed_order_t:s0"),
1990 ("/a", "system_u:object_r:fs_mixed_order_a_t:s0"),
1991 ("/a/a", "system_u:object_r:fs_mixed_order_a_a_t:s0"),
1992 ("/a/b", "system_u:object_r:fs_mixed_order_a_b_t:s0"),
1993 ("/a/b/c", "system_u:object_r:fs_mixed_order_a_b_t:s0"),
1994 ];
1995 for (path, expected_label) in path_label_expectations {
1996 let context =
1997 policy.genfscon_label_for_fs_and_path("fs_mixed_order".into(), path.into(), None);
1998 assert_eq!(
1999 policy.serialize_security_context(&context.unwrap()),
2000 expected_label.as_bytes()
2001 );
2002 }
2003 }
2004}