1pub mod error;
6pub mod index;
7pub mod parsed_policy;
8pub mod parser;
9
10mod constraints;
11mod security_context;
12
13pub use crate::new_policy::traits::{HasName, HasPolicyId, PolicyId};
14pub use crate::new_policy::{
15 AccessDecision, AccessVector, AccessVectorRules, CategoryId, ClassId, FsUseType, HandleUnknown,
16 IndexedAccessVectorRules, MlsLevel, MlsRange, POLICYDB_VERSION_MAX, PermissionId, RoleId,
17 SELINUX_AVD_FLAGS_PERMISSIVE, SensitivityId, TypeId, User, UserId, XpermsBitmap,
18};
19use crate::{ClassPermission, KernelClass, NullessByteStr, ObjectClass, new_policy as new};
20pub use index::FsUseLabelAndType;
21use index::PolicyIndex;
22use parsed_policy::ParsedPolicy;
23pub use parser::PolicyCursor;
24use parser::PolicyData;
25pub use security_context::{SecurityContext, SecurityContextError};
26
27use anyhow::Context as _;
28use std::fmt::Debug;
29use std::num::NonZeroU32;
30use std::ops::Deref;
31
32use std::sync::Arc;
33use zerocopy::little_endian as le;
34
35#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
41pub enum XpermsKind {
42 Ioctl,
43 Nlmsg,
44}
45
46#[derive(Debug, Clone, PartialEq)]
51pub struct XpermsAccessDecision {
52 pub allow: XpermsBitmap,
53 pub auditallow: XpermsBitmap,
54 pub auditdeny: XpermsBitmap,
55}
56
57impl XpermsAccessDecision {
58 pub const DENY_ALL: Self = Self {
59 allow: XpermsBitmap::NONE,
60 auditallow: XpermsBitmap::NONE,
61 auditdeny: XpermsBitmap::ALL,
62 };
63 pub const ALLOW_ALL: Self = Self {
64 allow: XpermsBitmap::ALL,
65 auditallow: XpermsBitmap::NONE,
66 auditdeny: XpermsBitmap::ALL,
67 };
68}
69
70pub fn parse_policy_by_value(binary_policy: Vec<u8>) -> Result<Unvalidated, anyhow::Error> {
79 let policy_data: PolicyData = Arc::from(binary_policy);
80 let policy = ParsedPolicy::parse(policy_data).context("parsing policy")?;
81 Ok(Unvalidated(policy))
82}
83
84#[derive(Debug)]
85pub struct Policy(PolicyIndex);
86
87impl Deref for Policy {
88 type Target = PolicyIndex;
89
90 fn deref(&self) -> &Self::Target {
91 &self.0
92 }
93}
94
95impl Policy {
96 pub fn serialize(&self) -> PolicyData {
98 let mut bytes = Vec::new();
99 self.0.serialize(&mut bytes).expect("serialization of new_policy should succeed");
100 std::sync::Arc::from(bytes)
101 }
102
103 pub fn conditional_booleans<'a>(&'a self) -> Vec<(&'a [u8], bool)> {
104 self.0
105 .conditional_booleans()
106 .iter()
107 .map(|boolean| (boolean.name(), boolean.active()))
108 .collect()
109 }
110
111 pub fn find_class_permissions_by_name(
116 &self,
117 class_name: &str,
118 ) -> Result<Vec<(PermissionId, Vec<u8>)>, ()> {
119 let classes = self.classes();
120 let class = classes.get_by_name(class_name.as_bytes()).ok_or(())?;
121 let owned_permissions = class.permissions();
122
123 let mut result: Vec<_> = owned_permissions
124 .iter()
125 .map(|permission| (permission.id(), permission.name().to_vec()))
126 .collect();
127
128 if class.common_name().is_empty() {
130 return Ok(result);
131 }
132
133 let common_symbol_permissions =
134 self.common_symbols().get_by_name(class.common_name()).ok_or(())?.permissions();
135
136 result.append(
137 &mut common_symbol_permissions
138 .iter()
139 .map(|permission| (permission.id(), permission.name().to_vec()))
140 .collect(),
141 );
142
143 Ok(result)
144 }
145
146 pub fn fs_use_label_and_type(&self, fs_type: NullessByteStr<'_>) -> Option<FsUseLabelAndType> {
149 self.0.fs_use_label_and_type(fs_type)
150 }
151
152 pub fn genfscon_label_for_fs_and_path(
155 &self,
156 fs_type: NullessByteStr<'_>,
157 node_path: NullessByteStr<'_>,
158 class_id: Option<KernelClass>,
159 ) -> Option<SecurityContext> {
160 self.0.genfscon_label_for_fs_and_path(fs_type, node_path, class_id)
161 }
162
163 pub fn initial_context(&self, id: crate::InitialSid) -> security_context::SecurityContext {
166 self.0.initial_context(id)
167 }
168
169 pub fn parse_security_context(
171 &self,
172 security_context: NullessByteStr<'_>,
173 ) -> Result<security_context::SecurityContext, security_context::SecurityContextError> {
174 security_context::SecurityContext::from_string(&self.0, security_context)
175 }
176
177 pub fn validate_security_context(
179 &self,
180 security_context: &SecurityContext,
181 ) -> Result<(), SecurityContextError> {
182 security_context.validate(&self.0)
183 }
184
185 pub fn serialize_security_context(&self, security_context: &SecurityContext) -> Vec<u8> {
187 security_context.to_string(&self.0)
188 }
189
190 pub fn compute_create_context(
210 &self,
211 source: &SecurityContext,
212 target: &SecurityContext,
213 class: impl Into<ObjectClass>,
214 name: &[u8],
215 ) -> SecurityContext {
216 self.0.compute_create_context(source, target, class.into(), name)
217 }
218
219 pub fn compute_access_decision(
229 &self,
230 source_context: &SecurityContext,
231 target_context: &SecurityContext,
232 object_class: impl Into<ObjectClass>,
233 ) -> AccessDecision {
234 if let Some(target_class) = self.0.class(object_class.into()) {
235 self.0.compute_access_decision(source_context, target_context, &target_class)
236 } else {
237 let mut decision = AccessDecision::allow(AccessVector::NONE);
238 if self.is_permissive(source_context.type_()) {
239 decision.flags |= SELINUX_AVD_FLAGS_PERMISSIVE;
240 }
241 decision
242 }
243 }
244
245 pub fn compute_xperms_access_decision(
249 &self,
250 xperms_kind: XpermsKind,
251 source_context: &SecurityContext,
252 target_context: &SecurityContext,
253 object_class: impl Into<ObjectClass>,
254 xperms_prefix: u8,
255 ) -> XpermsAccessDecision {
256 if let Some(target_class) = self.0.class(object_class.into()) {
257 self.0.compute_xperms_access_decision(
258 xperms_kind,
259 source_context,
260 target_context,
261 &target_class,
262 xperms_prefix,
263 )
264 } else {
265 XpermsAccessDecision::DENY_ALL
266 }
267 }
268
269 pub fn is_bounded_by(&self, bounded_type: TypeId, parent_type: TypeId) -> bool {
270 self.0.types().get_by_id(bounded_type).unwrap().bounded_by() == Some(parent_type)
271 }
272
273 pub fn is_permissive(&self, type_: TypeId) -> bool {
275 self.0.permissive_map().contains(type_)
276 }
277}
278
279impl AccessVectorComputer for Policy {
280 fn access_decision_to_kernel_access_decision(
281 &self,
282 class: KernelClass,
283 av: AccessDecision,
284 ) -> KernelAccessDecision {
285 let mut kernel_allow;
286 let mut kernel_audit;
287 if self.0.handle_unknown() == HandleUnknown::Allow {
290 kernel_allow = 0xffffffffu32;
292 kernel_audit = 0u32;
293 } else {
294 kernel_allow = 0u32;
296 kernel_audit = 0xffffffffu32;
297 }
298
299 let decision_allow = av.allow;
300 let decision_audit = (av.allow & av.auditallow) | (!av.allow & av.auditdeny);
301 for permission in class.permissions() {
302 if let Some(permission_access_vector) =
303 self.0.kernel_permission_to_access_vector(permission.clone())
304 {
305 let bit = 1 << permission.id();
308 let allow = decision_allow & permission_access_vector == permission_access_vector;
309 let audit = decision_audit & permission_access_vector == permission_access_vector;
310 kernel_allow = (kernel_allow & !bit) | ((allow as u32) << permission.id());
311 kernel_audit = (kernel_audit & !bit) | ((audit as u32) << permission.id());
312 }
313 }
314 KernelAccessDecision {
315 allow: AccessVector::from(kernel_allow),
316 audit: AccessVector::from(kernel_audit),
317 flags: av.flags,
318 todo_bug: av.todo_bug,
319 }
320 }
321}
322
323pub struct Unvalidated(ParsedPolicy);
325
326impl Unvalidated {
327 pub fn validate(self) -> Result<Policy, anyhow::Error> {
328 self.0.validate().context("validating parsed policy")?;
329 let index = PolicyIndex::new(self.0).context("building index")?;
330 Ok(Policy(index))
331 }
332}
333
334#[derive(Clone, Copy, Debug, PartialEq, Eq)]
335pub struct KernelAccessDecision {
336 pub allow: AccessVector,
337 pub audit: AccessVector,
338 pub flags: u32,
339 pub todo_bug: Option<NonZeroU32>,
340}
341
342pub trait AccessVectorComputer {
345 fn access_decision_to_kernel_access_decision(
352 &self,
353 class: KernelClass,
354 av: AccessDecision,
355 ) -> KernelAccessDecision;
356}
357
358pub trait Parse: Sized {
360 type Error: Into<anyhow::Error>;
363
364 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error>;
367}
368
369impl Parse for le::U32 {
371 type Error = anyhow::Error;
372
373 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
374 bytes.parse::<le::U32>().map_err(anyhow::Error::from)
375 }
376}
377
378impl<T: crate::new_policy::traits::Parse> Parse for T {
379 type Error = anyhow::Error;
380
381 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
382 let offset = bytes.offset() as usize;
383 let slice = &bytes.data().as_ref()[offset..];
384 let mut new_cursor = crate::new_policy::parser::PolicyCursor::new(slice);
385 let item = <T as crate::new_policy::traits::Parse>::parse(&mut new_cursor)
386 .map_err(|e| anyhow::anyhow!("Parse error: {:?}", e))?;
387 let new_offset = bytes.offset() + new_cursor.offset() as u32;
388 Ok((item, PolicyCursor::new_at(bytes.data(), new_offset)))
389 }
390}
391
392#[cfg(test)]
393pub(super) mod tests {
394 use super::security_context::SecurityContext;
395 use super::{
396 AccessVector, ClassId, HandleUnknown, Policy, TypeId, XpermsAccessDecision, XpermsBitmap,
397 XpermsKind, parse_policy_by_value,
398 };
399 use crate::new_policy::traits::HasPolicyId;
400 use crate::{FileClass, InitialSid, KernelClass};
401 use anyhow::Context as _;
402 use serde::Deserialize;
403
404 fn is_explicitly_allowed(
412 policy: &Policy,
413 source_type: TypeId,
414 target_type: TypeId,
415 target_class: &str,
416 permission: &str,
417 ) -> bool {
418 let classes = policy.classes();
419 let class = classes.get_by_name(target_class.as_bytes()).expect("class not found");
420 let class_permissions = policy
421 .find_class_permissions_by_name(target_class)
422 .expect("class permissions not found");
423 let (permission_id, _) = class_permissions
424 .iter()
425 .find(|(_, name)| permission.as_bytes() == name)
426 .expect("permission not found");
427 let permission_bit = AccessVector::from(*permission_id);
428 let access_decision = policy.0.compute_explicitly_allowed(source_type, target_type, class);
429 permission_bit == access_decision.allow & permission_bit
430 }
431
432 #[derive(Debug, Deserialize)]
433 struct Expectations {
434 expected_policy_version: u32,
435 expected_handle_unknown: LocalHandleUnknown,
436 }
437
438 #[derive(Debug, Deserialize, PartialEq)]
439 #[serde(rename_all = "snake_case")]
440 enum LocalHandleUnknown {
441 Deny,
442 Reject,
443 Allow,
444 }
445
446 impl PartialEq<HandleUnknown> for LocalHandleUnknown {
447 fn eq(&self, other: &HandleUnknown) -> bool {
448 match self {
449 LocalHandleUnknown::Deny => *other == HandleUnknown::Deny,
450 LocalHandleUnknown::Reject => *other == HandleUnknown::Reject,
451 LocalHandleUnknown::Allow => *other == HandleUnknown::Allow,
452 }
453 }
454 }
455
456 fn xperms_bitmap_from_elements(elements: &[u8]) -> XpermsBitmap {
459 let mut bitmap = [0u64; 4];
460 for element in elements {
461 let block_index = (*element as usize) / 64;
462 let bit_index = (*element as usize) % 64;
463 bitmap[block_index] |= 1u64 << bit_index;
464 }
465 XpermsBitmap::new(bitmap)
466 }
467
468 #[test]
469 fn known_policies() {
470 let policies_and_expectations = [
471 [
472 b"testdata/policies/emulator".to_vec(),
473 include_bytes!("../../testdata/policies/emulator").to_vec(),
474 include_bytes!("../../testdata/expectations/emulator").to_vec(),
475 ],
476 [
477 b"testdata/policies/selinux_testsuite".to_vec(),
478 include_bytes!("../../testdata/policies/selinux_testsuite").to_vec(),
479 include_bytes!("../../testdata/expectations/selinux_testsuite").to_vec(),
480 ],
481 ];
482
483 for [policy_path, policy_bytes, expectations_bytes] in policies_and_expectations {
484 let expectations = serde_json5::from_reader::<_, Expectations>(
485 &mut std::io::Cursor::new(expectations_bytes),
486 )
487 .expect("deserialize expectations");
488
489 let unvalidated_policy =
492 parse_policy_by_value(policy_bytes.clone()).expect("parse policy");
493
494 let policy = unvalidated_policy
495 .validate()
496 .with_context(|| {
497 format!(
498 "policy path: {:?}",
499 std::str::from_utf8(policy_path.as_slice()).unwrap()
500 )
501 })
502 .expect("validate policy");
503
504 assert_eq!(expectations.expected_policy_version, policy.version().get());
505 assert_eq!(expectations.expected_handle_unknown, policy.handle_unknown());
506
507 let binary_policy = policy.serialize();
509 assert_eq!(policy_bytes, binary_policy.as_ref());
510 }
511 }
512
513 #[test]
514 fn policy_lookup() {
515 let policy_bytes = include_bytes!("../../testdata/policies/selinux_testsuite");
516 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
517 let policy = policy.validate().expect("validate selinux testsuite policy");
518
519 let unconfined_t = policy.types().get_by_name(b"unconfined_t").expect("look up type").id();
520
521 assert!(is_explicitly_allowed(&policy, unconfined_t, unconfined_t, "process", "fork",));
522 }
523
524 #[test]
525 fn initial_contexts() {
526 let policy_bytes =
527 include_bytes!("../../testdata/micro_policies/multiple_levels_and_categories_policy");
528 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
529 let policy = policy.validate().expect("validate policy");
530
531 let kernel_context = policy.initial_context(InitialSid::Kernel);
532 assert_eq!(
533 policy.serialize_security_context(&kernel_context),
534 b"user0:object_r:type0:s0:c0-s1:c0.c2,c4"
535 )
536 }
537
538 #[test]
539 fn explicit_allow_type_type() {
540 let policy_bytes =
541 include_bytes!("../../testdata/micro_policies/allow_a_t_b_t_class0_perm0_policy");
542 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
543 let policy = policy.validate().expect("validate policy");
544
545 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
546 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
547
548 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
549 }
550
551 #[test]
552 fn no_explicit_allow_type_type() {
553 let policy_bytes =
554 include_bytes!("../../testdata/micro_policies/no_allow_a_t_b_t_class0_perm0_policy");
555 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
556 let policy = policy.validate().expect("validate policy");
557
558 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
559 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
560
561 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
562 }
563
564 #[test]
565 fn explicit_allow_type_attr() {
566 let policy_bytes =
567 include_bytes!("../../testdata/micro_policies/allow_a_t_b_attr_class0_perm0_policy");
568 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
569 let policy = policy.validate().expect("validate policy");
570
571 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
572 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
573
574 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
575 }
576
577 #[test]
578 fn no_explicit_allow_type_attr() {
579 let policy_bytes =
580 include_bytes!("../../testdata/micro_policies/no_allow_a_t_b_attr_class0_perm0_policy");
581 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
582 let policy = policy.validate().expect("validate policy");
583
584 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
585 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
586
587 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
588 }
589
590 #[test]
591 fn explicit_allow_attr_attr() {
592 let policy_bytes =
593 include_bytes!("../../testdata/micro_policies/allow_a_attr_b_attr_class0_perm0_policy");
594 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
595 let policy = policy.validate().expect("validate policy");
596
597 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
598 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
599
600 assert!(is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
601 }
602
603 #[test]
604 fn no_explicit_allow_attr_attr() {
605 let policy_bytes = include_bytes!(
606 "../../testdata/micro_policies/no_allow_a_attr_b_attr_class0_perm0_policy"
607 );
608 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
609 let policy = policy.validate().expect("validate policy");
610
611 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
612 let b_t = policy.types().get_by_name(b"b_t").expect("look up type").id();
613
614 assert!(!is_explicitly_allowed(&policy, a_t, b_t, "class0", "perm0"));
615 }
616
617 #[test]
618 fn compute_explicitly_allowed_multiple_attributes() {
619 let policy_bytes = include_bytes!(
620 "../../testdata/micro_policies/allow_a_t_a1_attr_class0_perm0_a2_attr_class0_perm1_policy"
621 );
622 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
623 let policy = policy.validate().expect("validate policy");
624
625 let a_t = policy.types().get_by_name(b"a_t").expect("look up type").id();
626
627 let classes = policy.classes();
628 let class = classes.get_by_name(b"class0").expect("class not found");
629 let raw_access_vector = policy.0.compute_explicitly_allowed(a_t, a_t, class).allow.value();
630
631 assert_eq!(2, raw_access_vector.count_ones());
636 }
637
638 #[test]
639 fn compute_access_decision_with_constraints() {
640 let policy_bytes =
641 include_bytes!("../../testdata/micro_policies/allow_with_constraints_policy");
642 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
643 let policy = policy.validate().expect("validate policy");
644
645 let source_context: SecurityContext = policy
646 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
647 .expect("create source security context");
648
649 let target_context_satisfied: SecurityContext = source_context.clone();
650 let decision_satisfied = policy.compute_access_decision(
651 &source_context,
652 &target_context_satisfied,
653 KernelClass::File,
654 );
655 assert_eq!(decision_satisfied.allow, AccessVector::from(7));
659
660 let target_context_unsatisfied: SecurityContext = policy
661 .parse_security_context(b"user1:object_r:type0:s0:c0-s0:c0".into())
662 .expect("create target security context failing some constraints");
663 let decision_unsatisfied = policy.compute_access_decision(
664 &source_context,
665 &target_context_unsatisfied,
666 KernelClass::File,
667 );
668 assert_eq!(decision_unsatisfied.allow, AccessVector::from(4));
671 }
672
673 #[test]
674 fn compute_ioctl_access_decision_explicitly_allowed() {
675 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
676 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
677 let policy = policy.validate().expect("validate policy");
678
679 let source_context: SecurityContext = policy
680 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
681 .expect("create source security context");
682 let target_context_matched: SecurityContext = source_context.clone();
683
684 let decision_single = policy.compute_xperms_access_decision(
702 XpermsKind::Ioctl,
703 &source_context,
704 &target_context_matched,
705 KernelClass::File,
706 0xab,
707 );
708
709 let mut expected_auditdeny =
710 xperms_bitmap_from_elements((0x0..=0xff).collect::<Vec<_>>().as_slice());
711 expected_auditdeny -= xperms_bitmap_from_elements(&[0xcd, 0xef]);
712
713 let expected_decision_single = XpermsAccessDecision {
714 allow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
715 auditallow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
716 auditdeny: expected_auditdeny,
717 };
718 assert_eq!(decision_single, expected_decision_single);
719
720 let decision_range = policy.compute_xperms_access_decision(
721 XpermsKind::Ioctl,
722 &source_context,
723 &target_context_matched,
724 KernelClass::File,
725 0x10,
726 );
727 let expected_decision_range = XpermsAccessDecision {
728 allow: XpermsBitmap::ALL,
729 auditallow: XpermsBitmap::ALL,
730 auditdeny: XpermsBitmap::NONE,
731 };
732 assert_eq!(decision_range, expected_decision_range);
733 }
734
735 #[test]
736 fn compute_ioctl_access_decision_denied() {
737 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
738 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
739 let class_id = unvalidated
740 .0
741 .classes()
742 .get_by_name(b"class_one_ioctl")
743 .expect("look up class_one_ioctl")
744 .id();
745 let policy = unvalidated.validate().expect("validate policy");
746 let source_context: SecurityContext = policy
747 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
748 .expect("create source security context");
749 let target_context_matched: SecurityContext = source_context.clone();
750
751 let decision_single = policy.compute_xperms_access_decision(
755 XpermsKind::Ioctl,
756 &source_context,
757 &target_context_matched,
758 class_id,
759 0xdb,
760 );
761
762 let expected_decision = XpermsAccessDecision {
763 allow: XpermsBitmap::NONE,
764 auditallow: XpermsBitmap::NONE,
765 auditdeny: XpermsBitmap::ALL,
766 };
767 assert_eq!(decision_single, expected_decision);
768 }
769
770 #[test]
771 fn compute_ioctl_access_decision_unmatched() {
772 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
773 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
774 let policy = policy.validate().expect("validate policy");
775
776 let source_context: SecurityContext = policy
777 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
778 .expect("create source security context");
779
780 let target_context_unmatched: SecurityContext = policy
782 .parse_security_context(b"user0:object_r:type1:s0-s0".into())
783 .expect("create source security context");
784
785 for prefix in 0x0..=0xff {
786 let decision = policy.compute_xperms_access_decision(
787 XpermsKind::Ioctl,
788 &source_context,
789 &target_context_unmatched,
790 KernelClass::File,
791 prefix,
792 );
793 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
794 }
795 }
796
797 #[test]
798 fn compute_ioctl_earlier_redundant_prefixful_not_coalesced_into_prefixless() {
799 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
800 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
801 let class_id = unvalidated
802 .0
803 .classes()
804 .get_by_name(b"class_earlier_redundant_prefixful_not_coalesced_into_prefixless")
805 .expect("look up class_earlier_redundant_prefixful_not_coalesced_into_prefixless")
806 .id();
807 let policy = unvalidated.validate().expect("validate policy");
808 let source_context: SecurityContext = policy
809 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
810 .expect("create source security context");
811 let target_context_matched: SecurityContext = source_context.clone();
812
813 let decision = policy.compute_xperms_access_decision(
818 XpermsKind::Ioctl,
819 &source_context,
820 &target_context_matched,
821 class_id,
822 0x7f,
823 );
824 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
825 let decision = policy.compute_xperms_access_decision(
826 XpermsKind::Ioctl,
827 &source_context,
828 &target_context_matched,
829 class_id,
830 0x80,
831 );
832 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
833 let decision = policy.compute_xperms_access_decision(
834 XpermsKind::Ioctl,
835 &source_context,
836 &target_context_matched,
837 class_id,
838 0x81,
839 );
840 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
841 }
842
843 #[test]
844 fn compute_ioctl_later_redundant_prefixful_not_coalesced_into_prefixless() {
845 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
846 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
847 let class_id = unvalidated
848 .0
849 .classes()
850 .get_by_name(b"class_later_redundant_prefixful_not_coalesced_into_prefixless")
851 .expect("look up class_later_redundant_prefixful_not_coalesced_into_prefixless")
852 .id();
853 let policy = unvalidated.validate().expect("validate policy");
854 let source_context: SecurityContext = policy
855 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
856 .expect("create source security context");
857 let target_context_matched: SecurityContext = source_context.clone();
858
859 let decision = policy.compute_xperms_access_decision(
864 XpermsKind::Ioctl,
865 &source_context,
866 &target_context_matched,
867 class_id,
868 0x8f,
869 );
870 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
871 let decision = policy.compute_xperms_access_decision(
872 XpermsKind::Ioctl,
873 &source_context,
874 &target_context_matched,
875 class_id,
876 0x90,
877 );
878 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
879 let decision = policy.compute_xperms_access_decision(
880 XpermsKind::Ioctl,
881 &source_context,
882 &target_context_matched,
883 class_id,
884 0x91,
885 );
886 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
887 }
888
889 #[test]
890 fn compute_ioctl_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless() {
891 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
892 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
893 let class_id = unvalidated
894 .0
895 .classes()
896 .get_by_name(
897 b"class_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless",
898 )
899 .expect(
900 "look up class_earlier_and_later_redundant_prefixful_not_coalesced_into_prefixless",
901 )
902 .id();
903 let policy = unvalidated.validate().expect("validate policy");
904 let source_context: SecurityContext = policy
905 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
906 .expect("create source security context");
907 let target_context_matched: SecurityContext = source_context.clone();
908
909 let decision = policy.compute_xperms_access_decision(
915 XpermsKind::Ioctl,
916 &source_context,
917 &target_context_matched,
918 class_id,
919 0x9f,
920 );
921 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
922 let decision = policy.compute_xperms_access_decision(
923 XpermsKind::Ioctl,
924 &source_context,
925 &target_context_matched,
926 class_id,
927 0xa0,
928 );
929 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
930 let decision = policy.compute_xperms_access_decision(
931 XpermsKind::Ioctl,
932 &source_context,
933 &target_context_matched,
934 class_id,
935 0xa1,
936 );
937 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
938 }
939
940 #[test]
941 fn compute_ioctl_prefixfuls_that_coalesce_to_prefixless() {
942 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
943 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
944 let class_id: ClassId = unvalidated
945 .0
946 .classes()
947 .get_by_name(b"class_prefixfuls_that_coalesce_to_prefixless")
948 .expect("look up class_prefixfuls_that_coalesce_to_prefixless")
949 .id();
950 let policy = unvalidated.validate().expect("validate policy");
951 let source_context: SecurityContext = policy
952 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
953 .expect("create source security context");
954 let target_context_matched: SecurityContext = source_context.clone();
955
956 let decision = policy.compute_xperms_access_decision(
962 XpermsKind::Ioctl,
963 &source_context,
964 &target_context_matched,
965 class_id,
966 0xaf,
967 );
968 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
969 let decision = policy.compute_xperms_access_decision(
970 XpermsKind::Ioctl,
971 &source_context,
972 &target_context_matched,
973 class_id,
974 0xb0,
975 );
976 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
977 let decision = policy.compute_xperms_access_decision(
978 XpermsKind::Ioctl,
979 &source_context,
980 &target_context_matched,
981 class_id,
982 0xb1,
983 );
984 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
985 }
986
987 #[test]
988 fn compute_ioctl_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless() {
989 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
990 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
991 let class_id = unvalidated
992 .0
993 .classes()
994 .get_by_name(b"class_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless")
995 .expect("look up class_prefixfuls_that_coalesce_to_prefixless_just_before_prefixless")
996 .id();
997 let policy = unvalidated.validate().expect("validate policy");
998 let source_context: SecurityContext = policy
999 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1000 .expect("create source security context");
1001 let target_context_matched: SecurityContext = source_context.clone();
1002
1003 let decision = policy.compute_xperms_access_decision(
1010 XpermsKind::Ioctl,
1011 &source_context,
1012 &target_context_matched,
1013 class_id,
1014 0xbf,
1015 );
1016 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1017 let decision = policy.compute_xperms_access_decision(
1018 XpermsKind::Ioctl,
1019 &source_context,
1020 &target_context_matched,
1021 class_id,
1022 0xc0,
1023 );
1024 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1025 let decision = policy.compute_xperms_access_decision(
1026 XpermsKind::Ioctl,
1027 &source_context,
1028 &target_context_matched,
1029 class_id,
1030 0xc1,
1031 );
1032 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1033 let decision = policy.compute_xperms_access_decision(
1034 XpermsKind::Ioctl,
1035 &source_context,
1036 &target_context_matched,
1037 class_id,
1038 0xc2,
1039 );
1040 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1041 }
1042
1043 #[test]
1044 fn compute_ioctl_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless() {
1045 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1046 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1047 let class_id = unvalidated
1048 .0
1049 .classes()
1050 .get_by_name(b"class_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless")
1051 .expect("look up class_prefixless_just_before_prefixfuls_that_coalesce_to_prefixless")
1052 .id();
1053 let policy = unvalidated.validate().expect("validate policy");
1054 let source_context: SecurityContext = policy
1055 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1056 .expect("create source security context");
1057 let target_context_matched: SecurityContext = source_context.clone();
1058
1059 let decision = policy.compute_xperms_access_decision(
1066 XpermsKind::Ioctl,
1067 &source_context,
1068 &target_context_matched,
1069 class_id,
1070 0xd5,
1071 );
1072 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1073 let decision = policy.compute_xperms_access_decision(
1074 XpermsKind::Ioctl,
1075 &source_context,
1076 &target_context_matched,
1077 class_id,
1078 0xd6,
1079 );
1080 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1081 let decision = policy.compute_xperms_access_decision(
1082 XpermsKind::Ioctl,
1083 &source_context,
1084 &target_context_matched,
1085 class_id,
1086 0xd7,
1087 );
1088 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1089 let decision = policy.compute_xperms_access_decision(
1090 XpermsKind::Ioctl,
1091 &source_context,
1092 &target_context_matched,
1093 class_id,
1094 0xd8,
1095 );
1096 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1097 }
1098
1099 #[test]
1110 fn compute_ioctl_ridiculous_permission_ordering() {
1111 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1112 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1113 let class_id = unvalidated
1114 .0
1115 .classes()
1116 .get_by_name(b"class_ridiculous_permission_ordering")
1117 .expect("look up class_ridiculous_permission_ordering")
1118 .id();
1119 let policy = unvalidated.validate().expect("validate policy");
1120 let source_context: SecurityContext = policy
1121 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1122 .expect("create source security context");
1123 let target_context_matched: SecurityContext = source_context.clone();
1124
1125 let decision = policy.compute_xperms_access_decision(
1130 XpermsKind::Ioctl,
1131 &source_context,
1132 &target_context_matched,
1133 class_id,
1134 0x00,
1135 );
1136 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1137 let decision = policy.compute_xperms_access_decision(
1138 XpermsKind::Ioctl,
1139 &source_context,
1140 &target_context_matched,
1141 class_id,
1142 0x01,
1143 );
1144 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1145 let decision = policy.compute_xperms_access_decision(
1146 XpermsKind::Ioctl,
1147 &source_context,
1148 &target_context_matched,
1149 class_id,
1150 0xbf,
1151 );
1152 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1153 let decision = policy.compute_xperms_access_decision(
1154 XpermsKind::Ioctl,
1155 &source_context,
1156 &target_context_matched,
1157 class_id,
1158 0xc0,
1159 );
1160 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1161 let decision = policy.compute_xperms_access_decision(
1162 XpermsKind::Ioctl,
1163 &source_context,
1164 &target_context_matched,
1165 class_id,
1166 0xce,
1167 );
1168 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1169 let decision = policy.compute_xperms_access_decision(
1170 XpermsKind::Ioctl,
1171 &source_context,
1172 &target_context_matched,
1173 class_id,
1174 0xcf,
1175 );
1176 assert_eq!(
1177 decision,
1178 XpermsAccessDecision {
1179 allow: xperms_bitmap_from_elements((0x0..=0xf2).collect::<Vec<_>>().as_slice()),
1180 auditallow: XpermsBitmap::NONE,
1181 auditdeny: XpermsBitmap::ALL,
1182 }
1183 );
1184 let decision = policy.compute_xperms_access_decision(
1185 XpermsKind::Ioctl,
1186 &source_context,
1187 &target_context_matched,
1188 class_id,
1189 0xd0,
1190 );
1191 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1192 let decision = policy.compute_xperms_access_decision(
1193 XpermsKind::Ioctl,
1194 &source_context,
1195 &target_context_matched,
1196 class_id,
1197 0xe9,
1198 );
1199 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1200 let decision = policy.compute_xperms_access_decision(
1201 XpermsKind::Ioctl,
1202 &source_context,
1203 &target_context_matched,
1204 class_id,
1205 0xf0,
1206 );
1207 assert_eq!(
1208 decision,
1209 XpermsAccessDecision {
1210 allow: xperms_bitmap_from_elements(&[0x01]),
1211 auditallow: XpermsBitmap::NONE,
1212 auditdeny: XpermsBitmap::ALL,
1213 }
1214 );
1215 let decision = policy.compute_xperms_access_decision(
1216 XpermsKind::Ioctl,
1217 &source_context,
1218 &target_context_matched,
1219 class_id,
1220 0xf1,
1221 );
1222 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1223 let decision = policy.compute_xperms_access_decision(
1224 XpermsKind::Ioctl,
1225 &source_context,
1226 &target_context_matched,
1227 class_id,
1228 0xfc,
1229 );
1230 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1231 let decision = policy.compute_xperms_access_decision(
1232 XpermsKind::Ioctl,
1233 &source_context,
1234 &target_context_matched,
1235 class_id,
1236 0xfd,
1237 );
1238 assert_eq!(
1239 decision,
1240 XpermsAccessDecision {
1241 allow: xperms_bitmap_from_elements((0xfa..=0xfd).collect::<Vec<_>>().as_slice()),
1242 auditallow: XpermsBitmap::NONE,
1243 auditdeny: XpermsBitmap::ALL,
1244 }
1245 );
1246 let decision = policy.compute_xperms_access_decision(
1247 XpermsKind::Ioctl,
1248 &source_context,
1249 &target_context_matched,
1250 class_id,
1251 0xfe,
1252 );
1253 assert_eq!(decision, XpermsAccessDecision::DENY_ALL);
1254 }
1255
1256 #[test]
1257 fn compute_nlmsg_access_decision_explicitly_allowed() {
1258 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1259 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1260 let policy = policy.validate().expect("validate policy");
1261
1262 let source_context: SecurityContext = policy
1263 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1264 .expect("create source security context");
1265 let target_context_matched: SecurityContext = source_context.clone();
1266
1267 let decision_single = policy.compute_xperms_access_decision(
1285 XpermsKind::Nlmsg,
1286 &source_context,
1287 &target_context_matched,
1288 KernelClass::NetlinkRouteSocket,
1289 0xab,
1290 );
1291
1292 let mut expected_auditdeny =
1293 xperms_bitmap_from_elements((0x0..=0xff).collect::<Vec<_>>().as_slice());
1294 expected_auditdeny -= xperms_bitmap_from_elements(&[0xcd, 0xef]);
1295
1296 let expected_decision_single = XpermsAccessDecision {
1297 allow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
1298 auditallow: xperms_bitmap_from_elements(&[0xcd, 0xef]),
1299 auditdeny: expected_auditdeny,
1300 };
1301 assert_eq!(decision_single, expected_decision_single);
1302
1303 let decision_range = policy.compute_xperms_access_decision(
1304 XpermsKind::Nlmsg,
1305 &source_context,
1306 &target_context_matched,
1307 KernelClass::NetlinkRouteSocket,
1308 0x10,
1309 );
1310 let expected_decision_range = XpermsAccessDecision {
1311 allow: XpermsBitmap::ALL,
1312 auditallow: XpermsBitmap::ALL,
1313 auditdeny: XpermsBitmap::NONE,
1314 };
1315 assert_eq!(decision_range, expected_decision_range);
1316 }
1317
1318 #[test]
1319 fn compute_nlmsg_access_decision_unmatched() {
1320 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1321 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1322 let policy = policy.validate().expect("validate policy");
1323
1324 let source_context: SecurityContext = policy
1325 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1326 .expect("create source security context");
1327
1328 let target_context_unmatched: SecurityContext = policy
1330 .parse_security_context(b"user0:object_r:type1:s0-s0".into())
1331 .expect("create source security context");
1332
1333 for prefix in 0x0..=0xff {
1334 let decision = policy.compute_xperms_access_decision(
1335 XpermsKind::Nlmsg,
1336 &source_context,
1337 &target_context_unmatched,
1338 KernelClass::NetlinkRouteSocket,
1339 prefix,
1340 );
1341 assert_eq!(decision, XpermsAccessDecision::ALLOW_ALL);
1342 }
1343 }
1344
1345 #[test]
1346 fn compute_ioctl_grant_does_not_cause_nlmsg_deny() {
1347 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1348 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1349 let class_id = unvalidated
1350 .0
1351 .classes()
1352 .get_by_name(b"class_ioctl_grant_does_not_cause_nlmsg_deny")
1353 .expect("look up class_ioctl_grant_does_not_cause_nlmsg_deny")
1354 .id();
1355 let policy = unvalidated.validate().expect("validate policy");
1356 let source_context: SecurityContext = policy
1357 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1358 .expect("create source security context");
1359 let target_context_matched: SecurityContext = source_context.clone();
1360
1361 let ioctl_decision = policy.compute_xperms_access_decision(
1365 XpermsKind::Ioctl,
1366 &source_context,
1367 &target_context_matched,
1368 class_id,
1369 0x00,
1370 );
1371 assert_eq!(
1372 ioctl_decision,
1373 XpermsAccessDecision {
1374 allow: xperms_bitmap_from_elements(&[0x0002]),
1375 auditallow: XpermsBitmap::NONE,
1376 auditdeny: XpermsBitmap::ALL,
1377 }
1378 );
1379 let nlmsg_decision = policy.compute_xperms_access_decision(
1380 XpermsKind::Nlmsg,
1381 &source_context,
1382 &target_context_matched,
1383 class_id,
1384 0x00,
1385 );
1386 assert_eq!(nlmsg_decision, XpermsAccessDecision::ALLOW_ALL);
1387 }
1388
1389 #[test]
1390 fn compute_nlmsg_grant_does_not_cause_ioctl_deny() {
1391 let policy_bytes = include_bytes!("../../testdata/micro_policies/allowxperm_policy");
1392 let unvalidated = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1393 let class_id = unvalidated
1394 .0
1395 .classes()
1396 .get_by_name(b"class_nlmsg_grant_does_not_cause_ioctl_deny")
1397 .expect("look up class_nlmsg_grant_does_not_cause_ioctl_deny")
1398 .id();
1399 let policy = unvalidated.validate().expect("validate policy");
1400 let source_context: SecurityContext = policy
1401 .parse_security_context(b"user0:object_r:type0:s0-s0".into())
1402 .expect("create source security context");
1403 let target_context_matched: SecurityContext = source_context.clone();
1404
1405 let nlmsg_decision = policy.compute_xperms_access_decision(
1409 XpermsKind::Nlmsg,
1410 &source_context,
1411 &target_context_matched,
1412 class_id,
1413 0x00,
1414 );
1415 assert_eq!(
1416 nlmsg_decision,
1417 XpermsAccessDecision {
1418 allow: xperms_bitmap_from_elements(&[0x0003]),
1419 auditallow: XpermsBitmap::NONE,
1420 auditdeny: XpermsBitmap::ALL,
1421 }
1422 );
1423 let ioctl_decision = policy.compute_xperms_access_decision(
1424 XpermsKind::Ioctl,
1425 &source_context,
1426 &target_context_matched,
1427 class_id,
1428 0x00,
1429 );
1430 assert_eq!(ioctl_decision, XpermsAccessDecision::ALLOW_ALL);
1431 }
1432
1433 #[test]
1434 fn compute_create_context_minimal() {
1435 let policy_bytes =
1436 include_bytes!("../../testdata/composite_policies/compiled/minimal_policy");
1437 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1438 let policy = policy.validate().expect("validate policy");
1439 let source = policy
1440 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1441 .expect("valid source security context");
1442 let target = policy
1443 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1444 .expect("valid target security context");
1445
1446 let actual = policy.compute_create_context(&source, &target, FileClass::File, &[]);
1447 let expected: SecurityContext = policy
1448 .parse_security_context(b"source_u:object_r:target_t:s0:c0".into())
1449 .expect("valid expected security context");
1450
1451 assert_eq!(expected, actual);
1452 }
1453
1454 #[test]
1455 fn new_security_context_minimal() {
1456 let policy_bytes =
1457 include_bytes!("../../testdata/composite_policies/compiled/minimal_policy");
1458 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1459 let policy = policy.validate().expect("validate policy");
1460 let source = policy
1461 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1462 .expect("valid source security context");
1463 let target = policy
1464 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1465 .expect("valid target security context");
1466
1467 let actual = policy.compute_create_context(&source, &target, KernelClass::Process, &[]);
1468
1469 assert_eq!(source, actual);
1470 }
1471
1472 #[test]
1473 fn compute_create_context_class_defaults() {
1474 let policy_bytes =
1475 include_bytes!("../../testdata/composite_policies/compiled/class_defaults_policy");
1476 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1477 let policy = policy.validate().expect("validate policy");
1478 let source = policy
1479 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1480 .expect("valid source security context");
1481 let target = policy
1482 .parse_security_context(b"target_u:target_r:target_t:s1:c0-s1:c0.c1".into())
1483 .expect("valid target security context");
1484
1485 let actual = policy.compute_create_context(&source, &target, FileClass::File, &[]);
1486 let expected: SecurityContext = policy
1487 .parse_security_context(b"target_u:source_r:source_t:s1:c0-s1:c0.c1".into())
1488 .expect("valid expected security context");
1489
1490 assert_eq!(expected, actual);
1491 }
1492
1493 #[test]
1494 fn new_security_context_class_defaults() {
1495 let policy_bytes =
1496 include_bytes!("../../testdata/composite_policies/compiled/class_defaults_policy");
1497 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1498 let policy = policy.validate().expect("validate policy");
1499 let source = policy
1500 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1501 .expect("valid source security context");
1502 let target = policy
1503 .parse_security_context(b"target_u:target_r:target_t:s1:c0-s1:c0.c1".into())
1504 .expect("valid target security context");
1505
1506 let actual = policy.compute_create_context(&source, &target, KernelClass::Process, &[]);
1507 let expected: SecurityContext = policy
1508 .parse_security_context(b"target_u:source_r:source_t:s1:c0-s1:c0.c1".into())
1509 .expect("valid expected security context");
1510
1511 assert_eq!(expected, actual);
1512 }
1513
1514 #[test]
1515 fn compute_create_context_role_transition() {
1516 let policy_bytes =
1517 include_bytes!("../../testdata/composite_policies/compiled/role_transition_policy");
1518 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1519 let policy = policy.validate().expect("validate policy");
1520 let source = policy
1521 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1522 .expect("valid source security context");
1523 let target = policy
1524 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1525 .expect("valid target security context");
1526
1527 let actual = policy.compute_create_context(&source, &target, FileClass::File, &[]);
1528 let expected: SecurityContext = policy
1529 .parse_security_context(b"source_u:transition_r:target_t:s0:c0".into())
1530 .expect("valid expected security context");
1531
1532 assert_eq!(expected, actual);
1533 }
1534
1535 #[test]
1536 fn new_security_context_role_transition() {
1537 let policy_bytes =
1538 include_bytes!("../../testdata/composite_policies/compiled/role_transition_policy");
1539 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1540 let policy = policy.validate().expect("validate policy");
1541 let source = policy
1542 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1543 .expect("valid source security context");
1544 let target = policy
1545 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1546 .expect("valid target security context");
1547
1548 let actual = policy.compute_create_context(&source, &target, KernelClass::Process, &[]);
1549 let expected: SecurityContext = policy
1550 .parse_security_context(b"source_u:transition_r:source_t:s0:c0-s2:c0.c1".into())
1551 .expect("valid expected security context");
1552
1553 assert_eq!(expected, actual);
1554 }
1555
1556 #[test]
1557 fn compute_create_context_role_transition_not_allowed() {
1558 let policy_bytes = include_bytes!(
1559 "../../testdata/composite_policies/compiled/role_transition_not_allowed_policy"
1560 );
1561 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1562 let policy = policy.validate().expect("validate policy");
1563 let source = policy
1564 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1565 .expect("valid source security context");
1566 let target = policy
1567 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1568 .expect("valid target security context");
1569
1570 let actual = policy.compute_create_context(&source, &target, FileClass::File, &[]);
1571 let expected: SecurityContext = policy
1572 .parse_security_context(b"source_u:transition_r:target_t:s0:c0".into())
1573 .expect("valid expected security context");
1574
1575 assert_eq!(expected, actual);
1578 assert!(policy.validate_security_context(&actual).is_ok());
1579 }
1580
1581 #[test]
1582 fn compute_access_decision_role_allow() {
1583 let policy_bytes =
1585 include_bytes!("../../testdata/composite_policies/compiled/role_transition_policy");
1586 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1587 let policy = policy.validate().expect("validate policy");
1588 let source = policy
1589 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1590 .expect("valid source security context");
1591 let target = policy
1592 .parse_security_context(b"source_u:transition_r:target_t:s0:c0".into())
1593 .expect("valid target security context");
1594
1595 let decision_allowed =
1596 policy.compute_access_decision(&source, &target, KernelClass::Process);
1597 assert_ne!(decision_allowed.allow, AccessVector::NONE);
1598
1599 let policy_bytes = include_bytes!(
1601 "../../testdata/composite_policies/compiled/role_transition_not_allowed_policy"
1602 );
1603 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1604 let policy = policy.validate().expect("validate policy");
1605 let source = policy
1606 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1607 .expect("valid source security context");
1608 let target = policy
1609 .parse_security_context(b"source_u:transition_r:target_t:s0:c0".into())
1610 .expect("valid target security context");
1611
1612 let decision_denied =
1613 policy.compute_access_decision(&source, &target, KernelClass::Process);
1614 assert_eq!(decision_denied.allow, AccessVector::NONE);
1615 }
1616
1617 #[test]
1618 fn compute_create_context_type_transition() {
1619 let policy_bytes =
1620 include_bytes!("../../testdata/composite_policies/compiled/type_transition_policy");
1621 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1622 let policy = policy.validate().expect("validate policy");
1623 let source = policy
1624 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1625 .expect("valid source security context");
1626 let target = policy
1627 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1628 .expect("valid target security context");
1629
1630 let actual = policy.compute_create_context(&source, &target, FileClass::File, &[]);
1631 let expected: SecurityContext = policy
1632 .parse_security_context(b"source_u:object_r:transition_t:s0:c0".into())
1633 .expect("valid expected security context");
1634
1635 assert_eq!(expected, actual);
1636 }
1637
1638 #[test]
1639 fn new_security_context_type_transition() {
1640 let policy_bytes =
1641 include_bytes!("../../testdata/composite_policies/compiled/type_transition_policy");
1642 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1643 let policy = policy.validate().expect("validate policy");
1644 let source = policy
1645 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1646 .expect("valid source security context");
1647 let target = policy
1648 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1649 .expect("valid target security context");
1650
1651 let actual = policy.compute_create_context(&source, &target, KernelClass::Process, &[]);
1652 let expected: SecurityContext = policy
1653 .parse_security_context(b"source_u:source_r:transition_t:s0:c0-s2:c0.c1".into())
1654 .expect("valid expected security context");
1655
1656 assert_eq!(expected, actual);
1657 }
1658
1659 #[test]
1660 fn compute_create_context_range_transition() {
1661 let policy_bytes =
1662 include_bytes!("../../testdata/composite_policies/compiled/range_transition_policy");
1663 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1664 let policy = policy.validate().expect("validate policy");
1665 let source = policy
1666 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1667 .expect("valid source security context");
1668 let target = policy
1669 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1670 .expect("valid target security context");
1671
1672 let actual = policy.compute_create_context(&source, &target, FileClass::File, &[]);
1673 let expected: SecurityContext = policy
1674 .parse_security_context(b"source_u:object_r:target_t:s1:c1-s2:c1.c2".into())
1675 .expect("valid expected security context");
1676
1677 assert_eq!(expected, actual);
1678 }
1679
1680 #[test]
1681 fn new_security_context_range_transition() {
1682 let policy_bytes =
1683 include_bytes!("../../testdata/composite_policies/compiled/range_transition_policy");
1684 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1685 let policy = policy.validate().expect("validate policy");
1686 let source = policy
1687 .parse_security_context(b"source_u:source_r:source_t:s0:c0-s2:c0.c1".into())
1688 .expect("valid source security context");
1689 let target = policy
1690 .parse_security_context(b"target_u:target_r:target_t:s1:c1".into())
1691 .expect("valid target security context");
1692
1693 let actual = policy.compute_create_context(&source, &target, KernelClass::Process, &[]);
1694 let expected: SecurityContext = policy
1695 .parse_security_context(b"source_u:source_r:source_t:s1:c1-s2:c1.c2".into())
1696 .expect("valid expected security context");
1697
1698 assert_eq!(expected, actual);
1699 }
1700
1701 #[test]
1702 fn access_vector_formats() {
1703 assert_eq!(format!("{:x}", AccessVector::NONE), "0");
1704 assert_eq!(format!("{:x}", AccessVector::ALL), "ffffffff");
1705 assert_eq!(format!("{:?}", AccessVector::NONE), "AccessVector(00000000)");
1706 assert_eq!(format!("{:?}", AccessVector::ALL), "AccessVector(ffffffff)");
1707 }
1708
1709 #[test]
1710 fn policy_genfscon_root_path() {
1711 let policy_bytes =
1712 include_bytes!("../../testdata/composite_policies/compiled/genfscon_policy");
1713 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1714 let policy = policy.validate().expect("validate selinux policy");
1715
1716 {
1717 let context = policy.genfscon_label_for_fs_and_path(
1718 "fs_with_path_rules".into(),
1719 "/".into(),
1720 None,
1721 );
1722 assert_eq!(
1723 policy.serialize_security_context(&context.unwrap()),
1724 b"system_u:object_r:fs_with_path_rules_t:s0"
1725 )
1726 }
1727 {
1728 let context = policy.genfscon_label_for_fs_and_path(
1729 "fs_2_with_path_rules".into(),
1730 "/".into(),
1731 None,
1732 );
1733 assert_eq!(
1734 policy.serialize_security_context(&context.unwrap()),
1735 b"system_u:object_r:fs_2_with_path_rules_t:s0"
1736 )
1737 }
1738 }
1739
1740 #[test]
1741 fn policy_genfscon_subpaths() {
1742 let policy_bytes =
1743 include_bytes!("../../testdata/composite_policies/compiled/genfscon_policy");
1744 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1745 let policy = policy.validate().expect("validate selinux policy");
1746
1747 let path_label_expectations = [
1748 ("/a1/", "system_u:object_r:fs_with_path_rules_a1_t:s0"),
1752 ("/a1/b", "system_u:object_r:fs_with_path_rules_a1_t:s0"),
1753 ("/a1/b/c", "system_u:object_r:fs_with_path_rules_a1_b_c_t:s0"),
1754 ("/a2/", "system_u:object_r:fs_with_path_rules_t:s0"),
1757 ("/a2/b/c/d", "system_u:object_r:fs_with_path_rules_a2_b_t:s0"),
1758 ("/a3/b/c/d", "system_u:object_r:fs_with_path_rules_a3_t:s0"),
1761 ];
1762 for (path, expected_label) in path_label_expectations {
1763 let context = policy.genfscon_label_for_fs_and_path(
1764 "fs_with_path_rules".into(),
1765 path.into(),
1766 None,
1767 );
1768 assert_eq!(
1769 policy.serialize_security_context(&context.unwrap()),
1770 expected_label.as_bytes()
1771 )
1772 }
1773 }
1774
1775 #[test]
1776 fn policy_genfscon_mixed_order() {
1777 let policy_bytes =
1778 include_bytes!("../../testdata/composite_policies/compiled/genfscon_policy");
1779 let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1780 let policy = policy.validate().expect("validate selinux policy");
1781
1782 let path_label_expectations = [
1783 ("/", "system_u:object_r:fs_mixed_order_t:s0"),
1784 ("/a", "system_u:object_r:fs_mixed_order_a_t:s0"),
1785 ("/a/a", "system_u:object_r:fs_mixed_order_a_a_t:s0"),
1786 ("/a/b", "system_u:object_r:fs_mixed_order_a_b_t:s0"),
1787 ("/a/b/c", "system_u:object_r:fs_mixed_order_a_b_t:s0"),
1788 ];
1789 for (path, expected_label) in path_label_expectations {
1790 let context =
1791 policy.genfscon_label_for_fs_and_path("fs_mixed_order".into(), path.into(), None);
1792 assert_eq!(
1793 policy.serialize_security_context(&context.unwrap()),
1794 expected_label.as_bytes()
1795 );
1796 }
1797 }
1798}