1use super::constraints::{ConstraintError, evaluate_constraint};
6use super::error::ValidateError;
7use super::extensible_bitmap::{
8 ExtensibleBitmap, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator,
9};
10use super::parser::PolicyCursor;
11use super::security_context::{CategoryIterator, Level, SecurityContext};
12use super::{
13 AccessVector, Array, CategoryId, ClassId, ClassPermissionId, Counted, Parse,
14 PolicyValidationContext, RoleId, SensitivityId, TypeId, UserId, Validate, ValidateArray,
15 array_type, array_type_validate_deref_both, array_type_validate_deref_data,
16 array_type_validate_deref_metadata_data_vec, array_type_validate_deref_none_data_vec,
17};
18
19use anyhow::{Context as _, anyhow};
20use std::fmt::Debug;
21use std::num::{NonZeroU8, NonZeroU32};
22use std::ops::Deref;
23use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned, little_endian as le};
24
25pub(super) const CONSTRAINT_TERM_TYPE_NOT_OPERATOR: u32 = 1;
30pub(super) const CONSTRAINT_TERM_TYPE_AND_OPERATOR: u32 = 2;
33pub(super) const CONSTRAINT_TERM_TYPE_OR_OPERATOR: u32 = 3;
36pub(super) const CONSTRAINT_TERM_TYPE_EXPR: u32 = 4;
40pub(super) const CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES: u32 = 5;
53
54pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_EQ: u32 = 1;
67pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_NE: u32 = 2;
70pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_DOM: u32 = 3;
73pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY: u32 = 4;
77pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP: u32 = 5;
81
82pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_USER: u32 = 0x1;
108pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_ROLE: u32 = 0x2;
110pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_TYPE: u32 = 0x4;
112pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2: u32 = 0x20;
115pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2: u32 = 0x40;
118pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2: u32 = 0x80;
121pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2: u32 = 0x100;
124pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1: u32 = 0x200;
127pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2: u32 = 0x400;
130
131pub(super) const CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK: u32 = 0x8;
144
145pub(super) const TYPE_PROPERTIES_TYPE: u32 = 1;
147
148pub(super) const TYPE_PROPERTIES_ALIAS: u32 = 0;
150
151pub(super) const TYPE_PROPERTIES_ATTRIBUTE: u32 = 0;
153
154#[derive(Debug, PartialEq)]
157pub(super) struct SymbolList<T>(Array<Metadata, Vec<T>>);
158
159impl<T> Deref for SymbolList<T> {
160 type Target = Array<Metadata, Vec<T>>;
161
162 fn deref(&self) -> &Self::Target {
163 &self.0
164 }
165}
166
167impl<T: Parse> Parse for SymbolList<T> {
168 type Error = <Array<Metadata, Vec<T>> as Parse>::Error;
169
170 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
171 let (array, tail) = Array::<Metadata, Vec<T>>::parse(bytes)?;
172 Ok((Self(array), tail))
173 }
174}
175
176impl<T> Validate for SymbolList<T>
177where
178 [T]: Validate,
179{
180 type Error = anyhow::Error;
181
182 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
184 self.metadata.validate(context).map_err(Into::<anyhow::Error>::into)?;
185 self.data.as_slice().validate(context).map_err(Into::<anyhow::Error>::into)?;
186
187 Ok(())
188 }
189}
190
191#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
193#[repr(C, packed)]
194pub(super) struct Metadata {
195 primary_names_count: le::U32,
197 count: le::U32,
199}
200
201impl Metadata {
202 pub fn primary_names_count(&self) -> u32 {
203 self.primary_names_count.get()
204 }
205}
206
207impl Counted for Metadata {
208 fn count(&self) -> u32 {
211 self.count.get()
212 }
213}
214
215impl Validate for Metadata {
216 type Error = anyhow::Error;
217
218 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
220 Ok(())
221 }
222}
223
224impl Validate for [CommonSymbol] {
225 type Error = <CommonSymbol as Validate>::Error;
226
227 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
230 Ok(())
231 }
232}
233
234array_type!(CommonSymbol, CommonSymbolMetadata, Permissions);
235
236array_type_validate_deref_none_data_vec!(CommonSymbol);
237
238impl CommonSymbol {
239 pub fn permissions(&self) -> &Permissions {
240 &self.data
241 }
242}
243
244pub(super) type CommonSymbols = Vec<CommonSymbol>;
245
246impl CommonSymbol {
247 pub fn name_bytes(&self) -> &[u8] {
251 &self.metadata.data
252 }
253}
254
255impl Counted for CommonSymbol {
256 fn count(&self) -> u32 {
259 self.metadata.count()
260 }
261}
262
263impl ValidateArray<CommonSymbolMetadata, Permission> for CommonSymbol {
264 type Error = anyhow::Error;
265
266 fn validate_array(
268 _context: &mut PolicyValidationContext,
269 _metadata: &CommonSymbolMetadata,
270 _items: &[Permission],
271 ) -> Result<(), Self::Error> {
272 Ok(())
273 }
274}
275
276array_type!(CommonSymbolMetadata, CommonSymbolStaticMetadata, Vec<u8>);
277
278array_type_validate_deref_both!(CommonSymbolMetadata);
279
280impl Counted for CommonSymbolMetadata {
281 fn count(&self) -> u32 {
284 self.metadata.count.get()
285 }
286}
287
288impl ValidateArray<CommonSymbolStaticMetadata, u8> for CommonSymbolMetadata {
289 type Error = anyhow::Error;
290
291 fn validate_array(
293 _context: &mut PolicyValidationContext,
294 _metadata: &CommonSymbolStaticMetadata,
295 _items: &[u8],
296 ) -> Result<(), Self::Error> {
297 Ok(())
298 }
299}
300
301#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
303#[repr(C, packed)]
304pub(super) struct CommonSymbolStaticMetadata {
305 length: le::U32,
307 id: le::U32,
310 primary_names_count: le::U32,
312 count: le::U32,
314}
315
316impl Validate for CommonSymbolStaticMetadata {
317 type Error = anyhow::Error;
318
319 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
321 Ok(())
322 }
323}
324
325impl Counted for CommonSymbolStaticMetadata {
326 fn count(&self) -> u32 {
328 self.length.get()
329 }
330}
331
332pub(super) type Permissions = Vec<Permission>;
334
335impl Validate for Permissions {
336 type Error = anyhow::Error;
337
338 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
341 Ok(())
342 }
343}
344
345array_type!(Permission, PermissionMetadata, Vec<u8>);
346
347array_type_validate_deref_both!(Permission);
348
349impl Permission {
350 pub fn name_bytes(&self) -> &[u8] {
354 &self.data
355 }
356
357 pub fn id(&self) -> ClassPermissionId {
359 let id = self.metadata.id.get() as u8;
360 ClassPermissionId(NonZeroU8::new(id).unwrap())
361 }
362}
363
364impl ValidateArray<PermissionMetadata, u8> for Permission {
365 type Error = anyhow::Error;
366
367 fn validate_array(
369 _context: &mut PolicyValidationContext,
370 _metadata: &PermissionMetadata,
371 _items: &[u8],
372 ) -> Result<(), Self::Error> {
373 Ok(())
374 }
375}
376
377#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
378#[repr(C, packed)]
379pub(super) struct PermissionMetadata {
380 length: le::U32,
382 id: le::U32,
383}
384
385impl Counted for PermissionMetadata {
386 fn count(&self) -> u32 {
388 self.length.get()
389 }
390}
391
392impl Validate for PermissionMetadata {
393 type Error = anyhow::Error;
394
395 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
397 if self.id < 1 || self.id > 32 {
399 return Err(anyhow!("Permission Id is not valid AV index"));
400 }
401 Ok(())
402 }
403}
404
405pub(super) type Constraints = Vec<Constraint>;
407
408impl Validate for Constraints {
409 type Error = anyhow::Error;
410
411 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
414 Ok(())
415 }
416}
417
418#[derive(Debug, PartialEq)]
422pub(super) struct Constraint {
423 access_vector: le::U32,
424 constraint_expr: ConstraintExpr,
425}
426
427impl Constraint {
428 pub(super) fn access_vector(&self) -> AccessVector {
429 AccessVector(self.access_vector.get())
430 }
431
432 pub(super) fn constraint_expr(&self) -> &ConstraintExpr {
433 &self.constraint_expr
434 }
435}
436
437impl Parse for Constraint {
438 type Error = anyhow::Error;
439
440 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
441 let tail = bytes;
442
443 let (access_vector, tail) = PolicyCursor::parse::<le::U32>(tail)?;
444 let (constraint_expr, tail) = ConstraintExpr::parse(tail)
445 .map_err(|error| anyhow!(error))
446 .context("parsing constraint expression")?;
447
448 Ok((Self { access_vector, constraint_expr }, tail))
449 }
450}
451
452array_type!(ConstraintExpr, ConstraintTermCount, ConstraintTerms);
455
456array_type_validate_deref_metadata_data_vec!(ConstraintExpr);
457
458impl ValidateArray<ConstraintTermCount, ConstraintTerm> for ConstraintExpr {
459 type Error = anyhow::Error;
460
461 fn validate_array(
465 _context: &mut PolicyValidationContext,
466 _metadata: &ConstraintTermCount,
467 _items: &[ConstraintTerm],
468 ) -> Result<(), Self::Error> {
469 Ok(())
470 }
471}
472
473impl ConstraintExpr {
474 pub(super) fn evaluate(
475 &self,
476 source_context: &SecurityContext,
477 target_context: &SecurityContext,
478 ) -> Result<bool, ConstraintError> {
479 evaluate_constraint(&self, source_context, target_context)
480 }
481
482 pub(super) fn constraint_terms(&self) -> &[ConstraintTerm] {
483 &self.data
484 }
485}
486
487#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
488#[repr(C, packed)]
489pub(super) struct ConstraintTermCount(le::U32);
490
491impl Counted for ConstraintTermCount {
492 fn count(&self) -> u32 {
493 self.0.get()
494 }
495}
496
497impl Validate for ConstraintTermCount {
498 type Error = anyhow::Error;
499
500 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
501 Ok(())
502 }
503}
504
505impl Validate for ConstraintTerms {
506 type Error = anyhow::Error;
507
508 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
513 Ok(())
514 }
515}
516
517#[derive(Debug, PartialEq)]
518pub(super) struct ConstraintTerm {
519 metadata: ConstraintTermMetadata,
520 names: Option<ExtensibleBitmap>,
521 names_type_set: Option<TypeSet>,
522}
523
524pub(super) type ConstraintTerms = Vec<ConstraintTerm>;
525
526impl Parse for ConstraintTerm {
527 type Error = anyhow::Error;
528
529 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
530 let tail = bytes;
531
532 let (metadata, tail) = PolicyCursor::parse::<ConstraintTermMetadata>(tail)
533 .context("parsing constraint term metadata")?;
534
535 let (names, names_type_set, tail) = match metadata.constraint_term_type.get() {
536 CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES => {
537 let (names, tail) = ExtensibleBitmap::parse(tail)
538 .map_err(Into::<anyhow::Error>::into)
539 .context("parsing constraint term names")?;
540 let (names_type_set, tail) =
541 TypeSet::parse(tail).context("parsing constraint term names type set")?;
542 (Some(names), Some(names_type_set), tail)
543 }
544 _ => (None, None, tail),
545 };
546
547 Ok((Self { metadata, names, names_type_set }, tail))
548 }
549}
550
551impl ConstraintTerm {
552 pub(super) fn constraint_term_type(&self) -> u32 {
553 self.metadata.constraint_term_type.get()
554 }
555
556 pub(super) fn expr_operand_type(&self) -> u32 {
557 self.metadata.expr_operand_type.get()
558 }
559
560 pub(super) fn expr_operator_type(&self) -> u32 {
561 self.metadata.expr_operator_type.get()
562 }
563
564 pub(super) fn names(&self) -> Option<&ExtensibleBitmap> {
565 self.names.as_ref()
566 }
567
568 #[allow(dead_code)]
572 pub(super) fn names_type_set(&self) -> &Option<TypeSet> {
573 &self.names_type_set
574 }
575}
576
577#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
578#[repr(C, packed)]
579pub(super) struct ConstraintTermMetadata {
580 constraint_term_type: le::U32,
581 expr_operand_type: le::U32,
582 expr_operator_type: le::U32,
583}
584
585impl Validate for ConstraintTermMetadata {
586 type Error = anyhow::Error;
587
588 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
591 if !(self.constraint_term_type > 0
592 && self.constraint_term_type <= CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
593 {
594 return Err(anyhow!("invalid constraint term type"));
595 }
596 if !(self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR
597 || self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
598 {
599 if self.expr_operand_type != 0 {
600 return Err(anyhow!(
601 "invalid operand type {} for constraint term type {}",
602 self.expr_operand_type,
603 self.constraint_term_type
604 ));
605 }
606 if self.expr_operator_type != 0 {
607 return Err(anyhow!(
608 "invalid operator type {} for constraint term type {}",
609 self.expr_operator_type,
610 self.constraint_term_type
611 ));
612 }
613 }
614 Ok(())
617 }
618}
619
620#[derive(Debug, PartialEq)]
621pub(super) struct TypeSet {
622 types: ExtensibleBitmap,
623 negative_set: ExtensibleBitmap,
624 flags: le::U32,
625}
626
627impl Parse for TypeSet {
628 type Error = anyhow::Error;
629
630 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
631 let tail = bytes;
632
633 let (types, tail) = ExtensibleBitmap::parse(tail)
634 .map_err(Into::<anyhow::Error>::into)
635 .context("parsing type set types")?;
636
637 let (negative_set, tail) = ExtensibleBitmap::parse(tail)
638 .map_err(Into::<anyhow::Error>::into)
639 .context("parsing type set negative set")?;
640
641 let (flags, tail) = PolicyCursor::parse::<le::U32>(tail)?;
642
643 Ok((Self { types, negative_set, flags }, tail))
644 }
645}
646
647pub(super) fn find_class_by_name<'a>(classes: &'a Classes, name: &str) -> Option<&'a Class> {
650 let name_bytes = name.as_bytes();
651 classes.iter().find(|class| class.name_bytes() == name_bytes)
652}
653
654pub(super) fn find_common_symbol_by_name_bytes<'a>(
658 common_symbols: &'a CommonSymbols,
659 name_bytes: &[u8],
660) -> Option<&'a CommonSymbol> {
661 common_symbols.iter().find(|common_symbol| common_symbol.name_bytes() == name_bytes)
662}
663
664impl Validate for [Class] {
665 type Error = anyhow::Error;
666
667 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
668 for class in self {
670 class.defaults().validate(context).context("class defaults")?;
672 }
673 Ok(())
674 }
675}
676
677#[derive(Debug, PartialEq)]
678pub(super) struct Class {
679 constraints: ClassConstraints,
680 validate_transitions: ClassValidateTransitions,
681 defaults: ClassDefaults,
682}
683
684pub(super) type Classes = Vec<Class>;
685
686impl Class {
687 pub fn common_name_bytes(&self) -> &[u8] {
694 let class_common_key: &ClassCommonKey = &self.constraints.metadata.metadata;
699 &class_common_key.data
700 }
701
702 pub fn name_bytes(&self) -> &[u8] {
704 let class_key: &ClassKey = &self.constraints.metadata.metadata.metadata;
708 &class_key.data
709 }
710
711 pub fn id(&self) -> ClassId {
715 let class_metadata: &ClassMetadata = &self.constraints.metadata.metadata.metadata.metadata;
716 ClassId(NonZeroU32::new(class_metadata.id.get()).unwrap())
717 }
718
719 pub fn permissions(&self) -> &Permissions {
721 &self.constraints.metadata.data
722 }
723
724 pub fn constraints(&self) -> &Vec<Constraint> {
732 &self.constraints.data
733 }
734
735 pub fn defaults(&self) -> &ClassDefaults {
736 &self.defaults
737 }
738}
739
740impl Parse for Class {
741 type Error = anyhow::Error;
742
743 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
744 let tail = bytes;
745
746 let (constraints, tail) = ClassConstraints::parse(tail)
747 .map_err(Into::<anyhow::Error>::into)
748 .context("parsing class constraints")?;
749
750 let (validate_transitions, tail) = ClassValidateTransitions::parse(tail)
751 .map_err(Into::<anyhow::Error>::into)
752 .context("parsing class validate transitions")?;
753
754 let (defaults, tail) =
755 PolicyCursor::parse::<ClassDefaults>(tail).context("parsing class defaults")?;
756
757 Ok((Self { constraints, validate_transitions, defaults }, tail))
758 }
759}
760
761#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
762#[repr(C, packed)]
763pub(super) struct ClassDefaults {
764 default_user: le::U32,
765 default_role: le::U32,
766 default_range: le::U32,
767 default_type: le::U32,
768}
769
770impl ClassDefaults {
771 pub fn user(&self) -> ClassDefault {
772 self.default_user.get().into()
773 }
774
775 pub fn role(&self) -> ClassDefault {
776 self.default_role.get().into()
777 }
778
779 pub fn range(&self) -> ClassDefaultRange {
780 self.default_range.get().into()
781 }
782
783 pub fn type_(&self) -> ClassDefault {
784 self.default_type.get().into()
785 }
786}
787
788impl Validate for ClassDefaults {
789 type Error = anyhow::Error;
790
791 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
792 ClassDefault::validate(self.default_user.get()).context("default user")?;
793 ClassDefault::validate(self.default_role.get()).context("default role")?;
794 ClassDefault::validate(self.default_type.get()).context("default type")?;
795 ClassDefaultRange::validate(self.default_range.get()).context("default range")?;
796 Ok(())
797 }
798}
799
800#[derive(PartialEq)]
801pub(super) enum ClassDefault {
802 Unspecified,
803 Source,
804 Target,
805}
806
807impl ClassDefault {
808 pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
809 pub(super) const DEFAULT_SOURCE: u32 = 1;
810 pub(super) const DEFAULT_TARGET: u32 = 2;
811
812 fn validate(value: u32) -> Result<(), ValidateError> {
813 match value {
814 Self::DEFAULT_UNSPECIFIED | Self::DEFAULT_SOURCE | Self::DEFAULT_TARGET => Ok(()),
815 value => Err(ValidateError::InvalidClassDefault { value }),
816 }
817 }
818}
819
820impl From<u32> for ClassDefault {
821 fn from(value: u32) -> Self {
822 match value {
823 Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
824 Self::DEFAULT_SOURCE => Self::Source,
825 Self::DEFAULT_TARGET => Self::Target,
826 v => panic!(
827 "invalid SELinux class default; expected {}, {}, or {}, but got {}",
828 Self::DEFAULT_UNSPECIFIED,
829 Self::DEFAULT_SOURCE,
830 Self::DEFAULT_TARGET,
831 v
832 ),
833 }
834 }
835}
836
837#[derive(PartialEq)]
838pub(super) enum ClassDefaultRange {
839 Unspecified,
840 SourceLow,
841 SourceHigh,
842 SourceLowHigh,
843 TargetLow,
844 TargetHigh,
845 TargetLowHigh,
846}
847
848impl ClassDefaultRange {
849 pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
850 pub(super) const DEFAULT_SOURCE_LOW: u32 = 1;
851 pub(super) const DEFAULT_SOURCE_HIGH: u32 = 2;
852 pub(super) const DEFAULT_SOURCE_LOW_HIGH: u32 = 3;
853 pub(super) const DEFAULT_TARGET_LOW: u32 = 4;
854 pub(super) const DEFAULT_TARGET_HIGH: u32 = 5;
855 pub(super) const DEFAULT_TARGET_LOW_HIGH: u32 = 6;
856 pub(super) const DEFAULT_UNKNOWN_USED_VALUE: u32 = 7;
858
859 fn validate(value: u32) -> Result<(), ValidateError> {
860 match value {
861 Self::DEFAULT_UNSPECIFIED
862 | Self::DEFAULT_SOURCE_LOW
863 | Self::DEFAULT_SOURCE_HIGH
864 | Self::DEFAULT_SOURCE_LOW_HIGH
865 | Self::DEFAULT_TARGET_LOW
866 | Self::DEFAULT_TARGET_HIGH
867 | Self::DEFAULT_TARGET_LOW_HIGH
868 | Self::DEFAULT_UNKNOWN_USED_VALUE => Ok(()),
869 value => Err(ValidateError::InvalidClassDefaultRange { value }),
870 }
871 }
872}
873
874impl From<u32> for ClassDefaultRange {
875 fn from(value: u32) -> Self {
876 match value {
877 Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
878 Self::DEFAULT_SOURCE_LOW => Self::SourceLow,
879 Self::DEFAULT_SOURCE_HIGH => Self::SourceHigh,
880 Self::DEFAULT_SOURCE_LOW_HIGH => Self::SourceLowHigh,
881 Self::DEFAULT_TARGET_LOW => Self::TargetLow,
882 Self::DEFAULT_TARGET_HIGH => Self::TargetHigh,
883 Self::DEFAULT_TARGET_LOW_HIGH => Self::TargetLowHigh,
884 v => panic!(
885 "invalid SELinux MLS range default; expected one of {:?}, but got {}",
886 [
887 Self::DEFAULT_UNSPECIFIED,
888 Self::DEFAULT_SOURCE_LOW,
889 Self::DEFAULT_SOURCE_HIGH,
890 Self::DEFAULT_SOURCE_LOW_HIGH,
891 Self::DEFAULT_TARGET_LOW,
892 Self::DEFAULT_TARGET_HIGH,
893 Self::DEFAULT_TARGET_LOW_HIGH,
894 ],
895 v
896 ),
897 }
898 }
899}
900
901array_type!(ClassValidateTransitions, ClassValidateTransitionsCount, ConstraintTerms);
902
903array_type_validate_deref_metadata_data_vec!(ClassValidateTransitions);
904
905impl ValidateArray<ClassValidateTransitionsCount, ConstraintTerm> for ClassValidateTransitions {
906 type Error = anyhow::Error;
907
908 fn validate_array(
910 _context: &mut PolicyValidationContext,
911 _metadata: &ClassValidateTransitionsCount,
912 _items: &[ConstraintTerm],
913 ) -> Result<(), Self::Error> {
914 Ok(())
915 }
916}
917
918#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
919#[repr(C, packed)]
920pub(super) struct ClassValidateTransitionsCount(le::U32);
921
922impl Counted for ClassValidateTransitionsCount {
923 fn count(&self) -> u32 {
924 self.0.get()
925 }
926}
927
928impl Validate for ClassValidateTransitionsCount {
929 type Error = anyhow::Error;
930
931 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
933 Ok(())
934 }
935}
936
937array_type!(ClassConstraints, ClassPermissions, Constraints);
938
939array_type_validate_deref_none_data_vec!(ClassConstraints);
940
941impl ValidateArray<ClassPermissions, Constraint> for ClassConstraints {
942 type Error = anyhow::Error;
943
944 fn validate_array(
946 _context: &mut PolicyValidationContext,
947 _metadata: &ClassPermissions,
948 _items: &[Constraint],
949 ) -> Result<(), Self::Error> {
950 Ok(())
951 }
952}
953
954array_type!(ClassPermissions, ClassCommonKey, Permissions);
955
956array_type_validate_deref_none_data_vec!(ClassPermissions);
957
958impl ValidateArray<ClassCommonKey, Permission> for ClassPermissions {
959 type Error = anyhow::Error;
960
961 fn validate_array(
963 _context: &mut PolicyValidationContext,
964 _metadata: &ClassCommonKey,
965 _items: &[Permission],
966 ) -> Result<(), Self::Error> {
967 Ok(())
968 }
969}
970
971impl Counted for ClassPermissions {
972 fn count(&self) -> u32 {
974 self.metadata.metadata.metadata.constraint_count.get()
975 }
976}
977
978array_type!(ClassCommonKey, ClassKey, Vec<u8>);
979
980array_type_validate_deref_data!(ClassCommonKey);
981
982impl ValidateArray<ClassKey, u8> for ClassCommonKey {
983 type Error = anyhow::Error;
984
985 fn validate_array(
987 _context: &mut PolicyValidationContext,
988 _metadata: &ClassKey,
989 _items: &[u8],
990 ) -> Result<(), Self::Error> {
991 Ok(())
992 }
993}
994
995impl Counted for ClassCommonKey {
996 fn count(&self) -> u32 {
998 self.metadata.metadata.elements_count.get()
999 }
1000}
1001
1002array_type!(ClassKey, ClassMetadata, Vec<u8>);
1003
1004array_type_validate_deref_both!(ClassKey);
1005
1006impl ValidateArray<ClassMetadata, u8> for ClassKey {
1007 type Error = anyhow::Error;
1008
1009 fn validate_array(
1011 _context: &mut PolicyValidationContext,
1012 _metadata: &ClassMetadata,
1013 _items: &[u8],
1014 ) -> Result<(), Self::Error> {
1015 Ok(())
1016 }
1017}
1018
1019impl Counted for ClassKey {
1020 fn count(&self) -> u32 {
1022 self.metadata.common_key_length.get()
1023 }
1024}
1025
1026#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1027#[repr(C, packed)]
1028pub(super) struct ClassMetadata {
1029 key_length: le::U32,
1030 common_key_length: le::U32,
1031 id: le::U32,
1032 primary_names_count: le::U32,
1033 elements_count: le::U32,
1034 constraint_count: le::U32,
1035}
1036
1037impl Counted for ClassMetadata {
1038 fn count(&self) -> u32 {
1039 self.key_length.get()
1040 }
1041}
1042
1043impl Validate for ClassMetadata {
1044 type Error = anyhow::Error;
1045
1046 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1048 if self.id.get() == 0 {
1049 return Err(ValidateError::NonOptionalIdIsZero.into());
1050 } else {
1051 Ok(())
1052 }
1053 }
1054}
1055
1056impl Validate for [Role] {
1057 type Error = anyhow::Error;
1058
1059 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1061 Ok(())
1062 }
1063}
1064
1065#[derive(Debug, PartialEq)]
1066pub(super) struct Role {
1067 metadata: RoleMetadata,
1068 role_dominates: ExtensibleBitmap,
1069 role_types: ExtensibleBitmap,
1070}
1071
1072impl Role {
1073 pub(super) fn id(&self) -> RoleId {
1074 RoleId(NonZeroU32::new(self.metadata.metadata.id.get()).unwrap())
1075 }
1076
1077 pub(super) fn name_bytes(&self) -> &[u8] {
1078 &self.metadata.data
1079 }
1080
1081 pub(super) fn types(&self) -> &ExtensibleBitmap {
1082 &self.role_types
1083 }
1084}
1085
1086impl Parse for Role {
1087 type Error = anyhow::Error;
1088
1089 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1090 let tail = bytes;
1091
1092 let (metadata, tail) = RoleMetadata::parse(tail)
1093 .map_err(Into::<anyhow::Error>::into)
1094 .context("parsing role metadata")?;
1095
1096 let (role_dominates, tail) = ExtensibleBitmap::parse(tail)
1097 .map_err(Into::<anyhow::Error>::into)
1098 .context("parsing role dominates")?;
1099
1100 let (role_types, tail) = ExtensibleBitmap::parse(tail)
1101 .map_err(Into::<anyhow::Error>::into)
1102 .context("parsing role types")?;
1103
1104 Ok((Self { metadata, role_dominates, role_types }, tail))
1105 }
1106}
1107
1108array_type!(RoleMetadata, RoleStaticMetadata, Vec<u8>);
1109
1110array_type_validate_deref_both!(RoleMetadata);
1111
1112impl ValidateArray<RoleStaticMetadata, u8> for RoleMetadata {
1113 type Error = anyhow::Error;
1114
1115 fn validate_array(
1117 _context: &mut PolicyValidationContext,
1118 _metadata: &RoleStaticMetadata,
1119 _items: &[u8],
1120 ) -> Result<(), Self::Error> {
1121 Ok(())
1122 }
1123}
1124
1125#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1126#[repr(C, packed)]
1127pub(super) struct RoleStaticMetadata {
1128 length: le::U32,
1129 id: le::U32,
1130 bounds: le::U32,
1131}
1132
1133impl Counted for RoleStaticMetadata {
1134 fn count(&self) -> u32 {
1136 self.length.get()
1137 }
1138}
1139
1140impl Validate for RoleStaticMetadata {
1141 type Error = anyhow::Error;
1142
1143 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1145 Ok(())
1146 }
1147}
1148
1149impl Validate for [Type] {
1150 type Error = anyhow::Error;
1151
1152 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1154 Ok(())
1155 }
1156}
1157
1158array_type!(Type, TypeMetadata, Vec<u8>);
1159
1160array_type_validate_deref_both!(Type);
1161
1162impl Type {
1163 pub fn name_bytes(&self) -> &[u8] {
1165 &self.data
1166 }
1167
1168 pub fn id(&self) -> TypeId {
1172 TypeId(NonZeroU32::new(self.metadata.id.get()).unwrap())
1173 }
1174
1175 pub fn bounded_by(&self) -> Option<TypeId> {
1177 NonZeroU32::new(self.metadata.bounds.get()).map(|id| TypeId(id))
1178 }
1179
1180 #[allow(dead_code)]
1184 pub fn is_type(&self) -> bool {
1185 self.metadata.properties.get() == TYPE_PROPERTIES_TYPE
1186 }
1187
1188 #[allow(dead_code)]
1193 pub fn is_alias(&self) -> bool {
1194 self.metadata.properties.get() == TYPE_PROPERTIES_ALIAS
1195 }
1196
1197 #[allow(dead_code)]
1201 pub fn is_attribute(&self) -> bool {
1202 self.metadata.properties.get() == TYPE_PROPERTIES_ATTRIBUTE
1203 }
1204}
1205
1206impl ValidateArray<TypeMetadata, u8> for Type {
1207 type Error = anyhow::Error;
1208
1209 fn validate_array(
1211 _context: &mut PolicyValidationContext,
1212 _metadata: &TypeMetadata,
1213 _items: &[u8],
1214 ) -> Result<(), Self::Error> {
1215 Ok(())
1216 }
1217}
1218
1219#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1220#[repr(C, packed)]
1221pub(super) struct TypeMetadata {
1222 length: le::U32,
1223 id: le::U32,
1224 properties: le::U32,
1225 bounds: le::U32,
1226}
1227
1228impl Counted for TypeMetadata {
1229 fn count(&self) -> u32 {
1230 self.length.get()
1231 }
1232}
1233
1234impl Validate for TypeMetadata {
1235 type Error = anyhow::Error;
1236
1237 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1239 Ok(())
1240 }
1241}
1242
1243impl Validate for [User] {
1244 type Error = anyhow::Error;
1245
1246 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1248 Ok(())
1249 }
1250}
1251
1252#[derive(Debug, PartialEq)]
1253pub(super) struct User {
1254 user_data: UserData,
1255 roles: ExtensibleBitmap,
1256 expanded_range: MlsRange,
1257 default_level: MlsLevel,
1258}
1259
1260impl User {
1261 pub(super) fn id(&self) -> UserId {
1262 UserId(NonZeroU32::new(self.user_data.metadata.id.get()).unwrap())
1263 }
1264
1265 pub(super) fn name_bytes(&self) -> &[u8] {
1266 &self.user_data.data
1267 }
1268
1269 pub(super) fn roles(&self) -> &ExtensibleBitmap {
1270 &self.roles
1271 }
1272
1273 pub(super) fn mls_range(&self) -> &MlsRange {
1274 &self.expanded_range
1275 }
1276}
1277
1278impl Parse for User {
1279 type Error = anyhow::Error;
1280
1281 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1282 let tail = bytes;
1283
1284 let (user_data, tail) = UserData::parse(tail)
1285 .map_err(Into::<anyhow::Error>::into)
1286 .context("parsing user data")?;
1287
1288 let (roles, tail) = ExtensibleBitmap::parse(tail)
1289 .map_err(Into::<anyhow::Error>::into)
1290 .context("parsing user roles")?;
1291
1292 let (expanded_range, tail) =
1293 MlsRange::parse(tail).context("parsing user expanded range")?;
1294
1295 let (default_level, tail) = MlsLevel::parse(tail).context("parsing user default level")?;
1296
1297 Ok((Self { user_data, roles, expanded_range, default_level }, tail))
1298 }
1299}
1300
1301array_type!(UserData, UserMetadata, Vec<u8>);
1302
1303array_type_validate_deref_both!(UserData);
1304
1305impl ValidateArray<UserMetadata, u8> for UserData {
1306 type Error = anyhow::Error;
1307
1308 fn validate_array(
1310 _context: &mut PolicyValidationContext,
1311 _metadata: &UserMetadata,
1312 _items: &[u8],
1313 ) -> Result<(), Self::Error> {
1314 Ok(())
1315 }
1316}
1317
1318#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1319#[repr(C, packed)]
1320pub(super) struct UserMetadata {
1321 length: le::U32,
1322 id: le::U32,
1323 bounds: le::U32,
1324}
1325
1326impl Counted for UserMetadata {
1327 fn count(&self) -> u32 {
1328 self.length.get()
1329 }
1330}
1331
1332impl Validate for UserMetadata {
1333 type Error = anyhow::Error;
1334
1335 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1337 Ok(())
1338 }
1339}
1340
1341#[derive(Debug, PartialEq)]
1342pub(super) struct MlsLevel {
1343 sensitivity: le::U32,
1344 categories: ExtensibleBitmap,
1345}
1346
1347impl MlsLevel {
1348 pub fn category_ids(&self) -> impl Iterator<Item = CategoryId> + use<'_> {
1349 self.categories.indices_of_set_bits().map(|i| CategoryId(NonZeroU32::new(i + 1).unwrap()))
1350 }
1351}
1352
1353impl Parse for MlsLevel {
1354 type Error = anyhow::Error;
1355
1356 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1357 let tail = bytes;
1358
1359 let (sensitivity, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1360
1361 let (categories, tail) = ExtensibleBitmap::parse(tail)
1362 .map_err(Into::<anyhow::Error>::into)
1363 .context("parsing mls level categories")?;
1364
1365 Ok((Self { sensitivity, categories }, tail))
1366 }
1367}
1368
1369impl<'a> Level<'a, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a>> for MlsLevel {
1370 fn sensitivity(&self) -> SensitivityId {
1371 SensitivityId(NonZeroU32::new(self.sensitivity.get()).unwrap())
1372 }
1373
1374 fn category_spans(
1375 &'a self,
1376 ) -> CategoryIterator<ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a>> {
1377 CategoryIterator::new(self.categories.spans())
1378 }
1379}
1380
1381#[derive(Debug, PartialEq)]
1382pub(super) struct MlsRange {
1383 count: le::U32,
1384 low: MlsLevel,
1385 high: Option<MlsLevel>,
1386}
1387
1388impl MlsRange {
1389 pub fn low(&self) -> &MlsLevel {
1390 &self.low
1391 }
1392
1393 pub fn high(&self) -> &Option<MlsLevel> {
1394 &self.high
1395 }
1396}
1397
1398impl Parse for MlsRange {
1399 type Error = anyhow::Error;
1400
1401 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1402 let tail = bytes;
1403
1404 let (count, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1405
1406 let (sensitivity_low, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1410
1411 let (low_categories, high_level, tail) = if count.get() > 1 {
1412 let (sensitivity_high, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1413 let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1414 .map_err(Into::<anyhow::Error>::into)
1415 .context("parsing mls range low categories")?;
1416 let (high_categories, tail) = ExtensibleBitmap::parse(tail)
1417 .map_err(Into::<anyhow::Error>::into)
1418 .context("parsing mls range high categories")?;
1419
1420 (
1421 low_categories,
1422 Some(MlsLevel { sensitivity: sensitivity_high, categories: high_categories }),
1423 tail,
1424 )
1425 } else {
1426 let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1427 .map_err(Into::<anyhow::Error>::into)
1428 .context("parsing mls range low categories")?;
1429
1430 (low_categories, None, tail)
1431 };
1432
1433 Ok((
1434 Self {
1435 count,
1436 low: MlsLevel { sensitivity: sensitivity_low, categories: low_categories },
1437 high: high_level,
1438 },
1439 tail,
1440 ))
1441 }
1442}
1443
1444impl Validate for [ConditionalBoolean] {
1445 type Error = anyhow::Error;
1446
1447 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1449 Ok(())
1450 }
1451}
1452
1453array_type!(ConditionalBoolean, ConditionalBooleanMetadata, Vec<u8>);
1454
1455array_type_validate_deref_both!(ConditionalBoolean);
1456
1457impl ValidateArray<ConditionalBooleanMetadata, u8> for ConditionalBoolean {
1458 type Error = anyhow::Error;
1459
1460 fn validate_array(
1462 _context: &mut PolicyValidationContext,
1463 _metadata: &ConditionalBooleanMetadata,
1464 _items: &[u8],
1465 ) -> Result<(), Self::Error> {
1466 Ok(())
1467 }
1468}
1469
1470#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1471#[repr(C, packed)]
1472pub(super) struct ConditionalBooleanMetadata {
1473 id: le::U32,
1474 active: le::U32,
1476 length: le::U32,
1477}
1478
1479impl ConditionalBooleanMetadata {
1480 pub(super) fn active(&self) -> bool {
1482 self.active != le::U32::ZERO
1483 }
1484}
1485
1486impl Counted for ConditionalBooleanMetadata {
1487 fn count(&self) -> u32 {
1490 self.length.get()
1491 }
1492}
1493
1494impl Validate for ConditionalBooleanMetadata {
1495 type Error = anyhow::Error;
1496
1497 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1499 Ok(())
1500 }
1501}
1502
1503impl Validate for [Sensitivity] {
1504 type Error = anyhow::Error;
1505
1506 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1508 Ok(())
1509 }
1510}
1511
1512#[derive(Debug, PartialEq)]
1513pub(super) struct Sensitivity {
1514 metadata: SensitivityMetadata,
1515 level: MlsLevel,
1516}
1517
1518impl Sensitivity {
1519 pub fn id(&self) -> SensitivityId {
1520 SensitivityId(NonZeroU32::new(self.level.sensitivity.get()).unwrap())
1521 }
1522
1523 pub fn name_bytes(&self) -> &[u8] {
1524 &self.metadata.data
1525 }
1526}
1527
1528impl Parse for Sensitivity {
1529 type Error = anyhow::Error;
1530
1531 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1532 let tail = bytes;
1533
1534 let (metadata, tail) = SensitivityMetadata::parse(tail)
1535 .map_err(Into::<anyhow::Error>::into)
1536 .context("parsing sensitivity metadata")?;
1537
1538 let (level, tail) = MlsLevel::parse(tail)
1539 .map_err(Into::<anyhow::Error>::into)
1540 .context("parsing sensitivity mls level")?;
1541
1542 Ok((Self { metadata, level }, tail))
1543 }
1544}
1545
1546impl Validate for Sensitivity {
1547 type Error = anyhow::Error;
1548
1549 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1551 NonZeroU32::new(self.level.sensitivity.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1552 Ok(())
1553 }
1554}
1555
1556array_type!(SensitivityMetadata, SensitivityStaticMetadata, Vec<u8>);
1557
1558array_type_validate_deref_both!(SensitivityMetadata);
1559
1560impl ValidateArray<SensitivityStaticMetadata, u8> for SensitivityMetadata {
1561 type Error = anyhow::Error;
1562
1563 fn validate_array(
1565 _context: &mut PolicyValidationContext,
1566 _metadata: &SensitivityStaticMetadata,
1567 _items: &[u8],
1568 ) -> Result<(), Self::Error> {
1569 Ok(())
1570 }
1571}
1572
1573#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1574#[repr(C, packed)]
1575pub(super) struct SensitivityStaticMetadata {
1576 length: le::U32,
1577 is_alias: le::U32,
1578}
1579
1580impl Counted for SensitivityStaticMetadata {
1581 fn count(&self) -> u32 {
1584 self.length.get()
1585 }
1586}
1587
1588impl Validate for SensitivityStaticMetadata {
1589 type Error = anyhow::Error;
1590
1591 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1593 Ok(())
1594 }
1595}
1596
1597impl Validate for [Category] {
1598 type Error = anyhow::Error;
1599
1600 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1602 Ok(())
1603 }
1604}
1605
1606array_type!(Category, CategoryMetadata, Vec<u8>);
1607
1608array_type_validate_deref_both!(Category);
1609
1610impl Category {
1611 pub fn id(&self) -> CategoryId {
1612 CategoryId(NonZeroU32::new(self.metadata.id.get()).unwrap())
1613 }
1614
1615 pub fn name_bytes(&self) -> &[u8] {
1616 &self.data
1617 }
1618}
1619
1620impl ValidateArray<CategoryMetadata, u8> for Category {
1621 type Error = anyhow::Error;
1622
1623 fn validate_array(
1625 _context: &mut PolicyValidationContext,
1626 _metadata: &CategoryMetadata,
1627 _items: &[u8],
1628 ) -> Result<(), Self::Error> {
1629 Ok(())
1630 }
1631}
1632
1633#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1634#[repr(C, packed)]
1635pub(super) struct CategoryMetadata {
1636 length: le::U32,
1637 id: le::U32,
1638 is_alias: le::U32,
1639}
1640
1641impl Counted for CategoryMetadata {
1642 fn count(&self) -> u32 {
1645 self.length.get()
1646 }
1647}
1648
1649impl Validate for CategoryMetadata {
1650 type Error = anyhow::Error;
1651
1652 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1654 NonZeroU32::new(self.id.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1655 Ok(())
1656 }
1657}
1658
1659#[cfg(test)]
1660mod tests {
1661 use super::super::security_context::Level;
1662 use super::super::{CategoryId, SensitivityId, UserId, parse_policy_by_value};
1663 use super::*;
1664
1665 use std::num::NonZeroU32;
1666
1667 #[test]
1668 fn mls_levels_for_user_context() {
1669 const TEST_POLICY: &[u8] = include_bytes! {"../../testdata/micro_policies/multiple_levels_and_categories_policy.pp"};
1670 let policy = parse_policy_by_value(TEST_POLICY.to_vec()).unwrap();
1671 let policy = policy.validate().unwrap();
1672 let parsed_policy = policy.0.parsed_policy();
1673
1674 let user = parsed_policy.user(UserId(NonZeroU32::new(1).expect("user with id 1")));
1675 let mls_range = user.mls_range();
1676 let low_level = mls_range.low();
1677 let high_level = mls_range.high().as_ref().expect("user 1 has a high mls level");
1678
1679 assert_eq!(low_level.sensitivity(), SensitivityId(NonZeroU32::new(1).unwrap()));
1680 assert_eq!(
1681 low_level.category_ids().collect::<Vec<_>>(),
1682 vec![CategoryId(NonZeroU32::new(1).unwrap())]
1683 );
1684
1685 assert_eq!(high_level.sensitivity(), SensitivityId(NonZeroU32::new(2).unwrap()));
1686 assert_eq!(
1687 high_level.category_ids().collect::<Vec<_>>(),
1688 vec![
1689 CategoryId(NonZeroU32::new(1).unwrap()),
1690 CategoryId(NonZeroU32::new(2).unwrap()),
1691 CategoryId(NonZeroU32::new(3).unwrap()),
1692 CategoryId(NonZeroU32::new(4).unwrap()),
1693 CategoryId(NonZeroU32::new(5).unwrap()),
1694 ]
1695 );
1696 }
1697
1698 #[test]
1699 fn parse_mls_constrain_statement() {
1700 let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1701 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1702 let parsed_policy = &policy.0;
1703 parsed_policy.validate().expect("validate policy");
1704
1705 let class = find_class_by_name(parsed_policy.classes(), "class_mls_constraints")
1706 .expect("look up class");
1707 let constraints = class.constraints();
1708 assert_eq!(constraints.len(), 6);
1709 let expected = [
1716 (
1717 CONSTRAINT_TERM_TYPE_EXPR,
1718 CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1719 CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1,
1720 ),
1721 (
1722 CONSTRAINT_TERM_TYPE_EXPR,
1723 CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1724 CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2,
1725 ),
1726 (
1727 CONSTRAINT_TERM_TYPE_EXPR,
1728 CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY,
1729 CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2,
1730 ),
1731 (
1732 CONSTRAINT_TERM_TYPE_EXPR,
1733 CONSTRAINT_EXPR_OPERATOR_TYPE_DOM,
1734 CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2,
1735 ),
1736 (
1737 CONSTRAINT_TERM_TYPE_EXPR,
1738 CONSTRAINT_EXPR_OPERATOR_TYPE_NE,
1739 CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2,
1740 ),
1741 (
1742 CONSTRAINT_TERM_TYPE_EXPR,
1743 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1744 CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2,
1745 ),
1746 ];
1747 for (i, constraint) in constraints.iter().enumerate() {
1748 assert_eq!(constraint.access_vector(), AccessVector(1), "constraint {}", i);
1749 let terms = constraint.constraint_expr().constraint_terms();
1750 assert_eq!(terms.len(), 1, "constraint {}", i);
1751 let term = &terms[0];
1752 assert_eq!(
1753 (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1754 expected[i],
1755 "constraint {}",
1756 i
1757 );
1758 }
1759 }
1760
1761 #[test]
1762 fn parse_constrain_statement() {
1763 let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1764 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1765 let parsed_policy = &policy.0;
1766 parsed_policy.validate().expect("validate policy");
1767
1768 let class = find_class_by_name(parsed_policy.classes(), "class_constraint_nested")
1769 .expect("look up class");
1770 let constraints = class.constraints();
1771 assert_eq!(constraints.len(), 1);
1772 let constraint = &constraints[0];
1773 assert_eq!(constraint.access_vector(), AccessVector(1));
1774 let terms = constraint.constraint_expr().constraint_terms();
1775 assert_eq!(terms.len(), 8);
1776
1777 let expected = [
1783 (
1784 CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES,
1785 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1786 CONSTRAINT_EXPR_OPERAND_TYPE_USER
1787 | CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK,
1788 ),
1789 (
1790 CONSTRAINT_TERM_TYPE_EXPR,
1791 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1792 CONSTRAINT_EXPR_OPERAND_TYPE_ROLE,
1793 ),
1794 (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1795 (
1796 CONSTRAINT_TERM_TYPE_EXPR,
1797 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1798 CONSTRAINT_EXPR_OPERAND_TYPE_USER,
1799 ),
1800 (
1801 CONSTRAINT_TERM_TYPE_EXPR,
1802 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1803 CONSTRAINT_EXPR_OPERAND_TYPE_TYPE,
1804 ),
1805 (CONSTRAINT_TERM_TYPE_NOT_OPERATOR, 0, 0),
1806 (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1807 (CONSTRAINT_TERM_TYPE_OR_OPERATOR, 0, 0),
1808 ];
1809 for (i, term) in terms.iter().enumerate() {
1810 assert_eq!(
1811 (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1812 expected[i],
1813 "term {}",
1814 i
1815 );
1816 }
1817 }
1818}