1use super::constraints::{ConstraintError, evaluate_constraint};
6use super::error::{ParseError, 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::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 ClassPermissionId(NonZeroU32::new(self.metadata.id.get()).unwrap())
360 }
361}
362
363impl ValidateArray<PermissionMetadata, u8> for Permission {
364 type Error = anyhow::Error;
365
366 fn validate_array(
368 _context: &mut PolicyValidationContext,
369 _metadata: &PermissionMetadata,
370 _items: &[u8],
371 ) -> Result<(), Self::Error> {
372 Ok(())
373 }
374}
375
376#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
377#[repr(C, packed)]
378pub(super) struct PermissionMetadata {
379 length: le::U32,
381 id: le::U32,
382}
383
384impl Counted for PermissionMetadata {
385 fn count(&self) -> u32 {
387 self.length.get()
388 }
389}
390
391impl Validate for PermissionMetadata {
392 type Error = anyhow::Error;
393
394 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
396 Ok(())
397 }
398}
399
400pub(super) type Constraints = Vec<Constraint>;
402
403impl Validate for Constraints {
404 type Error = anyhow::Error;
405
406 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
409 Ok(())
410 }
411}
412
413#[derive(Debug, PartialEq)]
417pub(super) struct Constraint {
418 access_vector: le::U32,
419 constraint_expr: ConstraintExpr,
420}
421
422impl Constraint {
423 pub(super) fn access_vector(&self) -> AccessVector {
424 AccessVector(self.access_vector.get())
425 }
426
427 pub(super) fn constraint_expr(&self) -> &ConstraintExpr {
428 &self.constraint_expr
429 }
430}
431
432impl Parse for Constraint {
433 type Error = anyhow::Error;
434
435 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
436 let tail = bytes;
437
438 let num_bytes = tail.len();
439 let (access_vector, tail) = PolicyCursor::parse::<le::U32>(tail).ok_or_else(|| {
440 Into::<anyhow::Error>::into(ParseError::MissingData {
441 type_name: "AccessVector",
442 type_size: std::mem::size_of::<le::U32>(),
443 num_bytes,
444 })
445 })?;
446 let (constraint_expr, tail) = ConstraintExpr::parse(tail)
447 .map_err(|error| anyhow!(error))
448 .context("parsing constraint expression")?;
449
450 Ok((Self { access_vector, constraint_expr }, tail))
451 }
452}
453
454array_type!(ConstraintExpr, ConstraintTermCount, ConstraintTerms);
457
458array_type_validate_deref_metadata_data_vec!(ConstraintExpr);
459
460impl ValidateArray<ConstraintTermCount, ConstraintTerm> for ConstraintExpr {
461 type Error = anyhow::Error;
462
463 fn validate_array(
467 _context: &mut PolicyValidationContext,
468 _metadata: &ConstraintTermCount,
469 _items: &[ConstraintTerm],
470 ) -> Result<(), Self::Error> {
471 Ok(())
472 }
473}
474
475impl ConstraintExpr {
476 pub(super) fn evaluate(
477 &self,
478 source_context: &SecurityContext,
479 target_context: &SecurityContext,
480 ) -> Result<bool, ConstraintError> {
481 evaluate_constraint(&self, source_context, target_context)
482 }
483
484 pub(super) fn constraint_terms(&self) -> &[ConstraintTerm] {
485 &self.data
486 }
487}
488
489#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
490#[repr(C, packed)]
491pub(super) struct ConstraintTermCount(le::U32);
492
493impl Counted for ConstraintTermCount {
494 fn count(&self) -> u32 {
495 self.0.get()
496 }
497}
498
499impl Validate for ConstraintTermCount {
500 type Error = anyhow::Error;
501
502 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
503 Ok(())
504 }
505}
506
507impl Validate for ConstraintTerms {
508 type Error = anyhow::Error;
509
510 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
515 Ok(())
516 }
517}
518
519#[derive(Debug, PartialEq)]
520pub(super) struct ConstraintTerm {
521 metadata: ConstraintTermMetadata,
522 names: Option<ExtensibleBitmap>,
523 names_type_set: Option<TypeSet>,
524}
525
526pub(super) type ConstraintTerms = Vec<ConstraintTerm>;
527
528impl Parse for ConstraintTerm {
529 type Error = anyhow::Error;
530
531 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
532 let tail = bytes;
533
534 let (metadata, tail) = PolicyCursor::parse::<ConstraintTermMetadata>(tail)
535 .context("parsing constraint term metadata")?;
536
537 let (names, names_type_set, tail) = match metadata.constraint_term_type.get() {
538 CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES => {
539 let (names, tail) = ExtensibleBitmap::parse(tail)
540 .map_err(Into::<anyhow::Error>::into)
541 .context("parsing constraint term names")?;
542 let (names_type_set, tail) =
543 TypeSet::parse(tail).context("parsing constraint term names type set")?;
544 (Some(names), Some(names_type_set), tail)
545 }
546 _ => (None, None, tail),
547 };
548
549 Ok((Self { metadata, names, names_type_set }, tail))
550 }
551}
552
553impl ConstraintTerm {
554 pub(super) fn constraint_term_type(&self) -> u32 {
555 self.metadata.constraint_term_type.get()
556 }
557
558 pub(super) fn expr_operand_type(&self) -> u32 {
559 self.metadata.expr_operand_type.get()
560 }
561
562 pub(super) fn expr_operator_type(&self) -> u32 {
563 self.metadata.expr_operator_type.get()
564 }
565
566 pub(super) fn names(&self) -> Option<&ExtensibleBitmap> {
567 self.names.as_ref()
568 }
569
570 #[allow(dead_code)]
574 pub(super) fn names_type_set(&self) -> &Option<TypeSet> {
575 &self.names_type_set
576 }
577}
578
579#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
580#[repr(C, packed)]
581pub(super) struct ConstraintTermMetadata {
582 constraint_term_type: le::U32,
583 expr_operand_type: le::U32,
584 expr_operator_type: le::U32,
585}
586
587impl Validate for ConstraintTermMetadata {
588 type Error = anyhow::Error;
589
590 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
593 if !(self.constraint_term_type > 0
594 && self.constraint_term_type <= CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
595 {
596 return Err(anyhow!("invalid constraint term type"));
597 }
598 if !(self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR
599 || self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
600 {
601 if self.expr_operand_type != 0 {
602 return Err(anyhow!(
603 "invalid operand type {} for constraint term type {}",
604 self.expr_operand_type,
605 self.constraint_term_type
606 ));
607 }
608 if self.expr_operator_type != 0 {
609 return Err(anyhow!(
610 "invalid operator type {} for constraint term type {}",
611 self.expr_operator_type,
612 self.constraint_term_type
613 ));
614 }
615 }
616 Ok(())
619 }
620}
621
622#[derive(Debug, PartialEq)]
623pub(super) struct TypeSet {
624 types: ExtensibleBitmap,
625 negative_set: ExtensibleBitmap,
626 flags: le::U32,
627}
628
629impl Parse for TypeSet {
630 type Error = anyhow::Error;
631
632 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
633 let tail = bytes;
634
635 let (types, tail) = ExtensibleBitmap::parse(tail)
636 .map_err(Into::<anyhow::Error>::into)
637 .context("parsing type set types")?;
638
639 let (negative_set, tail) = ExtensibleBitmap::parse(tail)
640 .map_err(Into::<anyhow::Error>::into)
641 .context("parsing type set negative set")?;
642
643 let num_bytes = tail.len();
644 let (flags, tail) = PolicyCursor::parse::<le::U32>(tail).ok_or_else(|| {
645 Into::<anyhow::Error>::into(ParseError::MissingData {
646 type_name: "TypeSetFlags",
647 type_size: std::mem::size_of::<le::U32>(),
648 num_bytes,
649 })
650 })?;
651
652 Ok((Self { types, negative_set, flags }, tail))
653 }
654}
655
656pub(super) fn find_class_by_name<'a>(classes: &'a Classes, name: &str) -> Option<&'a Class> {
659 find_class_by_name_bytes(classes, name.as_bytes())
660}
661
662fn find_class_by_name_bytes<'a>(classes: &'a Classes, name_bytes: &[u8]) -> Option<&'a Class> {
663 for cls in classes.into_iter() {
664 if cls.name_bytes() == name_bytes {
665 return Some(cls);
666 }
667 }
668
669 None
670}
671
672pub(super) fn find_common_symbol_by_name_bytes<'a>(
676 common_symbols: &'a CommonSymbols,
677 name_bytes: &[u8],
678) -> Option<&'a CommonSymbol> {
679 for common_symbol in common_symbols.into_iter() {
680 if common_symbol.name_bytes() == name_bytes {
681 return Some(common_symbol);
682 }
683 }
684
685 None
686}
687
688impl Validate for [Class] {
689 type Error = anyhow::Error;
690
691 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
692 for class in self {
694 class.defaults().validate(context).context("class defaults")?;
696 }
697 Ok(())
698 }
699}
700
701#[derive(Debug, PartialEq)]
702pub(super) struct Class {
703 constraints: ClassConstraints,
704 validate_transitions: ClassValidateTransitions,
705 defaults: ClassDefaults,
706}
707
708pub(super) type Classes = Vec<Class>;
709
710impl Class {
711 pub fn common_name_bytes(&self) -> &[u8] {
718 let class_common_key: &ClassCommonKey = &self.constraints.metadata.metadata;
723 &class_common_key.data
724 }
725
726 pub fn name_bytes(&self) -> &[u8] {
728 let class_key: &ClassKey = &self.constraints.metadata.metadata.metadata;
732 &class_key.data
733 }
734
735 pub fn id(&self) -> ClassId {
739 let class_metadata: &ClassMetadata = &self.constraints.metadata.metadata.metadata.metadata;
740 ClassId(NonZeroU32::new(class_metadata.id.get()).unwrap())
741 }
742
743 pub fn permissions(&self) -> &Permissions {
745 &self.constraints.metadata.data
746 }
747
748 pub fn constraints(&self) -> &Vec<Constraint> {
756 &self.constraints.data
757 }
758
759 pub fn defaults(&self) -> &ClassDefaults {
760 &self.defaults
761 }
762}
763
764impl Parse for Class {
765 type Error = anyhow::Error;
766
767 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
768 let tail = bytes;
769
770 let (constraints, tail) = ClassConstraints::parse(tail)
771 .map_err(Into::<anyhow::Error>::into)
772 .context("parsing class constraints")?;
773
774 let (validate_transitions, tail) = ClassValidateTransitions::parse(tail)
775 .map_err(Into::<anyhow::Error>::into)
776 .context("parsing class validate transitions")?;
777
778 let (defaults, tail) =
779 PolicyCursor::parse::<ClassDefaults>(tail).context("parsing class defaults")?;
780
781 Ok((Self { constraints, validate_transitions, defaults }, tail))
782 }
783}
784
785#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
786#[repr(C, packed)]
787pub(super) struct ClassDefaults {
788 default_user: le::U32,
789 default_role: le::U32,
790 default_range: le::U32,
791 default_type: le::U32,
792}
793
794impl ClassDefaults {
795 pub fn user(&self) -> ClassDefault {
796 self.default_user.get().into()
797 }
798
799 pub fn role(&self) -> ClassDefault {
800 self.default_role.get().into()
801 }
802
803 pub fn range(&self) -> ClassDefaultRange {
804 self.default_range.get().into()
805 }
806
807 pub fn type_(&self) -> ClassDefault {
808 self.default_type.get().into()
809 }
810}
811
812impl Validate for ClassDefaults {
813 type Error = anyhow::Error;
814
815 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
816 ClassDefault::validate(self.default_user.get()).context("default user")?;
817 ClassDefault::validate(self.default_role.get()).context("default role")?;
818 ClassDefault::validate(self.default_type.get()).context("default type")?;
819 ClassDefaultRange::validate(self.default_range.get()).context("default range")?;
820 Ok(())
821 }
822}
823
824#[derive(PartialEq)]
825pub(super) enum ClassDefault {
826 Unspecified,
827 Source,
828 Target,
829}
830
831impl ClassDefault {
832 pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
833 pub(super) const DEFAULT_SOURCE: u32 = 1;
834 pub(super) const DEFAULT_TARGET: u32 = 2;
835
836 fn validate(value: u32) -> Result<(), ValidateError> {
837 match value {
838 Self::DEFAULT_UNSPECIFIED | Self::DEFAULT_SOURCE | Self::DEFAULT_TARGET => Ok(()),
839 value => Err(ValidateError::InvalidClassDefault { value }),
840 }
841 }
842}
843
844impl From<u32> for ClassDefault {
845 fn from(value: u32) -> Self {
846 match value {
847 Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
848 Self::DEFAULT_SOURCE => Self::Source,
849 Self::DEFAULT_TARGET => Self::Target,
850 v => panic!(
851 "invalid SELinux class default; expected {}, {}, or {}, but got {}",
852 Self::DEFAULT_UNSPECIFIED,
853 Self::DEFAULT_SOURCE,
854 Self::DEFAULT_TARGET,
855 v
856 ),
857 }
858 }
859}
860
861#[derive(PartialEq)]
862pub(super) enum ClassDefaultRange {
863 Unspecified,
864 SourceLow,
865 SourceHigh,
866 SourceLowHigh,
867 TargetLow,
868 TargetHigh,
869 TargetLowHigh,
870}
871
872impl ClassDefaultRange {
873 pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
874 pub(super) const DEFAULT_SOURCE_LOW: u32 = 1;
875 pub(super) const DEFAULT_SOURCE_HIGH: u32 = 2;
876 pub(super) const DEFAULT_SOURCE_LOW_HIGH: u32 = 3;
877 pub(super) const DEFAULT_TARGET_LOW: u32 = 4;
878 pub(super) const DEFAULT_TARGET_HIGH: u32 = 5;
879 pub(super) const DEFAULT_TARGET_LOW_HIGH: u32 = 6;
880 pub(super) const DEFAULT_UNKNOWN_USED_VALUE: u32 = 7;
882
883 fn validate(value: u32) -> Result<(), ValidateError> {
884 match value {
885 Self::DEFAULT_UNSPECIFIED
886 | Self::DEFAULT_SOURCE_LOW
887 | Self::DEFAULT_SOURCE_HIGH
888 | Self::DEFAULT_SOURCE_LOW_HIGH
889 | Self::DEFAULT_TARGET_LOW
890 | Self::DEFAULT_TARGET_HIGH
891 | Self::DEFAULT_TARGET_LOW_HIGH
892 | Self::DEFAULT_UNKNOWN_USED_VALUE => Ok(()),
893 value => Err(ValidateError::InvalidClassDefaultRange { value }),
894 }
895 }
896}
897
898impl From<u32> for ClassDefaultRange {
899 fn from(value: u32) -> Self {
900 match value {
901 Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
902 Self::DEFAULT_SOURCE_LOW => Self::SourceLow,
903 Self::DEFAULT_SOURCE_HIGH => Self::SourceHigh,
904 Self::DEFAULT_SOURCE_LOW_HIGH => Self::SourceLowHigh,
905 Self::DEFAULT_TARGET_LOW => Self::TargetLow,
906 Self::DEFAULT_TARGET_HIGH => Self::TargetHigh,
907 Self::DEFAULT_TARGET_LOW_HIGH => Self::TargetLowHigh,
908 v => panic!(
909 "invalid SELinux MLS range default; expected one of {:?}, but got {}",
910 [
911 Self::DEFAULT_UNSPECIFIED,
912 Self::DEFAULT_SOURCE_LOW,
913 Self::DEFAULT_SOURCE_HIGH,
914 Self::DEFAULT_SOURCE_LOW_HIGH,
915 Self::DEFAULT_TARGET_LOW,
916 Self::DEFAULT_TARGET_HIGH,
917 Self::DEFAULT_TARGET_LOW_HIGH,
918 ],
919 v
920 ),
921 }
922 }
923}
924
925array_type!(ClassValidateTransitions, ClassValidateTransitionsCount, ConstraintTerms);
926
927array_type_validate_deref_metadata_data_vec!(ClassValidateTransitions);
928
929impl ValidateArray<ClassValidateTransitionsCount, ConstraintTerm> for ClassValidateTransitions {
930 type Error = anyhow::Error;
931
932 fn validate_array(
934 _context: &mut PolicyValidationContext,
935 _metadata: &ClassValidateTransitionsCount,
936 _items: &[ConstraintTerm],
937 ) -> Result<(), Self::Error> {
938 Ok(())
939 }
940}
941
942#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
943#[repr(C, packed)]
944pub(super) struct ClassValidateTransitionsCount(le::U32);
945
946impl Counted for ClassValidateTransitionsCount {
947 fn count(&self) -> u32 {
948 self.0.get()
949 }
950}
951
952impl Validate for ClassValidateTransitionsCount {
953 type Error = anyhow::Error;
954
955 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
957 Ok(())
958 }
959}
960
961array_type!(ClassConstraints, ClassPermissions, Constraints);
962
963array_type_validate_deref_none_data_vec!(ClassConstraints);
964
965impl ValidateArray<ClassPermissions, Constraint> for ClassConstraints {
966 type Error = anyhow::Error;
967
968 fn validate_array(
970 _context: &mut PolicyValidationContext,
971 _metadata: &ClassPermissions,
972 _items: &[Constraint],
973 ) -> Result<(), Self::Error> {
974 Ok(())
975 }
976}
977
978array_type!(ClassPermissions, ClassCommonKey, Permissions);
979
980array_type_validate_deref_none_data_vec!(ClassPermissions);
981
982impl ValidateArray<ClassCommonKey, Permission> for ClassPermissions {
983 type Error = anyhow::Error;
984
985 fn validate_array(
987 _context: &mut PolicyValidationContext,
988 _metadata: &ClassCommonKey,
989 _items: &[Permission],
990 ) -> Result<(), Self::Error> {
991 Ok(())
992 }
993}
994
995impl Counted for ClassPermissions {
996 fn count(&self) -> u32 {
998 self.metadata.metadata.metadata.constraint_count.get()
999 }
1000}
1001
1002array_type!(ClassCommonKey, ClassKey, Vec<u8>);
1003
1004array_type_validate_deref_data!(ClassCommonKey);
1005
1006impl ValidateArray<ClassKey, u8> for ClassCommonKey {
1007 type Error = anyhow::Error;
1008
1009 fn validate_array(
1011 _context: &mut PolicyValidationContext,
1012 _metadata: &ClassKey,
1013 _items: &[u8],
1014 ) -> Result<(), Self::Error> {
1015 Ok(())
1016 }
1017}
1018
1019impl Counted for ClassCommonKey {
1020 fn count(&self) -> u32 {
1022 self.metadata.metadata.elements_count.get()
1023 }
1024}
1025
1026array_type!(ClassKey, ClassMetadata, Vec<u8>);
1027
1028array_type_validate_deref_both!(ClassKey);
1029
1030impl ValidateArray<ClassMetadata, u8> for ClassKey {
1031 type Error = anyhow::Error;
1032
1033 fn validate_array(
1035 _context: &mut PolicyValidationContext,
1036 _metadata: &ClassMetadata,
1037 _items: &[u8],
1038 ) -> Result<(), Self::Error> {
1039 Ok(())
1040 }
1041}
1042
1043impl Counted for ClassKey {
1044 fn count(&self) -> u32 {
1046 self.metadata.common_key_length.get()
1047 }
1048}
1049
1050#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1051#[repr(C, packed)]
1052pub(super) struct ClassMetadata {
1053 key_length: le::U32,
1054 common_key_length: le::U32,
1055 id: le::U32,
1056 primary_names_count: le::U32,
1057 elements_count: le::U32,
1058 constraint_count: le::U32,
1059}
1060
1061impl Counted for ClassMetadata {
1062 fn count(&self) -> u32 {
1063 self.key_length.get()
1064 }
1065}
1066
1067impl Validate for ClassMetadata {
1068 type Error = anyhow::Error;
1069
1070 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1072 if self.id.get() == 0 {
1073 return Err(ValidateError::NonOptionalIdIsZero.into());
1074 } else {
1075 Ok(())
1076 }
1077 }
1078}
1079
1080impl Validate for [Role] {
1081 type Error = anyhow::Error;
1082
1083 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1085 Ok(())
1086 }
1087}
1088
1089#[derive(Debug, PartialEq)]
1090pub(super) struct Role {
1091 metadata: RoleMetadata,
1092 role_dominates: ExtensibleBitmap,
1093 role_types: ExtensibleBitmap,
1094}
1095
1096impl Role {
1097 pub(super) fn id(&self) -> RoleId {
1098 RoleId(NonZeroU32::new(self.metadata.metadata.id.get()).unwrap())
1099 }
1100
1101 pub(super) fn name_bytes(&self) -> &[u8] {
1102 &self.metadata.data
1103 }
1104
1105 pub(super) fn types(&self) -> &ExtensibleBitmap {
1106 &self.role_types
1107 }
1108}
1109
1110impl Parse for Role {
1111 type Error = anyhow::Error;
1112
1113 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1114 let tail = bytes;
1115
1116 let (metadata, tail) = RoleMetadata::parse(tail)
1117 .map_err(Into::<anyhow::Error>::into)
1118 .context("parsing role metadata")?;
1119
1120 let (role_dominates, tail) = ExtensibleBitmap::parse(tail)
1121 .map_err(Into::<anyhow::Error>::into)
1122 .context("parsing role dominates")?;
1123
1124 let (role_types, tail) = ExtensibleBitmap::parse(tail)
1125 .map_err(Into::<anyhow::Error>::into)
1126 .context("parsing role types")?;
1127
1128 Ok((Self { metadata, role_dominates, role_types }, tail))
1129 }
1130}
1131
1132array_type!(RoleMetadata, RoleStaticMetadata, Vec<u8>);
1133
1134array_type_validate_deref_both!(RoleMetadata);
1135
1136impl ValidateArray<RoleStaticMetadata, u8> for RoleMetadata {
1137 type Error = anyhow::Error;
1138
1139 fn validate_array(
1141 _context: &mut PolicyValidationContext,
1142 _metadata: &RoleStaticMetadata,
1143 _items: &[u8],
1144 ) -> Result<(), Self::Error> {
1145 Ok(())
1146 }
1147}
1148
1149#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1150#[repr(C, packed)]
1151pub(super) struct RoleStaticMetadata {
1152 length: le::U32,
1153 id: le::U32,
1154 bounds: le::U32,
1155}
1156
1157impl Counted for RoleStaticMetadata {
1158 fn count(&self) -> u32 {
1160 self.length.get()
1161 }
1162}
1163
1164impl Validate for RoleStaticMetadata {
1165 type Error = anyhow::Error;
1166
1167 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1169 Ok(())
1170 }
1171}
1172
1173impl Validate for [Type] {
1174 type Error = anyhow::Error;
1175
1176 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1178 Ok(())
1179 }
1180}
1181
1182array_type!(Type, TypeMetadata, Vec<u8>);
1183
1184array_type_validate_deref_both!(Type);
1185
1186impl Type {
1187 pub fn name_bytes(&self) -> &[u8] {
1189 &self.data
1190 }
1191
1192 pub fn id(&self) -> TypeId {
1196 TypeId(NonZeroU32::new(self.metadata.id.get()).unwrap())
1197 }
1198
1199 pub fn bounded_by(&self) -> Option<TypeId> {
1201 NonZeroU32::new(self.metadata.bounds.get()).map(|id| TypeId(id))
1202 }
1203
1204 #[allow(dead_code)]
1208 pub fn is_type(&self) -> bool {
1209 self.metadata.properties.get() == TYPE_PROPERTIES_TYPE
1210 }
1211
1212 #[allow(dead_code)]
1217 pub fn is_alias(&self) -> bool {
1218 self.metadata.properties.get() == TYPE_PROPERTIES_ALIAS
1219 }
1220
1221 #[allow(dead_code)]
1225 pub fn is_attribute(&self) -> bool {
1226 self.metadata.properties.get() == TYPE_PROPERTIES_ATTRIBUTE
1227 }
1228}
1229
1230impl ValidateArray<TypeMetadata, u8> for Type {
1231 type Error = anyhow::Error;
1232
1233 fn validate_array(
1235 _context: &mut PolicyValidationContext,
1236 _metadata: &TypeMetadata,
1237 _items: &[u8],
1238 ) -> Result<(), Self::Error> {
1239 Ok(())
1240 }
1241}
1242
1243#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1244#[repr(C, packed)]
1245pub(super) struct TypeMetadata {
1246 length: le::U32,
1247 id: le::U32,
1248 properties: le::U32,
1249 bounds: le::U32,
1250}
1251
1252impl Counted for TypeMetadata {
1253 fn count(&self) -> u32 {
1254 self.length.get()
1255 }
1256}
1257
1258impl Validate for TypeMetadata {
1259 type Error = anyhow::Error;
1260
1261 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1263 Ok(())
1264 }
1265}
1266
1267impl Validate for [User] {
1268 type Error = anyhow::Error;
1269
1270 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1272 Ok(())
1273 }
1274}
1275
1276#[derive(Debug, PartialEq)]
1277pub(super) struct User {
1278 user_data: UserData,
1279 roles: ExtensibleBitmap,
1280 expanded_range: MlsRange,
1281 default_level: MlsLevel,
1282}
1283
1284impl User {
1285 pub(super) fn id(&self) -> UserId {
1286 UserId(NonZeroU32::new(self.user_data.metadata.id.get()).unwrap())
1287 }
1288
1289 pub(super) fn name_bytes(&self) -> &[u8] {
1290 &self.user_data.data
1291 }
1292
1293 pub(super) fn roles(&self) -> &ExtensibleBitmap {
1294 &self.roles
1295 }
1296
1297 pub(super) fn mls_range(&self) -> &MlsRange {
1298 &self.expanded_range
1299 }
1300}
1301
1302impl Parse for User {
1303 type Error = anyhow::Error;
1304
1305 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1306 let tail = bytes;
1307
1308 let (user_data, tail) = UserData::parse(tail)
1309 .map_err(Into::<anyhow::Error>::into)
1310 .context("parsing user data")?;
1311
1312 let (roles, tail) = ExtensibleBitmap::parse(tail)
1313 .map_err(Into::<anyhow::Error>::into)
1314 .context("parsing user roles")?;
1315
1316 let (expanded_range, tail) =
1317 MlsRange::parse(tail).context("parsing user expanded range")?;
1318
1319 let (default_level, tail) = MlsLevel::parse(tail).context("parsing user default level")?;
1320
1321 Ok((Self { user_data, roles, expanded_range, default_level }, tail))
1322 }
1323}
1324
1325array_type!(UserData, UserMetadata, Vec<u8>);
1326
1327array_type_validate_deref_both!(UserData);
1328
1329impl ValidateArray<UserMetadata, u8> for UserData {
1330 type Error = anyhow::Error;
1331
1332 fn validate_array(
1334 _context: &mut PolicyValidationContext,
1335 _metadata: &UserMetadata,
1336 _items: &[u8],
1337 ) -> Result<(), Self::Error> {
1338 Ok(())
1339 }
1340}
1341
1342#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1343#[repr(C, packed)]
1344pub(super) struct UserMetadata {
1345 length: le::U32,
1346 id: le::U32,
1347 bounds: le::U32,
1348}
1349
1350impl Counted for UserMetadata {
1351 fn count(&self) -> u32 {
1352 self.length.get()
1353 }
1354}
1355
1356impl Validate for UserMetadata {
1357 type Error = anyhow::Error;
1358
1359 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1361 Ok(())
1362 }
1363}
1364
1365#[derive(Debug, PartialEq)]
1366pub(super) struct MlsLevel {
1367 sensitivity: le::U32,
1368 categories: ExtensibleBitmap,
1369}
1370
1371impl MlsLevel {
1372 pub fn category_ids(&self) -> impl Iterator<Item = CategoryId> + use<'_> {
1373 self.categories.indices_of_set_bits().map(|i| CategoryId(NonZeroU32::new(i + 1).unwrap()))
1374 }
1375}
1376
1377impl Parse for MlsLevel {
1378 type Error = anyhow::Error;
1379
1380 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1381 let tail = bytes;
1382
1383 let num_bytes = tail.len();
1384 let (sensitivity, tail) =
1385 PolicyCursor::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1386 type_name: "MlsLevelSensitivity",
1387 type_size: std::mem::size_of::<le::U32>(),
1388 num_bytes,
1389 })?;
1390
1391 let (categories, tail) = ExtensibleBitmap::parse(tail)
1392 .map_err(Into::<anyhow::Error>::into)
1393 .context("parsing mls level categories")?;
1394
1395 Ok((Self { sensitivity, categories }, tail))
1396 }
1397}
1398
1399impl<'a> Level<'a, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a>> for MlsLevel {
1400 fn sensitivity(&self) -> SensitivityId {
1401 SensitivityId(NonZeroU32::new(self.sensitivity.get()).unwrap())
1402 }
1403
1404 fn category_spans(
1405 &'a self,
1406 ) -> CategoryIterator<ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a>> {
1407 CategoryIterator::new(self.categories.spans())
1408 }
1409}
1410
1411#[derive(Debug, PartialEq)]
1412pub(super) struct MlsRange {
1413 count: le::U32,
1414 low: MlsLevel,
1415 high: Option<MlsLevel>,
1416}
1417
1418impl MlsRange {
1419 pub fn low(&self) -> &MlsLevel {
1420 &self.low
1421 }
1422
1423 pub fn high(&self) -> &Option<MlsLevel> {
1424 &self.high
1425 }
1426}
1427
1428impl Parse for MlsRange {
1429 type Error = anyhow::Error;
1430
1431 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1432 let tail = bytes;
1433
1434 let num_bytes = tail.len();
1435 let (count, tail) =
1436 PolicyCursor::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1437 type_name: "MlsLevelCount",
1438 type_size: std::mem::size_of::<le::U32>(),
1439 num_bytes,
1440 })?;
1441
1442 let num_bytes = tail.len();
1446 let (sensitivity_low, tail) =
1447 PolicyCursor::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1448 type_name: "MlsLevelSensitivityLow",
1449 type_size: std::mem::size_of::<le::U32>(),
1450 num_bytes,
1451 })?;
1452
1453 let (low_categories, high_level, tail) = if count.get() > 1 {
1454 let num_bytes = tail.len();
1455 let (sensitivity_high, tail) =
1456 PolicyCursor::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1457 type_name: "MlsLevelSensitivityHigh",
1458 type_size: std::mem::size_of::<le::U32>(),
1459 num_bytes,
1460 })?;
1461 let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1462 .map_err(Into::<anyhow::Error>::into)
1463 .context("parsing mls range low categories")?;
1464 let (high_categories, tail) = ExtensibleBitmap::parse(tail)
1465 .map_err(Into::<anyhow::Error>::into)
1466 .context("parsing mls range high categories")?;
1467
1468 (
1469 low_categories,
1470 Some(MlsLevel { sensitivity: sensitivity_high, categories: high_categories }),
1471 tail,
1472 )
1473 } else {
1474 let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1475 .map_err(Into::<anyhow::Error>::into)
1476 .context("parsing mls range low categories")?;
1477
1478 (low_categories, None, tail)
1479 };
1480
1481 Ok((
1482 Self {
1483 count,
1484 low: MlsLevel { sensitivity: sensitivity_low, categories: low_categories },
1485 high: high_level,
1486 },
1487 tail,
1488 ))
1489 }
1490}
1491
1492impl Validate for [ConditionalBoolean] {
1493 type Error = anyhow::Error;
1494
1495 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1497 Ok(())
1498 }
1499}
1500
1501array_type!(ConditionalBoolean, ConditionalBooleanMetadata, Vec<u8>);
1502
1503array_type_validate_deref_both!(ConditionalBoolean);
1504
1505impl ValidateArray<ConditionalBooleanMetadata, u8> for ConditionalBoolean {
1506 type Error = anyhow::Error;
1507
1508 fn validate_array(
1510 _context: &mut PolicyValidationContext,
1511 _metadata: &ConditionalBooleanMetadata,
1512 _items: &[u8],
1513 ) -> Result<(), Self::Error> {
1514 Ok(())
1515 }
1516}
1517
1518#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1519#[repr(C, packed)]
1520pub(super) struct ConditionalBooleanMetadata {
1521 id: le::U32,
1522 active: le::U32,
1524 length: le::U32,
1525}
1526
1527impl ConditionalBooleanMetadata {
1528 pub(super) fn active(&self) -> bool {
1530 self.active != le::U32::ZERO
1531 }
1532}
1533
1534impl Counted for ConditionalBooleanMetadata {
1535 fn count(&self) -> u32 {
1538 self.length.get()
1539 }
1540}
1541
1542impl Validate for ConditionalBooleanMetadata {
1543 type Error = anyhow::Error;
1544
1545 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1547 Ok(())
1548 }
1549}
1550
1551impl Validate for [Sensitivity] {
1552 type Error = anyhow::Error;
1553
1554 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1556 Ok(())
1557 }
1558}
1559
1560#[derive(Debug, PartialEq)]
1561pub(super) struct Sensitivity {
1562 metadata: SensitivityMetadata,
1563 level: MlsLevel,
1564}
1565
1566impl Sensitivity {
1567 pub fn id(&self) -> SensitivityId {
1568 SensitivityId(NonZeroU32::new(self.level.sensitivity.get()).unwrap())
1569 }
1570
1571 pub fn name_bytes(&self) -> &[u8] {
1572 &self.metadata.data
1573 }
1574}
1575
1576impl Parse for Sensitivity {
1577 type Error = anyhow::Error;
1578
1579 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1580 let tail = bytes;
1581
1582 let (metadata, tail) = SensitivityMetadata::parse(tail)
1583 .map_err(Into::<anyhow::Error>::into)
1584 .context("parsing sensitivity metadata")?;
1585
1586 let (level, tail) = MlsLevel::parse(tail)
1587 .map_err(Into::<anyhow::Error>::into)
1588 .context("parsing sensitivity mls level")?;
1589
1590 Ok((Self { metadata, level }, tail))
1591 }
1592}
1593
1594impl Validate for Sensitivity {
1595 type Error = anyhow::Error;
1596
1597 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1599 NonZeroU32::new(self.level.sensitivity.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1600 Ok(())
1601 }
1602}
1603
1604array_type!(SensitivityMetadata, SensitivityStaticMetadata, Vec<u8>);
1605
1606array_type_validate_deref_both!(SensitivityMetadata);
1607
1608impl ValidateArray<SensitivityStaticMetadata, u8> for SensitivityMetadata {
1609 type Error = anyhow::Error;
1610
1611 fn validate_array(
1613 _context: &mut PolicyValidationContext,
1614 _metadata: &SensitivityStaticMetadata,
1615 _items: &[u8],
1616 ) -> Result<(), Self::Error> {
1617 Ok(())
1618 }
1619}
1620
1621#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1622#[repr(C, packed)]
1623pub(super) struct SensitivityStaticMetadata {
1624 length: le::U32,
1625 is_alias: le::U32,
1626}
1627
1628impl Counted for SensitivityStaticMetadata {
1629 fn count(&self) -> u32 {
1632 self.length.get()
1633 }
1634}
1635
1636impl Validate for SensitivityStaticMetadata {
1637 type Error = anyhow::Error;
1638
1639 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1641 Ok(())
1642 }
1643}
1644
1645impl Validate for [Category] {
1646 type Error = anyhow::Error;
1647
1648 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1650 Ok(())
1651 }
1652}
1653
1654array_type!(Category, CategoryMetadata, Vec<u8>);
1655
1656array_type_validate_deref_both!(Category);
1657
1658impl Category {
1659 pub fn id(&self) -> CategoryId {
1660 CategoryId(NonZeroU32::new(self.metadata.id.get()).unwrap())
1661 }
1662
1663 pub fn name_bytes(&self) -> &[u8] {
1664 &self.data
1665 }
1666}
1667
1668impl ValidateArray<CategoryMetadata, u8> for Category {
1669 type Error = anyhow::Error;
1670
1671 fn validate_array(
1673 _context: &mut PolicyValidationContext,
1674 _metadata: &CategoryMetadata,
1675 _items: &[u8],
1676 ) -> Result<(), Self::Error> {
1677 Ok(())
1678 }
1679}
1680
1681#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1682#[repr(C, packed)]
1683pub(super) struct CategoryMetadata {
1684 length: le::U32,
1685 id: le::U32,
1686 is_alias: le::U32,
1687}
1688
1689impl Counted for CategoryMetadata {
1690 fn count(&self) -> u32 {
1693 self.length.get()
1694 }
1695}
1696
1697impl Validate for CategoryMetadata {
1698 type Error = anyhow::Error;
1699
1700 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1702 NonZeroU32::new(self.id.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1703 Ok(())
1704 }
1705}
1706
1707#[cfg(test)]
1708mod tests {
1709 use super::super::security_context::Level;
1710 use super::super::{CategoryId, SensitivityId, UserId, parse_policy_by_value};
1711 use super::*;
1712
1713 use std::num::NonZeroU32;
1714
1715 #[test]
1716 fn mls_levels_for_user_context() {
1717 const TEST_POLICY: &[u8] = include_bytes! {"../../testdata/micro_policies/multiple_levels_and_categories_policy.pp"};
1718 let policy = parse_policy_by_value(TEST_POLICY.to_vec()).unwrap();
1719 let policy = policy.validate().unwrap();
1720 let parsed_policy = policy.0.parsed_policy();
1721
1722 let user = parsed_policy.user(UserId(NonZeroU32::new(1).expect("user with id 1")));
1723 let mls_range = user.mls_range();
1724 let low_level = mls_range.low();
1725 let high_level = mls_range.high().as_ref().expect("user 1 has a high mls level");
1726
1727 assert_eq!(low_level.sensitivity(), SensitivityId(NonZeroU32::new(1).unwrap()));
1728 assert_eq!(
1729 low_level.category_ids().collect::<Vec<_>>(),
1730 vec![CategoryId(NonZeroU32::new(1).unwrap())]
1731 );
1732
1733 assert_eq!(high_level.sensitivity(), SensitivityId(NonZeroU32::new(2).unwrap()));
1734 assert_eq!(
1735 high_level.category_ids().collect::<Vec<_>>(),
1736 vec![
1737 CategoryId(NonZeroU32::new(1).unwrap()),
1738 CategoryId(NonZeroU32::new(2).unwrap()),
1739 CategoryId(NonZeroU32::new(3).unwrap()),
1740 CategoryId(NonZeroU32::new(4).unwrap()),
1741 CategoryId(NonZeroU32::new(5).unwrap()),
1742 ]
1743 );
1744 }
1745
1746 #[test]
1747 fn parse_mls_constrain_statement() {
1748 let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1749 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1750 let parsed_policy = &policy.0;
1751 parsed_policy.validate().expect("validate policy");
1752
1753 let class = find_class_by_name(parsed_policy.classes(), "class_mls_constraints")
1754 .expect("look up class");
1755 let constraints = class.constraints();
1756 assert_eq!(constraints.len(), 6);
1757 let expected = [
1764 (
1765 CONSTRAINT_TERM_TYPE_EXPR,
1766 CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1767 CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1,
1768 ),
1769 (
1770 CONSTRAINT_TERM_TYPE_EXPR,
1771 CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1772 CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2,
1773 ),
1774 (
1775 CONSTRAINT_TERM_TYPE_EXPR,
1776 CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY,
1777 CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2,
1778 ),
1779 (
1780 CONSTRAINT_TERM_TYPE_EXPR,
1781 CONSTRAINT_EXPR_OPERATOR_TYPE_DOM,
1782 CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2,
1783 ),
1784 (
1785 CONSTRAINT_TERM_TYPE_EXPR,
1786 CONSTRAINT_EXPR_OPERATOR_TYPE_NE,
1787 CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2,
1788 ),
1789 (
1790 CONSTRAINT_TERM_TYPE_EXPR,
1791 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1792 CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2,
1793 ),
1794 ];
1795 for (i, constraint) in constraints.iter().enumerate() {
1796 assert_eq!(constraint.access_vector(), AccessVector(1), "constraint {}", i);
1797 let terms = constraint.constraint_expr().constraint_terms();
1798 assert_eq!(terms.len(), 1, "constraint {}", i);
1799 let term = &terms[0];
1800 assert_eq!(
1801 (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1802 expected[i],
1803 "constraint {}",
1804 i
1805 );
1806 }
1807 }
1808
1809 #[test]
1810 fn parse_constrain_statement() {
1811 let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1812 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1813 let parsed_policy = &policy.0;
1814 parsed_policy.validate().expect("validate policy");
1815
1816 let class = find_class_by_name(parsed_policy.classes(), "class_constraint_nested")
1817 .expect("look up class");
1818 let constraints = class.constraints();
1819 assert_eq!(constraints.len(), 1);
1820 let constraint = &constraints[0];
1821 assert_eq!(constraint.access_vector(), AccessVector(1));
1822 let terms = constraint.constraint_expr().constraint_terms();
1823 assert_eq!(terms.len(), 8);
1824
1825 let expected = [
1831 (
1832 CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES,
1833 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1834 CONSTRAINT_EXPR_OPERAND_TYPE_USER
1835 | CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK,
1836 ),
1837 (
1838 CONSTRAINT_TERM_TYPE_EXPR,
1839 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1840 CONSTRAINT_EXPR_OPERAND_TYPE_ROLE,
1841 ),
1842 (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1843 (
1844 CONSTRAINT_TERM_TYPE_EXPR,
1845 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1846 CONSTRAINT_EXPR_OPERAND_TYPE_USER,
1847 ),
1848 (
1849 CONSTRAINT_TERM_TYPE_EXPR,
1850 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1851 CONSTRAINT_EXPR_OPERAND_TYPE_TYPE,
1852 ),
1853 (CONSTRAINT_TERM_TYPE_NOT_OPERATOR, 0, 0),
1854 (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1855 (CONSTRAINT_TERM_TYPE_OR_OPERATOR, 0, 0),
1856 ];
1857 for (i, term) in terms.iter().enumerate() {
1858 assert_eq!(
1859 (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1860 expected[i],
1861 "term {}",
1862 i
1863 );
1864 }
1865 }
1866}