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