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;
16mod symbols;
17
18pub use arrays::{FsUseType, XpermsBitmap};
19pub use index::FsUseLabelAndType;
20pub use parser::PolicyCursor;
21pub use security_context::{SecurityContext, SecurityContextError};
22
23use crate::{
24 ClassPermission, KernelClass, KernelPermission, NullessByteStr, ObjectClass, PolicyCap,
25};
26use index::PolicyIndex;
27use metadata::HandleUnknown;
28use parsed_policy::ParsedPolicy;
29use parser::PolicyData;
30use symbols::{find_class_by_name, find_common_symbol_by_name_bytes};
31
32use anyhow::Context as _;
33use std::fmt::{Debug, Display, LowerHex};
34use std::num::{NonZeroU8, NonZeroU32, NonZeroU64};
35use std::ops::Deref;
36use std::str::FromStr;
37use std::sync::Arc;
38use zerocopy::{
39 FromBytes, Immutable, KnownLayout, Ref, SplitByteSlice, Unaligned, little_endian as le,
40};
41
42#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
44pub struct UserId(NonZeroU32);
45
46#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
48pub struct RoleId(NonZeroU32);
49
50#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
52pub struct TypeId(NonZeroU32);
53
54#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
56pub struct SensitivityId(NonZeroU32);
57
58#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
60pub struct CategoryId(NonZeroU32);
61
62#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
65pub struct ClassId(NonZeroU32);
66
67impl ClassId {
68 pub fn new(id: NonZeroU32) -> Self {
70 Self(id)
71 }
72}
73
74impl Into<u32> for ClassId {
75 fn into(self) -> u32 {
76 self.0.into()
77 }
78}
79
80#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
82pub struct ClassPermissionId(NonZeroU8);
83
84impl Display for ClassPermissionId {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "{}", self.0)
87 }
88}
89
90#[derive(Debug, Clone, PartialEq)]
95pub struct AccessDecision {
96 pub allow: AccessVector,
97 pub auditallow: AccessVector,
98 pub auditdeny: AccessVector,
99 pub flags: u32,
100
101 pub todo_bug: Option<NonZeroU64>,
104}
105
106impl Default for AccessDecision {
107 fn default() -> Self {
108 Self::allow(AccessVector::NONE)
109 }
110}
111
112impl AccessDecision {
113 pub(super) const fn allow(allow: AccessVector) -> Self {
116 Self {
117 allow,
118 auditallow: AccessVector::NONE,
119 auditdeny: AccessVector::ALL,
120 flags: 0,
121 todo_bug: None,
122 }
123 }
124}
125
126pub(super) const SELINUX_AVD_FLAGS_PERMISSIVE: u32 = 1;
128
129#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
132pub struct AccessVector(u32);
133
134impl AccessVector {
135 pub const NONE: AccessVector = AccessVector(0);
136 pub const ALL: AccessVector = AccessVector(std::u32::MAX);
137
138 pub(super) fn from_class_permission_id(id: ClassPermissionId) -> Self {
139 Self((1 as u32) << (id.0.get() - 1))
140 }
141}
142
143impl Debug for AccessVector {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 write!(f, "AccessVector({:0>8x})", self)
146 }
147}
148
149impl FromStr for AccessVector {
150 type Err = <u32 as FromStr>::Err;
151
152 fn from_str(value: &str) -> Result<Self, Self::Err> {
153 Ok(AccessVector(u32::from_str_radix(value, 16)?))
155 }
156}
157
158impl LowerHex for AccessVector {
159 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160 LowerHex::fmt(&self.0, f)
161 }
162}
163
164impl std::ops::BitAnd for AccessVector {
165 type Output = Self;
166
167 fn bitand(self, rhs: Self) -> Self::Output {
168 AccessVector(self.0 & rhs.0)
169 }
170}
171
172impl std::ops::BitOr for AccessVector {
173 type Output = Self;
174
175 fn bitor(self, rhs: Self) -> Self::Output {
176 AccessVector(self.0 | rhs.0)
177 }
178}
179
180impl std::ops::BitAndAssign for AccessVector {
181 fn bitand_assign(&mut self, rhs: Self) {
182 self.0 &= rhs.0
183 }
184}
185
186impl std::ops::BitOrAssign for AccessVector {
187 fn bitor_assign(&mut self, rhs: Self) {
188 self.0 |= rhs.0
189 }
190}
191
192impl std::ops::SubAssign for AccessVector {
193 fn sub_assign(&mut self, rhs: Self) {
194 self.0 = self.0 ^ (self.0 & rhs.0);
195 }
196}
197
198impl std::ops::Sub for AccessVector {
199 type Output = Self;
200
201 fn sub(self, rhs: Self) -> Self::Output {
202 AccessVector(self.0 ^ (self.0 & rhs.0))
203 }
204}
205
206#[derive(Clone, Debug, Eq, Hash, PartialEq)]
209pub enum XpermsKind {
210 Ioctl,
211 Nlmsg,
212}
213
214#[derive(Debug, Clone, PartialEq)]
219pub struct XpermsAccessDecision {
220 pub allow: XpermsBitmap,
221 pub auditallow: XpermsBitmap,
222 pub auditdeny: XpermsBitmap,
223}
224
225impl XpermsAccessDecision {
226 pub const DENY_ALL: Self = Self {
227 allow: XpermsBitmap::NONE,
228 auditallow: XpermsBitmap::NONE,
229 auditdeny: XpermsBitmap::ALL,
230 };
231 pub const ALLOW_ALL: Self = Self {
232 allow: XpermsBitmap::ALL,
233 auditallow: XpermsBitmap::NONE,
234 auditdeny: XpermsBitmap::ALL,
235 };
236}
237
238pub fn parse_policy_by_value(binary_policy: Vec<u8>) -> Result<Unvalidated, anyhow::Error> {
247 let policy_data = Arc::new(binary_policy);
248 let policy = ParsedPolicy::parse(policy_data).context("parsing policy")?;
249 Ok(Unvalidated(policy))
250}
251
252pub struct ClassInfo {
254 pub class_name: Box<[u8]>,
256 pub class_id: ClassId,
258}
259
260#[derive(Debug)]
261pub struct Policy(PolicyIndex);
262
263impl Policy {
264 pub fn policy_version(&self) -> u32 {
266 self.0.parsed_policy().policy_version()
267 }
268
269 pub fn binary(&self) -> &PolicyData {
270 &self.0.parsed_policy().data
271 }
272
273 pub fn handle_unknown(&self) -> HandleUnknown {
276 self.0.parsed_policy().handle_unknown()
277 }
278
279 pub fn conditional_booleans<'a>(&'a self) -> Vec<(&'a [u8], bool)> {
280 self.0
281 .parsed_policy()
282 .conditional_booleans()
283 .iter()
284 .map(|boolean| (boolean.data.as_slice(), boolean.metadata.active()))
285 .collect()
286 }
287
288 pub fn classes(&self) -> Vec<ClassInfo> {
290 self.0
291 .parsed_policy()
292 .classes()
293 .into_iter()
294 .map(|class| ClassInfo {
295 class_name: Box::<[u8]>::from(class.name_bytes()),
296 class_id: class.id(),
297 })
298 .collect()
299 }
300
301 pub(super) fn type_id_by_name(&self, name: &str) -> Option<TypeId> {
303 self.0.parsed_policy().type_id_by_name(name)
304 }
305
306 pub fn find_class_permissions_by_name(
311 &self,
312 class_name: &str,
313 ) -> Result<Vec<(ClassPermissionId, Vec<u8>)>, ()> {
314 let classes = self.0.parsed_policy().classes();
315 let class = find_class_by_name(&classes, class_name).ok_or(())?;
316 let owned_permissions = class.permissions();
317
318 let mut result: Vec<_> = owned_permissions
319 .iter()
320 .map(|permission| (permission.id(), permission.name_bytes().to_vec()))
321 .collect();
322
323 if class.common_name_bytes().is_empty() {
325 return Ok(result);
326 }
327
328 let common_symbol_permissions = find_common_symbol_by_name_bytes(
329 self.0.parsed_policy().common_symbols(),
330 class.common_name_bytes(),
331 )
332 .ok_or(())?
333 .permissions();
334
335 result.append(
336 &mut common_symbol_permissions
337 .iter()
338 .map(|permission| (permission.id(), permission.name_bytes().to_vec()))
339 .collect(),
340 );
341
342 Ok(result)
343 }
344
345 pub fn fs_use_label_and_type(&self, fs_type: NullessByteStr<'_>) -> Option<FsUseLabelAndType> {
348 self.0.fs_use_label_and_type(fs_type)
349 }
350
351 pub fn genfscon_label_for_fs_and_path(
354 &self,
355 fs_type: NullessByteStr<'_>,
356 node_path: NullessByteStr<'_>,
357 class_id: Option<KernelClass>,
358 ) -> Option<SecurityContext> {
359 self.0.genfscon_label_for_fs_and_path(fs_type, node_path, class_id)
360 }
361
362 pub fn initial_context(&self, id: crate::InitialSid) -> security_context::SecurityContext {
365 self.0.initial_context(id)
366 }
367
368 pub fn parse_security_context(
370 &self,
371 security_context: NullessByteStr<'_>,
372 ) -> Result<security_context::SecurityContext, security_context::SecurityContextError> {
373 security_context::SecurityContext::parse(&self.0, security_context)
374 }
375
376 pub fn validate_security_context(
378 &self,
379 security_context: &SecurityContext,
380 ) -> Result<(), SecurityContextError> {
381 security_context.validate(&self.0)
382 }
383
384 pub fn serialize_security_context(&self, security_context: &SecurityContext) -> Vec<u8> {
386 security_context.serialize(&self.0)
387 }
388
389 pub fn compute_create_context_with_name(
397 &self,
398 source: &SecurityContext,
399 target: &SecurityContext,
400 class: impl Into<ObjectClass>,
401 name: NullessByteStr<'_>,
402 ) -> Option<SecurityContext> {
403 self.0.compute_create_context_with_name(source, target, class.into(), name)
404 }
405
406 pub fn compute_create_context(
424 &self,
425 source: &SecurityContext,
426 target: &SecurityContext,
427 class: impl Into<ObjectClass>,
428 ) -> SecurityContext {
429 self.0.compute_create_context(source, target, class.into())
430 }
431
432 pub fn compute_access_decision(
442 &self,
443 source_context: &SecurityContext,
444 target_context: &SecurityContext,
445 object_class: impl Into<ObjectClass>,
446 ) -> AccessDecision {
447 if let Some(target_class) = self.0.class(object_class.into()) {
448 self.0.parsed_policy().compute_access_decision(
449 source_context,
450 target_context,
451 &target_class,
452 )
453 } else {
454 let mut decision = AccessDecision::allow(AccessVector::NONE);
455 if self.is_permissive(source_context.type_()) {
456 decision.flags |= SELINUX_AVD_FLAGS_PERMISSIVE;
457 }
458 decision
459 }
460 }
461
462 pub fn compute_xperms_access_decision(
466 &self,
467 xperms_kind: XpermsKind,
468 source_context: &SecurityContext,
469 target_context: &SecurityContext,
470 object_class: impl Into<ObjectClass>,
471 xperms_prefix: u8,
472 ) -> XpermsAccessDecision {
473 if let Some(target_class) = self.0.class(object_class.into()) {
474 self.0.parsed_policy().compute_xperms_access_decision(
475 xperms_kind,
476 source_context,
477 target_context,
478 &target_class,
479 xperms_prefix,
480 )
481 } else {
482 XpermsAccessDecision::DENY_ALL
483 }
484 }
485
486 pub fn is_bounded_by(&self, bounded_type: TypeId, parent_type: TypeId) -> bool {
487 self.0.parsed_policy().type_(bounded_type).bounded_by() == Some(parent_type)
488 }
489
490 pub fn is_permissive(&self, type_: TypeId) -> bool {
492 self.0.parsed_policy().permissive_types().is_set(type_.0.get())
493 }
494
495 pub fn has_policycap(&self, policy_cap: PolicyCap) -> bool {
497 self.0.parsed_policy().has_policycap(policy_cap)
498 }
499}
500
501impl AccessVectorComputer for Policy {
502 fn kernel_permissions_to_access_vector<
503 P: ClassPermission + Into<KernelPermission> + Clone + 'static,
504 >(
505 &self,
506 permissions: &[P],
507 ) -> Option<AccessVector> {
508 let mut access_vector = AccessVector::NONE;
509 for permission in permissions {
510 if let Some(permission_access_vector) =
511 self.0.kernel_permission_to_access_vector(permission.clone())
512 {
513 access_vector |= permission_access_vector;
514 } else {
515 if self.0.parsed_policy().handle_unknown() != HandleUnknown::Allow {
517 return None;
518 }
519 }
520 }
521 Some(access_vector)
522 }
523}
524
525pub struct Unvalidated(ParsedPolicy);
527
528impl Unvalidated {
529 pub fn validate(self) -> Result<Policy, anyhow::Error> {
530 self.0.validate().context("validating parsed policy")?;
531 let index = PolicyIndex::new(self.0).context("building index")?;
532 Ok(Policy(index))
533 }
534}
535
536pub trait AccessVectorComputer {
539 fn kernel_permissions_to_access_vector<
546 P: ClassPermission + Into<KernelPermission> + Clone + 'static,
547 >(
548 &self,
549 permissions: &[P],
550 ) -> Option<AccessVector>;
551}
552
553pub trait Parse: Sized {
555 type Error: Into<anyhow::Error>;
558
559 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error>;
562}
563
564pub(super) struct PolicyValidationContext {
566 #[allow(unused)]
568 pub(super) data: PolicyData,
569}
570
571pub(super) trait Validate {
573 type Error: Into<anyhow::Error>;
576
577 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error>;
579}
580
581pub(super) trait ValidateArray<M, D> {
582 type Error: Into<anyhow::Error>;
585
586 fn validate_array(
588 context: &PolicyValidationContext,
589 metadata: &M,
590 items: &[D],
591 ) -> Result<(), Self::Error>;
592}
593
594pub(super) trait Counted {
596 fn count(&self) -> u32;
598}
599
600impl<T: Validate> Validate for Option<T> {
601 type Error = <T as Validate>::Error;
602
603 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
604 match self {
605 Some(value) => value.validate(context),
606 None => Ok(()),
607 }
608 }
609}
610
611impl<T: Validate> Validate for Vec<T> {
612 type Error = <T as Validate>::Error;
613
614 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
615 for item in self {
616 item.validate(context)?;
617 }
618 Ok(())
619 }
620}
621
622impl Validate for le::U32 {
623 type Error = anyhow::Error;
624
625 fn validate(&self, _context: &PolicyValidationContext) -> Result<(), Self::Error> {
628 Ok(())
629 }
630}
631
632impl Validate for u8 {
633 type Error = anyhow::Error;
634
635 fn validate(&self, _context: &PolicyValidationContext) -> Result<(), Self::Error> {
638 Ok(())
639 }
640}
641
642impl<B: SplitByteSlice, T: Validate + FromBytes + KnownLayout + Immutable> Validate for Ref<B, T> {
643 type Error = <T as Validate>::Error;
644
645 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
646 self.deref().validate(context)
647 }
648}
649
650impl<B: SplitByteSlice, T: Counted + FromBytes + KnownLayout + Immutable> Counted for Ref<B, T> {
651 fn count(&self) -> u32 {
652 self.deref().count()
653 }
654}
655
656#[derive(Clone, Debug, PartialEq)]
658struct Array<M, T> {
659 metadata: M,
660 data: Vec<T>,
661}
662
663impl<M: Counted + Parse, T: Parse> Parse for Array<M, T> {
664 type Error = anyhow::Error;
667
668 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
670 let tail = bytes;
671
672 let (metadata, tail) = M::parse(tail).map_err(Into::<anyhow::Error>::into)?;
673
674 let count = metadata.count() as usize;
675 let mut data = Vec::with_capacity(count);
676 let mut cur_tail = tail;
677 for _ in 0..count {
678 let (item, next_tail) = T::parse(cur_tail).map_err(Into::<anyhow::Error>::into)?;
679 data.push(item);
680 cur_tail = next_tail;
681 }
682 let tail = cur_tail;
683
684 let array = Self { metadata, data };
685
686 Ok((array, tail))
687 }
688}
689
690impl<T: Clone + Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned> Parse for T {
691 type Error = anyhow::Error;
692
693 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
694 bytes.parse::<T>().map_err(anyhow::Error::from)
695 }
696}
697
698macro_rules! array_type {
702 ($type_name:ident, $metadata_type:ty, $data_type:ty, $metadata_type_name:expr, $data_type_name:expr) => {
703 #[doc = "An [`Array`] with [`"]
704 #[doc = $metadata_type_name]
705 #[doc = "`] metadata and [`"]
706 #[doc = $data_type_name]
707 #[doc = "`] data items."]
708 #[derive(Debug, PartialEq)]
709 pub(super) struct $type_name(super::Array<$metadata_type, $data_type>);
710
711 impl std::ops::Deref for $type_name {
712 type Target = super::Array<$metadata_type, $data_type>;
713
714 fn deref(&self) -> &Self::Target {
715 &self.0
716 }
717 }
718
719 impl super::Parse for $type_name
720 where
721 super::Array<$metadata_type, $data_type>: super::Parse,
722 {
723 type Error = <Array<$metadata_type, $data_type> as super::Parse>::Error;
724
725 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
726 let (array, tail) = Array::<$metadata_type, $data_type>::parse(bytes)?;
727 Ok((Self(array), tail))
728 }
729 }
730 };
731
732 ($type_name:ident, $metadata_type:ty, $data_type:ty) => {
733 array_type!(
734 $type_name,
735 $metadata_type,
736 $data_type,
737 stringify!($metadata_type),
738 stringify!($data_type)
739 );
740 };
741}
742
743pub(super) use array_type;
744
745macro_rules! array_type_validate_deref_both {
746 ($type_name:ident) => {
747 impl Validate for $type_name {
748 type Error = anyhow::Error;
749
750 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
751 let metadata = &self.metadata;
752 metadata.validate(context)?;
753
754 self.data.validate(context).map_err(Into::<anyhow::Error>::into)?;
755
756 Self::validate_array(context, metadata, &self.data)
757 .map_err(Into::<anyhow::Error>::into)
758 }
759 }
760 };
761}
762
763pub(super) use array_type_validate_deref_both;
764
765macro_rules! array_type_validate_deref_data {
766 ($type_name:ident) => {
767 impl Validate for $type_name {
768 type Error = anyhow::Error;
769
770 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
771 let metadata = &self.metadata;
772 metadata.validate(context)?;
773
774 self.data.validate(context).map_err(Into::<anyhow::Error>::into)?;
775
776 Self::validate_array(context, metadata, &self.data)
777 }
778 }
779 };
780}
781
782pub(super) use array_type_validate_deref_data;
783
784macro_rules! array_type_validate_deref_metadata_data_vec {
785 ($type_name:ident) => {
786 impl Validate for $type_name {
787 type Error = anyhow::Error;
788
789 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
790 let metadata = &self.metadata;
791 metadata.validate(context)?;
792
793 self.data.validate(context).map_err(Into::<anyhow::Error>::into)?;
794
795 Self::validate_array(context, metadata, self.data.as_slice())
796 }
797 }
798 };
799}
800
801pub(super) use array_type_validate_deref_metadata_data_vec;
802
803macro_rules! array_type_validate_deref_none_data_vec {
804 ($type_name:ident) => {
805 impl Validate for $type_name {
806 type Error = anyhow::Error;
807
808 fn validate(&self, context: &PolicyValidationContext) -> Result<(), Self::Error> {
809 let metadata = &self.metadata;
810 metadata.validate(context)?;
811
812 self.data.validate(context).map_err(Into::<anyhow::Error>::into)?;
813
814 Self::validate_array(context, metadata, self.data.as_slice())
815 }
816 }
817 };
818}
819
820pub(super) use array_type_validate_deref_none_data_vec;
821
822#[cfg(test)]
823pub(super) mod testing {
824 use super::AccessVector;
825 use super::error::{ParseError, ValidateError};
826
827 pub const ACCESS_VECTOR_0001: AccessVector = AccessVector(0b0001u32);
828 pub const ACCESS_VECTOR_0010: AccessVector = AccessVector(0b0010u32);
829
830 pub(super) fn as_parse_error(error: anyhow::Error) -> ParseError {
832 error.downcast::<ParseError>().expect("parse error")
833 }
834
835 pub(super) fn as_validate_error(error: anyhow::Error) -> ValidateError {
837 error.downcast::<ValidateError>().expect("validate error")
838 }
839}
840
841#[cfg(test)]
842pub(super) mod tests {
843 use super::arrays::XpermsBitmap;
844 use super::metadata::HandleUnknown;
845 use super::security_context::SecurityContext;
846 use super::symbols::find_class_by_name;
847 use super::{
848 AccessVector, Policy, TypeId, XpermsAccessDecision, XpermsKind, parse_policy_by_value,
849 };
850 use crate::{FileClass, InitialSid, KernelClass};
851
852 use anyhow::Context as _;
853 use serde::Deserialize;
854 use std::ops::{Deref, Shl};
855 use zerocopy::little_endian as le;
856
857 fn is_explicitly_allowed(
865 policy: &Policy,
866 source_type: TypeId,
867 target_type: TypeId,
868 target_class: &str,
869 permission: &str,
870 ) -> bool {
871 let classes = policy.0.parsed_policy().classes();
872 let class = classes
873 .iter()
874 .find(|class| class.name_bytes() == target_class.as_bytes())
875 .expect("class not found");
876 let class_permissions = policy
877 .find_class_permissions_by_name(target_class)
878 .expect("class permissions not found");
879 let (permission_id, _) = class_permissions
880 .iter()
881 .find(|(_, name)| permission.as_bytes() == name)
882 .expect("permission not found");
883 let permission_bit = AccessVector::from_class_permission_id(*permission_id);
884 let access_decision =
885 policy.0.parsed_policy().compute_explicitly_allowed(source_type, target_type, class);
886 permission_bit == access_decision.allow & permission_bit
887 }
888
889 #[derive(Debug, Deserialize)]
890 struct Expectations {
891 expected_policy_version: u32,
892 expected_handle_unknown: LocalHandleUnknown,
893 }
894
895 #[derive(Debug, Deserialize, PartialEq)]
896 #[serde(rename_all = "snake_case")]
897 enum LocalHandleUnknown {
898 Deny,
899 Reject,
900 Allow,
901 }
902
903 impl PartialEq<HandleUnknown> for LocalHandleUnknown {
904 fn eq(&self, other: &HandleUnknown) -> bool {
905 match self {
906 LocalHandleUnknown::Deny => *other == HandleUnknown::Deny,
907 LocalHandleUnknown::Reject => *other == HandleUnknown::Reject,
908 LocalHandleUnknown::Allow => *other == HandleUnknown::Allow,
909 }
910 }
911 }
912
913 fn xperms_bitmap_from_elements(elements: &[u8]) -> XpermsBitmap {
916 let mut bitmap = [le::U32::ZERO; 8];
917 for element in elements {
918 let block_index = (*element as usize) / 32;
919 let bit_index = ((*element as usize) % 32) as u32;
920 let bitmask = le::U32::new(1).shl(bit_index);
921 bitmap[block_index] = bitmap[block_index] | bitmask;
922 }
923 XpermsBitmap::new(bitmap)
924 }
925
926 #[test]
927 fn known_policies() {
928 let policies_and_expectations = [
929 [
930 b"testdata/policies/emulator".to_vec(),
931 include_bytes!("../../testdata/policies/emulator").to_vec(),
932 include_bytes!("../../testdata/expectations/emulator").to_vec(),
933 ],
934 [
935 b"testdata/policies/selinux_testsuite".to_vec(),
936 include_bytes!("../../testdata/policies/selinux_testsuite").to_vec(),
937 include_bytes!("../../testdata/expectations/selinux_testsuite").to_vec(),
938 ],
939 ];
940
941 for [policy_path, policy_bytes, expectations_bytes] in policies_and_expectations {
942 let expectations = serde_json5::from_reader::<_, Expectations>(
943 &mut std::io::Cursor::new(expectations_bytes),
944 )
945 .expect("deserialize expectations");
946
947 let unvalidated_policy =
950 parse_policy_by_value(policy_bytes.clone()).expect("parse policy");
951
952 let policy = unvalidated_policy
953 .validate()
954 .with_context(|| {
955 format!(
956 "policy path: {:?}",
957 std::str::from_utf8(policy_path.as_slice()).unwrap()
958 )
959 })
960 .expect("validate policy");
961
962 assert_eq!(expectations.expected_policy_version, policy.policy_version());
963 assert_eq!(expectations.expected_handle_unknown, policy.handle_unknown());
964
965 let binary_policy = policy.binary().clone();
967 assert_eq!(&policy_bytes, binary_policy.deref());
968 }
969 }
970
971 #[test]
972 fn policy_lookup() {
973 let policy_bytes = include_bytes!("../../testdata/policies/selinux_testsuite");
974 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
975 let policy = policy.validate().expect("validate selinux testsuite policy");
976
977 let unconfined_t = policy.type_id_by_name("unconfined_t").expect("look up type id");
978
979 assert!(is_explicitly_allowed(&policy, unconfined_t, unconfined_t, "process", "fork",));
980 }
981
982 #[test]
983 fn initial_contexts() {
984 let policy_bytes = include_bytes!(
985 "../../testdata/micro_policies/multiple_levels_and_categories_policy.pp"
986 );
987 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
988 let policy = policy.validate().expect("validate policy");
989
990 let kernel_context = policy.initial_context(InitialSid::Kernel);
991 assert_eq!(
992 policy.serialize_security_context(&kernel_context),
993 b"user0:object_r:type0:s0:c0-s1:c0.c2,c4"
994 )
995 }
996
997 #[test]
998 fn explicit_allow_type_type() {
999 let policy_bytes =
1000 include_bytes!("../../testdata/micro_policies/allow_a_t_b_t_class0_perm0_policy.pp");
1001 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1002 let policy = policy.validate().expect("validate policy");
1003
1004 let a_t = policy.type_id_by_name("a_t").expect("look up type id");
1005 let b_t = policy.type_id_by_name("b_t").expect("look up type id");
1006
1007 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
1008 }
1009
1010 #[test]
1011 fn no_explicit_allow_type_type() {
1012 let policy_bytes =
1013 include_bytes!("../../testdata/micro_policies/no_allow_a_t_b_t_class0_perm0_policy.pp");
1014 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1015 let policy = policy.validate().expect("validate policy");
1016
1017 let a_t = policy.type_id_by_name("a_t").expect("look up type id");
1018 let b_t = policy.type_id_by_name("b_t").expect("look up type id");
1019
1020 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
1021 }
1022
1023 #[test]
1024 fn explicit_allow_type_attr() {
1025 let policy_bytes =
1026 include_bytes!("../../testdata/micro_policies/allow_a_t_b_attr_class0_perm0_policy.pp");
1027 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1028 let policy = policy.validate().expect("validate policy");
1029
1030 let a_t = policy.type_id_by_name("a_t").expect("look up type id");
1031 let b_t = policy.type_id_by_name("b_t").expect("look up type id");
1032
1033 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
1034 }
1035
1036 #[test]
1037 fn no_explicit_allow_type_attr() {
1038 let policy_bytes = include_bytes!(
1039 "../../testdata/micro_policies/no_allow_a_t_b_attr_class0_perm0_policy.pp"
1040 );
1041 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1042 let policy = policy.validate().expect("validate policy");
1043
1044 let a_t = policy.type_id_by_name("a_t").expect("look up type id");
1045 let b_t = policy.type_id_by_name("b_t").expect("look up type id");
1046
1047 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
1048 }
1049
1050 #[test]
1051 fn explicit_allow_attr_attr() {
1052 let policy_bytes = include_bytes!(
1053 "../../testdata/micro_policies/allow_a_attr_b_attr_class0_perm0_policy.pp"
1054 );
1055 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1056 let policy = policy.validate().expect("validate policy");
1057
1058 let a_t = policy.type_id_by_name("a_t").expect("look up type id");
1059 let b_t = policy.type_id_by_name("b_t").expect("look up type id");
1060
1061 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
1062 }
1063
1064 #[test]
1065 fn no_explicit_allow_attr_attr() {
1066 let policy_bytes = include_bytes!(
1067 "../../testdata/micro_policies/no_allow_a_attr_b_attr_class0_perm0_policy.pp"
1068 );
1069 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1070 let policy = policy.validate().expect("validate policy");
1071
1072 let a_t = policy.type_id_by_name("a_t").expect("look up type id");
1073 let b_t = policy.type_id_by_name("b_t").expect("look up type id");
1074
1075 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
1076 }
1077
1078 #[test]
1079 fn compute_explicitly_allowed_multiple_attributes() {
1080 let policy_bytes = include_bytes!(
1081 "../../testdata/micro_policies/allow_a_t_a1_attr_class0_perm0_a2_attr_class0_perm1_policy.pp"
1082 );
1083 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1084 let policy = policy.validate().expect("validate policy");
1085
1086 let a_t = policy.type_id_by_name("a_t").expect("look up type id");
1087
1088 let classes = policy.0.parsed_policy().classes();
1089 let class =
1090 classes.iter().find(|class| class.name_bytes() == b"class0").expect("class not found");
1091 let raw_access_vector =
1092 policy.0.parsed_policy().compute_explicitly_allowed(a_t, a_t, class).allow.0;
1093
1094 assert_eq!(2, raw_access_vector.count_ones());
1099 }
1100
1101 #[test]
1102 fn compute_access_decision_with_constraints() {
1103 let policy_bytes =
1104 include_bytes!("../../testdata/micro_policies/allow_with_constraints_policy.pp");
1105 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1106 let policy = policy.validate().expect("validate policy");
1107
1108 let source_context: SecurityContext = policy
1109 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1110 .expect("create source security context");
1111
1112 let target_context_satisfied: SecurityContext = source_context.clone();
1113 let decision_satisfied = policy.compute_access_decision(
1114 &source_context,
1115 &target_context_satisfied,
1116 KernelClass::File,
1117 );
1118 assert_eq!(decision_satisfied.allow, AccessVector(7));
1122
1123 let target_context_unsatisfied: SecurityContext = policy
1124 .parse_security_context(b"user1:object_r:type0:s0:c0-s0:c0".into())
1125 .expect("create target security context failing some constraints");
1126 let decision_unsatisfied = policy.compute_access_decision(
1127 &source_context,
1128 &target_context_unsatisfied,
1129 KernelClass::File,
1130 );
1131 assert_eq!(decision_unsatisfied.allow, AccessVector(4));
1134 }
1135
1136 #[test]
1137 fn compute_ioctl_access_decision_explicitly_allowed() {
1138 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1139 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1140 let policy = policy.validate().expect("validate policy");
1141
1142 let source_context: SecurityContext = policy
1143 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1144 .expect("create source security context");
1145 let target_context_matched: SecurityContext = source_context.clone();
1146
1147 let decision_single = policy.compute_xperms_access_decision(
1165 XpermsKind::Ioctl,
1166 &source_context,
1167 &target_context_matched,
1168 KernelClass::File,
1169 0xab,
1170 );
1171
1172 let mut expected_auditdeny =
1173 xperms_bitmap_from_elements((0x0..=0xff).collect::<Vec<_>>().as_slice());
1174 expected_auditdeny -= &xperms_bitmap_from_elements(&[0xcd, 0xef]);
1175
1176 let expected_decision_single = XpermsAccessDecision {
1177 allow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
1178 auditallow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
1179 auditdeny: expected_auditdeny,
1180 };
1181 assert_eq!(decision_single, expected_decision_single);
1182
1183 let decision_range = policy.compute_xperms_access_decision(
1184 XpermsKind::Ioctl,
1185 &source_context,
1186 &target_context_matched,
1187 KernelClass::File,
1188 0x10,
1189 );
1190 let expected_decision_range = XpermsAccessDecision {
1191 allow: XpermsBitmap::ALL,
1192 auditallow: XpermsBitmap::ALL,
1193 auditdeny: XpermsBitmap::NONE,
1194 };
1195 assert_eq!(decision_range, expected_decision_range);
1196 }
1197
1198 #[test]
1199 fn compute_ioctl_access_decision_denied() {
1200 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1201 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1202 let class_id = find_class_by_name(&unvalidated.0.classes(), "class_one_ioctl")
1203 .expect("look up class_one_ioctl")
1204 .id();
1205 let policy = unvalidated.validate().expect("validate policy");
1206 let source_context: SecurityContext = policy
1207 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1208 .expect("create source security context");
1209 let target_context_matched: SecurityContext = source_context.clone();
1210
1211 let decision_single = policy.compute_xperms_access_decision(
1215 XpermsKind::Ioctl,
1216 &source_context,
1217 &target_context_matched,
1218 class_id,
1219 0xdb,
1220 );
1221
1222 let expected_decision = XpermsAccessDecision {
1223 allow: XpermsBitmap::NONE,
1224 auditallow: XpermsBitmap::NONE,
1225 auditdeny: XpermsBitmap::ALL,
1226 };
1227 assert_eq!(decision_single, expected_decision);
1228 }
1229
1230 #[test]
1231 fn compute_ioctl_access_decision_unmatched() {
1232 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1233 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1234 let policy = policy.validate().expect("validate policy");
1235
1236 let source_context: SecurityContext = policy
1237 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1238 .expect("create source security context");
1239
1240 let target_context_unmatched: SecurityContext = policy
1242 .parse_security_context(b"user0:object_r:type1:s0-s0".into())
1243 .expect("create source security context");
1244
1245 for prefix in 0x0..=0xff {
1246 let decision = policy.compute_xperms_access_decision(
1247 XpermsKind::Ioctl,
1248 &source_context,
1249 &target_context_unmatched,
1250 KernelClass::File,
1251 prefix,
1252 );
1253 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1254 }
1255 }
1256
1257 #[test]
1258 fn compute_ioctl_earlier_redundant_prefixful_not_coalesced_into_prefixless() {
1259 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1260 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1261 let class_id = find_class_by_name(
1262 &unvalidated.0.classes(),
1263 "class_earlier_redundant_prefixful_not_coalesced_into_prefixless",
1264 )
1265 .expect("look up class_earlier_redundant_prefixful_not_coalesced_into_prefixless")
1266 .id();
1267 let policy = unvalidated.validate().expect("validate policy");
1268 let source_context: SecurityContext = policy
1269 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1270 .expect("create source security context");
1271 let target_context_matched: SecurityContext = source_context.clone();
1272
1273 let decision = policy.compute_xperms_access_decision(
1278 XpermsKind::Ioctl,
1279 &source_context,
1280 &target_context_matched,
1281 class_id,
1282 0x7f,
1283 );
1284 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1285 let decision = policy.compute_xperms_access_decision(
1286 XpermsKind::Ioctl,
1287 &source_context,
1288 &target_context_matched,
1289 class_id,
1290 0x80,
1291 );
1292 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1293 let decision = policy.compute_xperms_access_decision(
1294 XpermsKind::Ioctl,
1295 &source_context,
1296 &target_context_matched,
1297 class_id,
1298 0x81,
1299 );
1300 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1301 }
1302
1303 #[test]
1304 fn compute_ioctl_later_redundant_prefixful_not_coalesced_into_prefixless() {
1305 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1306 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1307 let class_id = find_class_by_name(
1308 &unvalidated.0.classes(),
1309 "class_later_redundant_prefixful_not_coalesced_into_prefixless",
1310 )
1311 .expect("look up class_later_redundant_prefixful_not_coalesced_into_prefixless")
1312 .id();
1313 let policy = unvalidated.validate().expect("validate policy");
1314 let source_context: SecurityContext = policy
1315 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1316 .expect("create source security context");
1317 let target_context_matched: SecurityContext = source_context.clone();
1318
1319 let decision = policy.compute_xperms_access_decision(
1324 XpermsKind::Ioctl,
1325 &source_context,
1326 &target_context_matched,
1327 class_id,
1328 0x8f,
1329 );
1330 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1331 let decision = policy.compute_xperms_access_decision(
1332 XpermsKind::Ioctl,
1333 &source_context,
1334 &target_context_matched,
1335 class_id,
1336 0x90,
1337 );
1338 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1339 let decision = policy.compute_xperms_access_decision(
1340 XpermsKind::Ioctl,
1341 &source_context,
1342 &target_context_matched,
1343 class_id,
1344 0x91,
1345 );
1346 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1347 }
1348
1349 #[test]
1350 fn compute_ioctl_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless() {
1351 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1352 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1353 let class_id = find_class_by_name(
1354 &unvalidated.0.classes(),
1355 "class_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless",
1356 )
1357 .expect("look up class_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless")
1358 .id();
1359 let policy = unvalidated.validate().expect("validate policy");
1360 let source_context: SecurityContext = policy
1361 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1362 .expect("create source security context");
1363 let target_context_matched: SecurityContext = source_context.clone();
1364
1365 let decision = policy.compute_xperms_access_decision(
1371 XpermsKind::Ioctl,
1372 &source_context,
1373 &target_context_matched,
1374 class_id,
1375 0x9f,
1376 );
1377 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1378 let decision = policy.compute_xperms_access_decision(
1379 XpermsKind::Ioctl,
1380 &source_context,
1381 &target_context_matched,
1382 class_id,
1383 0xa0,
1384 );
1385 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1386 let decision = policy.compute_xperms_access_decision(
1387 XpermsKind::Ioctl,
1388 &source_context,
1389 &target_context_matched,
1390 class_id,
1391 0xa1,
1392 );
1393 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1394 }
1395
1396 #[test]
1397 fn compute_ioctl_prefixfuls_that_coalesce_to_prefixless() {
1398 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1399 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1400 let class_id = find_class_by_name(
1401 &unvalidated.0.classes(),
1402 "class_prefixfuls_that_coalesce_to_prefixless",
1403 )
1404 .expect("look up class_prefixfuls_that_coalesce_to_prefixless")
1405 .id();
1406 let policy = unvalidated.validate().expect("validate policy");
1407 let source_context: SecurityContext = policy
1408 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1409 .expect("create source security context");
1410 let target_context_matched: SecurityContext = source_context.clone();
1411
1412 let decision = policy.compute_xperms_access_decision(
1418 XpermsKind::Ioctl,
1419 &source_context,
1420 &target_context_matched,
1421 class_id,
1422 0xaf,
1423 );
1424 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1425 let decision = policy.compute_xperms_access_decision(
1426 XpermsKind::Ioctl,
1427 &source_context,
1428 &target_context_matched,
1429 class_id,
1430 0xb0,
1431 );
1432 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1433 let decision = policy.compute_xperms_access_decision(
1434 XpermsKind::Ioctl,
1435 &source_context,
1436 &target_context_matched,
1437 class_id,
1438 0xb1,
1439 );
1440 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1441 }
1442
1443 #[test]
1444 fn compute_ioctl_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless() {
1445 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1446 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1447 let class_id = find_class_by_name(
1448 &unvalidated.0.classes(),
1449 "class_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless",
1450 )
1451 .expect("look up class_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless")
1452 .id();
1453 let policy = unvalidated.validate().expect("validate policy");
1454 let source_context: SecurityContext = policy
1455 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1456 .expect("create source security context");
1457 let target_context_matched: SecurityContext = source_context.clone();
1458
1459 let decision = policy.compute_xperms_access_decision(
1466 XpermsKind::Ioctl,
1467 &source_context,
1468 &target_context_matched,
1469 class_id,
1470 0xbf,
1471 );
1472 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1473 let decision = policy.compute_xperms_access_decision(
1474 XpermsKind::Ioctl,
1475 &source_context,
1476 &target_context_matched,
1477 class_id,
1478 0xc0,
1479 );
1480 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1481 let decision = policy.compute_xperms_access_decision(
1482 XpermsKind::Ioctl,
1483 &source_context,
1484 &target_context_matched,
1485 class_id,
1486 0xc1,
1487 );
1488 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1489 let decision = policy.compute_xperms_access_decision(
1490 XpermsKind::Ioctl,
1491 &source_context,
1492 &target_context_matched,
1493 class_id,
1494 0xc2,
1495 );
1496 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1497 }
1498
1499 #[test]
1500 fn compute_ioctl_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless() {
1501 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1502 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1503 let class_id = find_class_by_name(
1504 &unvalidated.0.classes(),
1505 "class_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless",
1506 )
1507 .expect("look up class_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless")
1508 .id();
1509 let policy = unvalidated.validate().expect("validate policy");
1510 let source_context: SecurityContext = policy
1511 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1512 .expect("create source security context");
1513 let target_context_matched: SecurityContext = source_context.clone();
1514
1515 let decision = policy.compute_xperms_access_decision(
1522 XpermsKind::Ioctl,
1523 &source_context,
1524 &target_context_matched,
1525 class_id,
1526 0xd5,
1527 );
1528 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1529 let decision = policy.compute_xperms_access_decision(
1530 XpermsKind::Ioctl,
1531 &source_context,
1532 &target_context_matched,
1533 class_id,
1534 0xd6,
1535 );
1536 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1537 let decision = policy.compute_xperms_access_decision(
1538 XpermsKind::Ioctl,
1539 &source_context,
1540 &target_context_matched,
1541 class_id,
1542 0xd7,
1543 );
1544 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1545 let decision = policy.compute_xperms_access_decision(
1546 XpermsKind::Ioctl,
1547 &source_context,
1548 &target_context_matched,
1549 class_id,
1550 0xd8,
1551 );
1552 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1553 }
1554
1555 #[test]
1566 fn compute_ioctl_ridiculous_permission_ordering() {
1567 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1568 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1569 let class_id =
1570 find_class_by_name(&unvalidated.0.classes(), "class_ridiculous_permission_ordering")
1571 .expect("look up class_ridiculous_permission_ordering")
1572 .id();
1573 let policy = unvalidated.validate().expect("validate policy");
1574 let source_context: SecurityContext = policy
1575 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1576 .expect("create source security context");
1577 let target_context_matched: SecurityContext = source_context.clone();
1578
1579 let decision = policy.compute_xperms_access_decision(
1584 XpermsKind::Ioctl,
1585 &source_context,
1586 &target_context_matched,
1587 class_id,
1588 0x00,
1589 );
1590 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1591 let decision = policy.compute_xperms_access_decision(
1592 XpermsKind::Ioctl,
1593 &source_context,
1594 &target_context_matched,
1595 class_id,
1596 0x01,
1597 );
1598 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1599 let decision = policy.compute_xperms_access_decision(
1600 XpermsKind::Ioctl,
1601 &source_context,
1602 &target_context_matched,
1603 class_id,
1604 0xbf,
1605 );
1606 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1607 let decision = policy.compute_xperms_access_decision(
1608 XpermsKind::Ioctl,
1609 &source_context,
1610 &target_context_matched,
1611 class_id,
1612 0xc0,
1613 );
1614 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1615 let decision = policy.compute_xperms_access_decision(
1616 XpermsKind::Ioctl,
1617 &source_context,
1618 &target_context_matched,
1619 class_id,
1620 0xce,
1621 );
1622 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1623 let decision = policy.compute_xperms_access_decision(
1624 XpermsKind::Ioctl,
1625 &source_context,
1626 &target_context_matched,
1627 class_id,
1628 0xcf,
1629 );
1630 assert_eq!(
1631 decision,
1632 XpermsAccessDecision {
1633 allow: xperms_bitmap_from_elements((0x0..=0xf2).collect::<Vec<_>>().as_slice()),
1634 auditallow: XpermsBitmap::NONE,
1635 auditdeny: XpermsBitmap::ALL,
1636 }
1637 );
1638 let decision = policy.compute_xperms_access_decision(
1639 XpermsKind::Ioctl,
1640 &source_context,
1641 &target_context_matched,
1642 class_id,
1643 0xd0,
1644 );
1645 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1646 let decision = policy.compute_xperms_access_decision(
1647 XpermsKind::Ioctl,
1648 &source_context,
1649 &target_context_matched,
1650 class_id,
1651 0xe9,
1652 );
1653 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1654 let decision = policy.compute_xperms_access_decision(
1655 XpermsKind::Ioctl,
1656 &source_context,
1657 &target_context_matched,
1658 class_id,
1659 0xf0,
1660 );
1661 assert_eq!(
1662 decision,
1663 XpermsAccessDecision {
1664 allow: xperms_bitmap_from_elements(&[0x01]),
1665 auditallow: XpermsBitmap::NONE,
1666 auditdeny: XpermsBitmap::ALL,
1667 }
1668 );
1669 let decision = policy.compute_xperms_access_decision(
1670 XpermsKind::Ioctl,
1671 &source_context,
1672 &target_context_matched,
1673 class_id,
1674 0xf1,
1675 );
1676 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1677 let decision = policy.compute_xperms_access_decision(
1678 XpermsKind::Ioctl,
1679 &source_context,
1680 &target_context_matched,
1681 class_id,
1682 0xfc,
1683 );
1684 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1685 let decision = policy.compute_xperms_access_decision(
1686 XpermsKind::Ioctl,
1687 &source_context,
1688 &target_context_matched,
1689 class_id,
1690 0xfd,
1691 );
1692 assert_eq!(
1693 decision,
1694 XpermsAccessDecision {
1695 allow: xperms_bitmap_from_elements((0xfa..=0xfd).collect::<Vec<_>>().as_slice()),
1696 auditallow: XpermsBitmap::NONE,
1697 auditdeny: XpermsBitmap::ALL,
1698 }
1699 );
1700 let decision = policy.compute_xperms_access_decision(
1701 XpermsKind::Ioctl,
1702 &source_context,
1703 &target_context_matched,
1704 class_id,
1705 0xfe,
1706 );
1707 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1708 }
1709
1710 #[test]
1711 fn compute_nlmsg_access_decision_explicitly_allowed() {
1712 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1713 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1714 let policy = policy.validate().expect("validate policy");
1715
1716 let source_context: SecurityContext = policy
1717 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1718 .expect("create source security context");
1719 let target_context_matched: SecurityContext = source_context.clone();
1720
1721 let decision_single = policy.compute_xperms_access_decision(
1739 XpermsKind::Nlmsg,
1740 &source_context,
1741 &target_context_matched,
1742 KernelClass::NetlinkRouteSocket,
1743 0xab,
1744 );
1745
1746 let mut expected_auditdeny =
1747 xperms_bitmap_from_elements((0x0..=0xff).collect::<Vec<_>>().as_slice());
1748 expected_auditdeny -= &xperms_bitmap_from_elements(&[0xcd, 0xef]);
1749
1750 let expected_decision_single = XpermsAccessDecision {
1751 allow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
1752 auditallow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
1753 auditdeny: expected_auditdeny,
1754 };
1755 assert_eq!(decision_single, expected_decision_single);
1756
1757 let decision_range = policy.compute_xperms_access_decision(
1758 XpermsKind::Nlmsg,
1759 &source_context,
1760 &target_context_matched,
1761 KernelClass::NetlinkRouteSocket,
1762 0x10,
1763 );
1764 let expected_decision_range = XpermsAccessDecision {
1765 allow: XpermsBitmap::ALL,
1766 auditallow: XpermsBitmap::ALL,
1767 auditdeny: XpermsBitmap::NONE,
1768 };
1769 assert_eq!(decision_range, expected_decision_range);
1770 }
1771
1772 #[test]
1773 fn compute_nlmsg_access_decision_unmatched() {
1774 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1775 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1776 let policy = policy.validate().expect("validate policy");
1777
1778 let source_context: SecurityContext = policy
1779 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1780 .expect("create source security context");
1781
1782 let target_context_unmatched: SecurityContext = policy
1784 .parse_security_context(b"user0:object_r:type1:s0-s0".into())
1785 .expect("create source security context");
1786
1787 for prefix in 0x0..=0xff {
1788 let decision = policy.compute_xperms_access_decision(
1789 XpermsKind::Nlmsg,
1790 &source_context,
1791 &target_context_unmatched,
1792 KernelClass::NetlinkRouteSocket,
1793 prefix,
1794 );
1795 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1796 }
1797 }
1798
1799 #[test]
1800 fn compute_ioctl_grant_does_not_cause_nlmsg_deny() {
1801 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1802 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1803 let class_id = find_class_by_name(
1804 &unvalidated.0.classes(),
1805 "class_ioctl_grant_does_not_cause_nlmsg_deny",
1806 )
1807 .expect("look up class_ioctl_grant_does_not_cause_nlmsg_deny")
1808 .id();
1809 let policy = unvalidated.validate().expect("validate policy");
1810 let source_context: SecurityContext = policy
1811 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1812 .expect("create source security context");
1813 let target_context_matched: SecurityContext = source_context.clone();
1814
1815 let ioctl_decision = policy.compute_xperms_access_decision(
1819 XpermsKind::Ioctl,
1820 &source_context,
1821 &target_context_matched,
1822 class_id,
1823 0x00,
1824 );
1825 assert_eq!(
1826 ioctl_decision,
1827 XpermsAccessDecision {
1828 allow: xperms_bitmap_from_elements(&[0x0002]),
1829 auditallow: XpermsBitmap::NONE,
1830 auditdeny: XpermsBitmap::ALL,
1831 }
1832 );
1833 let nlmsg_decision = policy.compute_xperms_access_decision(
1834 XpermsKind::Nlmsg,
1835 &source_context,
1836 &target_context_matched,
1837 class_id,
1838 0x00,
1839 );
1840 assert_eq!(nlmsg_decision, XpermsAccessDecision::ALLOW_ALL);
1841 }
1842
1843 #[test]
1844 fn compute_nlmsg_grant_does_not_cause_ioctl_deny() {
1845 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1846 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1847 let class_id = find_class_by_name(
1848 &unvalidated.0.classes(),
1849 "class_nlmsg_grant_does_not_cause_ioctl_deny",
1850 )
1851 .expect("look up class_nlmsg_grant_does_not_cause_ioctl_deny")
1852 .id();
1853 let policy = unvalidated.validate().expect("validate policy");
1854 let source_context: SecurityContext = policy
1855 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1856 .expect("create source security context");
1857 let target_context_matched: SecurityContext = source_context.clone();
1858
1859 let nlmsg_decision = policy.compute_xperms_access_decision(
1863 XpermsKind::Nlmsg,
1864 &source_context,
1865 &target_context_matched,
1866 class_id,
1867 0x00,
1868 );
1869 assert_eq!(
1870 nlmsg_decision,
1871 XpermsAccessDecision {
1872 allow: xperms_bitmap_from_elements(&[0x0003]),
1873 auditallow: XpermsBitmap::NONE,
1874 auditdeny: XpermsBitmap::ALL,
1875 }
1876 );
1877 let ioctl_decision = policy.compute_xperms_access_decision(
1878 XpermsKind::Ioctl,
1879 &source_context,
1880 &target_context_matched,
1881 class_id,
1882 0x00,
1883 );
1884 assert_eq!(ioctl_decision, XpermsAccessDecision::ALLOW_ALL);
1885 }
1886
1887 #[test]
1888 fn compute_create_context_minimal() {
1889 let policy_bytes =
1890 include_bytes!("../../testdata/composite_policies/compiled/minimal_policy.pp");
1891 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1892 let policy = policy.validate().expect("validate policy");
1893 let source = policy
1894 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1895 .expect("valid source security context");
1896 let target = policy
1897 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1898 .expect("valid target security context");
1899
1900 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1901 let expected: SecurityContext = policy
1902 .parse_security_context(b"source_u:object_r:target_t:s0:c0".into())
1903 .expect("valid expected security context");
1904
1905 assert_eq!(expected, actual);
1906 }
1907
1908 #[test]
1909 fn new_security_context_minimal() {
1910 let policy_bytes =
1911 include_bytes!("../../testdata/composite_policies/compiled/minimal_policy.pp");
1912 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1913 let policy = policy.validate().expect("validate policy");
1914 let source = policy
1915 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1916 .expect("valid source security context");
1917 let target = policy
1918 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1919 .expect("valid target security context");
1920
1921 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
1922
1923 assert_eq!(source, actual);
1924 }
1925
1926 #[test]
1927 fn compute_create_context_class_defaults() {
1928 let policy_bytes =
1929 include_bytes!("../../testdata/composite_policies/compiled/class_defaults_policy.pp");
1930 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1931 let policy = policy.validate().expect("validate policy");
1932 let source = policy
1933 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1934 .expect("valid source security context");
1935 let target = policy
1936 .parse_security_context(b"target_u:target_r:target_t:s1:c0-s1:c0.c1".into())
1937 .expect("valid target security context");
1938
1939 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1940 let expected: SecurityContext = policy
1941 .parse_security_context(b"target_u:source_r:source_t:s1:c0-s1:c0.c1".into())
1942 .expect("valid expected security context");
1943
1944 assert_eq!(expected, actual);
1945 }
1946
1947 #[test]
1948 fn new_security_context_class_defaults() {
1949 let policy_bytes =
1950 include_bytes!("../../testdata/composite_policies/compiled/class_defaults_policy.pp");
1951 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1952 let policy = policy.validate().expect("validate policy");
1953 let source = policy
1954 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1955 .expect("valid source security context");
1956 let target = policy
1957 .parse_security_context(b"target_u:target_r:target_t:s1:c0-s1:c0.c1".into())
1958 .expect("valid target security context");
1959
1960 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
1961 let expected: SecurityContext = policy
1962 .parse_security_context(b"target_u:source_r:source_t:s1:c0-s1:c0.c1".into())
1963 .expect("valid expected security context");
1964
1965 assert_eq!(expected, actual);
1966 }
1967
1968 #[test]
1969 fn compute_create_context_role_transition() {
1970 let policy_bytes =
1971 include_bytes!("../../testdata/composite_policies/compiled/role_transition_policy.pp");
1972 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1973 let policy = policy.validate().expect("validate policy");
1974 let source = policy
1975 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1976 .expect("valid source security context");
1977 let target = policy
1978 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1979 .expect("valid target security context");
1980
1981 let actual = policy.compute_create_context(&source, &target, FileClass::File);
1982 let expected: SecurityContext = policy
1983 .parse_security_context(b"source_u:transition_r:target_t:s0:c0".into())
1984 .expect("valid expected security context");
1985
1986 assert_eq!(expected, actual);
1987 }
1988
1989 #[test]
1990 fn new_security_context_role_transition() {
1991 let policy_bytes =
1992 include_bytes!("../../testdata/composite_policies/compiled/role_transition_policy.pp");
1993 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1994 let policy = policy.validate().expect("validate policy");
1995 let source = policy
1996 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1997 .expect("valid source security context");
1998 let target = policy
1999 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
2000 .expect("valid target security context");
2001
2002 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
2003 let expected: SecurityContext = policy
2004 .parse_security_context(b"source_u:transition_r:source_t:s0:c0-s2:c0.c1".into())
2005 .expect("valid expected security context");
2006
2007 assert_eq!(expected, actual);
2008 }
2009
2010 #[test]
2011 #[ignore]
2013 fn compute_create_context_role_transition_not_allowed() {
2014 let policy_bytes = include_bytes!(
2015 "../../testdata/composite_policies/compiled/role_transition_not_allowed_policy.pp"
2016 );
2017 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2018 let policy = policy.validate().expect("validate policy");
2019 let source = policy
2020 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
2021 .expect("valid source security context");
2022 let target = policy
2023 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
2024 .expect("valid target security context");
2025
2026 let actual = policy.compute_create_context(&source, &target, FileClass::File);
2027
2028 assert!(policy.validate_security_context(&actual).is_err());
2030 }
2031
2032 #[test]
2033 fn compute_create_context_type_transition() {
2034 let policy_bytes =
2035 include_bytes!("../../testdata/composite_policies/compiled/type_transition_policy.pp");
2036 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2037 let policy = policy.validate().expect("validate policy");
2038 let source = policy
2039 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
2040 .expect("valid source security context");
2041 let target = policy
2042 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
2043 .expect("valid target security context");
2044
2045 let actual = policy.compute_create_context(&source, &target, FileClass::File);
2046 let expected: SecurityContext = policy
2047 .parse_security_context(b"source_u:object_r:transition_t:s0:c0".into())
2048 .expect("valid expected security context");
2049
2050 assert_eq!(expected, actual);
2051 }
2052
2053 #[test]
2054 fn new_security_context_type_transition() {
2055 let policy_bytes =
2056 include_bytes!("../../testdata/composite_policies/compiled/type_transition_policy.pp");
2057 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2058 let policy = policy.validate().expect("validate policy");
2059 let source = policy
2060 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
2061 .expect("valid source security context");
2062 let target = policy
2063 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
2064 .expect("valid target security context");
2065
2066 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
2067 let expected: SecurityContext = policy
2068 .parse_security_context(b"source_u:source_r:transition_t:s0:c0-s2:c0.c1".into())
2069 .expect("valid expected security context");
2070
2071 assert_eq!(expected, actual);
2072 }
2073
2074 #[test]
2075 fn compute_create_context_range_transition() {
2076 let policy_bytes =
2077 include_bytes!("../../testdata/composite_policies/compiled/range_transition_policy.pp");
2078 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2079 let policy = policy.validate().expect("validate policy");
2080 let source = policy
2081 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
2082 .expect("valid source security context");
2083 let target = policy
2084 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
2085 .expect("valid target security context");
2086
2087 let actual = policy.compute_create_context(&source, &target, FileClass::File);
2088 let expected: SecurityContext = policy
2089 .parse_security_context(b"source_u:object_r:target_t:s1:c1-s2:c1.c2".into())
2090 .expect("valid expected security context");
2091
2092 assert_eq!(expected, actual);
2093 }
2094
2095 #[test]
2096 fn new_security_context_range_transition() {
2097 let policy_bytes =
2098 include_bytes!("../../testdata/composite_policies/compiled/range_transition_policy.pp");
2099 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2100 let policy = policy.validate().expect("validate policy");
2101 let source = policy
2102 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
2103 .expect("valid source security context");
2104 let target = policy
2105 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
2106 .expect("valid target security context");
2107
2108 let actual = policy.compute_create_context(&source, &target, KernelClass::Process);
2109 let expected: SecurityContext = policy
2110 .parse_security_context(b"source_u:source_r:source_t:s1:c1-s2:c1.c2".into())
2111 .expect("valid expected security context");
2112
2113 assert_eq!(expected, actual);
2114 }
2115
2116 #[test]
2117 fn access_vector_formats() {
2118 assert_eq!(format!("{:x}", AccessVector::NONE), "0");
2119 assert_eq!(format!("{:x}", AccessVector::ALL), "ffffffff");
2120 assert_eq!(format!("{:?}", AccessVector::NONE), "AccessVector(00000000)");
2121 assert_eq!(format!("{:?}", AccessVector::ALL), "AccessVector(ffffffff)");
2122 }
2123
2124 #[test]
2125 fn policy_genfscon_root_path() {
2126 let policy_bytes =
2127 include_bytes!("../../testdata/composite_policies/compiled/genfscon_policy.pp");
2128 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2129 let policy = policy.validate().expect("validate selinux policy");
2130
2131 {
2132 let context = policy.genfscon_label_for_fs_and_path(
2133 "fs_with_path_rules".into(),
2134 "/".into(),
2135 None,
2136 );
2137 assert_eq!(
2138 policy.serialize_security_context(&context.unwrap()),
2139 b"system_u:object_r:fs_with_path_rules_t:s0"
2140 )
2141 }
2142 {
2143 let context = policy.genfscon_label_for_fs_and_path(
2144 "fs_2_with_path_rules".into(),
2145 "/".into(),
2146 None,
2147 );
2148 assert_eq!(
2149 policy.serialize_security_context(&context.unwrap()),
2150 b"system_u:object_r:fs_2_with_path_rules_t:s0"
2151 )
2152 }
2153 }
2154
2155 #[test]
2156 fn policy_genfscon_subpaths() {
2157 let policy_bytes =
2158 include_bytes!("../../testdata/composite_policies/compiled/genfscon_policy.pp");
2159 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2160 let policy = policy.validate().expect("validate selinux policy");
2161
2162 let path_label_expectations = [
2163 ("/a1/", "system_u:object_r:fs_with_path_rules_a1_t:s0"),
2167 ("/a1/b", "system_u:object_r:fs_with_path_rules_a1_t:s0"),
2168 ("/a1/b/c", "system_u:object_r:fs_with_path_rules_a1_b_c_t:s0"),
2169 ("/a2/", "system_u:object_r:fs_with_path_rules_t:s0"),
2172 ("/a2/b/c/d", "system_u:object_r:fs_with_path_rules_a2_b_t:s0"),
2173 ("/a3/b/c/d", "system_u:object_r:fs_with_path_rules_a3_t:s0"),
2176 ];
2177 for (path, expected_label) in path_label_expectations {
2178 let context = policy.genfscon_label_for_fs_and_path(
2179 "fs_with_path_rules".into(),
2180 path.into(),
2181 None,
2182 );
2183 assert_eq!(
2184 policy.serialize_security_context(&context.unwrap()),
2185 expected_label.as_bytes()
2186 )
2187 }
2188 }
2189}