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