1use std::num::NonZeroU32;
6use std::sync::atomic::{AtomicU64, Ordering};
7
8use hashbrown::HashTable;
9use hashbrown::hash_table::Entry;
10use rapidhash::RapidBuildHasher;
11
12use super::error::{ParseError, SerializeError, ValidateError};
13use super::parser::{Array, PolicyCursor};
14use super::traits::{Parse, PolicyId, Serialize, Validate};
15use super::{AccessVector, ClassId, ConditionalBooleanId, NewPolicy, TypeId, U24Index};
16
17pub use selinux_policy_derive::{Parse, Serialize};
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 Vec<u8>) -> 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 std::ops::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 std::ops::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 std::ops::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 std::ops::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 std::ops::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 std::ops::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 std::ops::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
297#[derive(Clone, Debug, PartialEq, Eq)]
299pub struct AccessRule {
300 key: RuleKey,
301 kind: RuleKind,
302 access_vector: AccessVector,
303 enabled: bool,
304}
305
306impl AccessRule {
307 pub fn access_vector(&self) -> AccessVector {
309 self.access_vector
310 }
311
312 pub fn enabled(&self) -> bool {
314 self.enabled
315 }
316}
317
318#[derive(Clone, Debug, PartialEq, Eq)]
320pub struct TypeRule {
321 key: RuleKey,
322 kind: RuleKind,
323 new_type: TypeId,
324 enabled: bool,
325}
326
327impl TypeRule {
328 pub fn new_type(&self) -> TypeId {
330 self.new_type
331 }
332
333 pub fn enabled(&self) -> bool {
335 self.enabled
336 }
337}
338
339#[derive(Clone, Debug, PartialEq, Eq)]
341pub struct XpermRule {
342 key: RuleKey,
343 kind: RuleKind,
344 extended_permissions: ExtendedPermissions,
345 enabled: bool,
346}
347
348impl XpermRule {
349 pub fn extended_permissions(&self) -> &ExtendedPermissions {
351 &self.extended_permissions
352 }
353
354 pub fn enabled(&self) -> bool {
356 self.enabled
357 }
358}
359
360#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
362pub struct RuleKey {
363 source_type: TypeId,
364 target_type: TypeId,
365 class: ClassId,
366}
367
368impl RuleKey {
369 pub fn new(source_type: TypeId, target_type: TypeId, class: ClassId) -> Self {
371 Self { source_type, target_type, class }
372 }
373
374 pub fn hash(&self, hasher: &RapidBuildHasher) -> u64 {
376 use std::hash::{BuildHasher, Hash, Hasher};
377 let mut state = hasher.build_hasher();
378 Hash::hash(self, &mut state);
379 state.finish()
380 }
381
382 fn to_header(&self, kind: RuleKind, enabled: bool) -> BinaryAccessVectorRuleHeader {
384 let mut rule_flags = u16::from(kind);
385 if enabled {
386 rule_flags |= AV_ENABLED_RULE_FLAG;
387 }
388 BinaryAccessVectorRuleHeader {
389 source_type: self.source_type.as_u16(),
390 target_type: self.target_type.as_u16(),
391 class: self.class.as_u16(),
392 rule_flags,
393 }
394 }
395}
396
397impl Validate for RuleKey {
398 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
399 self.source_type.validate(policy)?;
400 self.target_type.validate(policy)?;
401 self.class.validate(policy)?;
402 Ok(())
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, PartialEq, Eq)]
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 pub fn av_rules(&self) -> &[AccessRule] {
501 &self.av_rules
502 }
503
504 pub fn type_rules(&self) -> &[TypeRule] {
506 &self.type_rules
507 }
508
509 pub fn xperm_rules(&self) -> &[XpermRule] {
511 &self.xperm_rules
512 }
513
514 pub fn rule_order(&self) -> &[RuleKind] {
516 &self.rule_order
517 }
518}
519
520impl Parse for AccessVectorRules {
521 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
522 let count = u32::parse(cursor)? as usize;
523
524 let mut av_rules = Vec::new();
525 let mut type_rules = Vec::new();
526 let mut xperm_rules = Vec::new();
527 let mut rule_order = Vec::with_capacity(count);
528
529 for _ in 0..count {
532 let header = BinaryAccessVectorRuleHeader::parse(cursor)?;
533 let kind = RuleKind::try_from(header.rule_flags)?;
534 let enabled = (header.rule_flags & AV_ENABLED_RULE_FLAG) != 0;
535
536 let source_val = header.source_type;
537 let source_type = TypeId::from_u16(source_val)
538 .ok_or(ParseError::InvalidId { value: source_val as u32 })?;
539
540 let target_val = header.target_type;
541 let target_type = TypeId::from_u16(target_val)
542 .ok_or(ParseError::InvalidId { value: target_val as u32 })?;
543
544 let class_val = header.class;
545 let class = ClassId::from_u16(class_val)
546 .ok_or(ParseError::InvalidId { value: class_val as u32 })?;
547
548 let key = RuleKey::new(source_type, target_type, class);
549
550 match kind {
551 RuleKind::AllowXperm | RuleKind::AuditAllowXperm | RuleKind::DontAuditXperm => {
552 let extended_permissions = ExtendedPermissions::parse(cursor)?;
553 xperm_rules.push(XpermRule { key, kind, extended_permissions, enabled });
554 rule_order.push(kind);
555 }
556 RuleKind::TypeTransition | RuleKind::TypeChange | RuleKind::TypeMember => {
557 let new_type = TypeId::parse(cursor)?;
558 type_rules.push(TypeRule { key, kind, new_type, enabled });
559 rule_order.push(kind);
560 }
561 RuleKind::Allow | RuleKind::AuditAllow | RuleKind::DontAudit => {
562 let access_vector = AccessVector::parse(cursor)?;
563 av_rules.push(AccessRule { key, kind, access_vector, enabled });
564 rule_order.push(kind);
565 }
566 }
567 }
568
569 let av_rules = av_rules.into_boxed_slice();
570 let type_rules = type_rules.into_boxed_slice();
571 let xperm_rules = xperm_rules.into_boxed_slice();
572 let rule_order = rule_order.into_boxed_slice();
573
574 Ok(Self { av_rules, type_rules, xperm_rules, rule_order })
575 }
576}
577
578impl Serialize for AccessVectorRules {
579 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
580 let count = self.rule_order.len() as u32;
581 count.serialize(writer)?;
582
583 let mut av_rules = self.av_rules.iter();
584 let mut type_rules = self.type_rules.iter();
585 let mut xperm_rules = self.xperm_rules.iter();
586
587 for &kind in self.rule_order.iter() {
588 match kind {
589 RuleKind::Allow | RuleKind::AuditAllow | RuleKind::DontAudit => {
590 let rule = av_rules.next().unwrap();
591 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
592 let val: u32 = rule.access_vector.into();
593 val.serialize(writer)?;
594 }
595 RuleKind::TypeTransition | RuleKind::TypeChange | RuleKind::TypeMember => {
596 let rule = type_rules.next().unwrap();
597 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
598 rule.new_type.serialize(writer)?;
599 }
600 RuleKind::AllowXperm | RuleKind::AuditAllowXperm | RuleKind::DontAuditXperm => {
601 let rule = xperm_rules.next().unwrap();
602 rule.key.to_header(kind, rule.enabled).serialize(writer)?;
603 rule.extended_permissions.serialize(writer)?;
604 }
605 }
606 }
607 Ok(())
608 }
609}
610
611impl Validate for AccessVectorRules {
612 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
613 for rule in self.av_rules.iter() {
614 rule.key.validate(policy)?;
615 }
616 for rule in self.type_rules.iter() {
617 rule.key.validate(policy)?;
618 rule.new_type.validate(policy)?;
619 }
620 for rule in self.xperm_rules.iter() {
621 rule.key.validate(policy)?;
622 rule.extended_permissions.validate(policy)?;
623 }
624 Ok(())
625 }
626}
627
628#[derive(Debug, Clone)]
634pub struct IndexedAccessVectorRules {
635 rules: AccessVectorRules,
636 av_table: HashTable<U24Index>,
637 type_transition_table: HashTable<U24Index>,
638 xperms_table: HashTable<U24Index>,
639 hasher: RapidBuildHasher,
640}
641
642impl IndexedAccessVectorRules {
643 pub fn new(rules: AccessVectorRules) -> Result<Self, ParseError> {
647 let hasher = RapidBuildHasher::default();
648 let av_table = build_index(&rules.av_rules, &hasher)?;
649 let type_transition_table = build_index(&rules.type_rules, &hasher)?;
650 let xperms_table = build_index(&rules.xperm_rules, &hasher)?;
651
652 Ok(Self { rules, av_table, type_transition_table, xperms_table, hasher })
653 }
654
655 pub fn rules(&self) -> &AccessVectorRules {
657 &self.rules
658 }
659
660 fn find_rules<'a, R: HasRuleKey>(
661 table: &HashTable<U24Index>,
662 rules: &'a [R],
663 key: RuleKey,
664 hasher: &RapidBuildHasher,
665 ) -> impl Iterator<Item = &'a R> {
666 let hash = key.hash(hasher);
667 let slice = match table.find(hash, |&i| rules[usize::from(i)].key() == key) {
668 Some(&i) => &rules[usize::from(i)..],
669 None => &[],
670 };
671 slice.iter().take_while(move |rule| rule.key() == key)
672 }
673
674 pub fn find_av_rules(
676 &self,
677 source: TypeId,
678 target: TypeId,
679 class: ClassId,
680 ) -> impl Iterator<Item = &AccessRule> {
681 Self::find_rules(
682 &self.av_table,
683 &self.rules.av_rules,
684 RuleKey::new(source, target, class),
685 &self.hasher,
686 )
687 }
688
689 pub fn find_type_rules(
691 &self,
692 source: TypeId,
693 target: TypeId,
694 class: ClassId,
695 ) -> impl Iterator<Item = &TypeRule> {
696 Self::find_rules(
697 &self.type_transition_table,
698 &self.rules.type_rules,
699 RuleKey::new(source, target, class),
700 &self.hasher,
701 )
702 }
703
704 pub fn find_xperm_rules(
706 &self,
707 source: TypeId,
708 target: TypeId,
709 class: ClassId,
710 ) -> impl Iterator<Item = &XpermRule> {
711 Self::find_rules(
712 &self.xperms_table,
713 &self.rules.xperm_rules,
714 RuleKey::new(source, target, class),
715 &self.hasher,
716 )
717 }
718}
719
720impl Parse for IndexedAccessVectorRules {
721 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
722 let rules = AccessVectorRules::parse(cursor)?;
723 Self::new(rules)
724 }
725}
726
727impl Serialize for IndexedAccessVectorRules {
728 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
729 self.rules.serialize(writer)
730 }
731}
732
733impl Validate for IndexedAccessVectorRules {
734 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
735 self.rules.validate(policy)
736 }
737}
738
739fn build_index<R: HasRuleKey>(
747 rules: &[R],
748 hasher: &RapidBuildHasher,
749) -> Result<HashTable<U24Index>, ParseError> {
750 let mut table = HashTable::new();
751 let mut offset = 0;
752
753 for chunk in rules.chunk_by(|a, b| a.key() == b.key()) {
754 let key = chunk[0].key();
755 let u24_idx = offset.try_into()?;
756 let hash = key.hash(hasher);
757
758 let Entry::Vacant(entry) = table.entry(
759 hash,
760 |&i| rules[usize::from(i)].key() == key,
761 |&i| rules[usize::from(i)].key().hash(hasher),
762 ) else {
763 return Err(ParseError::DuplicateAccessVectorRule { key, kind: chunk[0].kind() });
764 };
765 entry.insert(u24_idx);
766 offset += chunk.len();
767 }
768
769 Ok(table)
770}
771
772pub const COND_EXPR_BOOL: u32 = 1;
774pub const COND_EXPR_NOT: u32 = 2;
776pub const COND_EXPR_OR: u32 = 3;
778pub const COND_EXPR_AND: u32 = 4;
780pub const COND_EXPR_EQ: u32 = 5;
782pub const COND_EXPR_NEQ: u32 = 6;
784
785#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
787pub enum ConditionalExpressionElement {
788 Boolean(ConditionalBooleanId),
790 Not,
792 Or,
794 And,
796 Equals,
798 NotEquals,
800}
801
802impl Parse for ConditionalExpressionElement {
803 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
804 let expr_type = u32::parse(cursor)?;
805 let boolean_id = u32::parse(cursor)?;
806 match expr_type {
807 COND_EXPR_BOOL => {
808 let id = ConditionalBooleanId::from_u32(boolean_id)
809 .ok_or(ParseError::InvalidId { value: boolean_id })?;
810 Ok(Self::Boolean(id))
811 }
812 COND_EXPR_NOT => Ok(Self::Not),
813 COND_EXPR_OR => Ok(Self::Or),
814 COND_EXPR_AND => Ok(Self::And),
815 COND_EXPR_EQ => Ok(Self::Equals),
816 COND_EXPR_NEQ => Ok(Self::NotEquals),
817 invalid => Err(ParseError::InvalidEnumValue {
818 enum_name: "ConditionalExpressionElement",
819 value: invalid as u64,
820 }),
821 }
822 }
823}
824
825impl Serialize for ConditionalExpressionElement {
826 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
827 let (expr_type, boolean_id) = match self {
828 Self::Boolean(id) => (COND_EXPR_BOOL, id.as_u32()),
829 Self::Not => (COND_EXPR_NOT, 0),
830 Self::Or => (COND_EXPR_OR, 0),
831 Self::And => (COND_EXPR_AND, 0),
832 Self::Equals => (COND_EXPR_EQ, 0),
833 Self::NotEquals => (COND_EXPR_NEQ, 0),
834 };
835 expr_type.serialize(writer)?;
836 boolean_id.serialize(writer)?;
837 Ok(())
838 }
839}
840
841impl Validate for ConditionalExpressionElement {
842 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
843 if let Self::Boolean(id) = self {
844 id.validate(policy)?;
845 }
846 Ok(())
847 }
848}
849
850#[derive(Clone, Debug, Eq, PartialEq, Parse, Serialize)]
852pub struct ConditionalNode {
853 state: u32,
854 expression_elements: Array<ConditionalExpressionElement>,
855 true_rules: AccessVectorRules,
856 false_rules: AccessVectorRules,
857}
858
859impl ConditionalNode {
860 pub fn state(&self) -> u32 {
862 self.state
863 }
864
865 pub fn expression_elements(&self) -> &[ConditionalExpressionElement] {
867 self.expression_elements.as_ref()
868 }
869
870 pub fn true_rules(&self) -> &AccessVectorRules {
872 &self.true_rules
873 }
874
875 pub fn false_rules(&self) -> &AccessVectorRules {
877 &self.false_rules
878 }
879}
880
881impl Validate for ConditionalNode {
882 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
883 self.expression_elements.validate(policy)?;
884 self.true_rules.validate(policy)?;
885 self.false_rules.validate(policy)?;
886 Ok(())
887 }
888}
889
890#[derive(Clone, Debug, Eq, PartialEq, Hash, Parse, Serialize)]
892struct BinaryAccessVectorRuleHeader {
893 source_type: u16,
894 target_type: u16,
895 class: u16,
896 rule_flags: u16,
897}
898
899#[cfg(test)]
900mod tests {
901 use super::*;
902 use crate::new_policy::traits::PolicyId;
903
904 #[test]
905 fn test_xperms_bitmap_ops_and_contains() {
906 let mut bitmap1 = XpermsBitmap::NONE;
907 let mut bitmap2 = XpermsBitmap::NONE;
908 assert!(!bitmap1.contains(10));
909 assert!(!bitmap2.contains(10));
910
911 bitmap1.0[0] = 1 << 10;
912 bitmap2.0[0] = 1 << 20;
913 assert!(bitmap1.contains(10));
914 assert!(!bitmap1.contains(20));
915 assert!(bitmap2.contains(20));
916
917 let or_bitmap = bitmap1 | bitmap2;
918 assert!(or_bitmap.contains(10));
919 assert!(or_bitmap.contains(20));
920
921 let and_bitmap = or_bitmap & bitmap1;
922 assert!(and_bitmap.contains(10));
923 assert!(!and_bitmap.contains(20));
924
925 let sub_bitmap = or_bitmap - bitmap1;
926 assert!(!sub_bitmap.contains(10));
927 assert!(sub_bitmap.contains(20));
928
929 let not_bitmap = !XpermsBitmap::NONE;
930 assert_eq!(not_bitmap, XpermsBitmap::ALL);
931 assert!(not_bitmap.contains(0));
932 assert!(not_bitmap.contains(255));
933 }
934
935 #[test]
936 fn test_av_rule_parse_and_serialize() {
937 let data = [
938 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 1, 0, 5, 0, 0, 0, ];
945 let mut cursor = PolicyCursor::new(&data);
946 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
947 assert_eq!(av_rules.av_rules.len(), 1);
948 assert_eq!(av_rules.av_rules[0].key.source_type, TypeId::from_u32(1).unwrap());
949 assert_eq!(av_rules.av_rules[0].key.target_type, TypeId::from_u32(2).unwrap());
950 assert_eq!(av_rules.av_rules[0].key.class, ClassId::from_u32(3).unwrap());
951 assert_eq!(av_rules.av_rules[0].access_vector, AccessVector::from(5));
952
953 let mut writer = Vec::new();
954 av_rules.serialize(&mut writer).expect("serialize rules table");
955 assert_eq!(writer.as_slice(), &data);
956 }
957
958 #[test]
959 fn test_av_rule_type_transition_parse_and_serialize() {
960 let data = [
961 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 16, 0, 10, 0, 0, 0, ];
968 let mut cursor = PolicyCursor::new(&data);
969 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
970 assert_eq!(av_rules.type_rules.len(), 1);
971 assert_eq!(av_rules.type_rules[0].key.source_type, TypeId::from_u32(1).unwrap());
972 assert_eq!(av_rules.type_rules[0].key.target_type, TypeId::from_u32(2).unwrap());
973 assert_eq!(av_rules.type_rules[0].key.class, ClassId::from_u32(3).unwrap());
974 assert_eq!(av_rules.type_rules[0].new_type, TypeId::from_u32(10).unwrap());
975
976 let mut writer = Vec::new();
977 av_rules.serialize(&mut writer).expect("serialize rules table");
978 assert_eq!(writer.as_slice(), &data);
979 }
980
981 #[test]
982 fn test_av_rule_xperm_parse_and_serialize() {
983 let mut data = vec![
984 1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 0, 1, 1, 0, ];
992 data.extend_from_slice(&[
993 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, ]);
998 let mut cursor = PolicyCursor::new(&data);
999 let av_rules = AccessVectorRules::parse(&mut cursor).expect("parse rules table");
1000 assert_eq!(av_rules.xperm_rules.len(), 1);
1001 let xp = &av_rules.xperm_rules[0].extended_permissions;
1002 assert_eq!(xp.xperms_type, XPERMS_TYPE_IOCTL_PREFIX_AND_POSTFIXES);
1003 assert!(xp.xperms_bitmap.contains(0));
1004 assert!(!xp.xperms_bitmap.contains(1));
1005
1006 let mut writer = Vec::new();
1007 av_rules.serialize(&mut writer).expect("serialize rules table");
1008 assert_eq!(writer.as_slice(), &data);
1009 }
1010
1011 #[test]
1012 fn test_access_vector_rules_indexing_and_decisions() {
1013 let data = [
1014 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, ];
1028
1029 let mut cursor = PolicyCursor::new(&data);
1030 let av_rules = IndexedAccessVectorRules::parse(&mut cursor).expect("parse rules table");
1031
1032 let s1 = TypeId::from_u32(1).unwrap();
1033 let t2 = TypeId::from_u32(2).unwrap();
1034 let c3 = ClassId::from_u32(3).unwrap();
1035
1036 let av_rules_list: Vec<_> = av_rules.find_av_rules(s1, t2, c3).collect();
1037 assert_eq!(av_rules_list.len(), 1);
1038 assert_eq!(av_rules_list[0].kind(), RuleKind::Allow);
1039 assert_eq!(av_rules_list[0].access_vector(), AccessVector::from(7));
1040
1041 let type_rules_list: Vec<_> = av_rules.find_type_rules(s1, t2, c3).collect();
1042 assert_eq!(type_rules_list.len(), 1);
1043 assert_eq!(type_rules_list[0].kind(), RuleKind::TypeTransition);
1044 assert_eq!(type_rules_list[0].new_type(), TypeId::from_u32(9).unwrap());
1045 }
1046
1047 #[test]
1048 fn test_unindexed_access_vector_rules_allows_duplicate_keys() {
1049 let data = [
1050 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, ];
1058
1059 let mut cursor = PolicyCursor::new(&data);
1060 let av_rules =
1061 AccessVectorRules::parse(&mut cursor).expect("unindexed rules parse duplicate keys");
1062 assert_eq!(av_rules.av_rules.len(), 3);
1063
1064 let mut cursor = PolicyCursor::new(&data);
1065 let err = IndexedAccessVectorRules::parse(&mut cursor)
1066 .expect_err("indexed rules reject duplicate keys");
1067 assert!(matches!(
1068 err,
1069 ParseError::DuplicateAccessVectorRule { key: _, kind: RuleKind::Allow }
1070 ));
1071 }
1072}