1use super::error::ValidateError;
6use super::extensible_bitmap::ExtensibleBitmap;
7use super::parser::{PolicyCursor, PolicyData, PolicyOffset};
8use super::symbols::{MlsLevel, MlsRange};
9use super::view::{ArrayView, HasMetadata, Walk};
10use super::{
11 AccessVector, Array, ClassId, Counted, Parse, PolicyValidationContext, RoleId, TypeId, UserId,
12 Validate, ValidateArray, array_type, array_type_validate_deref_both,
13};
14
15use anyhow::Context as _;
16use std::num::NonZeroU32;
17use std::ops::Shl;
18use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned, little_endian as le};
19
20pub(super) const MIN_POLICY_VERSION_FOR_INFINITIBAND_PARTITION_KEY: u32 = 31;
21
22pub(super) const ACCESS_VECTOR_RULE_DATA_IS_TYPE_ID_MASK: u16 = 0x070;
25pub(super) const ACCESS_VECTOR_RULE_DATA_IS_XPERM_MASK: u16 = 0x0700;
29
30pub(super) const ACCESS_VECTOR_RULE_TYPE_ALLOW: u16 = 0x1;
40pub(super) const ACCESS_VECTOR_RULE_TYPE_AUDITALLOW: u16 = 0x2;
44pub(super) const ACCESS_VECTOR_RULE_TYPE_DONTAUDIT: u16 = 0x4;
48pub(super) const ACCESS_VECTOR_RULE_TYPE_TYPE_TRANSITION: u16 = 0x10;
52#[allow(dead_code)]
56pub(super) const ACCESS_VECTOR_RULE_TYPE_TYPE_MEMBER: u16 = 0x20;
57#[allow(dead_code)]
61pub(super) const ACCESS_VECTOR_RULE_TYPE_TYPE_CHANGE: u16 = 0x40;
62pub(super) const ACCESS_VECTOR_RULE_TYPE_ALLOWXPERM: u16 = 0x100;
67pub(super) const ACCESS_VECTOR_RULE_TYPE_AUDITALLOWXPERM: u16 = 0x200;
72pub(super) const ACCESS_VECTOR_RULE_TYPE_DONTAUDITXPERM: u16 = 0x400;
77
78pub(super) const XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES: u8 = 1;
84pub(super) const XPERMS_TYPE_IOCTL_PREFIXES: u8 = 2;
88pub(super) const XPERMS_TYPE_NLMSG: u8 = 3;
94
95#[allow(type_alias_bounds)]
96pub(super) type SimpleArray<T> = Array<le::U32, T>;
97
98impl<T: Validate> Validate for SimpleArray<T> {
99 type Error = <T as Validate>::Error;
100
101 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
104 self.data.validate(context)
105 }
106}
107
108pub(super) type SimpleArrayView<T> = ArrayView<le::U32, T>;
109
110impl<T: Validate + Parse + Walk> Validate for SimpleArrayView<T> {
111 type Error = anyhow::Error;
112
113 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
116 for item in self.data().iter(&context.data) {
117 item.validate(context)?;
118 }
119 Ok(())
120 }
121}
122
123impl Counted for le::U32 {
124 fn count(&self) -> u32 {
125 self.get()
126 }
127}
128
129pub(super) type ConditionalNodes = Vec<ConditionalNode>;
130
131impl Validate for ConditionalNodes {
132 type Error = anyhow::Error;
133
134 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
136 Ok(())
137 }
138}
139
140array_type!(ConditionalNodeItems, ConditionalNodeMetadata, Vec<ConditionalNodeDatum>);
141
142array_type_validate_deref_both!(ConditionalNodeItems);
143
144impl ValidateArray<ConditionalNodeMetadata, ConditionalNodeDatum> for ConditionalNodeItems {
145 type Error = anyhow::Error;
146
147 fn validate_array(
150 _context: &mut PolicyValidationContext,
151 _metadata: &ConditionalNodeMetadata,
152 _items: &[ConditionalNodeDatum],
153 ) -> Result<(), Self::Error> {
154 Ok(())
155 }
156}
157
158#[derive(Debug, PartialEq)]
159pub(super) struct ConditionalNode {
160 items: ConditionalNodeItems,
161 true_list: SimpleArray<AccessVectorRules>,
162 false_list: SimpleArray<AccessVectorRules>,
163}
164
165impl Parse for ConditionalNode
166where
167 ConditionalNodeItems: Parse,
168 SimpleArray<AccessVectorRules>: Parse,
169{
170 type Error = anyhow::Error;
171
172 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
173 let tail = bytes;
174
175 let (items, tail) = ConditionalNodeItems::parse(tail)
176 .map_err(Into::<anyhow::Error>::into)
177 .context("parsing conditional node items")?;
178
179 let (true_list, tail) = SimpleArray::<AccessVectorRules>::parse(tail)
180 .map_err(Into::<anyhow::Error>::into)
181 .context("parsing conditional node true list")?;
182
183 let (false_list, tail) = SimpleArray::<AccessVectorRules>::parse(tail)
184 .map_err(Into::<anyhow::Error>::into)
185 .context("parsing conditional node false list")?;
186
187 Ok((Self { items, true_list, false_list }, tail))
188 }
189}
190
191#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
192#[repr(C, packed)]
193pub(super) struct ConditionalNodeMetadata {
194 state: le::U32,
195 count: le::U32,
196}
197
198impl Counted for ConditionalNodeMetadata {
199 fn count(&self) -> u32 {
200 self.count.get()
201 }
202}
203
204impl Validate for ConditionalNodeMetadata {
205 type Error = anyhow::Error;
206
207 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
209 Ok(())
210 }
211}
212
213#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
214#[repr(C, packed)]
215pub(super) struct ConditionalNodeDatum {
216 node_type: le::U32,
217 boolean: le::U32,
218}
219
220impl Validate for [ConditionalNodeDatum] {
221 type Error = anyhow::Error;
222
223 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
225 Ok(())
226 }
227}
228
229pub(super) type AccessVectorRules = Vec<AccessVectorRule>;
238
239impl Validate for AccessVectorRules {
240 type Error = anyhow::Error;
241
242 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
243 for access_vector_rule in self {
244 access_vector_rule.validate(context)?;
245 }
246 Ok(())
247 }
248}
249
250#[derive(Debug, PartialEq)]
251pub(super) struct AccessVectorRule {
252 metadata: AccessVectorRuleMetadata,
253 permission_data: PermissionData,
254}
255
256impl AccessVectorRule {
257 pub fn access_vector(&self) -> Option<AccessVector> {
263 match &self.permission_data {
264 PermissionData::AccessVector(access_vector_raw) => {
265 Some(AccessVector(access_vector_raw.get()))
266 }
267 _ => None,
268 }
269 }
270
271 pub fn new_type(&self) -> Option<TypeId> {
277 match &self.permission_data {
278 PermissionData::NewType(new_type) => {
279 Some(TypeId(NonZeroU32::new(new_type.get().into()).unwrap()))
280 }
281 _ => None,
282 }
283 }
284
285 pub fn extended_permissions(&self) -> Option<&ExtendedPermissions> {
291 match &self.permission_data {
292 PermissionData::ExtendedPermissions(xperms) => Some(xperms),
293 _ => None,
294 }
295 }
296}
297
298impl Walk for AccessVectorRule {
299 fn walk(policy_data: &PolicyData, offset: PolicyOffset) -> PolicyOffset {
300 const METADATA_SIZE: u32 = std::mem::size_of::<AccessVectorRuleMetadata>() as u32;
301 let bytes = &policy_data[offset as usize..(offset + METADATA_SIZE) as usize];
302 let metadata = AccessVectorRuleMetadata::read_from_bytes(bytes).unwrap();
303 let permission_data_size = metadata.permission_data_size() as u32;
304 offset + METADATA_SIZE + permission_data_size
305 }
306}
307
308impl HasMetadata for AccessVectorRule {
309 type Metadata = AccessVectorRuleMetadata;
310}
311
312impl Parse for AccessVectorRule {
313 type Error = anyhow::Error;
314
315 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
316 let tail = bytes;
317
318 let (metadata, tail) = PolicyCursor::parse::<AccessVectorRuleMetadata>(tail)?;
319 let access_vector_rule_type = metadata.access_vector_rule_type;
320 let (permission_data, tail) =
321 if (access_vector_rule_type & ACCESS_VECTOR_RULE_DATA_IS_XPERM_MASK) != 0 {
322 let (xperms, tail) = ExtendedPermissions::parse(tail)
323 .map_err(Into::<anyhow::Error>::into)
324 .context("parsing extended permissions")?;
325 (PermissionData::ExtendedPermissions(xperms), tail)
326 } else if (access_vector_rule_type & ACCESS_VECTOR_RULE_DATA_IS_TYPE_ID_MASK) != 0 {
327 let (new_type, tail) = PolicyCursor::parse::<le::U32>(tail)?;
328 (PermissionData::NewType(new_type), tail)
329 } else {
330 let (access_vector, tail) = PolicyCursor::parse::<le::U32>(tail)?;
331 (PermissionData::AccessVector(access_vector), tail)
332 };
333 Ok((Self { metadata, permission_data }, tail))
334 }
335}
336
337impl Validate for AccessVectorRule {
338 type Error = anyhow::Error;
339
340 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
341 if self.metadata.class.get() == 0 {
342 return Err(ValidateError::NonOptionalIdIsZero.into());
343 }
344 if let PermissionData::ExtendedPermissions(xperms) = &self.permission_data {
345 let xperms_type = xperms.xperms_type;
346 if !(xperms_type == XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES
347 || xperms_type == XPERMS_TYPE_IOCTL_PREFIXES
348 || xperms_type == XPERMS_TYPE_NLMSG)
349 {
350 return Err(
351 ValidateError::InvalidExtendedPermissionsType { type_: xperms_type }.into()
352 );
353 }
354 }
355 Ok(())
356 }
357}
358
359#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, Eq, PartialEq, Unaligned, Hash)]
360#[repr(C, packed)]
361pub(super) struct AccessVectorRuleMetadata {
362 source_type: le::U16,
363 target_type: le::U16,
364 class: le::U16,
365 access_vector_rule_type: le::U16,
366}
367
368impl AccessVectorRuleMetadata {
369 pub fn for_query(source: TypeId, target: TypeId, class: ClassId, rule_type: u16) -> Self {
370 let source_type = le::U16::new(source.0.get() as u16);
371 let target_type = le::U16::new(target.0.get() as u16);
372 let class = le::U16::new(class.0.get() as u16);
373 let access_vector_rule_type = le::U16::new(rule_type);
374 Self { source_type, target_type, class, access_vector_rule_type }
375 }
376
377 fn permission_data_size(&self) -> usize {
378 if (self.access_vector_rule_type & ACCESS_VECTOR_RULE_DATA_IS_XPERM_MASK) != 0 {
379 std::mem::size_of::<ExtendedPermissions>()
380 } else if (self.access_vector_rule_type & ACCESS_VECTOR_RULE_DATA_IS_TYPE_ID_MASK) != 0 {
381 std::mem::size_of::<le::U32>()
382 } else {
383 std::mem::size_of::<le::U32>()
384 }
385 }
386}
387
388#[derive(Debug, PartialEq)]
389pub(super) enum PermissionData {
390 AccessVector(le::U32),
391 NewType(le::U32),
392 ExtendedPermissions(ExtendedPermissions),
393}
394
395#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
396#[repr(C, packed)]
397pub(super) struct ExtendedPermissions {
398 pub(super) xperms_type: u8,
399 pub(super) xperms_optional_prefix: u8,
403 pub(super) xperms_bitmap: XpermsBitmap,
404}
405
406impl ExtendedPermissions {
407 #[cfg(test)]
408 fn count(&self) -> u64 {
409 let count = self
410 .xperms_bitmap
411 .0
412 .iter()
413 .fold(0, |count, block| (count as u64) + (block.get().count_ones() as u64));
414 match self.xperms_type {
415 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES | XPERMS_TYPE_NLMSG => count,
416 XPERMS_TYPE_IOCTL_PREFIXES => count * 0x100,
417 _ => unreachable!("invalid xperms_type in validated ExtendedPermissions"),
418 }
419 }
420
421 #[cfg(test)]
422 fn contains(&self, xperm: u16) -> bool {
423 let [postfix, prefix] = xperm.to_le_bytes();
424 if (self.xperms_type == XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES
425 || self.xperms_type == XPERMS_TYPE_NLMSG)
426 && self.xperms_optional_prefix != prefix
427 {
428 return false;
429 }
430 let value = match self.xperms_type {
431 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES | XPERMS_TYPE_NLMSG => postfix,
432 XPERMS_TYPE_IOCTL_PREFIXES => prefix,
433 _ => unreachable!("invalid xperms_type in validated ExtendedPermissions"),
434 };
435 self.xperms_bitmap.contains(value)
436 }
437}
438
439#[derive(Clone, Copy, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
441#[repr(C, packed)]
442pub struct XpermsBitmap([le::U32; 8]);
443
444impl XpermsBitmap {
445 const BITMAP_BLOCKS: usize = 8;
446 pub const ALL: Self = Self([le::U32::MAX_VALUE; Self::BITMAP_BLOCKS]);
447 pub const NONE: Self = Self([le::U32::ZERO; Self::BITMAP_BLOCKS]);
448
449 #[cfg(test)]
450 pub fn new(elements: [le::U32; 8]) -> Self {
451 Self(elements)
452 }
453
454 pub fn contains(&self, value: u8) -> bool {
455 let block_index = (value as usize) / 32;
456 let bit_index = ((value as usize) % 32) as u32;
457 self.0[block_index] & le::U32::new(1).shl(bit_index) != 0
458 }
459}
460
461impl std::ops::BitOrAssign<&Self> for XpermsBitmap {
462 fn bitor_assign(&mut self, rhs: &Self) {
463 (0..Self::BITMAP_BLOCKS).for_each(|i| self.0[i] |= rhs.0[i])
464 }
465}
466
467impl std::ops::SubAssign<&Self> for XpermsBitmap {
468 fn sub_assign(&mut self, rhs: &Self) {
469 (0..Self::BITMAP_BLOCKS).for_each(|i| self.0[i] = self.0[i] ^ (self.0[i] & rhs.0[i]))
470 }
471}
472
473array_type!(RoleTransitions, le::U32, Vec<RoleTransition>);
474
475array_type_validate_deref_both!(RoleTransitions);
476
477impl ValidateArray<le::U32, RoleTransition> for RoleTransitions {
478 type Error = anyhow::Error;
479
480 fn validate_array(
482 context: &mut PolicyValidationContext,
483 _metadata: &le::U32,
484 items: &[RoleTransition],
485 ) -> Result<(), Self::Error> {
486 items.validate(context)
487 }
488}
489
490#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
491#[repr(C, packed)]
492pub(super) struct RoleTransition {
493 role: le::U32,
494 role_type: le::U32,
495 new_role: le::U32,
496 tclass: le::U32,
497}
498
499impl RoleTransition {
500 pub(super) fn current_role(&self) -> RoleId {
501 RoleId(NonZeroU32::new(self.role.get()).unwrap())
502 }
503
504 pub(super) fn type_(&self) -> TypeId {
505 TypeId(NonZeroU32::new(self.role_type.get()).unwrap())
506 }
507
508 pub(super) fn class(&self) -> ClassId {
509 ClassId(NonZeroU32::new(self.tclass.get()).unwrap())
510 }
511
512 pub(super) fn new_role(&self) -> RoleId {
513 RoleId(NonZeroU32::new(self.new_role.get()).unwrap())
514 }
515}
516
517impl Validate for [RoleTransition] {
518 type Error = anyhow::Error;
519
520 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
521 for role_transition in self {
522 NonZeroU32::new(role_transition.role.get())
523 .ok_or(ValidateError::NonOptionalIdIsZero)?;
524 NonZeroU32::new(role_transition.role_type.get())
525 .ok_or(ValidateError::NonOptionalIdIsZero)?;
526 NonZeroU32::new(role_transition.tclass.get())
527 .ok_or(ValidateError::NonOptionalIdIsZero)?;
528 NonZeroU32::new(role_transition.new_role.get())
529 .ok_or(ValidateError::NonOptionalIdIsZero)?;
530 }
531 Ok(())
532 }
533}
534
535array_type!(RoleAllows, le::U32, Vec<RoleAllow>);
536
537array_type_validate_deref_both!(RoleAllows);
538
539impl ValidateArray<le::U32, RoleAllow> for RoleAllows {
540 type Error = anyhow::Error;
541
542 fn validate_array(
544 context: &mut PolicyValidationContext,
545 _metadata: &le::U32,
546 items: &[RoleAllow],
547 ) -> Result<(), Self::Error> {
548 items.validate(context)
549 }
550}
551
552#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
553#[repr(C, packed)]
554pub(super) struct RoleAllow {
555 role: le::U32,
556 new_role: le::U32,
557}
558
559impl RoleAllow {
560 pub(super) fn source_role(&self) -> RoleId {
561 RoleId(NonZeroU32::new(self.role.get()).unwrap())
562 }
563
564 pub(super) fn new_role(&self) -> RoleId {
565 RoleId(NonZeroU32::new(self.new_role.get()).unwrap())
566 }
567}
568
569impl Validate for [RoleAllow] {
570 type Error = anyhow::Error;
571
572 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
573 for rule in self {
574 NonZeroU32::new(rule.role.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
575 NonZeroU32::new(rule.new_role.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
576 }
577 Ok(())
578 }
579}
580
581#[derive(Debug, PartialEq)]
582pub(super) enum FilenameTransitionList {
583 PolicyVersionGeq33(SimpleArray<FilenameTransitions>),
584 PolicyVersionLeq32(SimpleArray<DeprecatedFilenameTransitions>),
585}
586
587impl Validate for FilenameTransitionList {
588 type Error = anyhow::Error;
589
590 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
591 match self {
592 Self::PolicyVersionLeq32(list) => {
593 list.validate(context).map_err(Into::<anyhow::Error>::into)
594 }
595 Self::PolicyVersionGeq33(list) => {
596 list.validate(context).map_err(Into::<anyhow::Error>::into)
597 }
598 }
599 }
600}
601
602pub(super) type FilenameTransitions = Vec<FilenameTransition>;
603
604impl Validate for FilenameTransitions {
605 type Error = anyhow::Error;
606
607 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
609 Ok(())
610 }
611}
612
613#[derive(Debug, PartialEq)]
614pub(super) struct FilenameTransition {
615 filename: SimpleArray<Vec<u8>>,
616 transition_type: le::U32,
617 transition_class: le::U32,
618 items: SimpleArray<FilenameTransitionItems>,
619}
620
621impl FilenameTransition {
622 pub(super) fn name_bytes(&self) -> &[u8] {
623 &self.filename.data
624 }
625
626 pub(super) fn target_type(&self) -> TypeId {
627 TypeId(NonZeroU32::new(self.transition_type.get()).unwrap())
628 }
629
630 pub(super) fn target_class(&self) -> ClassId {
631 ClassId(NonZeroU32::new(self.transition_class.get()).unwrap())
632 }
633
634 pub(super) fn outputs(&self) -> &[FilenameTransitionItem] {
635 &self.items.data
636 }
637}
638
639impl Parse for FilenameTransition
640where
641 SimpleArray<Vec<u8>>: Parse,
642 SimpleArray<FilenameTransitionItems>: Parse,
643{
644 type Error = anyhow::Error;
645
646 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
647 let tail = bytes;
648
649 let (filename, tail) = SimpleArray::<Vec<u8>>::parse(tail)
650 .map_err(Into::<anyhow::Error>::into)
651 .context("parsing filename for filename transition")?;
652
653 let (transition_type, tail) = PolicyCursor::parse::<le::U32>(tail)?;
654
655 let (transition_class, tail) = PolicyCursor::parse::<le::U32>(tail)?;
656
657 let (items, tail) = SimpleArray::<FilenameTransitionItems>::parse(tail)
658 .map_err(Into::<anyhow::Error>::into)
659 .context("parsing items for filename transition")?;
660
661 Ok((Self { filename, transition_type, transition_class, items }, tail))
662 }
663}
664
665pub(super) type FilenameTransitionItems = Vec<FilenameTransitionItem>;
666
667#[derive(Debug, PartialEq)]
668pub(super) struct FilenameTransitionItem {
669 stypes: ExtensibleBitmap,
670 out_type: le::U32,
671}
672
673impl FilenameTransitionItem {
674 pub(super) fn has_source_type(&self, source_type: TypeId) -> bool {
675 self.stypes.is_set(source_type.0.get() - 1)
676 }
677
678 pub(super) fn out_type(&self) -> TypeId {
679 TypeId(NonZeroU32::new(self.out_type.get()).unwrap())
680 }
681}
682
683impl Parse for FilenameTransitionItem
684where
685 ExtensibleBitmap: Parse,
686{
687 type Error = anyhow::Error;
688
689 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
690 let tail = bytes;
691
692 let (stypes, tail) = ExtensibleBitmap::parse(tail)
693 .map_err(Into::<anyhow::Error>::into)
694 .context("parsing stypes extensible bitmap for file transition")?;
695
696 let (out_type, tail) = PolicyCursor::parse::<le::U32>(tail)?;
697
698 Ok((Self { stypes, out_type }, tail))
699 }
700}
701
702pub(super) type DeprecatedFilenameTransitions = Vec<DeprecatedFilenameTransition>;
703
704impl Validate for DeprecatedFilenameTransitions {
705 type Error = anyhow::Error;
706
707 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
709 Ok(())
710 }
711}
712
713#[derive(Debug, PartialEq)]
714pub(super) struct DeprecatedFilenameTransition {
715 filename: SimpleArray<Vec<u8>>,
716 metadata: DeprecatedFilenameTransitionMetadata,
717}
718
719impl DeprecatedFilenameTransition {
720 pub(super) fn name_bytes(&self) -> &[u8] {
721 &self.filename.data
722 }
723
724 pub(super) fn source_type(&self) -> TypeId {
725 TypeId(NonZeroU32::new(self.metadata.source_type.get()).unwrap())
726 }
727
728 pub(super) fn target_type(&self) -> TypeId {
729 TypeId(NonZeroU32::new(self.metadata.transition_type.get()).unwrap())
730 }
731
732 pub(super) fn target_class(&self) -> ClassId {
733 ClassId(NonZeroU32::new(self.metadata.transition_class.get()).unwrap())
734 }
735
736 pub(super) fn out_type(&self) -> TypeId {
737 TypeId(NonZeroU32::new(self.metadata.out_type.get()).unwrap())
738 }
739}
740
741impl Parse for DeprecatedFilenameTransition
742where
743 SimpleArray<Vec<u8>>: Parse,
744{
745 type Error = anyhow::Error;
746
747 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
748 let tail = bytes;
749
750 let (filename, tail) = SimpleArray::<Vec<u8>>::parse(tail)
751 .map_err(Into::<anyhow::Error>::into)
752 .context("parsing filename for deprecated filename transition")?;
753
754 let (metadata, tail) = PolicyCursor::parse::<DeprecatedFilenameTransitionMetadata>(tail)?;
755
756 Ok((Self { filename, metadata }, tail))
757 }
758}
759
760#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
761#[repr(C, packed)]
762pub(super) struct DeprecatedFilenameTransitionMetadata {
763 source_type: le::U32,
764 transition_type: le::U32,
765 transition_class: le::U32,
766 out_type: le::U32,
767}
768
769pub(super) type InitialSids = Vec<InitialSid>;
770
771impl Validate for InitialSids {
772 type Error = anyhow::Error;
773
774 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
776 for initial_sid in crate::InitialSid::all_variants() {
777 self.iter()
778 .find(|initial| initial.id().get() == *initial_sid as u32)
779 .ok_or(ValidateError::MissingInitialSid { initial_sid: *initial_sid })?;
780 }
781 Ok(())
782 }
783}
784
785#[derive(Debug, PartialEq)]
786pub(super) struct InitialSid {
787 id: le::U32,
788 context: Context,
789}
790
791impl InitialSid {
792 pub(super) fn id(&self) -> le::U32 {
793 self.id
794 }
795
796 pub(super) fn context(&self) -> &Context {
797 &self.context
798 }
799}
800
801impl Parse for InitialSid
802where
803 Context: Parse,
804{
805 type Error = anyhow::Error;
806
807 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
808 let tail = bytes;
809
810 let (id, tail) = PolicyCursor::parse::<le::U32>(tail)?;
811
812 let (context, tail) = Context::parse(tail)
813 .map_err(Into::<anyhow::Error>::into)
814 .context("parsing context for initial sid")?;
815
816 Ok((Self { id, context }, tail))
817 }
818}
819
820#[derive(Debug, PartialEq)]
821pub(super) struct Context {
822 metadata: ContextMetadata,
823 mls_range: MlsRange,
824}
825
826impl Context {
827 pub(super) fn user_id(&self) -> UserId {
828 UserId(NonZeroU32::new(self.metadata.user.get()).unwrap())
829 }
830 pub(super) fn role_id(&self) -> RoleId {
831 RoleId(NonZeroU32::new(self.metadata.role.get()).unwrap())
832 }
833 pub(super) fn type_id(&self) -> TypeId {
834 TypeId(NonZeroU32::new(self.metadata.context_type.get()).unwrap())
835 }
836 pub(super) fn low_level(&self) -> &MlsLevel {
837 self.mls_range.low()
838 }
839 pub(super) fn high_level(&self) -> &Option<MlsLevel> {
840 self.mls_range.high()
841 }
842}
843
844impl Parse for Context
845where
846 MlsRange: Parse,
847{
848 type Error = anyhow::Error;
849
850 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
851 let tail = bytes;
852
853 let (metadata, tail) =
854 PolicyCursor::parse::<ContextMetadata>(tail).context("parsing metadata for context")?;
855
856 let (mls_range, tail) = MlsRange::parse(tail)
857 .map_err(Into::<anyhow::Error>::into)
858 .context("parsing mls range for context")?;
859
860 Ok((Self { metadata, mls_range }, tail))
861 }
862}
863
864#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
865#[repr(C, packed)]
866pub(super) struct ContextMetadata {
867 user: le::U32,
868 role: le::U32,
869 context_type: le::U32,
870}
871
872pub(super) type NamedContextPairs = Vec<NamedContextPair>;
873
874impl Validate for NamedContextPairs {
875 type Error = anyhow::Error;
876
877 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
882 Ok(())
883 }
884}
885
886#[derive(Debug, PartialEq)]
887pub(super) struct NamedContextPair {
888 name: SimpleArray<Vec<u8>>,
889 context1: Context,
890 context2: Context,
891}
892
893impl Parse for NamedContextPair
894where
895 SimpleArray<Vec<u8>>: Parse,
896 Context: Parse,
897{
898 type Error = anyhow::Error;
899
900 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
901 let tail = bytes;
902
903 let (name, tail) = SimpleArray::parse(tail)
904 .map_err(Into::<anyhow::Error>::into)
905 .context("parsing filesystem context name")?;
906
907 let (context1, tail) = Context::parse(tail)
908 .map_err(Into::<anyhow::Error>::into)
909 .context("parsing first context for filesystem context")?;
910
911 let (context2, tail) = Context::parse(tail)
912 .map_err(Into::<anyhow::Error>::into)
913 .context("parsing second context for filesystem context")?;
914
915 Ok((Self { name, context1, context2 }, tail))
916 }
917}
918
919pub(super) type Ports = Vec<Port>;
920
921impl Validate for Ports {
922 type Error = anyhow::Error;
923
924 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
926 Ok(())
927 }
928}
929
930#[derive(Debug, PartialEq)]
931pub(super) struct Port {
932 metadata: PortMetadata,
933 context: Context,
934}
935
936impl Parse for Port
937where
938 Context: Parse,
939{
940 type Error = anyhow::Error;
941
942 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
943 let tail = bytes;
944
945 let (metadata, tail) =
946 PolicyCursor::parse::<PortMetadata>(tail).context("parsing metadata for context")?;
947
948 let (context, tail) = Context::parse(tail)
949 .map_err(Into::<anyhow::Error>::into)
950 .context("parsing context for port")?;
951
952 Ok((Self { metadata, context }, tail))
953 }
954}
955
956#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
957#[repr(C, packed)]
958pub(super) struct PortMetadata {
959 protocol: le::U32,
960 low_port: le::U32,
961 high_port: le::U32,
962}
963
964pub(super) type Nodes = Vec<Node>;
965
966impl Validate for Nodes {
967 type Error = anyhow::Error;
968
969 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
971 Ok(())
972 }
973}
974
975#[derive(Debug, PartialEq)]
976pub(super) struct Node {
977 address: le::U32,
978 mask: le::U32,
979 context: Context,
980}
981
982impl Parse for Node
983where
984 Context: Parse,
985{
986 type Error = anyhow::Error;
987
988 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
989 let tail = bytes;
990
991 let (address, tail) = PolicyCursor::parse::<le::U32>(tail)?;
992
993 let (mask, tail) = PolicyCursor::parse::<le::U32>(tail)?;
994
995 let (context, tail) = Context::parse(tail)
996 .map_err(Into::<anyhow::Error>::into)
997 .context("parsing context for node")?;
998
999 Ok((Self { address, mask, context }, tail))
1000 }
1001}
1002
1003impl Validate for Node {
1004 type Error = anyhow::Error;
1005
1006 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1008 Ok(())
1009 }
1010}
1011
1012pub(super) type FsUses = Vec<FsUse>;
1013
1014impl Validate for FsUses {
1015 type Error = anyhow::Error;
1016
1017 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1018 for fs_use in self {
1019 fs_use.validate(context)?;
1020 }
1021 Ok(())
1022 }
1023}
1024
1025#[derive(Debug, PartialEq)]
1026pub(super) struct FsUse {
1027 behavior_and_name: Array<FsUseMetadata, Vec<u8>>,
1028 context: Context,
1029}
1030
1031impl FsUse {
1032 pub fn fs_type(&self) -> &[u8] {
1033 &self.behavior_and_name.data
1034 }
1035
1036 pub(super) fn behavior(&self) -> FsUseType {
1037 FsUseType::try_from(self.behavior_and_name.metadata.behavior).unwrap()
1038 }
1039
1040 pub(super) fn context(&self) -> &Context {
1041 &self.context
1042 }
1043}
1044
1045impl Parse for FsUse
1046where
1047 Array<FsUseMetadata, Vec<u8>>: Parse,
1048 Context: Parse,
1049{
1050 type Error = anyhow::Error;
1051
1052 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1053 let tail = bytes;
1054
1055 let (behavior_and_name, tail) = Array::<FsUseMetadata, Vec<u8>>::parse(tail)
1056 .map_err(Into::<anyhow::Error>::into)
1057 .context("parsing fs use metadata")?;
1058
1059 let (context, tail) = Context::parse(tail)
1060 .map_err(Into::<anyhow::Error>::into)
1061 .context("parsing context for fs use")?;
1062
1063 Ok((Self { behavior_and_name, context }, tail))
1064 }
1065}
1066
1067impl Validate for FsUse {
1068 type Error = anyhow::Error;
1069
1070 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1071 FsUseType::try_from(self.behavior_and_name.metadata.behavior)?;
1072
1073 Ok(())
1074 }
1075}
1076
1077#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1078#[repr(C, packed)]
1079pub(super) struct FsUseMetadata {
1080 behavior: le::U32,
1082 name_length: le::U32,
1084}
1085
1086impl Counted for FsUseMetadata {
1087 fn count(&self) -> u32 {
1088 self.name_length.get()
1089 }
1090}
1091
1092#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1095pub enum FsUseType {
1096 Xattr = 1,
1097 Trans = 2,
1098 Task = 3,
1099}
1100
1101impl TryFrom<le::U32> for FsUseType {
1102 type Error = anyhow::Error;
1103
1104 fn try_from(value: le::U32) -> Result<Self, Self::Error> {
1105 match value.get() {
1106 1 => Ok(FsUseType::Xattr),
1107 2 => Ok(FsUseType::Trans),
1108 3 => Ok(FsUseType::Task),
1109 _ => Err(ValidateError::InvalidFsUseType { value: value.get() }.into()),
1110 }
1111 }
1112}
1113
1114pub(super) type IPv6Nodes = Vec<IPv6Node>;
1115
1116impl Validate for IPv6Nodes {
1117 type Error = anyhow::Error;
1118
1119 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1121 Ok(())
1122 }
1123}
1124
1125#[derive(Debug, PartialEq)]
1126pub(super) struct IPv6Node {
1127 address: [le::U32; 4],
1128 mask: [le::U32; 4],
1129 context: Context,
1130}
1131
1132impl Parse for IPv6Node
1133where
1134 Context: Parse,
1135{
1136 type Error = anyhow::Error;
1137
1138 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1139 let tail = bytes;
1140
1141 let (address, tail) = PolicyCursor::parse::<[le::U32; 4]>(tail)?;
1142
1143 let (mask, tail) = PolicyCursor::parse::<[le::U32; 4]>(tail)?;
1144
1145 let (context, tail) = Context::parse(tail)
1146 .map_err(Into::<anyhow::Error>::into)
1147 .context("parsing context for ipv6 node")?;
1148
1149 Ok((Self { address, mask, context }, tail))
1150 }
1151}
1152
1153pub(super) type InfinitiBandPartitionKeys = Vec<InfinitiBandPartitionKey>;
1154
1155impl Validate for InfinitiBandPartitionKeys {
1156 type Error = anyhow::Error;
1157
1158 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1160 Ok(())
1161 }
1162}
1163
1164#[derive(Debug, PartialEq)]
1165pub(super) struct InfinitiBandPartitionKey {
1166 low: le::U32,
1167 high: le::U32,
1168 context: Context,
1169}
1170
1171impl Parse for InfinitiBandPartitionKey
1172where
1173 Context: Parse,
1174{
1175 type Error = anyhow::Error;
1176
1177 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1178 let tail = bytes;
1179
1180 let (low, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1181
1182 let (high, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1183
1184 let (context, tail) = Context::parse(tail)
1185 .map_err(Into::<anyhow::Error>::into)
1186 .context("parsing context for infiniti band partition key")?;
1187
1188 Ok((Self { low, high, context }, tail))
1189 }
1190}
1191
1192impl Validate for InfinitiBandPartitionKey {
1193 type Error = anyhow::Error;
1194
1195 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1197 Ok(())
1198 }
1199}
1200
1201pub(super) type InfinitiBandEndPorts = Vec<InfinitiBandEndPort>;
1202
1203impl Validate for InfinitiBandEndPorts {
1204 type Error = anyhow::Error;
1205
1206 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1208 Ok(())
1209 }
1210}
1211
1212#[derive(Debug, PartialEq)]
1213pub(super) struct InfinitiBandEndPort {
1214 port_and_name: Array<InfinitiBandEndPortMetadata, Vec<u8>>,
1215 context: Context,
1216}
1217
1218impl Parse for InfinitiBandEndPort
1219where
1220 Array<InfinitiBandEndPortMetadata, Vec<u8>>: Parse,
1221 Context: Parse,
1222{
1223 type Error = anyhow::Error;
1224
1225 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1226 let tail = bytes;
1227
1228 let (port_and_name, tail) = Array::<InfinitiBandEndPortMetadata, Vec<u8>>::parse(tail)
1229 .map_err(Into::<anyhow::Error>::into)
1230 .context("parsing infiniti band end port metadata")?;
1231
1232 let (context, tail) = Context::parse(tail)
1233 .map_err(Into::<anyhow::Error>::into)
1234 .context("parsing context for infiniti band end port")?;
1235
1236 Ok((Self { port_and_name, context }, tail))
1237 }
1238}
1239
1240#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1241#[repr(C, packed)]
1242pub(super) struct InfinitiBandEndPortMetadata {
1243 length: le::U32,
1244 port: le::U32,
1245}
1246
1247impl Counted for InfinitiBandEndPortMetadata {
1248 fn count(&self) -> u32 {
1249 self.length.get()
1250 }
1251}
1252
1253pub(super) type GenericFsContexts = Vec<GenericFsContext>;
1254
1255impl Validate for GenericFsContexts {
1256 type Error = anyhow::Error;
1257
1258 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1260 Ok(())
1261 }
1262}
1263
1264#[derive(Debug, PartialEq)]
1267pub(super) struct GenericFsContext {
1268 fs_type: SimpleArray<Vec<u8>>,
1270 contexts: SimpleArray<FsContexts>,
1272}
1273
1274impl GenericFsContext {
1275 pub(super) fn fs_type(&self) -> &[u8] {
1276 &self.fs_type.data
1277 }
1278
1279 pub(super) fn contexts(&self) -> &FsContexts {
1280 &self.contexts.data
1281 }
1282}
1283
1284impl Parse for GenericFsContext
1285where
1286 SimpleArray<Vec<u8>>: Parse,
1287 SimpleArray<FsContexts>: Parse,
1288{
1289 type Error = anyhow::Error;
1290
1291 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1292 let tail = bytes;
1293
1294 let (fs_type, tail) = SimpleArray::<Vec<u8>>::parse(tail)
1295 .map_err(Into::<anyhow::Error>::into)
1296 .context("parsing generic filesystem context name")?;
1297
1298 let (contexts, tail) = SimpleArray::<FsContexts>::parse(tail)
1299 .map_err(Into::<anyhow::Error>::into)
1300 .context("parsing generic filesystem contexts")?;
1301
1302 Ok((Self { fs_type, contexts }, tail))
1303 }
1304}
1305
1306pub(super) type FsContexts = Vec<FsContext>;
1307
1308#[derive(Debug, PartialEq)]
1309pub(super) struct FsContext {
1310 partial_path: SimpleArray<Vec<u8>>,
1313 class: le::U32,
1317 context: Context,
1319}
1320
1321impl FsContext {
1322 pub(super) fn partial_path(&self) -> &[u8] {
1323 &self.partial_path.data
1324 }
1325
1326 pub(super) fn context(&self) -> &Context {
1327 &self.context
1328 }
1329
1330 pub(super) fn class(&self) -> Option<ClassId> {
1331 NonZeroU32::new(self.class.into()).map(ClassId)
1332 }
1333}
1334
1335impl Parse for FsContext
1336where
1337 SimpleArray<Vec<u8>>: Parse,
1338 Context: Parse,
1339{
1340 type Error = anyhow::Error;
1341
1342 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1343 let tail = bytes;
1344
1345 let (partial_path, tail) = SimpleArray::<Vec<u8>>::parse(tail)
1346 .map_err(Into::<anyhow::Error>::into)
1347 .context("parsing filesystem context partial path")?;
1348
1349 let (class, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1350
1351 let (context, tail) = Context::parse(tail)
1352 .map_err(Into::<anyhow::Error>::into)
1353 .context("parsing context for filesystem context")?;
1354
1355 Ok((Self { partial_path, class, context }, tail))
1356 }
1357}
1358
1359pub(super) type RangeTransitions = Vec<RangeTransition>;
1360
1361impl Validate for RangeTransitions {
1362 type Error = anyhow::Error;
1363
1364 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1366 for range_transition in self {
1367 if range_transition.metadata.target_class.get() == 0 {
1368 return Err(ValidateError::NonOptionalIdIsZero.into());
1369 }
1370 }
1371 Ok(())
1372 }
1373}
1374
1375#[derive(Debug, PartialEq)]
1376pub(super) struct RangeTransition {
1377 metadata: RangeTransitionMetadata,
1378 mls_range: MlsRange,
1379}
1380
1381impl RangeTransition {
1382 pub fn source_type(&self) -> TypeId {
1383 TypeId(NonZeroU32::new(self.metadata.source_type.get()).unwrap())
1384 }
1385
1386 pub fn target_type(&self) -> TypeId {
1387 TypeId(NonZeroU32::new(self.metadata.target_type.get()).unwrap())
1388 }
1389
1390 pub fn target_class(&self) -> ClassId {
1391 ClassId(NonZeroU32::new(self.metadata.target_class.get()).unwrap())
1392 }
1393
1394 pub fn mls_range(&self) -> &MlsRange {
1395 &self.mls_range
1396 }
1397}
1398
1399impl Parse for RangeTransition
1400where
1401 MlsRange: Parse,
1402{
1403 type Error = anyhow::Error;
1404
1405 fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1406 let tail = bytes;
1407
1408 let (metadata, tail) = PolicyCursor::parse::<RangeTransitionMetadata>(tail)
1409 .context("parsing range transition metadata")?;
1410
1411 let (mls_range, tail) = MlsRange::parse(tail)
1412 .map_err(Into::<anyhow::Error>::into)
1413 .context("parsing mls range for range transition")?;
1414
1415 Ok((Self { metadata, mls_range }, tail))
1416 }
1417}
1418
1419#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1420#[repr(C, packed)]
1421pub(super) struct RangeTransitionMetadata {
1422 source_type: le::U32,
1423 target_type: le::U32,
1424 target_class: le::U32,
1425}
1426
1427#[cfg(test)]
1428pub(super) mod testing {
1429 use super::AccessVectorRule;
1430 use std::cmp::Ordering;
1431
1432 pub(in super::super) fn access_vector_rule_ordering(
1433 left: &AccessVectorRule,
1434 right: &AccessVectorRule,
1435 ) -> Ordering {
1436 (
1437 left.metadata.source_type,
1438 left.metadata.target_type,
1439 left.metadata.class,
1440 left.metadata.access_vector_rule_type,
1441 )
1442 .cmp(&(
1443 right.metadata.source_type,
1444 right.metadata.target_type,
1445 right.metadata.class,
1446 right.metadata.access_vector_rule_type,
1447 ))
1448 }
1449}
1450
1451#[cfg(test)]
1452mod tests {
1453 use super::super::{ClassId, find_class_by_name, parse_policy_by_value};
1454 use super::{
1455 ACCESS_VECTOR_RULE_TYPE_ALLOWXPERM, ACCESS_VECTOR_RULE_TYPE_AUDITALLOWXPERM,
1456 ACCESS_VECTOR_RULE_TYPE_DONTAUDITXPERM, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES,
1457 XPERMS_TYPE_IOCTL_PREFIXES, XPERMS_TYPE_NLMSG,
1458 };
1459 use std::num::NonZeroU32;
1460
1461 impl super::AccessVectorRuleMetadata {
1462 pub fn is_allowxperm(&self) -> bool {
1466 (self.access_vector_rule_type & ACCESS_VECTOR_RULE_TYPE_ALLOWXPERM) != 0
1467 }
1468
1469 pub fn is_auditallowxperm(&self) -> bool {
1473 (self.access_vector_rule_type & ACCESS_VECTOR_RULE_TYPE_AUDITALLOWXPERM) != 0
1474 }
1475
1476 pub fn is_dontauditxperm(&self) -> bool {
1480 (self.access_vector_rule_type & ACCESS_VECTOR_RULE_TYPE_DONTAUDITXPERM) != 0
1481 }
1482
1483 pub fn target_class(&self) -> ClassId {
1488 ClassId(NonZeroU32::new(self.class.into()).unwrap())
1489 }
1490 }
1491
1492 #[test]
1493 fn parse_allowxperm_one_ioctl() {
1494 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1495 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1496 let parsed_policy = &policy.0;
1497 parsed_policy.validate().expect("validate policy");
1498
1499 let class_id = find_class_by_name(parsed_policy.classes(), "class_one_ioctl")
1500 .expect("look up class_one_ioctl")
1501 .id();
1502
1503 let rules: Vec<_> = parsed_policy
1504 .access_vector_rules_for_test()
1505 .filter(|rule| rule.metadata.target_class() == class_id)
1506 .collect();
1507
1508 assert_eq!(rules.len(), 1);
1509 assert!(rules[0].metadata.is_allowxperm());
1510 if let Some(xperms) = rules[0].extended_permissions() {
1511 assert_eq!(xperms.count(), 1);
1512 assert!(xperms.contains(0xabcd));
1513 } else {
1514 panic!("unexpected permission data type")
1515 }
1516 }
1517
1518 #[test]
1521 fn parse_allowxperm_two_ioctls_same_range() {
1522 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1523 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1524 let parsed_policy = &policy.0;
1525 parsed_policy.validate().expect("validate policy");
1526
1527 let class_id = find_class_by_name(parsed_policy.classes(), "class_two_ioctls_same_range")
1528 .expect("look up class_two_ioctls_same_range")
1529 .id();
1530
1531 let rules: Vec<_> = parsed_policy
1532 .access_vector_rules_for_test()
1533 .filter(|rule| rule.metadata.target_class() == class_id)
1534 .collect();
1535
1536 assert_eq!(rules.len(), 1);
1537 assert!(rules[0].metadata.is_allowxperm());
1538 if let Some(xperms) = rules[0].extended_permissions() {
1539 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1540 assert_eq!(xperms.xperms_optional_prefix, 0x12);
1541 assert_eq!(xperms.count(), 2);
1542 assert!(xperms.contains(0x1234));
1543 assert!(xperms.contains(0x1256));
1544 } else {
1545 panic!("unexpected permission data type")
1546 }
1547 }
1548
1549 #[test]
1552 fn parse_allowxperm_two_ioctls_same_range_diff_rules() {
1553 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1554 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1555 let parsed_policy = &policy.0;
1556 parsed_policy.validate().expect("validate policy");
1557
1558 let class_id =
1559 find_class_by_name(parsed_policy.classes(), "class_four_ioctls_same_range_diff_rules")
1560 .expect("look up class_four_ioctls_same_range_diff_rules")
1561 .id();
1562
1563 let rules: Vec<_> = parsed_policy
1564 .access_vector_rules_for_test()
1565 .filter(|rule| rule.metadata.target_class() == class_id)
1566 .collect();
1567
1568 assert_eq!(rules.len(), 1);
1569 assert!(rules[0].metadata.is_allowxperm());
1570 if let Some(xperms) = rules[0].extended_permissions() {
1571 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1572 assert_eq!(xperms.xperms_optional_prefix, 0x30);
1573 assert_eq!(xperms.count(), 4);
1574 assert!(xperms.contains(0x3008));
1575 assert!(xperms.contains(0x3009));
1576 assert!(xperms.contains(0x3011));
1577 assert!(xperms.contains(0x3013));
1578 } else {
1579 panic!("unexpected permission data type")
1580 }
1581 }
1582
1583 #[test]
1586 fn parse_allowxperm_two_ioctls_different_range() {
1587 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1588 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1589 let parsed_policy = &policy.0;
1590 parsed_policy.validate().expect("validate policy");
1591
1592 let class_id = find_class_by_name(parsed_policy.classes(), "class_two_ioctls_diff_range")
1593 .expect("look up class_two_ioctls_diff_range")
1594 .id();
1595
1596 let rules: Vec<_> = parsed_policy
1597 .access_vector_rules_for_test()
1598 .filter(|rule| rule.metadata.target_class() == class_id)
1599 .collect();
1600
1601 assert_eq!(rules.len(), 2);
1602 assert!(rules[0].metadata.is_allowxperm());
1603 if let Some(xperms) = rules[0].extended_permissions() {
1604 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1605 assert_eq!(xperms.xperms_optional_prefix, 0x56);
1606 assert_eq!(xperms.count(), 1);
1607 assert!(xperms.contains(0x5678));
1608 } else {
1609 panic!("unexpected permission data type")
1610 }
1611 assert!(rules[1].metadata.is_allowxperm());
1612 if let Some(xperms) = rules[1].extended_permissions() {
1613 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1614 assert_eq!(xperms.xperms_optional_prefix, 0x12);
1615 assert_eq!(xperms.count(), 1);
1616 assert!(xperms.contains(0x1234));
1617 } else {
1618 panic!("unexpected permission data type")
1619 }
1620 }
1621
1622 #[test]
1625 fn parse_allowxperm_one_driver_range() {
1626 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1627 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1628 let parsed_policy = &policy.0;
1629 parsed_policy.validate().expect("validate policy");
1630
1631 let class_id = find_class_by_name(parsed_policy.classes(), "class_one_driver_range")
1632 .expect("look up class_one_driver_range")
1633 .id();
1634
1635 let rules: Vec<_> = parsed_policy
1636 .access_vector_rules_for_test()
1637 .filter(|rule| rule.metadata.target_class() == class_id)
1638 .collect();
1639
1640 assert_eq!(rules.len(), 1);
1641 assert!(rules[0].metadata.is_allowxperm());
1642 if let Some(xperms) = rules[0].extended_permissions() {
1643 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIXES);
1644 assert_eq!(xperms.count(), 0x100);
1645 assert!(xperms.contains(0x1000));
1646 assert!(xperms.contains(0x10ab));
1647 } else {
1648 panic!("unexpected permission data type")
1649 }
1650 }
1651
1652 #[test]
1656 fn parse_allowxperm_most_ioctls() {
1657 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1658 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1659 let parsed_policy = &policy.0;
1660 parsed_policy.validate().expect("validate policy");
1661
1662 let class_id = find_class_by_name(parsed_policy.classes(), "class_most_ioctls")
1663 .expect("look up class_most_ioctls")
1664 .id();
1665
1666 let rules: Vec<_> = parsed_policy
1667 .access_vector_rules_for_test()
1668 .filter(|rule| rule.metadata.target_class() == class_id)
1669 .collect();
1670
1671 assert_eq!(rules.len(), 3);
1672 assert!(rules[0].metadata.is_allowxperm());
1673 if let Some(xperms) = rules[0].extended_permissions() {
1674 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1675 assert_eq!(xperms.xperms_optional_prefix, 0xff);
1676 assert_eq!(xperms.count(), 0xfe);
1677 for xperm in 0xff00..0xfffd {
1678 assert!(xperms.contains(xperm));
1679 }
1680 } else {
1681 panic!("unexpected permission data type")
1682 }
1683 if let Some(xperms) = rules[1].extended_permissions() {
1684 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1685 assert_eq!(xperms.xperms_optional_prefix, 0x00);
1686 assert_eq!(xperms.count(), 0xfe);
1687 for xperm in 0x0002..0x0100 {
1688 assert!(xperms.contains(xperm));
1689 }
1690 } else {
1691 panic!("unexpected permission data type")
1692 }
1693 if let Some(xperms) = rules[2].extended_permissions() {
1694 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIXES);
1695 assert_eq!(xperms.count(), 0xfe00);
1696 for xperm in 0x0100..0xff00 {
1697 assert!(xperms.contains(xperm));
1698 }
1699 } else {
1700 panic!("unexpected permission data type")
1701 }
1702 }
1703
1704 #[test]
1708 fn parse_allowxperm_most_ioctls_with_hole() {
1709 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1710 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1711 let parsed_policy = &policy.0;
1712 parsed_policy.validate().expect("validate policy");
1713
1714 let class_id = find_class_by_name(parsed_policy.classes(), "class_most_ioctls_with_hole")
1715 .expect("look up class_most_ioctls_with_hole")
1716 .id();
1717
1718 let rules: Vec<_> = parsed_policy
1719 .access_vector_rules_for_test()
1720 .filter(|rule| rule.metadata.target_class() == class_id)
1721 .collect();
1722
1723 assert_eq!(rules.len(), 5);
1724 assert!(rules[0].metadata.is_allowxperm());
1725 if let Some(xperms) = rules[0].extended_permissions() {
1726 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1727 assert_eq!(xperms.xperms_optional_prefix, 0xff);
1728 assert_eq!(xperms.count(), 0xfe);
1729 for xperm in 0xff00..0xfffd {
1730 assert!(xperms.contains(xperm));
1731 }
1732 } else {
1733 panic!("unexpected permission data type")
1734 }
1735 if let Some(xperms) = rules[1].extended_permissions() {
1736 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1737 assert_eq!(xperms.xperms_optional_prefix, 0x40);
1738 assert_eq!(xperms.count(), 0xfe);
1739 for xperm in 0x4002..0x4100 {
1740 assert!(xperms.contains(xperm));
1741 }
1742 } else {
1743 panic!("unexpected permission data type")
1744 }
1745 assert!(rules[0].metadata.is_allowxperm());
1746 if let Some(xperms) = rules[2].extended_permissions() {
1747 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1748 assert_eq!(xperms.xperms_optional_prefix, 0x2f);
1749 assert_eq!(xperms.count(), 0xfe);
1750 for xperm in 0x2f00..0x2ffd {
1751 assert!(xperms.contains(xperm));
1752 }
1753 } else {
1754 panic!("unexpected permission data type")
1755 }
1756 if let Some(xperms) = rules[3].extended_permissions() {
1757 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1758 assert_eq!(xperms.xperms_optional_prefix, 0x00);
1759 assert_eq!(xperms.count(), 0xfe);
1760 for xperm in 0x0002..0x0100 {
1761 assert!(xperms.contains(xperm));
1762 }
1763 } else {
1764 panic!("unexpected permission data type")
1765 }
1766 if let Some(xperms) = rules[4].extended_permissions() {
1767 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIXES);
1768 assert_eq!(xperms.count(), 0xec00);
1769 for xperm in 0x0100..0x2f00 {
1770 assert!(xperms.contains(xperm));
1771 }
1772 for xperm in 0x4100..0xff00 {
1773 assert!(xperms.contains(xperm));
1774 }
1775 } else {
1776 panic!("unexpected permission data type")
1777 }
1778 }
1779
1780 #[test]
1785 fn parse_allowxperm_all_ioctls() {
1786 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1787 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1788 let parsed_policy = &policy.0;
1789 parsed_policy.validate().expect("validate policy");
1790
1791 let class_id = find_class_by_name(parsed_policy.classes(), "class_all_ioctls")
1792 .expect("look up class_all_ioctls")
1793 .id();
1794
1795 let rules: Vec<_> = parsed_policy
1796 .access_vector_rules_for_test()
1797 .filter(|rule| rule.metadata.target_class() == class_id)
1798 .collect();
1799
1800 assert_eq!(rules.len(), 1);
1801 assert!(rules[0].metadata.is_allowxperm());
1802 if let Some(xperms) = rules[0].extended_permissions() {
1803 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIXES);
1804 assert_eq!(xperms.count(), 0x10000);
1805 } else {
1806 panic!("unexpected permission data type")
1807 }
1808 }
1809
1810 #[test]
1811 fn parse_allowxperm_one_nlmsg() {
1812 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1813 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1814 let parsed_policy = &policy.0;
1815 parsed_policy.validate().expect("validate policy");
1816
1817 let class_id = find_class_by_name(parsed_policy.classes(), "class_one_nlmsg")
1818 .expect("look up class_one_nlmsg")
1819 .id();
1820
1821 let rules: Vec<_> = parsed_policy
1822 .access_vector_rules_for_test()
1823 .filter(|rule| rule.metadata.target_class() == class_id)
1824 .collect();
1825
1826 assert_eq!(rules.len(), 1);
1827 assert!(rules[0].metadata.is_allowxperm());
1828 if let Some(xperms) = rules[0].extended_permissions() {
1829 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
1830 assert_eq!(xperms.xperms_optional_prefix, 0x00);
1831 assert_eq!(xperms.count(), 1);
1832 assert!(xperms.contains(0x12));
1833 } else {
1834 panic!("unexpected permission data type")
1835 }
1836 }
1837
1838 #[test]
1841 fn parse_allowxperm_two_nlmsg_same_range() {
1842 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1843 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1844 let parsed_policy = &policy.0;
1845 parsed_policy.validate().expect("validate policy");
1846
1847 let class_id = find_class_by_name(parsed_policy.classes(), "class_two_nlmsg_same_range")
1848 .expect("look up class_two_nlmsg_same_range")
1849 .id();
1850
1851 let rules: Vec<_> = parsed_policy
1852 .access_vector_rules_for_test()
1853 .filter(|rule| rule.metadata.target_class() == class_id)
1854 .collect();
1855
1856 assert_eq!(rules.len(), 1);
1857 assert!(rules[0].metadata.is_allowxperm());
1858 if let Some(xperms) = rules[0].extended_permissions() {
1859 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
1860 assert_eq!(xperms.xperms_optional_prefix, 0x00);
1861 assert_eq!(xperms.count(), 2);
1862 assert!(xperms.contains(0x12));
1863 assert!(xperms.contains(0x24));
1864 } else {
1865 panic!("unexpected permission data type")
1866 }
1867 }
1868
1869 #[test]
1872 fn parse_allowxperm_two_nlmsg_different_range() {
1873 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1874 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1875 let parsed_policy = &policy.0;
1876 parsed_policy.validate().expect("validate policy");
1877
1878 let class_id = find_class_by_name(parsed_policy.classes(), "class_two_nlmsg_diff_range")
1879 .expect("look up class_two_nlmsg_diff_range")
1880 .id();
1881
1882 let rules: Vec<_> = parsed_policy
1883 .access_vector_rules_for_test()
1884 .filter(|rule| rule.metadata.target_class() == class_id)
1885 .collect();
1886
1887 assert_eq!(rules.len(), 2);
1888 assert!(rules[0].metadata.is_allowxperm());
1889 if let Some(xperms) = rules[0].extended_permissions() {
1890 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
1891 assert_eq!(xperms.xperms_optional_prefix, 0x10);
1892 assert_eq!(xperms.count(), 1);
1893 assert!(xperms.contains(0x1024));
1894 } else {
1895 panic!("unexpected permission data type")
1896 }
1897 assert!(rules[1].metadata.is_allowxperm());
1898 if let Some(xperms) = rules[1].extended_permissions() {
1899 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
1900 assert_eq!(xperms.xperms_optional_prefix, 0x00);
1901 assert_eq!(xperms.count(), 1);
1902 assert!(xperms.contains(0x12));
1903 } else {
1904 panic!("unexpected permission data type")
1905 }
1906 }
1907
1908 #[test]
1911 fn parse_allowxperm_one_nlmsg_range() {
1912 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1913 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1914 let parsed_policy = &policy.0;
1915 parsed_policy.validate().expect("validate policy");
1916
1917 let class_id = find_class_by_name(parsed_policy.classes(), "class_one_nlmsg_range")
1918 .expect("look up class_one_nlmsg_range")
1919 .id();
1920
1921 let rules: Vec<_> = parsed_policy
1922 .access_vector_rules_for_test()
1923 .filter(|rule| rule.metadata.target_class() == class_id)
1924 .collect();
1925
1926 assert_eq!(rules.len(), 1);
1927 assert!(rules[0].metadata.is_allowxperm());
1928 if let Some(xperms) = rules[0].extended_permissions() {
1929 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
1930 assert_eq!(xperms.xperms_optional_prefix, 0x00);
1931 assert_eq!(xperms.count(), 0x100);
1932 for i in 0x0..0xff {
1933 assert!(xperms.contains(i), "{i}");
1934 }
1935 } else {
1936 panic!("unexpected permission data type")
1937 }
1938 }
1939
1940 #[test]
1946 fn parse_allowxperm_two_nlmsg_ranges() {
1947 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1948 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1949 let parsed_policy = &policy.0;
1950 parsed_policy.validate().expect("validate policy");
1951
1952 let class_id = find_class_by_name(parsed_policy.classes(), "class_two_nlmsg_ranges")
1953 .expect("look up class_two_nlmsg_ranges")
1954 .id();
1955
1956 let rules: Vec<_> = parsed_policy
1957 .access_vector_rules_for_test()
1958 .filter(|rule| rule.metadata.target_class() == class_id)
1959 .collect();
1960
1961 assert_eq!(rules.len(), 2);
1962 assert!(rules[0].metadata.is_allowxperm());
1963 if let Some(xperms) = rules[0].extended_permissions() {
1964 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
1965 assert_eq!(xperms.xperms_optional_prefix, 0x01);
1966 assert_eq!(xperms.count(), 0x100);
1967 for i in 0x0100..0x01ff {
1968 assert!(xperms.contains(i), "{i}");
1969 }
1970 } else {
1971 panic!("unexpected permission data type")
1972 }
1973 if let Some(xperms) = rules[1].extended_permissions() {
1974 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
1975 assert_eq!(xperms.xperms_optional_prefix, 0x00);
1976 assert_eq!(xperms.count(), 0x100);
1977 for i in 0x0..0xff {
1978 assert!(xperms.contains(i), "{i}");
1979 }
1980 } else {
1981 panic!("unexpected permission data type")
1982 }
1983 }
1984
1985 #[test]
1992 fn parse_allowxperm_three_separate_nlmsg_ranges() {
1993 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
1994 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1995 let parsed_policy = &policy.0;
1996 parsed_policy.validate().expect("validate policy");
1997
1998 let class_id =
1999 find_class_by_name(parsed_policy.classes(), "class_three_separate_nlmsg_ranges")
2000 .expect("look up class_three_separate_nlmsg_ranges")
2001 .id();
2002
2003 let rules: Vec<_> = parsed_policy
2004 .access_vector_rules_for_test()
2005 .filter(|rule| rule.metadata.target_class() == class_id)
2006 .collect();
2007
2008 assert_eq!(rules.len(), 3);
2009 assert!(rules[0].metadata.is_allowxperm());
2010 if let Some(xperms) = rules[0].extended_permissions() {
2011 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
2012 assert_eq!(xperms.xperms_optional_prefix, 0x20);
2013 assert_eq!(xperms.count(), 0x100);
2014 for i in 0x2000..0x20ff {
2015 assert!(xperms.contains(i), "{i}");
2016 }
2017 } else {
2018 panic!("unexpected permission data type")
2019 }
2020 if let Some(xperms) = rules[1].extended_permissions() {
2021 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
2022 assert_eq!(xperms.xperms_optional_prefix, 0x10);
2023 assert_eq!(xperms.count(), 0x100);
2024 for i in 0x1000..0x10ff {
2025 assert!(xperms.contains(i), "{i}");
2026 }
2027 } else {
2028 panic!("unexpected permission data type")
2029 }
2030 if let Some(xperms) = rules[2].extended_permissions() {
2031 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
2032 assert_eq!(xperms.xperms_optional_prefix, 0x00);
2033 assert_eq!(xperms.count(), 0x100);
2034 for i in 0x0..0xff {
2035 assert!(xperms.contains(i), "{i}");
2036 }
2037 } else {
2038 panic!("unexpected permission data type")
2039 }
2040 }
2041
2042 #[test]
2049 fn parse_allowxperm_three_contiguous_nlmsg_ranges() {
2050 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
2051 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2052 let parsed_policy = &policy.0;
2053 parsed_policy.validate().expect("validate policy");
2054
2055 let class_id =
2056 find_class_by_name(parsed_policy.classes(), "class_three_contiguous_nlmsg_ranges")
2057 .expect("look up class_three_contiguous_nlmsg_ranges")
2058 .id();
2059
2060 let rules: Vec<_> = parsed_policy
2061 .access_vector_rules_for_test()
2062 .filter(|rule| rule.metadata.target_class() == class_id)
2063 .collect();
2064
2065 assert_eq!(rules.len(), 2);
2066 assert!(rules[0].metadata.is_allowxperm());
2067 if let Some(xperms) = rules[0].extended_permissions() {
2068 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
2069 assert_eq!(xperms.xperms_optional_prefix, 0x02);
2070 assert_eq!(xperms.count(), 0x100);
2071 for i in 0x0200..0x02ff {
2072 assert!(xperms.contains(i), "{i}");
2073 }
2074 } else {
2075 panic!("unexpected permission data type")
2076 }
2077 if let Some(xperms) = rules[1].extended_permissions() {
2078 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
2079 assert_eq!(xperms.xperms_optional_prefix, 0x00);
2080 assert_eq!(xperms.count(), 0x100);
2081 for i in 0x0..0xff {
2082 assert!(xperms.contains(i), "{i}");
2083 }
2084 } else {
2085 panic!("unexpected permission data type")
2086 }
2087 }
2088
2089 #[test]
2092 fn parse_auditallowxperm() {
2093 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
2094 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2095 let parsed_policy = &policy.0;
2096 parsed_policy.validate().expect("validate policy");
2097
2098 let class_id = find_class_by_name(parsed_policy.classes(), "class_auditallowxperm")
2099 .expect("look up class_auditallowxperm")
2100 .id();
2101
2102 let rules: Vec<_> = parsed_policy
2103 .access_vector_rules_for_test()
2104 .filter(|rule| rule.metadata.target_class() == class_id)
2105 .collect();
2106
2107 assert_eq!(rules.len(), 2);
2108 assert!(rules[0].metadata.is_auditallowxperm());
2109 if let Some(xperms) = rules[0].extended_permissions() {
2110 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
2111 assert_eq!(xperms.xperms_optional_prefix, 0x00);
2112 assert_eq!(xperms.count(), 1);
2113 assert!(xperms.contains(0x10));
2114 } else {
2115 panic!("unexpected permission data type")
2116 }
2117 if let Some(xperms) = rules[1].extended_permissions() {
2118 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
2119 assert_eq!(xperms.xperms_optional_prefix, 0x10);
2120 assert_eq!(xperms.count(), 1);
2121 assert!(xperms.contains(0x1000));
2122 } else {
2123 panic!("unexpected permission data type")
2124 }
2125 }
2126
2127 #[test]
2135 fn parse_dontauditxperm() {
2136 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
2137 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2138 let parsed_policy = &policy.0;
2139 parsed_policy.validate().expect("validate policy");
2140
2141 let class_id = find_class_by_name(parsed_policy.classes(), "class_dontauditxperm")
2142 .expect("look up class_dontauditxperm")
2143 .id();
2144
2145 let rules: Vec<_> = parsed_policy
2146 .access_vector_rules_for_test()
2147 .filter(|rule| rule.metadata.target_class() == class_id)
2148 .collect();
2149
2150 assert_eq!(rules.len(), 2);
2151 assert!(rules[0].metadata.is_dontauditxperm());
2152 if let Some(xperms) = rules[0].extended_permissions() {
2153 assert_eq!(xperms.xperms_type, XPERMS_TYPE_NLMSG);
2154 assert_eq!(xperms.xperms_optional_prefix, 0x00);
2155 assert_eq!(xperms.count(), 1);
2156 assert!(xperms.contains(0x11));
2157 } else {
2158 panic!("unexpected permission data type")
2159 }
2160 if let Some(xperms) = rules[1].extended_permissions() {
2161 assert_eq!(xperms.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
2162 assert_eq!(xperms.xperms_optional_prefix, 0x10);
2163 assert_eq!(xperms.count(), 1);
2164 assert!(xperms.contains(0x1000));
2165 } else {
2166 panic!("unexpected permission data type")
2167 }
2168 }
2169
2170 #[test]
2174 fn parse_auditallowxperm_not_coalesced() {
2175 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy.pp");
2176 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
2177 let parsed_policy = &policy.0;
2178 parsed_policy.validate().expect("validate policy");
2179
2180 let class_id =
2181 find_class_by_name(parsed_policy.classes(), "class_auditallowxperm_not_coalesced")
2182 .expect("class_auditallowxperm_not_coalesced")
2183 .id();
2184
2185 let rules: Vec<_> = parsed_policy
2186 .access_vector_rules_for_test()
2187 .filter(|rule| rule.metadata.target_class() == class_id)
2188 .collect();
2189
2190 assert_eq!(rules.len(), 2);
2191 assert!(rules[0].metadata.is_allowxperm());
2192 assert!(!rules[0].metadata.is_auditallowxperm());
2193 if let Some(xperms) = rules[0].extended_permissions() {
2194 assert_eq!(xperms.count(), 1);
2195 assert!(xperms.contains(0xabcd));
2196 } else {
2197 panic!("unexpected permission data type")
2198 }
2199 assert!(!rules[1].metadata.is_allowxperm());
2200 assert!(rules[1].metadata.is_auditallowxperm());
2201 if let Some(xperms) = rules[1].extended_permissions() {
2202 assert_eq!(xperms.count(), 1);
2203 assert!(xperms.contains(0xabcd));
2204 } else {
2205 panic!("unexpected permission data type")
2206 }
2207 }
2208}