1use std::hash::Hash;
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 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, Policy, TypeId, U24Index};
18
19const AV_ALLOW_RULE_FLAG: u16 = 0x1;
21const AV_AUDITALLOW_RULE_FLAG: u16 = 0x2;
23const AV_DONTAUDIT_RULE_FLAG: u16 = 0x4;
25
26const AV_TYPE_TRANSITION_RULE_FLAG: u16 = 0x10;
28const AV_TYPE_MEMBER_RULE_FLAG: u16 = 0x20;
30const AV_TYPE_CHANGE_RULE_FLAG: u16 = 0x40;
32
33const AV_ALLOWXPERM_RULE_FLAG: u16 = 0x100;
35const AV_AUDITALLOWXPERM_RULE_FLAG: u16 = 0x200;
37const AV_DONTAUDITXPERM_RULE_FLAG: u16 = 0x400;
39
40const 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
53const 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 #[cfg(test)]
91 pub fn new(elements: [u64; Self::BITMAP_BLOCKS]) -> Self {
92 Self(elements)
93 }
94
95 pub fn contains(&self, value: u8) -> bool {
97 let block_index = (value as usize) / (u64::BITS as usize);
98 let bit_index = (value as usize) % (u64::BITS as usize);
99 self.0[block_index] & (1u64 << bit_index) != 0
100 }
101
102 pub fn from_atomics(atomics: &[AtomicU64; Self::BITMAP_BLOCKS]) -> Self {
104 let mut words = [0u64; Self::BITMAP_BLOCKS];
105 for (i, word) in words.iter_mut().enumerate() {
106 *word = atomics[i].load(Ordering::Relaxed);
107 }
108 Self(words)
109 }
110
111 pub fn to_atomics(&self, atomics: &[AtomicU64; Self::BITMAP_BLOCKS]) {
113 for (i, word) in self.0.iter().enumerate() {
114 atomics[i].store(*word, Ordering::Relaxed);
115 }
116 }
117}
118
119impl BitAnd for XpermsBitmap {
120 type Output = Self;
121 fn bitand(self, rhs: Self) -> Self::Output {
122 Self(std::array::from_fn(|i| self.0[i] & rhs.0[i]))
123 }
124}
125
126impl BitAndAssign for XpermsBitmap {
127 fn bitand_assign(&mut self, rhs: Self) {
128 for i in 0..4 {
129 self.0[i] &= rhs.0[i];
130 }
131 }
132}
133
134impl BitOr for XpermsBitmap {
135 type Output = Self;
136 fn bitor(self, rhs: Self) -> Self::Output {
137 Self(std::array::from_fn(|i| self.0[i] | rhs.0[i]))
138 }
139}
140
141impl BitOrAssign for XpermsBitmap {
142 fn bitor_assign(&mut self, rhs: Self) {
143 for i in 0..4 {
144 self.0[i] |= rhs.0[i];
145 }
146 }
147}
148
149impl Sub for XpermsBitmap {
150 type Output = Self;
151 fn sub(self, rhs: Self) -> Self {
152 Self(std::array::from_fn(|i| self.0[i] & !rhs.0[i]))
153 }
154}
155
156impl SubAssign for XpermsBitmap {
157 fn sub_assign(&mut self, rhs: Self) {
158 for i in 0..4 {
159 self.0[i] &= !rhs.0[i];
160 }
161 }
162}
163
164impl Not for XpermsBitmap {
165 type Output = Self;
166 fn not(self) -> Self::Output {
167 Self(self.0.map(|word| !word))
168 }
169}
170
171impl Validate for XpermsBitmap {
172 fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
173 Ok(())
174 }
175}
176
177#[derive(Clone, Debug, PartialEq, Eq, Parse, Serialize)]
179pub struct ExtendedPermissions {
180 xperms_type: u8,
181 xperms_optional_prefix: u8,
182 xperms_bitmap: XpermsBitmap,
183}
184
185impl Validate for ExtendedPermissions {
186 fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
187 match self.xperms_type {
188 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES
189 | XPERMS_TYPE_IOCTL_PREFIXES
190 | XPERMS_TYPE_NLMSG => Ok(()),
191 v => Err(ValidateError::InvalidExtendedPermissionsType { value: v }),
192 }
193 }
194}
195
196impl ExtendedPermissions {
197 pub fn xperms_type(&self) -> u8 {
199 self.xperms_type
200 }
201
202 pub fn xperms_optional_prefix(&self) -> u8 {
204 self.xperms_optional_prefix
205 }
206
207 pub fn xperms_bitmap(&self) -> &XpermsBitmap {
209 &self.xperms_bitmap
210 }
211
212 #[cfg(test)]
214 pub fn count(&self) -> u64 {
215 let count = self
216 .xperms_bitmap
217 .0
218 .iter()
219 .fold(0, |count, block| count as u64 + block.count_ones() as u64);
220 match self.xperms_type {
221 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES | XPERMS_TYPE_NLMSG => count,
222 XPERMS_TYPE_IOCTL_PREFIXES => count * 0x100,
223 _ => unreachable!("invalid xperms_type in validated ExtendedPermissions"),
224 }
225 }
226
227 #[cfg(test)]
229 pub fn contains(&self, xperm: u16) -> bool {
230 let [postfix, prefix] = xperm.to_le_bytes();
231 if (self.xperms_type == XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES
232 || self.xperms_type == XPERMS_TYPE_NLMSG)
233 && self.xperms_optional_prefix != prefix
234 {
235 return false;
236 }
237 let value = match self.xperms_type {
238 XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES | XPERMS_TYPE_NLMSG => postfix,
239 XPERMS_TYPE_IOCTL_PREFIXES => prefix,
240 _ => unreachable!("invalid xperms_type in validated ExtendedPermissions"),
241 };
242 self.xperms_bitmap.contains(value)
243 }
244}
245
246#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
248pub enum RuleKind {
249 Allow,
250 AuditAllow,
251 DontAudit,
252 TypeTransition,
253 TypeMember,
254 TypeChange,
255 AllowXperm,
256 AuditAllowXperm,
257 DontAuditXperm,
258}
259
260impl TryFrom<u16> for RuleKind {
261 type Error = ParseError;
262
263 fn try_from(rule_type: u16) -> Result<Self, Self::Error> {
264 let base_kind = rule_type & !AV_ENABLED_RULE_FLAG;
265 match base_kind {
266 AV_ALLOW_RULE_FLAG => Ok(Self::Allow),
267 AV_AUDITALLOW_RULE_FLAG => Ok(Self::AuditAllow),
268 AV_DONTAUDIT_RULE_FLAG => Ok(Self::DontAudit),
269 AV_TYPE_TRANSITION_RULE_FLAG => Ok(Self::TypeTransition),
270 AV_TYPE_MEMBER_RULE_FLAG => Ok(Self::TypeMember),
271 AV_TYPE_CHANGE_RULE_FLAG => Ok(Self::TypeChange),
272 AV_ALLOWXPERM_RULE_FLAG => Ok(Self::AllowXperm),
273 AV_AUDITALLOWXPERM_RULE_FLAG => Ok(Self::AuditAllowXperm),
274 AV_DONTAUDITXPERM_RULE_FLAG => Ok(Self::DontAuditXperm),
275 _ => {
276 Err(ParseError::InvalidEnumValue { enum_name: "RuleKind", value: rule_type as u64 })
277 }
278 }
279 }
280}
281
282impl From<RuleKind> for u16 {
283 fn from(kind: RuleKind) -> Self {
284 match kind {
285 RuleKind::Allow => AV_ALLOW_RULE_FLAG,
286 RuleKind::AuditAllow => AV_AUDITALLOW_RULE_FLAG,
287 RuleKind::DontAudit => AV_DONTAUDIT_RULE_FLAG,
288 RuleKind::TypeTransition => AV_TYPE_TRANSITION_RULE_FLAG,
289 RuleKind::TypeMember => AV_TYPE_MEMBER_RULE_FLAG,
290 RuleKind::TypeChange => AV_TYPE_CHANGE_RULE_FLAG,
291 RuleKind::AllowXperm => AV_ALLOWXPERM_RULE_FLAG,
292 RuleKind::AuditAllowXperm => AV_AUDITALLOWXPERM_RULE_FLAG,
293 RuleKind::DontAuditXperm => AV_DONTAUDITXPERM_RULE_FLAG,
294 }
295 }
296}
297
298impl Validate for RuleKind {
299 fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
300 Ok(())
301 }
302}
303
304#[derive(Clone, Debug, Validate)]
306pub struct AccessRule {
307 key: RuleKey,
308 kind: RuleKind,
309 access_vector: AccessVector,
310 enabled: bool,
311}
312
313impl AccessRule {
314 pub fn access_vector(&self) -> AccessVector {
316 self.access_vector
317 }
318}
319
320#[derive(Clone, Debug, Validate)]
322pub struct TypeRule {
323 key: RuleKey,
324 kind: RuleKind,
325 new_type: TypeId,
326 enabled: bool,
327}
328
329impl TypeRule {
330 pub fn new_type(&self) -> TypeId {
332 self.new_type
333 }
334}
335
336#[derive(Clone, Debug, Validate)]
338pub struct XpermRule {
339 key: RuleKey,
340 kind: RuleKind,
341 extended_permissions: ExtendedPermissions,
342 enabled: bool,
343}
344
345impl XpermRule {
346 pub fn extended_permissions(&self) -> &ExtendedPermissions {
348 &self.extended_permissions
349 }
350}
351
352#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Validate)]
354pub struct RuleKey {
355 source_type: TypeId,
356 target_type: TypeId,
357 class: ClassId,
358}
359
360impl RuleKey {
361 fn new(source_type: TypeId, target_type: TypeId, class: ClassId) -> Self {
363 Self { source_type, target_type, class }
364 }
365
366 fn hash(&self) -> u64 {
368 let packed = (self.source_type.as_u16() as u64)
369 | ((self.target_type.as_u16() as u64) << 16)
370 | ((self.class.as_u16() as u64) << 32);
371 rapidhash::rapidhash(&packed.to_ne_bytes())
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, Eq)]
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 let min_bytes = count.saturating_mul(std::mem::size_of::<BinaryAccessVectorRuleHeader>());
493 if min_bytes > cursor.remaining() {
494 return Err(ParseError::MissingData {
495 type_name: std::any::type_name::<BinaryAccessVectorRuleHeader>(),
496 type_size: min_bytes,
497 num_bytes: cursor.remaining(),
498 });
499 }
500
501 let mut av_rules = Vec::new();
502 let mut type_rules = Vec::new();
503 let mut xperm_rules = Vec::new();
504 let mut rule_order = Vec::with_capacity(count);
505
506 for _ in 0..count {
509 let header = BinaryAccessVectorRuleHeader::parse(cursor)?;
510 let kind = RuleKind::try_from(header.rule_flags)?;
511 let enabled = (header.rule_flags & AV_ENABLED_RULE_FLAG) != 0;
512
513 let source_val = header.source_type;
514 let source_type = TypeId::from_u16(source_val)
515 .ok_or(ParseError::InvalidId { value: source_val as u32 })?;
516
517 let target_val = header.target_type;
518 let target_type = TypeId::from_u16(target_val)
519 .ok_or(ParseError::InvalidId { value: target_val as u32 })?;
520
521 let class_val = header.class;
522 let class = ClassId::from_u16(class_val)
523 .ok_or(ParseError::InvalidId { value: class_val as u32 })?;
524
525 let key = RuleKey::new(source_type, target_type, class);
526
527 match kind {
528 RuleKind::AllowXperm | RuleKind::AuditAllowXperm | RuleKind::DontAuditXperm => {
529 let extended_permissions = ExtendedPermissions::parse(cursor)?;
530 xperm_rules.push(XpermRule { key, kind, extended_permissions, enabled });
531 rule_order.push(kind);
532 }
533 RuleKind::TypeTransition | RuleKind::TypeChange | RuleKind::TypeMember => {
534 let new_type = TypeId::parse(cursor)?;
535 type_rules.push(TypeRule { key, kind, new_type, enabled });
536 rule_order.push(kind);
537 }
538 RuleKind::Allow | RuleKind::AuditAllow | RuleKind::DontAudit => {
539 let access_vector = AccessVector::parse(cursor)?;
540 av_rules.push(AccessRule { key, kind, access_vector, enabled });
541 rule_order.push(kind);
542 }
543 }
544 }
545
546 let av_rules = av_rules.into_boxed_slice();
547 let type_rules = type_rules.into_boxed_slice();
548 let xperm_rules = xperm_rules.into_boxed_slice();
549 let rule_order = rule_order.into_boxed_slice();
550
551 Ok(Self { av_rules, type_rules, xperm_rules, rule_order })
552 }
553}
554
555impl Serialize for AccessVectorRules {
556 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
557 let count = self.rule_order.len() as u32;
558 count.serialize(writer)?;
559
560 let mut av_rules = self.av_rules.iter();
561 let mut type_rules = self.type_rules.iter();
562 let mut xperm_rules = self.xperm_rules.iter();
563
564 for &kind in self.rule_order.iter() {
565 match kind {
566 RuleKind::Allow | RuleKind::AuditAllow | RuleKind::DontAudit => {
567 let rule = av_rules.next().unwrap();
568 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
569 let val: u32 = rule.access_vector.into();
570 val.serialize(writer)?;
571 }
572 RuleKind::TypeTransition | RuleKind::TypeChange | RuleKind::TypeMember => {
573 let rule = type_rules.next().unwrap();
574 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
575 rule.new_type.serialize(writer)?;
576 }
577 RuleKind::AllowXperm | RuleKind::AuditAllowXperm | RuleKind::DontAuditXperm => {
578 let rule = xperm_rules.next().unwrap();
579 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
580 rule.extended_permissions.serialize(writer)?;
581 }
582 }
583 }
584 Ok(())
585 }
586}
587
588impl Validate for AccessVectorRules {
589 fn validate(&self, policy: &Policy) -> Result<(), ValidateError> {
590 self.av_rules.validate(policy)?;
591 self.type_rules.validate(policy)?;
592 self.xperm_rules.validate(policy)?;
593 Ok(())
594 }
595}
596
597#[derive(Debug)]
603pub struct IndexedAccessVectorRules {
604 rules: AccessVectorRules,
605 av_table: HashTable<U24Index>,
606 type_transition_table: HashTable<U24Index>,
607 xperms_table: HashTable<U24Index>,
608}
609
610impl IndexedAccessVectorRules {
611 fn new(rules: AccessVectorRules) -> Result<Self, ParseError> {
615 let av_table = build_index(&rules.av_rules)?;
616 let type_transition_table = build_index(&rules.type_rules)?;
617 let xperms_table = build_index(&rules.xperm_rules)?;
618
619 Ok(Self { rules, av_table, type_transition_table, xperms_table })
620 }
621
622 fn find_rules<'a, R: HasRuleKey>(
623 table: &HashTable<U24Index>,
624 rules: &'a [R],
625 key: RuleKey,
626 ) -> impl Iterator<Item = &'a R> {
627 let hash = key.hash();
628 let slice = match table.find(hash, |&i| rules[usize::from(i)].key() == key) {
629 Some(&i) => &rules[usize::from(i)..],
630 None => &[],
631 };
632 slice.iter().take_while(move |rule| rule.key() == key)
633 }
634
635 pub fn find_av_rules(
637 &self,
638 source: TypeId,
639 target: TypeId,
640 class: ClassId,
641 ) -> impl Iterator<Item = &AccessRule> {
642 Self::find_rules(&self.av_table, &self.rules.av_rules, RuleKey::new(source, target, class))
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 )
657 }
658
659 pub fn find_xperm_rules(
661 &self,
662 source: TypeId,
663 target: TypeId,
664 class: ClassId,
665 ) -> impl Iterator<Item = &XpermRule> {
666 Self::find_rules(
667 &self.xperms_table,
668 &self.rules.xperm_rules,
669 RuleKey::new(source, target, class),
670 )
671 }
672}
673
674impl Parse for IndexedAccessVectorRules {
675 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
676 let rules = AccessVectorRules::parse(cursor)?;
677 Self::new(rules)
678 }
679}
680
681impl Serialize for IndexedAccessVectorRules {
682 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
683 self.rules.serialize(writer)
684 }
685}
686
687impl Validate for IndexedAccessVectorRules {
688 fn validate(&self, policy: &Policy) -> Result<(), ValidateError> {
689 self.rules.validate(policy)
690 }
691}
692
693fn build_index<R: HasRuleKey>(rules: &[R]) -> Result<HashTable<U24Index>, ParseError> {
701 let mut table = HashTable::new();
702 let mut offset = 0;
703
704 for chunk in rules.chunk_by(|a, b| a.key() == b.key()) {
705 let key = chunk[0].key();
706 let u24_idx = offset.try_into()?;
707 let hash = key.hash();
708
709 let Entry::Vacant(entry) = table.entry(
710 hash,
711 |&i| rules[usize::from(i)].key() == key,
712 |&i| rules[usize::from(i)].key().hash(),
713 ) else {
714 return Err(ParseError::DuplicateAccessVectorRule { key, kind: chunk[0].kind() });
715 };
716 entry.insert(u24_idx);
717 offset += chunk.len();
718 }
719
720 Ok(table)
721}
722
723const COND_EXPR_BOOL: u32 = 1;
725const COND_EXPR_NOT: u32 = 2;
727const COND_EXPR_OR: u32 = 3;
729const COND_EXPR_AND: u32 = 4;
731const COND_EXPR_EQ: u32 = 5;
733const COND_EXPR_NEQ: u32 = 6;
735
736#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
738enum ConditionalExpressionElement {
739 Boolean(ConditionalBooleanId),
741 Not,
743 Or,
745 And,
747 Equals,
749 NotEquals,
751}
752
753impl Parse for ConditionalExpressionElement {
754 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
755 let expr_type = u32::parse(cursor)?;
756 let boolean_id = u32::parse(cursor)?;
757 match expr_type {
758 COND_EXPR_BOOL => {
759 let id = ConditionalBooleanId::from_u32(boolean_id)
760 .ok_or(ParseError::InvalidId { value: boolean_id })?;
761 Ok(Self::Boolean(id))
762 }
763 COND_EXPR_NOT => Ok(Self::Not),
764 COND_EXPR_OR => Ok(Self::Or),
765 COND_EXPR_AND => Ok(Self::And),
766 COND_EXPR_EQ => Ok(Self::Equals),
767 COND_EXPR_NEQ => Ok(Self::NotEquals),
768 invalid => Err(ParseError::InvalidEnumValue {
769 enum_name: "ConditionalExpressionElement",
770 value: invalid as u64,
771 }),
772 }
773 }
774}
775
776impl Serialize for ConditionalExpressionElement {
777 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
778 let (expr_type, boolean_id) = match self {
779 Self::Boolean(id) => (COND_EXPR_BOOL, id.as_u32()),
780 Self::Not => (COND_EXPR_NOT, 0),
781 Self::Or => (COND_EXPR_OR, 0),
782 Self::And => (COND_EXPR_AND, 0),
783 Self::Equals => (COND_EXPR_EQ, 0),
784 Self::NotEquals => (COND_EXPR_NEQ, 0),
785 };
786 expr_type.serialize(writer)?;
787 boolean_id.serialize(writer)?;
788 Ok(())
789 }
790}
791
792impl Validate for ConditionalExpressionElement {
793 fn validate(&self, policy: &Policy) -> Result<(), ValidateError> {
794 if let Self::Boolean(id) = self {
795 id.validate(policy)?;
796 }
797 Ok(())
798 }
799}
800
801#[derive(Clone, Debug, Parse, Serialize, Validate)]
803pub struct ConditionalNode {
804 state: u32,
805 expression_elements: Array<ConditionalExpressionElement>,
806 true_rules: AccessVectorRules,
807 false_rules: AccessVectorRules,
808}
809
810#[derive(Clone, Debug, Eq, PartialEq, Hash, Parse, Serialize)]
812struct BinaryAccessVectorRuleHeader {
813 source_type: u16,
814 target_type: u16,
815 class: u16,
816 rule_flags: u16,
817}
818
819#[cfg(test)]
820mod tests {
821 use super::*;
822 use crate::policy::metadata::PolicyVersion;
823 use crate::policy::parser::PolicyWriter;
824 use crate::policy::traits::{HasPolicyId, PolicyId};
825
826 #[test]
827 fn test_xperms_bitmap_ops_and_contains() {
828 let mut bitmap1 = XpermsBitmap::NONE;
829 let mut bitmap2 = XpermsBitmap::NONE;
830 assert!(!bitmap1.contains(10));
831 assert!(!bitmap2.contains(10));
832
833 bitmap1.0[0] = 1 << 10;
834 bitmap2.0[0] = 1 << 20;
835 assert!(bitmap1.contains(10));
836 assert!(!bitmap1.contains(20));
837 assert!(bitmap2.contains(20));
838
839 let or_bitmap = bitmap1 | bitmap2;
840 assert!(or_bitmap.contains(10));
841 assert!(or_bitmap.contains(20));
842
843 let and_bitmap = or_bitmap & bitmap1;
844 assert!(and_bitmap.contains(10));
845 assert!(!and_bitmap.contains(20));
846
847 let sub_bitmap = or_bitmap - bitmap1;
848 assert!(!sub_bitmap.contains(10));
849 assert!(sub_bitmap.contains(20));
850
851 let not_bitmap = !XpermsBitmap::NONE;
852 assert_eq!(not_bitmap, XpermsBitmap::ALL);
853 assert!(not_bitmap.contains(0));
854 assert!(not_bitmap.contains(255));
855 }
856
857 #[test]
858 fn test_av_rule_parse_and_serialize() {
859 let data = [
860 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 1, 0, 5, 0, 0, 0, ];
867 let mut cursor = PolicyCursor::new(&data);
868 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
869 assert_eq!(av_rules.av_rules.len(), 1);
870 assert_eq!(av_rules.av_rules[0].key.source_type, TypeId::from_u32(1).unwrap());
871 assert_eq!(av_rules.av_rules[0].key.target_type, TypeId::from_u32(2).unwrap());
872 assert_eq!(av_rules.av_rules[0].key.class, ClassId::from_u32(3).unwrap());
873 assert_eq!(av_rules.av_rules[0].access_vector, AccessVector::from(5));
874
875 let mut writer = Vec::new();
876 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
877 av_rules.serialize(&mut policy_writer).expect("serialize rules table");
878 assert_eq!(writer.as_slice(), &data);
879 }
880
881 #[test]
882 fn test_av_rule_type_transition_parse_and_serialize() {
883 let data = [
884 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 16, 0, 10, 0, 0, 0, ];
891 let mut cursor = PolicyCursor::new(&data);
892 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
893 assert_eq!(av_rules.type_rules.len(), 1);
894 assert_eq!(av_rules.type_rules[0].key.source_type, TypeId::from_u32(1).unwrap());
895 assert_eq!(av_rules.type_rules[0].key.target_type, TypeId::from_u32(2).unwrap());
896 assert_eq!(av_rules.type_rules[0].key.class, ClassId::from_u32(3).unwrap());
897 assert_eq!(av_rules.type_rules[0].new_type, TypeId::from_u32(10).unwrap());
898
899 let mut writer = Vec::new();
900 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
901 av_rules.serialize(&mut policy_writer).expect("serialize rules table");
902 assert_eq!(writer.as_slice(), &data);
903 }
904
905 #[test]
906 fn test_av_rule_xperm_parse_and_serialize() {
907 let mut data = vec![
908 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 0, 1, 1, 0, ];
916 data.extend_from_slice(&[
917 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, ]);
922 let mut cursor = PolicyCursor::new(&data);
923 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
924 assert_eq!(av_rules.xperm_rules.len(), 1);
925 let xp = &av_rules.xperm_rules[0].extended_permissions;
926 assert_eq!(xp.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
927 assert!(xp.xperms_bitmap.contains(0));
928 assert!(!xp.xperms_bitmap.contains(1));
929
930 let mut writer = Vec::new();
931 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
932 av_rules.serialize(&mut policy_writer).expect("serialize rules table");
933 assert_eq!(writer.as_slice(), &data);
934 }
935
936 #[test]
937 fn test_access_vector_rules_indexing_and_decisions() {
938 let data = [
939 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, ];
953
954 let mut cursor = PolicyCursor::new(&data);
955 let av_rules = IndexedAccessVectorRules::parse(&mut cursor).expect("parse rules table");
956
957 let s1 = TypeId::from_u32(1).unwrap();
958 let t2 = TypeId::from_u32(2).unwrap();
959 let c3 = ClassId::from_u32(3).unwrap();
960
961 let av_rules_list: Vec<_> = av_rules.find_av_rules(s1, t2, c3).collect();
962 assert_eq!(av_rules_list.len(), 1);
963 assert_eq!(av_rules_list[0].kind(), RuleKind::Allow);
964 assert_eq!(av_rules_list[0].access_vector(), AccessVector::from(7));
965
966 let type_rules_list: Vec<_> = av_rules.find_type_rules(s1, t2, c3).collect();
967 assert_eq!(type_rules_list.len(), 1);
968 assert_eq!(type_rules_list[0].kind(), RuleKind::TypeTransition);
969 assert_eq!(type_rules_list[0].new_type(), TypeId::from_u32(9).unwrap());
970 }
971
972 #[test]
973 fn test_unindexed_access_vector_rules_allows_duplicate_keys() {
974 let data = [
975 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, ];
983
984 let mut cursor = PolicyCursor::new(&data);
985 let av_rules =
986 AccessVectorRules::parse(&mut cursor).expect("unindexed rules parse duplicate keys");
987 assert_eq!(av_rules.av_rules.len(), 3);
988
989 let mut cursor = PolicyCursor::new(&data);
990 let err = IndexedAccessVectorRules::parse(&mut cursor)
991 .expect_err("indexed rules reject duplicate keys");
992 assert!(matches!(
993 err,
994 ParseError::DuplicateAccessVectorRule { key: _, kind: RuleKind::Allow }
995 ));
996 }
997
998 #[test]
999 fn test_conditional_nodes() {
1000 let policy_bytes =
1001 include_bytes!("../../testdata/composite_policies/compiled/conditional_policy");
1002 let policy = Policy::parse_and_validate(policy_bytes);
1003
1004 let nodes = &policy.conditional_nodes;
1005 assert_eq!(nodes.len(), 4);
1006 assert_eq!(nodes[0].true_rules.av_rules().len(), 1);
1007 assert_eq!(nodes[0].false_rules.av_rules().len(), 0);
1008 assert_eq!(nodes[1].true_rules.av_rules().len(), 1);
1009 assert_eq!(nodes[1].false_rules.av_rules().len(), 1);
1010 assert_eq!(nodes[2].true_rules.av_rules().len(), 2);
1011 assert_eq!(nodes[2].false_rules.av_rules().len(), 0);
1012 assert_eq!(nodes[3].true_rules.av_rules().len(), 1);
1013 assert_eq!(nodes[3].false_rules.av_rules().len(), 0);
1014 }
1015
1016 #[test]
1017 fn parse_allowxperm_one_ioctl() {
1018 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1019 let policy = Policy::parse_and_validate(policy_bytes);
1020
1021 let class_id =
1022 policy.classes().get_by_name(b"class_one_ioctl").expect("look up class_one_ioctl").id();
1023 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1024 let rules: Vec<_> = policy
1025 .access_vector_rules
1026 .find_xperm_rules(type0, type0, class_id)
1027 .filter(|r| r.kind() == RuleKind::AllowXperm)
1028 .map(|r| r.extended_permissions())
1029 .collect();
1030
1031 assert_eq!(rules.len(), 1);
1032 assert_eq!(rules[0].count(), 1);
1033 assert!(rules[0].contains(0xabcd));
1034 }
1035
1036 #[test]
1039 fn parse_allowxperm_two_ioctls_same_range_coalesced() {
1040 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1041 let policy = Policy::parse_and_validate(policy_bytes);
1042
1043 let class_id = policy
1044 .classes()
1045 .get_by_name(b"class_two_ioctls_same_range")
1046 .expect("look up class_two_ioctls_same_range")
1047 .id();
1048 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1049 let rules: Vec<_> = policy
1050 .access_vector_rules
1051 .find_xperm_rules(type0, type0, class_id)
1052 .filter(|r| r.kind() == RuleKind::AllowXperm)
1053 .map(|r| r.extended_permissions())
1054 .collect();
1055
1056 assert_eq!(rules.len(), 1);
1057 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1058 assert_eq!(rules[0].xperms_optional_prefix(), 0x12);
1059 assert_eq!(rules[0].count(), 2);
1060 assert!(rules[0].contains(0x1234));
1061 assert!(rules[0].contains(0x1256));
1062 }
1063
1064 #[test]
1065 fn parse_allowxperm_one_driver_range() {
1066 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1067 let policy = Policy::parse_and_validate(policy_bytes);
1068
1069 let class_id = policy
1070 .classes()
1071 .get_by_name(b"class_one_driver_range")
1072 .expect("look up class_one_driver_range")
1073 .id();
1074 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1075 let rules: Vec<_> = policy
1076 .access_vector_rules
1077 .find_xperm_rules(type0, type0, class_id)
1078 .filter(|r| r.kind() == RuleKind::AllowXperm)
1079 .map(|r| r.extended_permissions())
1080 .collect();
1081
1082 assert_eq!(rules.len(), 1);
1083 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_IOCTL_PREFIXES);
1084 assert_eq!(rules[0].count(), 0x100);
1085 assert!(rules[0].contains(0x1000));
1086 assert!(rules[0].contains(0x10ab));
1087 }
1088
1089 #[test]
1090 fn parse_allowxperm_two_ioctls_different_range() {
1091 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1092 let policy = Policy::parse_and_validate(policy_bytes);
1093
1094 let class_id = policy
1095 .classes()
1096 .get_by_name(b"class_two_ioctls_diff_range")
1097 .expect("look up class_two_ioctls_diff_range")
1098 .id();
1099 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1100 let rules: Vec<_> = policy
1101 .access_vector_rules
1102 .find_xperm_rules(type0, type0, class_id)
1103 .filter(|r| r.kind() == RuleKind::AllowXperm)
1104 .map(|r| r.extended_permissions())
1105 .collect();
1106
1107 assert_eq!(rules.len(), 2);
1108 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1109 assert_eq!(rules[0].xperms_optional_prefix(), 0x56);
1110 assert_eq!(rules[0].count(), 1);
1111 assert!(rules[0].contains(0x5678));
1112 assert_eq!(rules[1].xperms_type(), XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1113 assert_eq!(rules[1].xperms_optional_prefix(), 0x12);
1114 assert_eq!(rules[1].count(), 1);
1115 assert!(rules[1].contains(0x1234));
1116 }
1117
1118 #[test]
1119 fn parse_allowxperm_one_nlmsg() {
1120 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1121 let policy = Policy::parse_and_validate(policy_bytes);
1122
1123 let class_id =
1124 policy.classes().get_by_name(b"class_one_nlmsg").expect("look up class_one_nlmsg").id();
1125 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1126 let rules: Vec<_> = policy
1127 .access_vector_rules
1128 .find_xperm_rules(type0, type0, class_id)
1129 .filter(|r| r.kind() == RuleKind::AllowXperm)
1130 .map(|r| r.extended_permissions())
1131 .collect();
1132
1133 assert_eq!(rules.len(), 1);
1134 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_NLMSG);
1135 assert_eq!(rules[0].count(), 1);
1136 assert!(rules[0].contains(0x12));
1137 }
1138
1139 #[test]
1143 fn parse_auditallowxperm_not_coalesced() {
1144 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1145 let policy = Policy::parse_and_validate(policy_bytes);
1146
1147 let class_id = policy
1148 .classes()
1149 .get_by_name(b"class_auditallowxperm_not_coalesced")
1150 .expect("look up class_auditallowxperm_not_coalesced")
1151 .id();
1152 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1153 let allow_rules: Vec<_> = policy
1154 .access_vector_rules
1155 .find_xperm_rules(type0, type0, class_id)
1156 .filter(|r| r.kind() == RuleKind::AllowXperm)
1157 .map(|r| r.extended_permissions())
1158 .collect();
1159 let auditallow_rules: Vec<_> = policy
1160 .access_vector_rules
1161 .find_xperm_rules(type0, type0, class_id)
1162 .filter(|r| r.kind() == RuleKind::AuditAllowXperm)
1163 .map(|r| r.extended_permissions())
1164 .collect();
1165
1166 assert_eq!(allow_rules.len(), 1);
1167 assert_eq!(allow_rules[0].count(), 1);
1168 assert!(allow_rules[0].contains(0xabcd));
1169 assert_eq!(auditallow_rules.len(), 1);
1170 assert_eq!(auditallow_rules[0].count(), 1);
1171 assert!(auditallow_rules[0].contains(0xabcd));
1172 }
1173
1174 #[test]
1175 fn parse_dontauditxperm() {
1176 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1177 let policy = Policy::parse_and_validate(policy_bytes);
1178
1179 let class_id = policy
1180 .classes()
1181 .get_by_name(b"class_dontauditxperm")
1182 .expect("look up class_dontauditxperm")
1183 .id();
1184 let type0 = policy.types().get_by_name(b"type0").expect("look up type0").id();
1185 let rules: Vec<_> = policy
1186 .access_vector_rules
1187 .find_xperm_rules(type0, type0, class_id)
1188 .filter(|r| r.kind() == RuleKind::DontAuditXperm)
1189 .map(|r| r.extended_permissions())
1190 .collect();
1191
1192 assert_eq!(rules.len(), 2);
1193 assert_eq!(rules[0].xperms_type(), XPERMS_TYPE_NLMSG);
1194 assert_eq!(rules[0].xperms_optional_prefix(), 0x00);
1195 assert_eq!(rules[0].count(), 1);
1196 assert!(rules[0].contains(0x11));
1197 assert_eq!(rules[1].xperms_type(), XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1198 assert_eq!(rules[1].xperms_optional_prefix(), 0x10);
1199 assert_eq!(rules[1].count(), 1);
1200 assert!(rules[1].contains(0x1000));
1201 }
1202}