1use std::num::NonZeroU32;
6use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not, Sub, SubAssign};
7use std::sync::atomic::{AtomicU64, Ordering};
8
9use hashbrown::HashTable;
10use hashbrown::hash_table::Entry;
11use rapidhash::RapidBuildHasher;
12pub use selinux_policy_derive::{Parse, Serialize, Validate};
13
14use super::error::{ParseError, SerializeError, ValidateError};
15use super::parser::{Array, PolicyCursor, PolicyWriter};
16use super::traits::{Parse, PolicyId, Serialize, Validate};
17use super::{AccessVector, ClassId, ConditionalBooleanId, NewPolicy, TypeId, U24Index};
18
19pub const AV_ALLOW_RULE_FLAG: u16 = 0x1;
21pub const AV_AUDITALLOW_RULE_FLAG: u16 = 0x2;
23pub const AV_DONTAUDIT_RULE_FLAG: u16 = 0x4;
25
26pub const AV_TYPE_TRANSITION_RULE_FLAG: u16 = 0x10;
28pub const AV_TYPE_MEMBER_RULE_FLAG: u16 = 0x20;
30pub const AV_TYPE_CHANGE_RULE_FLAG: u16 = 0x40;
32
33pub const AV_ALLOWXPERM_RULE_FLAG: u16 = 0x100;
35pub const AV_AUDITALLOWXPERM_RULE_FLAG: u16 = 0x200;
37pub const AV_DONTAUDITXPERM_RULE_FLAG: u16 = 0x400;
39
40pub const AV_ENABLED_RULE_FLAG: u16 = 0x8000;
42
43pub const SELINUX_AVD_FLAGS_PERMISSIVE: u32 = 1;
45
46pub const XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES: u8 = 1;
48pub const XPERMS_TYPE_IOCTL_PREFIXES: u8 = 2;
50pub const XPERMS_TYPE_NLMSG: u8 = 3;
52
53pub const XPERMS_BITMAP_BLOCKS: usize = 4;
55
56#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
58pub struct XpermsBitmap([u64; XPERMS_BITMAP_BLOCKS]);
59
60impl Parse for XpermsBitmap {
61 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
62 let mut words = [0u64; XPERMS_BITMAP_BLOCKS];
63 for word in words.iter_mut() {
64 let low = cursor.parse::<u32>()? as u64;
65 let high = cursor.parse::<u32>()? as u64;
66 *word = low | (high << 32);
67 }
68 Ok(Self(words))
69 }
70}
71
72impl Serialize for XpermsBitmap {
73 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
74 for &word in self.0.iter() {
75 (word as u32).serialize(writer)?;
76 ((word >> 32) as u32).serialize(writer)?;
77 }
78 Ok(())
79 }
80}
81
82impl XpermsBitmap {
83 pub const BITMAP_BLOCKS: usize = XPERMS_BITMAP_BLOCKS;
84 pub const ALL: Self = Self([u64::MAX; Self::BITMAP_BLOCKS]);
86 pub const NONE: Self = Self([0u64; Self::BITMAP_BLOCKS]);
88
89 pub fn new(elements: [u64; Self::BITMAP_BLOCKS]) -> Self {
91 Self(elements)
92 }
93
94 pub fn contains(&self, value: u8) -> bool {
96 let block_index = (value as usize) / (u64::BITS as usize);
97 let bit_index = (value as usize) % (u64::BITS as usize);
98 self.0[block_index] & (1u64 << bit_index) != 0
99 }
100
101 pub fn from_atomics(atomics: &[AtomicU64; Self::BITMAP_BLOCKS]) -> Self {
103 let mut words = [0u64; Self::BITMAP_BLOCKS];
104 for (i, word) in words.iter_mut().enumerate() {
105 *word = atomics[i].load(Ordering::Relaxed);
106 }
107 Self(words)
108 }
109
110 pub fn to_atomics(&self, atomics: &[AtomicU64; Self::BITMAP_BLOCKS]) {
112 for (i, word) in self.0.iter().enumerate() {
113 atomics[i].store(*word, Ordering::Relaxed);
114 }
115 }
116}
117
118impl BitAnd for XpermsBitmap {
119 type Output = Self;
120 fn bitand(self, rhs: Self) -> Self::Output {
121 Self(std::array::from_fn(|i| self.0[i] & rhs.0[i]))
122 }
123}
124
125impl BitAndAssign for XpermsBitmap {
126 fn bitand_assign(&mut self, rhs: Self) {
127 for i in 0..4 {
128 self.0[i] &= rhs.0[i];
129 }
130 }
131}
132
133impl BitOr for XpermsBitmap {
134 type Output = Self;
135 fn bitor(self, rhs: Self) -> Self::Output {
136 Self(std::array::from_fn(|i| self.0[i] | rhs.0[i]))
137 }
138}
139
140impl BitOrAssign for XpermsBitmap {
141 fn bitor_assign(&mut self, rhs: Self) {
142 for i in 0..4 {
143 self.0[i] |= rhs.0[i];
144 }
145 }
146}
147
148impl Sub for XpermsBitmap {
149 type Output = Self;
150 fn sub(self, rhs: Self) -> Self {
151 Self(std::array::from_fn(|i| self.0[i] & !rhs.0[i]))
152 }
153}
154
155impl SubAssign for XpermsBitmap {
156 fn sub_assign(&mut self, rhs: Self) {
157 for i in 0..4 {
158 self.0[i] &= !rhs.0[i];
159 }
160 }
161}
162
163impl Not for XpermsBitmap {
164 type Output = Self;
165 fn not(self) -> Self::Output {
166 Self(self.0.map(|word| !word))
167 }
168}
169
170impl Validate for XpermsBitmap {
171 fn validate(&self, _policy: &NewPolicy) -> Result<(), ValidateError> {
172 Ok(())
173 }
174}
175
176#[derive(Clone, Debug, PartialEq, Eq, Parse, Serialize)]
178pub struct ExtendedPermissions {
179 xperms_type: u8,
180 xperms_optional_prefix: u8,
181 xperms_bitmap: XpermsBitmap,
182}
183
184impl Validate for ExtendedPermissions {
185 fn validate(&self, _policy: &NewPolicy) -> Result<(), ValidateError> {
186 match self.xperms_type {
187 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES
188 | XPERMS_TYPE_IOCTL_PREFIXES
189 | XPERMS_TYPE_NLMSG => Ok(()),
190 v => Err(ValidateError::InvalidExtendedPermissionsType { value: v }),
191 }
192 }
193}
194
195impl ExtendedPermissions {
196 pub fn xperms_type(&self) -> u8 {
198 self.xperms_type
199 }
200
201 pub fn xperms_optional_prefix(&self) -> u8 {
203 self.xperms_optional_prefix
204 }
205
206 pub fn xperms_bitmap(&self) -> &XpermsBitmap {
208 &self.xperms_bitmap
209 }
210
211 #[cfg(test)]
213 pub fn count(&self) -> u64 {
214 let count = self
215 .xperms_bitmap
216 .0
217 .iter()
218 .fold(0, |count, block| count as u64 + block.count_ones() as u64);
219 match self.xperms_type {
220 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES | XPERMS_TYPE_NLMSG => count,
221 XPERMS_TYPE_IOCTL_PREFIXES => count * 0x100,
222 _ => unreachable!("invalid xperms_type in validated ExtendedPermissions"),
223 }
224 }
225
226 #[cfg(test)]
228 pub fn contains(&self, xperm: u16) -> bool {
229 let [postfix, prefix] = xperm.to_le_bytes();
230 if (self.xperms_type == XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES
231 || self.xperms_type == XPERMS_TYPE_NLMSG)
232 && self.xperms_optional_prefix != prefix
233 {
234 return false;
235 }
236 let value = match self.xperms_type {
237 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES | XPERMS_TYPE_NLMSG => postfix,
238 XPERMS_TYPE_IOCTL_PREFIXES => prefix,
239 _ => unreachable!("invalid xperms_type in validated ExtendedPermissions"),
240 };
241 self.xperms_bitmap.contains(value)
242 }
243}
244
245#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
247pub enum RuleKind {
248 Allow,
249 AuditAllow,
250 DontAudit,
251 TypeTransition,
252 TypeMember,
253 TypeChange,
254 AllowXperm,
255 AuditAllowXperm,
256 DontAuditXperm,
257}
258
259impl TryFrom<u16> for RuleKind {
260 type Error = ParseError;
261
262 fn try_from(rule_type: u16) -> Result<Self, Self::Error> {
263 let base_kind = rule_type & !AV_ENABLED_RULE_FLAG;
264 match base_kind {
265 AV_ALLOW_RULE_FLAG => Ok(Self::Allow),
266 AV_AUDITALLOW_RULE_FLAG => Ok(Self::AuditAllow),
267 AV_DONTAUDIT_RULE_FLAG => Ok(Self::DontAudit),
268 AV_TYPE_TRANSITION_RULE_FLAG => Ok(Self::TypeTransition),
269 AV_TYPE_MEMBER_RULE_FLAG => Ok(Self::TypeMember),
270 AV_TYPE_CHANGE_RULE_FLAG => Ok(Self::TypeChange),
271 AV_ALLOWXPERM_RULE_FLAG => Ok(Self::AllowXperm),
272 AV_AUDITALLOWXPERM_RULE_FLAG => Ok(Self::AuditAllowXperm),
273 AV_DONTAUDITXPERM_RULE_FLAG => Ok(Self::DontAuditXperm),
274 _ => {
275 Err(ParseError::InvalidEnumValue { enum_name: "RuleKind", value: rule_type as u64 })
276 }
277 }
278 }
279}
280
281impl From<RuleKind> for u16 {
282 fn from(kind: RuleKind) -> Self {
283 match kind {
284 RuleKind::Allow => AV_ALLOW_RULE_FLAG,
285 RuleKind::AuditAllow => AV_AUDITALLOW_RULE_FLAG,
286 RuleKind::DontAudit => AV_DONTAUDIT_RULE_FLAG,
287 RuleKind::TypeTransition => AV_TYPE_TRANSITION_RULE_FLAG,
288 RuleKind::TypeMember => AV_TYPE_MEMBER_RULE_FLAG,
289 RuleKind::TypeChange => AV_TYPE_CHANGE_RULE_FLAG,
290 RuleKind::AllowXperm => AV_ALLOWXPERM_RULE_FLAG,
291 RuleKind::AuditAllowXperm => AV_AUDITALLOWXPERM_RULE_FLAG,
292 RuleKind::DontAuditXperm => AV_DONTAUDITXPERM_RULE_FLAG,
293 }
294 }
295}
296
297impl Validate for RuleKind {
298 fn validate(&self, _policy: &NewPolicy) -> Result<(), ValidateError> {
299 Ok(())
300 }
301}
302
303#[derive(Clone, Debug, Validate)]
305pub struct AccessRule {
306 key: RuleKey,
307 kind: RuleKind,
308 access_vector: AccessVector,
309 enabled: bool,
310}
311
312impl AccessRule {
313 pub fn access_vector(&self) -> AccessVector {
315 self.access_vector
316 }
317
318 #[cfg(test)]
320 pub fn enabled(&self) -> bool {
321 self.enabled
322 }
323}
324
325#[derive(Clone, Debug, Validate)]
327pub struct TypeRule {
328 key: RuleKey,
329 kind: RuleKind,
330 new_type: TypeId,
331 enabled: bool,
332}
333
334impl TypeRule {
335 pub fn new_type(&self) -> TypeId {
337 self.new_type
338 }
339
340 #[cfg(test)]
342 pub fn enabled(&self) -> bool {
343 self.enabled
344 }
345}
346
347#[derive(Clone, Debug, Validate)]
349pub struct XpermRule {
350 key: RuleKey,
351 kind: RuleKind,
352 extended_permissions: ExtendedPermissions,
353 enabled: bool,
354}
355
356impl XpermRule {
357 pub fn extended_permissions(&self) -> &ExtendedPermissions {
359 &self.extended_permissions
360 }
361
362 #[cfg(test)]
364 pub fn enabled(&self) -> bool {
365 self.enabled
366 }
367}
368
369#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Validate)]
371pub struct RuleKey {
372 source_type: TypeId,
373 target_type: TypeId,
374 class: ClassId,
375}
376
377impl RuleKey {
378 pub fn new(source_type: TypeId, target_type: TypeId, class: ClassId) -> Self {
380 Self { source_type, target_type, class }
381 }
382
383 pub fn hash(&self, hasher: &RapidBuildHasher) -> u64 {
385 use std::hash::{BuildHasher, Hash, Hasher};
386 let mut state = hasher.build_hasher();
387 Hash::hash(self, &mut state);
388 state.finish()
389 }
390
391 fn to_header(&self, kind: RuleKind, enabled: bool) -> BinaryAccessVectorRuleHeader {
393 let mut rule_flags = u16::from(kind);
394 if enabled {
395 rule_flags |= AV_ENABLED_RULE_FLAG;
396 }
397 BinaryAccessVectorRuleHeader {
398 source_type: self.source_type.as_u16(),
399 target_type: self.target_type.as_u16(),
400 class: self.class.as_u16(),
401 rule_flags,
402 }
403 }
404}
405
406pub trait HasRuleKey {
408 fn key(&self) -> RuleKey;
410
411 fn kind(&self) -> RuleKind;
413}
414
415impl HasRuleKey for AccessRule {
416 fn key(&self) -> RuleKey {
417 self.key
418 }
419 fn kind(&self) -> RuleKind {
420 self.kind
421 }
422}
423
424impl HasRuleKey for TypeRule {
425 fn key(&self) -> RuleKey {
426 self.key
427 }
428 fn kind(&self) -> RuleKind {
429 self.kind
430 }
431}
432
433impl HasRuleKey for XpermRule {
434 fn key(&self) -> RuleKey {
435 self.key
436 }
437 fn kind(&self) -> RuleKind {
438 self.kind
439 }
440}
441
442#[derive(Debug, Clone, PartialEq)]
447pub struct AccessDecision {
448 pub allow: AccessVector,
449 pub auditallow: AccessVector,
450 pub auditdeny: AccessVector,
451 pub flags: u32,
452
453 pub todo_bug: Option<NonZeroU32>,
456}
457
458impl Default for AccessDecision {
459 fn default() -> Self {
460 Self::allow(AccessVector::NONE)
461 }
462}
463
464impl AccessDecision {
465 pub const fn allow(allow: AccessVector) -> Self {
468 Self {
469 allow,
470 auditallow: AccessVector::NONE,
471 auditdeny: AccessVector::ALL,
472 flags: 0,
473 todo_bug: None,
474 }
475 }
476}
477
478#[derive(Debug, Clone)]
491pub struct AccessVectorRules {
492 av_rules: Box<[AccessRule]>,
493 type_rules: Box<[TypeRule]>,
494 xperm_rules: Box<[XpermRule]>,
495 rule_order: Box<[RuleKind]>,
496}
497
498impl AccessVectorRules {
499 #[cfg(test)]
501 pub fn av_rules(&self) -> &[AccessRule] {
502 &self.av_rules
503 }
504}
505
506impl Parse for AccessVectorRules {
507 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
508 let count = u32::parse(cursor)? as usize;
509
510 let mut av_rules = Vec::new();
511 let mut type_rules = Vec::new();
512 let mut xperm_rules = Vec::new();
513 let mut rule_order = Vec::with_capacity(count);
514
515 for _ in 0..count {
518 let header = BinaryAccessVectorRuleHeader::parse(cursor)?;
519 let kind = RuleKind::try_from(header.rule_flags)?;
520 let enabled = (header.rule_flags & AV_ENABLED_RULE_FLAG) != 0;
521
522 let source_val = header.source_type;
523 let source_type = TypeId::from_u16(source_val)
524 .ok_or(ParseError::InvalidId { value: source_val as u32 })?;
525
526 let target_val = header.target_type;
527 let target_type = TypeId::from_u16(target_val)
528 .ok_or(ParseError::InvalidId { value: target_val as u32 })?;
529
530 let class_val = header.class;
531 let class = ClassId::from_u16(class_val)
532 .ok_or(ParseError::InvalidId { value: class_val as u32 })?;
533
534 let key = RuleKey::new(source_type, target_type, class);
535
536 match kind {
537 RuleKind::AllowXperm | RuleKind::AuditAllowXperm | RuleKind::DontAuditXperm => {
538 let extended_permissions = ExtendedPermissions::parse(cursor)?;
539 xperm_rules.push(XpermRule { key, kind, extended_permissions, enabled });
540 rule_order.push(kind);
541 }
542 RuleKind::TypeTransition | RuleKind::TypeChange | RuleKind::TypeMember => {
543 let new_type = TypeId::parse(cursor)?;
544 type_rules.push(TypeRule { key, kind, new_type, enabled });
545 rule_order.push(kind);
546 }
547 RuleKind::Allow | RuleKind::AuditAllow | RuleKind::DontAudit => {
548 let access_vector = AccessVector::parse(cursor)?;
549 av_rules.push(AccessRule { key, kind, access_vector, enabled });
550 rule_order.push(kind);
551 }
552 }
553 }
554
555 let av_rules = av_rules.into_boxed_slice();
556 let type_rules = type_rules.into_boxed_slice();
557 let xperm_rules = xperm_rules.into_boxed_slice();
558 let rule_order = rule_order.into_boxed_slice();
559
560 Ok(Self { av_rules, type_rules, xperm_rules, rule_order })
561 }
562}
563
564impl Serialize for AccessVectorRules {
565 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
566 let count = self.rule_order.len() as u32;
567 count.serialize(writer)?;
568
569 let mut av_rules = self.av_rules.iter();
570 let mut type_rules = self.type_rules.iter();
571 let mut xperm_rules = self.xperm_rules.iter();
572
573 for &kind in self.rule_order.iter() {
574 match kind {
575 RuleKind::Allow | RuleKind::AuditAllow | RuleKind::DontAudit => {
576 let rule = av_rules.next().unwrap();
577 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
578 let val: u32 = rule.access_vector.into();
579 val.serialize(writer)?;
580 }
581 RuleKind::TypeTransition | RuleKind::TypeChange | RuleKind::TypeMember => {
582 let rule = type_rules.next().unwrap();
583 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
584 rule.new_type.serialize(writer)?;
585 }
586 RuleKind::AllowXperm | RuleKind::AuditAllowXperm | RuleKind::DontAuditXperm => {
587 let rule = xperm_rules.next().unwrap();
588 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
589 rule.extended_permissions.serialize(writer)?;
590 }
591 }
592 }
593 Ok(())
594 }
595}
596
597impl Validate for AccessVectorRules {
598 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
599 self.av_rules.validate(policy)?;
600 self.type_rules.validate(policy)?;
601 self.xperm_rules.validate(policy)?;
602 Ok(())
603 }
604}
605
606#[derive(Debug)]
612pub struct IndexedAccessVectorRules {
613 rules: AccessVectorRules,
614 av_table: HashTable<U24Index>,
615 type_transition_table: HashTable<U24Index>,
616 xperms_table: HashTable<U24Index>,
617 hasher: RapidBuildHasher,
618}
619
620impl IndexedAccessVectorRules {
621 pub fn new(rules: AccessVectorRules) -> Result<Self, ParseError> {
625 let hasher = RapidBuildHasher::default();
626 let av_table = build_index(&rules.av_rules, &hasher)?;
627 let type_transition_table = build_index(&rules.type_rules, &hasher)?;
628 let xperms_table = build_index(&rules.xperm_rules, &hasher)?;
629
630 Ok(Self { rules, av_table, type_transition_table, xperms_table, hasher })
631 }
632
633 pub fn rules(&self) -> &AccessVectorRules {
635 &self.rules
636 }
637
638 fn find_rules<'a, R: HasRuleKey>(
639 table: &HashTable<U24Index>,
640 rules: &'a [R],
641 key: RuleKey,
642 hasher: &RapidBuildHasher,
643 ) -> impl Iterator<Item = &'a R> {
644 let hash = key.hash(hasher);
645 let slice = match table.find(hash, |&i| rules[usize::from(i)].key() == key) {
646 Some(&i) => &rules[usize::from(i)..],
647 None => &[],
648 };
649 slice.iter().take_while(move |rule| rule.key() == key)
650 }
651
652 pub fn find_av_rules(
654 &self,
655 source: TypeId,
656 target: TypeId,
657 class: ClassId,
658 ) -> impl Iterator<Item = &AccessRule> {
659 Self::find_rules(
660 &self.av_table,
661 &self.rules.av_rules,
662 RuleKey::new(source, target, class),
663 &self.hasher,
664 )
665 }
666
667 pub fn find_type_rules(
669 &self,
670 source: TypeId,
671 target: TypeId,
672 class: ClassId,
673 ) -> impl Iterator<Item = &TypeRule> {
674 Self::find_rules(
675 &self.type_transition_table,
676 &self.rules.type_rules,
677 RuleKey::new(source, target, class),
678 &self.hasher,
679 )
680 }
681
682 pub fn find_xperm_rules(
684 &self,
685 source: TypeId,
686 target: TypeId,
687 class: ClassId,
688 ) -> impl Iterator<Item = &XpermRule> {
689 Self::find_rules(
690 &self.xperms_table,
691 &self.rules.xperm_rules,
692 RuleKey::new(source, target, class),
693 &self.hasher,
694 )
695 }
696}
697
698impl Parse for IndexedAccessVectorRules {
699 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
700 let rules = AccessVectorRules::parse(cursor)?;
701 Self::new(rules)
702 }
703}
704
705impl Serialize for IndexedAccessVectorRules {
706 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
707 self.rules.serialize(writer)
708 }
709}
710
711impl Validate for IndexedAccessVectorRules {
712 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
713 self.rules.validate(policy)
714 }
715}
716
717fn build_index<R: HasRuleKey>(
725 rules: &[R],
726 hasher: &RapidBuildHasher,
727) -> Result<HashTable<U24Index>, ParseError> {
728 let mut table = HashTable::new();
729 let mut offset = 0;
730
731 for chunk in rules.chunk_by(|a, b| a.key() == b.key()) {
732 let key = chunk[0].key();
733 let u24_idx = offset.try_into()?;
734 let hash = key.hash(hasher);
735
736 let Entry::Vacant(entry) = table.entry(
737 hash,
738 |&i| rules[usize::from(i)].key() == key,
739 |&i| rules[usize::from(i)].key().hash(hasher),
740 ) else {
741 return Err(ParseError::DuplicateAccessVectorRule { key, kind: chunk[0].kind() });
742 };
743 entry.insert(u24_idx);
744 offset += chunk.len();
745 }
746
747 Ok(table)
748}
749
750pub const COND_EXPR_BOOL: u32 = 1;
752pub const COND_EXPR_NOT: u32 = 2;
754pub const COND_EXPR_OR: u32 = 3;
756pub const COND_EXPR_AND: u32 = 4;
758pub const COND_EXPR_EQ: u32 = 5;
760pub const COND_EXPR_NEQ: u32 = 6;
762
763#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
765pub enum ConditionalExpressionElement {
766 Boolean(ConditionalBooleanId),
768 Not,
770 Or,
772 And,
774 Equals,
776 NotEquals,
778}
779
780impl Parse for ConditionalExpressionElement {
781 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
782 let expr_type = u32::parse(cursor)?;
783 let boolean_id = u32::parse(cursor)?;
784 match expr_type {
785 COND_EXPR_BOOL => {
786 let id = ConditionalBooleanId::from_u32(boolean_id)
787 .ok_or(ParseError::InvalidId { value: boolean_id })?;
788 Ok(Self::Boolean(id))
789 }
790 COND_EXPR_NOT => Ok(Self::Not),
791 COND_EXPR_OR => Ok(Self::Or),
792 COND_EXPR_AND => Ok(Self::And),
793 COND_EXPR_EQ => Ok(Self::Equals),
794 COND_EXPR_NEQ => Ok(Self::NotEquals),
795 invalid => Err(ParseError::InvalidEnumValue {
796 enum_name: "ConditionalExpressionElement",
797 value: invalid as u64,
798 }),
799 }
800 }
801}
802
803impl Serialize for ConditionalExpressionElement {
804 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
805 let (expr_type, boolean_id) = match self {
806 Self::Boolean(id) => (COND_EXPR_BOOL, id.as_u32()),
807 Self::Not => (COND_EXPR_NOT, 0),
808 Self::Or => (COND_EXPR_OR, 0),
809 Self::And => (COND_EXPR_AND, 0),
810 Self::Equals => (COND_EXPR_EQ, 0),
811 Self::NotEquals => (COND_EXPR_NEQ, 0),
812 };
813 expr_type.serialize(writer)?;
814 boolean_id.serialize(writer)?;
815 Ok(())
816 }
817}
818
819impl Validate for ConditionalExpressionElement {
820 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
821 if let Self::Boolean(id) = self {
822 id.validate(policy)?;
823 }
824 Ok(())
825 }
826}
827
828#[derive(Clone, Debug, Parse, Serialize, Validate)]
830pub struct ConditionalNode {
831 state: u32,
832 expression_elements: Array<ConditionalExpressionElement>,
833 true_rules: AccessVectorRules,
834 false_rules: AccessVectorRules,
835}
836
837#[derive(Clone, Debug, Eq, PartialEq, Hash, Parse, Serialize)]
839struct BinaryAccessVectorRuleHeader {
840 source_type: u16,
841 target_type: u16,
842 class: u16,
843 rule_flags: u16,
844}
845
846#[cfg(test)]
847mod tests {
848 use super::*;
849 use crate::new_policy::NewPolicy;
850 use crate::new_policy::metadata::PolicyVersion;
851 use crate::new_policy::parser::PolicyWriter;
852 use crate::new_policy::traits::{HasPolicyId, PolicyId};
853
854 #[test]
855 fn test_xperms_bitmap_ops_and_contains() {
856 let mut bitmap1 = XpermsBitmap::NONE;
857 let mut bitmap2 = XpermsBitmap::NONE;
858 assert!(!bitmap1.contains(10));
859 assert!(!bitmap2.contains(10));
860
861 bitmap1.0[0] = 1 << 10;
862 bitmap2.0[0] = 1 << 20;
863 assert!(bitmap1.contains(10));
864 assert!(!bitmap1.contains(20));
865 assert!(bitmap2.contains(20));
866
867 let or_bitmap = bitmap1 | bitmap2;
868 assert!(or_bitmap.contains(10));
869 assert!(or_bitmap.contains(20));
870
871 let and_bitmap = or_bitmap & bitmap1;
872 assert!(and_bitmap.contains(10));
873 assert!(!and_bitmap.contains(20));
874
875 let sub_bitmap = or_bitmap - bitmap1;
876 assert!(!sub_bitmap.contains(10));
877 assert!(sub_bitmap.contains(20));
878
879 let not_bitmap = !XpermsBitmap::NONE;
880 assert_eq!(not_bitmap, XpermsBitmap::ALL);
881 assert!(not_bitmap.contains(0));
882 assert!(not_bitmap.contains(255));
883 }
884
885 #[test]
886 fn test_av_rule_parse_and_serialize() {
887 let data = [
888 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 1, 0, 5, 0, 0, 0, ];
895 let mut cursor = PolicyCursor::new(&data);
896 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
897 assert_eq!(av_rules.av_rules.len(), 1);
898 assert_eq!(av_rules.av_rules[0].key.source_type, TypeId::from_u32(1).unwrap());
899 assert_eq!(av_rules.av_rules[0].key.target_type, TypeId::from_u32(2).unwrap());
900 assert_eq!(av_rules.av_rules[0].key.class, ClassId::from_u32(3).unwrap());
901 assert_eq!(av_rules.av_rules[0].access_vector, AccessVector::from(5));
902
903 let mut writer = Vec::new();
904 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
905 av_rules.serialize(&mut policy_writer).expect("serialize rules table");
906 assert_eq!(writer.as_slice(), &data);
907 }
908
909 #[test]
910 fn test_av_rule_type_transition_parse_and_serialize() {
911 let data = [
912 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 16, 0, 10, 0, 0, 0, ];
919 let mut cursor = PolicyCursor::new(&data);
920 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
921 assert_eq!(av_rules.type_rules.len(), 1);
922 assert_eq!(av_rules.type_rules[0].key.source_type, TypeId::from_u32(1).unwrap());
923 assert_eq!(av_rules.type_rules[0].key.target_type, TypeId::from_u32(2).unwrap());
924 assert_eq!(av_rules.type_rules[0].key.class, ClassId::from_u32(3).unwrap());
925 assert_eq!(av_rules.type_rules[0].new_type, TypeId::from_u32(10).unwrap());
926
927 let mut writer = Vec::new();
928 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
929 av_rules.serialize(&mut policy_writer).expect("serialize rules table");
930 assert_eq!(writer.as_slice(), &data);
931 }
932
933 #[test]
934 fn test_av_rule_xperm_parse_and_serialize() {
935 let mut data = vec![
936 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 0, 1, 1, 0, ];
944 data.extend_from_slice(&[
945 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]);
950 let mut cursor = PolicyCursor::new(&data);
951 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
952 assert_eq!(av_rules.xperm_rules.len(), 1);
953 let xp = &av_rules.xperm_rules[0].extended_permissions;
954 assert_eq!(xp.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
955 assert!(xp.xperms_bitmap.contains(0));
956 assert!(!xp.xperms_bitmap.contains(1));
957
958 let mut writer = Vec::new();
959 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
960 av_rules.serialize(&mut policy_writer).expect("serialize rules table");
961 assert_eq!(writer.as_slice(), &data);
962 }
963
964 #[test]
965 fn test_access_vector_rules_indexing_and_decisions() {
966 let data = [
967 2, 0, 0, 0, 1, 0, 2, 0, 3, 0, 1, 0, 7, 0, 0, 0, 1, 0, 2, 0, 3, 0, 16, 0, 9, 0, 0, 0, ];
981
982 let mut cursor = PolicyCursor::new(&data);
983 let av_rules = IndexedAccessVectorRules::parse(&mut cursor).expect("parse rules table");
984
985 let s1 = TypeId::from_u32(1).unwrap();
986 let t2 = TypeId::from_u32(2).unwrap();
987 let c3 = ClassId::from_u32(3).unwrap();
988
989 let av_rules_list: Vec<_> = av_rules.find_av_rules(s1, t2, c3).collect();
990 assert_eq!(av_rules_list.len(), 1);
991 assert_eq!(av_rules_list[0].kind(), RuleKind::Allow);
992 assert_eq!(av_rules_list[0].access_vector(), AccessVector::from(7));
993
994 let type_rules_list: Vec<_> = av_rules.find_type_rules(s1, t2, c3).collect();
995 assert_eq!(type_rules_list.len(), 1);
996 assert_eq!(type_rules_list[0].kind(), RuleKind::TypeTransition);
997 assert_eq!(type_rules_list[0].new_type(), TypeId::from_u32(9).unwrap());
998 }
999
1000 #[test]
1001 fn test_unindexed_access_vector_rules_allows_duplicate_keys() {
1002 let data = [
1003 3, 0, 0, 0, 1, 0, 2, 0, 3, 0, 1, 0, 7, 0, 0, 0, 4, 0, 5, 0, 6, 0, 1, 0, 8, 0, 0, 0, 1, 0, 2, 0, 3, 0, 1, 0, 9, 0, 0, 0, ];
1011
1012 let mut cursor = PolicyCursor::new(&data);
1013 let av_rules =
1014 AccessVectorRules::parse(&mut cursor).expect("unindexed rules parse duplicate keys");
1015 assert_eq!(av_rules.av_rules.len(), 3);
1016
1017 let mut cursor = PolicyCursor::new(&data);
1018 let err = IndexedAccessVectorRules::parse(&mut cursor)
1019 .expect_err("indexed rules reject duplicate keys");
1020 assert!(matches!(
1021 err,
1022 ParseError::DuplicateAccessVectorRule { key: _, kind: RuleKind::Allow }
1023 ));
1024 }
1025
1026 #[test]
1027 fn test_conditional_nodes() {
1028 let policy_bytes =
1029 include_bytes!("../../testdata/composite_policies/compiled/conditional_policy");
1030 let new_policy = NewPolicy::parse(policy_bytes).expect("parse conditional policy");
1031 new_policy.validate().expect("validate conditional policy");
1032
1033 let nodes = new_policy.conditional_nodes();
1034 assert_eq!(nodes.len(), 4);
1035 assert_eq!(nodes[0].true_rules.av_rules().len(), 1);
1036 assert_eq!(nodes[0].false_rules.av_rules().len(), 0);
1037 assert_eq!(nodes[1].true_rules.av_rules().len(), 1);
1038 assert_eq!(nodes[1].false_rules.av_rules().len(), 1);
1039 assert_eq!(nodes[2].true_rules.av_rules().len(), 2);
1040 assert_eq!(nodes[2].false_rules.av_rules().len(), 0);
1041 assert_eq!(nodes[3].true_rules.av_rules().len(), 1);
1042 assert_eq!(nodes[3].false_rules.av_rules().len(), 0);
1043 }
1044
1045 #[test]
1046 fn parse_allowxperm_one_ioctl() {
1047 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1048 let policy = NewPolicy::parse(policy_bytes).expect("parse policy");
1049 policy.validate().expect("validate policy");
1050
1051 let class_id =
1052 policy.classes().get_by_name(b"class_one_ioctl").expect("look up class_one_ioctl").id();
1053 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1054 let rules: Vec<_> = policy
1055 .access_vector_rules()
1056 .find_xperm_rules(type0, type0, class_id)
1057 .filter(|r| r.kind() == RuleKind::AllowXperm)
1058 .map(|r| r.extended_permissions())
1059 .collect();
1060
1061 assert_eq!(rules.len(), 1);
1062 assert_eq!(rules[0].count(), 1);
1063 assert!(rules[0].contains(0xabcd));
1064 }
1065
1066 #[test]
1069 fn parse_allowxperm_two_ioctls_same_range_coalesced() {
1070 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1071 let policy = NewPolicy::parse(policy_bytes).expect("parse policy");
1072 policy.validate().expect("validate policy");
1073
1074 let class_id = policy
1075 .classes()
1076 .get_by_name(b"class_two_ioctls_same_range")
1077 .expect("look up class_two_ioctls_same_range")
1078 .id();
1079 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1080 let rules: Vec<_> = policy
1081 .access_vector_rules()
1082 .find_xperm_rules(type0, type0, class_id)
1083 .filter(|r| r.kind() == RuleKind::AllowXperm)
1084 .map(|r| r.extended_permissions())
1085 .collect();
1086
1087 assert_eq!(rules.len(), 1);
1088 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1089 assert_eq!(rules[0].xperms_optional_prefix(), 0x12);
1090 assert_eq!(rules[0].count(), 2);
1091 assert!(rules[0].contains(0x1234));
1092 assert!(rules[0].contains(0x1256));
1093 }
1094
1095 #[test]
1096 fn parse_allowxperm_one_driver_range() {
1097 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1098 let policy = NewPolicy::parse(policy_bytes).expect("parse policy");
1099 policy.validate().expect("validate policy");
1100
1101 let class_id = policy
1102 .classes()
1103 .get_by_name(b"class_one_driver_range")
1104 .expect("look up class_one_driver_range")
1105 .id();
1106 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1107 let rules: Vec<_> = policy
1108 .access_vector_rules()
1109 .find_xperm_rules(type0, type0, class_id)
1110 .filter(|r| r.kind() == RuleKind::AllowXperm)
1111 .map(|r| r.extended_permissions())
1112 .collect();
1113
1114 assert_eq!(rules.len(), 1);
1115 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_IOCTL_PREFIXES);
1116 assert_eq!(rules[0].count(), 0x100);
1117 assert!(rules[0].contains(0x1000));
1118 assert!(rules[0].contains(0x10ab));
1119 }
1120
1121 #[test]
1122 fn parse_allowxperm_two_ioctls_different_range() {
1123 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1124 let policy = NewPolicy::parse(policy_bytes).expect("parse policy");
1125 policy.validate().expect("validate policy");
1126
1127 let class_id = policy
1128 .classes()
1129 .get_by_name(b"class_two_ioctls_diff_range")
1130 .expect("look up class_two_ioctls_diff_range")
1131 .id();
1132 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1133 let rules: Vec<_> = policy
1134 .access_vector_rules()
1135 .find_xperm_rules(type0, type0, class_id)
1136 .filter(|r| r.kind() == RuleKind::AllowXperm)
1137 .map(|r| r.extended_permissions())
1138 .collect();
1139
1140 assert_eq!(rules.len(), 2);
1141 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1142 assert_eq!(rules[0].xperms_optional_prefix(), 0x56);
1143 assert_eq!(rules[0].count(), 1);
1144 assert!(rules[0].contains(0x5678));
1145 assert_eq!(rules[1].xperms_type(), XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1146 assert_eq!(rules[1].xperms_optional_prefix(), 0x12);
1147 assert_eq!(rules[1].count(), 1);
1148 assert!(rules[1].contains(0x1234));
1149 }
1150
1151 #[test]
1152 fn parse_allowxperm_one_nlmsg() {
1153 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1154 let policy = NewPolicy::parse(policy_bytes).expect("parse policy");
1155 policy.validate().expect("validate policy");
1156
1157 let class_id =
1158 policy.classes().get_by_name(b"class_one_nlmsg").expect("look up class_one_nlmsg").id();
1159 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1160 let rules: Vec<_> = policy
1161 .access_vector_rules()
1162 .find_xperm_rules(type0, type0, class_id)
1163 .filter(|r| r.kind() == RuleKind::AllowXperm)
1164 .map(|r| r.extended_permissions())
1165 .collect();
1166
1167 assert_eq!(rules.len(), 1);
1168 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_NLMSG);
1169 assert_eq!(rules[0].count(), 1);
1170 assert!(rules[0].contains(0x12));
1171 }
1172
1173 #[test]
1177 fn parse_auditallowxperm_not_coalesced() {
1178 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1179 let policy = NewPolicy::parse(policy_bytes).expect("parse policy");
1180 policy.validate().expect("validate policy");
1181
1182 let class_id = policy
1183 .classes()
1184 .get_by_name(b"class_auditallowxperm_not_coalesced")
1185 .expect("look up class_auditallowxperm_not_coalesced")
1186 .id();
1187 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1188 let allow_rules: Vec<_> = policy
1189 .access_vector_rules()
1190 .find_xperm_rules(type0, type0, class_id)
1191 .filter(|r| r.kind() == RuleKind::AllowXperm)
1192 .map(|r| r.extended_permissions())
1193 .collect();
1194 let auditallow_rules: Vec<_> = policy
1195 .access_vector_rules()
1196 .find_xperm_rules(type0, type0, class_id)
1197 .filter(|r| r.kind() == RuleKind::AuditAllowXperm)
1198 .map(|r| r.extended_permissions())
1199 .collect();
1200
1201 assert_eq!(allow_rules.len(), 1);
1202 assert_eq!(allow_rules[0].count(), 1);
1203 assert!(allow_rules[0].contains(0xabcd));
1204 assert_eq!(auditallow_rules.len(), 1);
1205 assert_eq!(auditallow_rules[0].count(), 1);
1206 assert!(auditallow_rules[0].contains(0xabcd));
1207 }
1208
1209 #[test]
1210 fn parse_dontauditxperm() {
1211 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1212 let policy = NewPolicy::parse(policy_bytes).expect("parse policy");
1213 policy.validate().expect("validate policy");
1214
1215 let class_id = policy
1216 .classes()
1217 .get_by_name(b"class_dontauditxperm")
1218 .expect("look up class_dontauditxperm")
1219 .id();
1220 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1221 let rules: Vec<_> = policy
1222 .access_vector_rules()
1223 .find_xperm_rules(type0, type0, class_id)
1224 .filter(|r| r.kind() == RuleKind::DontAuditXperm)
1225 .map(|r| r.extended_permissions())
1226 .collect();
1227
1228 assert_eq!(rules.len(), 2);
1229 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_NLMSG);
1230 assert_eq!(rules[0].xperms_optional_prefix(), 0x00);
1231 assert_eq!(rules[0].count(), 1);
1232 assert!(rules[0].contains(0x11));
1233 assert_eq!(rules[1].xperms_type(), XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1234 assert_eq!(rules[1].xperms_optional_prefix(), 0x10);
1235 assert_eq!(rules[1].count(), 1);
1236 assert!(rules[1].contains(0x1000));
1237 }
1238}