1use crate::access_vector_cache::{AccessVectorCache, CacheStats, Query};
6use crate::exceptions_config::ExceptionsConfig;
7use crate::permission_check::PermissionCheck;
8use crate::policy::metadata::HandleUnknown;
9use crate::policy::parser::PolicyData;
10
11use crate::policy::{
12 AccessDecision, AccessVector, AccessVectorComputer, ClassId, ClassPermissionId,
13 FsUseLabelAndType, FsUseType, Policy, SecurityContext, XpermsAccessDecision, XpermsKind,
14 parse_policy_by_value,
15};
16use crate::sid_table::SidTable;
17use crate::sync::RwLock;
18use crate::{
19 ClassPermission, FileSystemLabel, FileSystemLabelingScheme, FileSystemMountOptions,
20 FileSystemMountSids, FsNodeClass, InitialSid, KernelClass, KernelPermission, NullessByteStr,
21 ObjectClass, PolicyCap, SeLinuxStatus, SeLinuxStatusPublisher, SecurityId,
22};
23
24use anyhow::Context as _;
25use std::collections::HashMap;
26use std::ops::DerefMut;
27use std::sync::Arc;
28
29const ROOT_PATH: &'static str = "/";
30
31struct ActivePolicy {
32 parsed: Arc<Policy>,
34
35 binary: PolicyData,
37
38 sid_table: SidTable,
40
41 exceptions: ExceptionsConfig,
43}
44
45#[derive(Default)]
46struct SeLinuxBooleans {
47 active: HashMap<String, bool>,
50 pending: HashMap<String, bool>,
52}
53
54impl SeLinuxBooleans {
55 fn reset(&mut self, booleans: Vec<(String, bool)>) {
56 self.active = HashMap::from_iter(booleans);
57 self.pending.clear();
58 }
59 fn names(&self) -> Vec<String> {
60 self.active.keys().cloned().collect()
61 }
62 fn set_pending(&mut self, name: &str, value: bool) -> Result<(), ()> {
63 if !self.active.contains_key(name) {
64 return Err(());
65 }
66 self.pending.insert(name.into(), value);
67 Ok(())
68 }
69 fn get(&self, name: &str) -> Result<(bool, bool), ()> {
70 let active = self.active.get(name).ok_or(())?;
71 let pending = self.pending.get(name).unwrap_or(active);
72 Ok((*active, *pending))
73 }
74 fn commit_pending(&mut self) {
75 self.active.extend(self.pending.drain());
76 }
77}
78
79struct SecurityServerState {
80 active_policy: Option<ActivePolicy>,
82
83 booleans: SeLinuxBooleans,
85
86 status_publisher: Option<Box<dyn SeLinuxStatusPublisher>>,
88
89 enforcing: bool,
91
92 policy_change_count: u32,
96}
97
98impl SecurityServerState {
99 fn deny_unknown(&self) -> bool {
100 self.active_policy
101 .as_ref()
102 .map_or(true, |p| p.parsed.handle_unknown() != HandleUnknown::Allow)
103 }
104 fn reject_unknown(&self) -> bool {
105 self.active_policy
106 .as_ref()
107 .map_or(false, |p| p.parsed.handle_unknown() == HandleUnknown::Reject)
108 }
109
110 fn expect_active_policy(&self) -> &ActivePolicy {
111 &self.active_policy.as_ref().expect("policy should be loaded")
112 }
113
114 fn expect_active_policy_mut(&mut self) -> &mut ActivePolicy {
115 self.active_policy.as_mut().expect("policy should be loaded")
116 }
117}
118
119pub(crate) struct SecurityServerBackend {
120 state: RwLock<SecurityServerState>,
122}
123
124pub struct SecurityServer {
125 access_vector_cache: AccessVectorCache,
128
129 backend: Arc<SecurityServerBackend>,
131
132 exceptions: Vec<String>,
134}
135
136impl SecurityServer {
137 pub fn new_default() -> Arc<Self> {
139 Self::new(String::new(), Vec::new())
140 }
141
142 pub fn new(options: String, exceptions: Vec<String>) -> Arc<Self> {
144 assert_eq!(options, String::new());
146
147 let backend = Arc::new(SecurityServerBackend {
148 state: RwLock::new(SecurityServerState {
149 active_policy: None,
150 booleans: SeLinuxBooleans::default(),
151 status_publisher: None,
152 enforcing: false,
153 policy_change_count: 0,
154 }),
155 });
156
157 let access_vector_cache = AccessVectorCache::new(backend.clone());
158
159 Arc::new(Self { access_vector_cache, backend, exceptions })
160 }
161
162 pub fn as_permission_check<'a>(self: &'a Self) -> PermissionCheck<'a> {
165 PermissionCheck::new(self, &self.access_vector_cache)
166 }
167
168 pub fn security_context_to_sid(
172 &self,
173 security_context: NullessByteStr<'_>,
174 ) -> Result<SecurityId, anyhow::Error> {
175 self.backend.compute_sid(|active_policy| {
176 active_policy
177 .parsed
178 .parse_security_context(security_context)
179 .map_err(anyhow::Error::from)
180 })
181 }
182
183 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
188 let locked_state = self.backend.state.read();
189 let active_policy = locked_state.active_policy.as_ref()?;
190 let context = active_policy.sid_table.try_sid_to_security_context(sid)?;
191 Some(active_policy.parsed.serialize_security_context(context))
192 }
193
194 pub fn sid_to_security_context_with_nul(&self, sid: SecurityId) -> Option<Vec<u8>> {
196 self.sid_to_security_context(sid).map(|mut context| {
197 context.push(0u8);
198 context
199 })
200 }
201
202 pub fn load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
204 let unvalidated_policy = parse_policy_by_value(binary_policy)?;
207 let parsed = Arc::new(unvalidated_policy.validate()?);
208 let binary = parsed.binary().clone();
209
210 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
211 let exceptions = ExceptionsConfig::new(&parsed, &exceptions)?;
212
213 self.with_mut_state_and_update_status(|state| {
215 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
216 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
217 } else {
218 SidTable::new(parsed.clone())
219 };
220
221 state.booleans.reset(
224 parsed
225 .conditional_booleans()
226 .iter()
227 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
229 .collect(),
230 );
231
232 state.active_policy = Some(ActivePolicy { parsed, binary, sid_table, exceptions });
233 state.policy_change_count += 1;
234 });
235
236 self.access_vector_cache.reset();
239
240 Ok(())
241 }
242
243 pub fn get_binary_policy(&self) -> Option<PolicyData> {
245 self.backend.state.read().active_policy.as_ref().map(|p| p.binary.clone())
246 }
247
248 pub fn set_enforcing(&self, enforcing: bool) {
250 self.with_mut_state_and_update_status(|state| state.enforcing = enforcing);
251 }
252
253 pub fn is_enforcing(&self) -> bool {
254 self.backend.state.read().enforcing
255 }
256
257 pub fn deny_unknown(&self) -> bool {
260 self.backend.state.read().deny_unknown()
261 }
262
263 pub fn reject_unknown(&self) -> bool {
266 self.backend.state.read().reject_unknown()
267 }
268
269 pub fn conditional_booleans(&self) -> Vec<String> {
272 self.backend.state.read().booleans.names()
273 }
274
275 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
277 self.backend.state.read().booleans.get(name)
278 }
279
280 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
282 self.backend.state.write().booleans.set_pending(name, value)
283 }
284
285 pub fn commit_pending_booleans(&self) {
287 self.with_mut_state_and_update_status(|state| {
289 state.booleans.commit_pending();
290 state.policy_change_count += 1;
291 });
292 }
293
294 pub fn is_policycap_enabled(&self, policy_cap: PolicyCap) -> bool {
296 let locked_state = self.backend.state.read();
297 let Some(policy) = &locked_state.active_policy else {
298 return false;
299 };
300 policy.parsed.has_policycap(policy_cap)
301 }
302
303 pub fn avc_cache_stats(&self) -> CacheStats {
305 self.access_vector_cache.cache_stats()
306 }
307
308 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
310 let locked_state = self.backend.state.read();
311 let names = locked_state
312 .expect_active_policy()
313 .parsed
314 .classes()
315 .iter()
316 .map(|class| class.class_name.to_vec())
317 .collect();
318 Ok(names)
319 }
320
321 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
323 let locked_state = self.backend.state.read();
324 Ok(locked_state
325 .expect_active_policy()
326 .parsed
327 .classes()
328 .iter()
329 .find(|class| class.class_name == name.as_bytes())
330 .ok_or(())?
331 .class_id)
332 }
333
334 pub fn class_permissions_by_name(
338 &self,
339 name: &str,
340 ) -> Result<Vec<(ClassPermissionId, Vec<u8>)>, ()> {
341 let locked_state = self.backend.state.read();
342 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
343 }
344
345 pub fn resolve_fs_label(
349 &self,
350 fs_type: NullessByteStr<'_>,
351 mount_options: &FileSystemMountOptions,
352 ) -> FileSystemLabel {
353 let mut locked_state = self.backend.state.write();
354 let active_policy = locked_state.expect_active_policy_mut();
355
356 let mount_sids = FileSystemMountSids {
357 context: sid_from_mount_option(active_policy, &mount_options.context),
358 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context),
359 def_context: sid_from_mount_option(active_policy, &mount_options.def_context),
360 root_context: sid_from_mount_option(active_policy, &mount_options.root_context),
361 };
362 if let Some(mountpoint_sid) = mount_sids.context {
363 FileSystemLabel {
367 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
368 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
369 mount_sids,
370 }
371 } else if let Some(FsUseLabelAndType { context, use_type }) =
372 active_policy.parsed.fs_use_label_and_type(fs_type)
373 {
374 let fs_sid_from_policy =
376 active_policy.sid_table.security_context_to_sid(&context).unwrap();
377 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
378 FileSystemLabel {
379 sid: fs_sid,
380 scheme: FileSystemLabelingScheme::FsUse {
381 fs_use_type: use_type,
382 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
383 },
384 mount_sids,
385 }
386 } else if let Some(context) =
387 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
388 {
389 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
391 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
392
393 let fs_type = fs_type.as_bytes();
403 let mut supports_seclabel = matches!(fs_type, b"sysfs" | b"tracefs" | b"pstore");
404 supports_seclabel |= matches!(fs_type, b"cgroup" | b"cgroup2")
405 && active_policy.parsed.has_policycap(PolicyCap::CgroupSeclabel);
406 supports_seclabel |= fs_type == b"functionfs"
407 && active_policy.parsed.has_policycap(PolicyCap::FunctionfsSeclabel);
408
409 FileSystemLabel {
410 sid: fs_sid,
411 scheme: FileSystemLabelingScheme::GenFsCon { supports_seclabel },
412 mount_sids,
413 }
414 } else {
415 FileSystemLabel {
417 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
418 scheme: FileSystemLabelingScheme::FsUse {
419 fs_use_type: FsUseType::Xattr,
420 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
421 },
422 mount_sids,
423 }
424 }
425 }
426
427 pub fn genfscon_label_for_fs_and_path(
432 &self,
433 fs_type: NullessByteStr<'_>,
434 node_path: NullessByteStr<'_>,
435 class_id: Option<KernelClass>,
436 ) -> Result<SecurityId, anyhow::Error> {
437 self.backend.compute_sid(|active_policy| {
438 active_policy
439 .parsed
440 .genfscon_label_for_fs_and_path(fs_type, node_path.into(), class_id)
441 .ok_or_else(|| {
442 anyhow::anyhow!("Genfscon label requested for non-genfscon labeled filesystem")
443 })
444 })
445 }
446
447 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
452 let locked_state = self.backend.state.read();
453 let active_policy = locked_state.expect_active_policy();
454 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
455 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
456 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
457 }
458
459 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
466 self.with_mut_state_and_update_status(|state| {
467 assert!(state.status_publisher.is_none());
468 state.status_publisher = Some(status_holder);
469 });
470 }
471
472 fn with_mut_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
476 let mut locked_state = self.backend.state.write();
477 f(locked_state.deref_mut());
478 let new_value = SeLinuxStatus {
479 is_enforcing: locked_state.enforcing,
480 change_count: locked_state.policy_change_count,
481 deny_unknown: locked_state.deny_unknown(),
482 };
483 if let Some(status_publisher) = &mut locked_state.status_publisher {
484 status_publisher.set_status(new_value);
485 }
486 }
487
488 pub fn compute_create_sid(
493 &self,
494 source_sid: SecurityId,
495 target_sid: SecurityId,
496 target_class: ObjectClass,
497 ) -> Result<SecurityId, anyhow::Error> {
498 self.backend.compute_create_sid(source_sid, target_sid, target_class)
499 }
500}
501
502impl SecurityServerBackend {
503 fn compute_create_sid(
504 &self,
505 source_sid: SecurityId,
506 target_sid: SecurityId,
507 target_class: ObjectClass,
508 ) -> Result<SecurityId, anyhow::Error> {
509 self.compute_sid(|active_policy| {
510 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
511 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
512
513 Ok(active_policy.parsed.compute_create_context(
514 source_context,
515 target_context,
516 target_class,
517 ))
518 })
519 .context("computing new security context from policy")
520 }
521
522 fn compute_sid(
524 &self,
525 compute_context: impl Fn(&ActivePolicy) -> Result<SecurityContext, anyhow::Error>,
526 ) -> Result<SecurityId, anyhow::Error> {
527 let readable_state = self.state.read();
530 let policy_change_count = readable_state.policy_change_count;
531 let policy_state = readable_state
532 .active_policy
533 .as_ref()
534 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
535 let context = compute_context(policy_state)?;
536 if let Some(sid) = policy_state.sid_table.security_context_to_existing_sid(&context) {
537 return Ok(sid);
538 }
539 std::mem::drop(readable_state);
540
541 let mut writable_state = self.state.write();
546 let needs_recompute = policy_change_count != writable_state.policy_change_count;
547 let policy_state = writable_state.active_policy.as_mut().unwrap();
548 let context = if needs_recompute { compute_context(policy_state)? } else { context };
549 policy_state.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
550 }
551}
552
553impl Query for SecurityServerBackend {
554 fn compute_access_decision(
555 &self,
556 source_sid: SecurityId,
557 target_sid: SecurityId,
558 target_class: ObjectClass,
559 ) -> AccessDecision {
560 let locked_state = self.state.read();
561
562 let active_policy = match &locked_state.active_policy {
563 Some(active_policy) => active_policy,
564 None => return AccessDecision::allow(AccessVector::ALL),
566 };
567
568 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
569 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
570
571 let mut decision = active_policy.parsed.compute_access_decision(
572 &source_context,
573 &target_context,
574 target_class,
575 );
576
577 decision.todo_bug = active_policy.exceptions.lookup(
578 source_context.type_(),
579 target_context.type_(),
580 target_class,
581 );
582
583 decision
584 }
585
586 fn compute_create_sid(
587 &self,
588 source_sid: SecurityId,
589 target_sid: SecurityId,
590 target_class: ObjectClass,
591 ) -> Result<SecurityId, anyhow::Error> {
592 self.compute_create_sid(source_sid, target_sid, target_class)
593 }
594
595 fn compute_new_fs_node_sid_with_name(
596 &self,
597 source_sid: SecurityId,
598 target_sid: SecurityId,
599 fs_node_class: FsNodeClass,
600 fs_node_name: NullessByteStr<'_>,
601 ) -> Option<SecurityId> {
602 let mut locked_state = self.state.write();
603
604 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
606
607 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
608 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
609
610 let new_file_context = active_policy.parsed.compute_create_context_with_name(
611 source_context,
612 target_context,
613 fs_node_class,
614 fs_node_name,
615 )?;
616
617 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
618 }
619
620 fn compute_xperms_access_decision(
621 &self,
622 xperms_kind: XpermsKind,
623 source_sid: SecurityId,
624 target_sid: SecurityId,
625 target_class: ObjectClass,
626 xperms_prefix: u8,
627 ) -> XpermsAccessDecision {
628 let locked_state = self.state.read();
629
630 let active_policy = match &locked_state.active_policy {
631 Some(active_policy) => active_policy,
632 None => return XpermsAccessDecision::ALLOW_ALL,
634 };
635
636 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
637 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
638
639 active_policy.parsed.compute_xperms_access_decision(
640 xperms_kind,
641 &source_context,
642 &target_context,
643 target_class,
644 xperms_prefix,
645 )
646 }
647}
648
649impl AccessVectorComputer for SecurityServer {
650 fn kernel_permissions_to_access_vector<
651 P: ClassPermission + Into<KernelPermission> + Clone + 'static,
652 >(
653 &self,
654 permissions: &[P],
655 ) -> Option<AccessVector> {
656 match &self.backend.state.read().active_policy {
657 Some(policy) => policy.parsed.kernel_permissions_to_access_vector(permissions),
658 None => Some(AccessVector::NONE),
659 }
660 }
661}
662
663fn sid_from_mount_option(
666 active_policy: &mut ActivePolicy,
667 mount_option: &Option<Vec<u8>>,
668) -> Option<SecurityId> {
669 if let Some(label) = mount_option.as_ref() {
670 Some(
671 if let Some(context) = active_policy.parsed.parse_security_context(label.into()).ok() {
672 active_policy.sid_table.security_context_to_sid(&context).unwrap()
673 } else {
674 InitialSid::Unlabeled.into()
676 },
677 )
678 } else {
679 None
680 }
681}
682
683#[cfg(test)]
684mod tests {
685 use super::*;
686 use crate::permission_check::PermissionCheckResult;
687 use crate::{
688 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
689 ProcessPermission,
690 };
691 use std::num::NonZeroU64;
692
693 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
694 const TESTS_BINARY_POLICY: &[u8] =
695 include_bytes!("../testdata/micro_policies/security_server_tests_policy.pp");
696 const MINIMAL_BINARY_POLICY: &[u8] =
697 include_bytes!("../testdata/composite_policies/compiled/minimal_policy.pp");
698
699 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
700 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
701 let security_server = SecurityServer::new_default();
702 assert_eq!(
703 Ok(()),
704 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
705 );
706 security_server
707 }
708
709 #[test]
710 fn compute_access_vector_allows_all() {
711 let security_server = SecurityServer::new_default();
712 let sid1 = InitialSid::Kernel.into();
713 let sid2 = InitialSid::Unlabeled.into();
714 assert_eq!(
715 security_server
716 .backend
717 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
718 .allow,
719 AccessVector::ALL
720 );
721 }
722
723 #[test]
724 fn loaded_policy_can_be_retrieved() {
725 let security_server = security_server_with_tests_policy();
726 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_slice());
727 }
728
729 #[test]
730 fn loaded_policy_is_validated() {
731 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
732 let security_server = SecurityServer::new_default();
733 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
734 }
735
736 #[test]
737 fn enforcing_mode_is_reported() {
738 let security_server = SecurityServer::new_default();
739 assert!(!security_server.is_enforcing());
740
741 security_server.set_enforcing(true);
742 assert!(security_server.is_enforcing());
743 }
744
745 #[test]
746 fn without_policy_conditional_booleans_are_empty() {
747 let security_server = SecurityServer::new_default();
748 assert!(security_server.conditional_booleans().is_empty());
749 }
750
751 #[test]
752 fn conditional_booleans_can_be_queried() {
753 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
754 let security_server = SecurityServer::new_default();
755 assert_eq!(
756 Ok(()),
757 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
758 );
759
760 let booleans = security_server.conditional_booleans();
761 assert!(!booleans.is_empty());
762 let boolean = booleans[0].as_str();
763
764 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
765 assert!(security_server.get_boolean(boolean).is_ok());
766 }
767
768 #[test]
769 fn conditional_booleans_can_be_changed() {
770 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
771 let security_server = SecurityServer::new_default();
772 assert_eq!(
773 Ok(()),
774 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
775 );
776
777 let booleans = security_server.conditional_booleans();
778 assert!(!booleans.is_empty());
779 let boolean = booleans[0].as_str();
780
781 let (active, pending) = security_server.get_boolean(boolean).unwrap();
782 assert_eq!(active, pending, "Initially active and pending values should match");
783
784 security_server.set_pending_boolean(boolean, !active).unwrap();
785 let (active, pending) = security_server.get_boolean(boolean).unwrap();
786 assert!(active != pending, "Before commit pending should differ from active");
787
788 security_server.commit_pending_booleans();
789 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
790 assert_eq!(final_active, pending, "Pending value should be active after commit");
791 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
792 }
793
794 #[test]
795 fn parse_security_context_no_policy() {
796 let security_server = SecurityServer::new_default();
797 let error = security_server
798 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
799 .expect_err("expected error");
800 let error_string = format!("{:?}", error);
801 assert!(error_string.contains("no policy"));
802 }
803
804 #[test]
805 fn compute_new_fs_node_sid_no_defaults() {
806 let security_server = SecurityServer::new_default();
807 let policy_bytes =
808 include_bytes!("../testdata/micro_policies/file_no_defaults_policy.pp").to_vec();
809 security_server.load_policy(policy_bytes).expect("binary policy loads");
810
811 let source_sid = security_server
812 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
813 .expect("creating SID from security context should succeed");
814 let target_sid = security_server
815 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
816 .expect("creating SID from security context should succeed");
817
818 let computed_sid = security_server
819 .as_permission_check()
820 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
821 .expect("new sid computed");
822 let computed_context = security_server
823 .sid_to_security_context(computed_sid)
824 .expect("computed sid associated with context");
825
826 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
829 }
830
831 #[test]
832 fn compute_new_fs_node_sid_source_defaults() {
833 let security_server = SecurityServer::new_default();
834 let policy_bytes =
835 include_bytes!("../testdata/micro_policies/file_source_defaults_policy.pp").to_vec();
836 security_server.load_policy(policy_bytes).expect("binary policy loads");
837
838 let source_sid = security_server
839 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
840 .expect("creating SID from security context should succeed");
841 let target_sid = security_server
842 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
843 .expect("creating SID from security context should succeed");
844
845 let computed_sid = security_server
846 .as_permission_check()
847 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
848 .expect("new sid computed");
849 let computed_context = security_server
850 .sid_to_security_context(computed_sid)
851 .expect("computed sid associated with context");
852
853 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
856 }
857
858 #[test]
859 fn compute_new_fs_node_sid_target_defaults() {
860 let security_server = SecurityServer::new_default();
861 let policy_bytes =
862 include_bytes!("../testdata/micro_policies/file_target_defaults_policy.pp").to_vec();
863 security_server.load_policy(policy_bytes).expect("binary policy loads");
864
865 let source_sid = security_server
866 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
867 .expect("creating SID from security context should succeed");
868 let target_sid = security_server
869 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
870 .expect("creating SID from security context should succeed");
871
872 let computed_sid = security_server
873 .as_permission_check()
874 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
875 .expect("new sid computed");
876 let computed_context = security_server
877 .sid_to_security_context(computed_sid)
878 .expect("computed sid associated with context");
879
880 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
882 }
883
884 #[test]
885 fn compute_new_fs_node_sid_range_source_low_default() {
886 let security_server = SecurityServer::new_default();
887 let policy_bytes =
888 include_bytes!("../testdata/micro_policies/file_range_source_low_policy.pp").to_vec();
889 security_server.load_policy(policy_bytes).expect("binary policy loads");
890
891 let source_sid = security_server
892 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
893 .expect("creating SID from security context should succeed");
894 let target_sid = security_server
895 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
896 .expect("creating SID from security context should succeed");
897
898 let computed_sid = security_server
899 .as_permission_check()
900 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
901 .expect("new sid computed");
902 let computed_context = security_server
903 .sid_to_security_context(computed_sid)
904 .expect("computed sid associated with context");
905
906 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
908 }
909
910 #[test]
911 fn compute_new_fs_node_sid_range_source_low_high_default() {
912 let security_server = SecurityServer::new_default();
913 let policy_bytes =
914 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy.pp")
915 .to_vec();
916 security_server.load_policy(policy_bytes).expect("binary policy loads");
917
918 let source_sid = security_server
919 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
920 .expect("creating SID from security context should succeed");
921 let target_sid = security_server
922 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
923 .expect("creating SID from security context should succeed");
924
925 let computed_sid = security_server
926 .as_permission_check()
927 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
928 .expect("new sid computed");
929 let computed_context = security_server
930 .sid_to_security_context(computed_sid)
931 .expect("computed sid associated with context");
932
933 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
935 }
936
937 #[test]
938 fn compute_new_fs_node_sid_range_source_high_default() {
939 let security_server = SecurityServer::new_default();
940 let policy_bytes =
941 include_bytes!("../testdata/micro_policies/file_range_source_high_policy.pp").to_vec();
942 security_server.load_policy(policy_bytes).expect("binary policy loads");
943
944 let source_sid = security_server
945 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
946 .expect("creating SID from security context should succeed");
947 let target_sid = security_server
948 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
949 .expect("creating SID from security context should succeed");
950
951 let computed_sid = security_server
952 .as_permission_check()
953 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
954 .expect("new sid computed");
955 let computed_context = security_server
956 .sid_to_security_context(computed_sid)
957 .expect("computed sid associated with context");
958
959 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
961 }
962
963 #[test]
964 fn compute_new_fs_node_sid_range_target_low_default() {
965 let security_server = SecurityServer::new_default();
966 let policy_bytes =
967 include_bytes!("../testdata/micro_policies/file_range_target_low_policy.pp").to_vec();
968 security_server.load_policy(policy_bytes).expect("binary policy loads");
969
970 let source_sid = security_server
971 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
972 .expect("creating SID from security context should succeed");
973 let target_sid = security_server
974 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
975 .expect("creating SID from security context should succeed");
976
977 let computed_sid = security_server
978 .as_permission_check()
979 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
980 .expect("new sid computed");
981 let computed_context = security_server
982 .sid_to_security_context(computed_sid)
983 .expect("computed sid associated with context");
984
985 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
987 }
988
989 #[test]
990 fn compute_new_fs_node_sid_range_target_low_high_default() {
991 let security_server = SecurityServer::new_default();
992 let policy_bytes =
993 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy.pp")
994 .to_vec();
995 security_server.load_policy(policy_bytes).expect("binary policy loads");
996
997 let source_sid = security_server
998 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
999 .expect("creating SID from security context should succeed");
1000 let target_sid = security_server
1001 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1002 .expect("creating SID from security context should succeed");
1003
1004 let computed_sid = security_server
1005 .as_permission_check()
1006 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1007 .expect("new sid computed");
1008 let computed_context = security_server
1009 .sid_to_security_context(computed_sid)
1010 .expect("computed sid associated with context");
1011
1012 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1014 }
1015
1016 #[test]
1017 fn compute_new_fs_node_sid_range_target_high_default() {
1018 let security_server = SecurityServer::new_default();
1019 let policy_bytes =
1020 include_bytes!("../testdata/micro_policies/file_range_target_high_policy.pp").to_vec();
1021 security_server.load_policy(policy_bytes).expect("binary policy loads");
1022
1023 let source_sid = security_server
1024 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1025 .expect("creating SID from security context should succeed");
1026 let target_sid = security_server
1027 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1028 .expect("creating SID from security context should succeed");
1029
1030 let computed_sid = security_server
1031 .as_permission_check()
1032 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1033 .expect("new sid computed");
1034 let computed_context = security_server
1035 .sid_to_security_context(computed_sid)
1036 .expect("computed sid associated with context");
1037
1038 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1040 }
1041
1042 #[test]
1043 fn compute_new_fs_node_sid_with_name() {
1044 let security_server = SecurityServer::new_default();
1045 let policy_bytes =
1046 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy.pp")
1047 .to_vec();
1048 security_server.load_policy(policy_bytes).expect("binary policy loads");
1049
1050 let source_sid = security_server
1051 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1052 .expect("creating SID from security context should succeed");
1053 let target_sid = security_server
1054 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1055 .expect("creating SID from security context should succeed");
1056
1057 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1058 let computed_sid = security_server
1059 .as_permission_check()
1060 .compute_new_fs_node_sid(
1061 source_sid,
1062 target_sid,
1063 FileClass::File.into(),
1064 SPECIAL_FILE_NAME.into(),
1065 )
1066 .expect("new sid computed");
1067 let computed_context = security_server
1068 .sid_to_security_context(computed_sid)
1069 .expect("computed sid associated with context");
1070
1071 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1073
1074 let computed_sid = security_server
1075 .as_permission_check()
1076 .compute_new_fs_node_sid(
1077 source_sid,
1078 target_sid,
1079 FileClass::Character.into(),
1080 SPECIAL_FILE_NAME.into(),
1081 )
1082 .expect("new sid computed");
1083 let computed_context = security_server
1084 .sid_to_security_context(computed_sid)
1085 .expect("computed sid associated with context");
1086
1087 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1090
1091 const OTHER_FILE_NAME: &[u8] = b"other_file";
1092 let computed_sid = security_server
1093 .as_permission_check()
1094 .compute_new_fs_node_sid(
1095 source_sid,
1096 target_sid,
1097 FileClass::File.into(),
1098 OTHER_FILE_NAME.into(),
1099 )
1100 .expect("new sid computed");
1101 let computed_context = security_server
1102 .sid_to_security_context(computed_sid)
1103 .expect("computed sid associated with context");
1104
1105 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1108 }
1109
1110 #[test]
1111 fn permissions_are_fresh_after_different_policy_load() {
1112 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1113 let allow_fork_bytes =
1114 include_bytes!("../testdata/composite_policies/compiled/allow_fork.pp").to_vec();
1115 let context = b"source_u:object_r:source_t:s0:c0";
1116
1117 let security_server = SecurityServer::new_default();
1118 security_server.set_enforcing(true);
1119
1120 let permission_check = security_server.as_permission_check();
1121
1122 assert_eq!(
1124 Ok(()),
1125 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1126 );
1127 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1128
1129 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1131
1132 assert_eq!(
1134 Ok(()),
1135 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1136 );
1137
1138 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1140 }
1141
1142 #[test]
1143 fn unknown_sids_are_effectively_unlabeled() {
1144 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1145 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy.pp"
1146 )
1147 .to_vec();
1148 let with_additional_domain_policy_bytes = include_bytes!(
1149 "../testdata/composite_policies/compiled/with_additional_domain_policy.pp"
1150 )
1151 .to_vec();
1152 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1153 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1154
1155 let security_server = SecurityServer::new_default();
1156 security_server.set_enforcing(true);
1157
1158 assert_eq!(
1161 Ok(()),
1162 security_server
1163 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1164 .map_err(|e| format!("{:?}", e))
1165 );
1166 let allowed_type_sid =
1167 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1168 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1169
1170 assert_eq!(
1173 Ok(()),
1174 security_server
1175 .load_policy(with_additional_domain_policy_bytes.clone())
1176 .map_err(|e| format!("{:?}", e))
1177 );
1178 let additional_type_sid =
1179 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1180 assert_eq!(
1181 allowed_type_sid,
1182 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1183 );
1184
1185 let permission_check = security_server.as_permission_check();
1186
1187 assert!(
1191 !permission_check
1192 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1193 .permit
1194 );
1195 assert!(
1196 !permission_check
1197 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1198 .permit
1199 );
1200 assert!(
1201 !permission_check
1202 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1203 .permit
1204 );
1205 assert!(
1206 !permission_check
1207 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1208 .permit
1209 );
1210
1211 assert_eq!(
1213 Ok(()),
1214 security_server
1215 .load_policy(with_unlabeled_access_domain_policy_bytes)
1216 .map_err(|e| format!("{:?}", e))
1217 );
1218
1219 assert!(
1223 permission_check
1224 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1225 .permit
1226 );
1227 assert!(
1228 !permission_check
1229 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1230 .permit
1231 );
1232
1233 assert!(
1238 !permission_check
1239 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1240 .permit
1241 );
1242 assert!(
1243 permission_check
1244 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1245 .permit
1246 );
1247
1248 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1250
1251 assert_eq!(
1254 Ok(()),
1255 security_server
1256 .load_policy(with_additional_domain_policy_bytes)
1257 .map_err(|e| format!("{:?}", e))
1258 );
1259 assert_eq!(
1260 additional_type_context.to_vec(),
1261 security_server.sid_to_security_context(additional_type_sid).unwrap()
1262 );
1263 }
1264
1265 #[test]
1266 fn permission_check_permissive() {
1267 let security_server = security_server_with_tests_policy();
1268 security_server.set_enforcing(false);
1269 assert!(!security_server.is_enforcing());
1270
1271 let sid =
1272 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1273 let permission_check = security_server.as_permission_check();
1274
1275 assert_eq!(
1278 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1279 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1280 );
1281
1282 assert_eq!(
1286 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1287 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1288 );
1289
1290 assert_eq!(
1294 permission_check.has_permission(
1295 sid,
1296 sid,
1297 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1298 ),
1299 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1300 );
1301 }
1302
1303 #[test]
1304 fn permission_check_enforcing() {
1305 let security_server = security_server_with_tests_policy();
1306 security_server.set_enforcing(true);
1307 assert!(security_server.is_enforcing());
1308
1309 let sid =
1310 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1311 let permission_check = security_server.as_permission_check();
1312
1313 assert_eq!(
1315 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1316 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1317 );
1318
1319 assert_eq!(
1322 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1323 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1324 );
1325
1326 assert_eq!(
1329 permission_check.has_permission(
1330 sid,
1331 sid,
1332 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1333 ),
1334 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1335 );
1336 }
1337
1338 #[test]
1339 fn permissive_domain() {
1340 let security_server = security_server_with_tests_policy();
1341 security_server.set_enforcing(true);
1342 assert!(security_server.is_enforcing());
1343
1344 let permissive_sid = security_server
1345 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1346 .unwrap();
1347 let non_permissive_sid = security_server
1348 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1349 .unwrap();
1350
1351 let permission_check = security_server.as_permission_check();
1352
1353 assert_eq!(
1355 permission_check.has_permission(
1356 permissive_sid,
1357 permissive_sid,
1358 ProcessPermission::GetSched
1359 ),
1360 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1361 );
1362 assert_eq!(
1363 permission_check.has_permission(
1364 non_permissive_sid,
1365 non_permissive_sid,
1366 ProcessPermission::GetSched
1367 ),
1368 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1369 );
1370
1371 assert_eq!(
1374 permission_check.has_permission(
1375 permissive_sid,
1376 non_permissive_sid,
1377 ProcessPermission::GetSched
1378 ),
1379 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1380 );
1381 assert_eq!(
1382 permission_check.has_permission(
1383 non_permissive_sid,
1384 permissive_sid,
1385 ProcessPermission::GetSched
1386 ),
1387 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1388 );
1389
1390 assert_eq!(
1395 permission_check.has_permission(
1396 permissive_sid,
1397 non_permissive_sid,
1398 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1399 ),
1400 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1401 );
1402 assert_eq!(
1403 permission_check.has_permission(
1404 non_permissive_sid,
1405 non_permissive_sid,
1406 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1407 ),
1408 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1409 );
1410 }
1411
1412 #[test]
1413 fn auditallow_and_dontaudit() {
1414 let security_server = security_server_with_tests_policy();
1415 security_server.set_enforcing(true);
1416 assert!(security_server.is_enforcing());
1417
1418 let audit_sid = security_server
1419 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1420 .unwrap();
1421
1422 let permission_check = security_server.as_permission_check();
1423
1424 assert_eq!(
1426 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork),
1427 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1428 );
1429
1430 assert_eq!(
1432 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched),
1433 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1434 );
1435
1436 assert_eq!(
1438 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched),
1439 PermissionCheckResult { permit: false, audit: false, todo_bug: None }
1440 );
1441
1442 assert_eq!(
1444 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid),
1445 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1446 );
1447 }
1448
1449 #[test]
1450 fn access_checks_with_exceptions_config() {
1451 const EXCEPTIONS_CONFIG: &[&str] = &[
1452 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1454 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1455 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1456 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1457 "todo_permissive b/005 test_exception_todo_permissive_t",
1458 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1460 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1461 "todo_permissive b/103 test_undefined_source_t",
1462 ];
1463 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1464 let security_server = SecurityServer::new(String::new(), exceptions_config);
1465 security_server.set_enforcing(true);
1466
1467 const EXCEPTIONS_POLICY: &[u8] =
1468 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1469 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1470
1471 let source_sid = security_server
1472 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1473 .unwrap();
1474 let target_sid = security_server
1475 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1476 .unwrap();
1477 let other_sid = security_server
1478 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1479 .unwrap();
1480 let permissive_sid = security_server
1481 .security_context_to_sid(
1482 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1483 )
1484 .unwrap();
1485 let unmatched_sid = security_server
1486 .security_context_to_sid(
1487 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1488 )
1489 .unwrap();
1490 let todo_permissive_sid = security_server
1491 .security_context_to_sid(
1492 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1493 )
1494 .unwrap();
1495
1496 let permission_check = security_server.as_permission_check();
1497
1498 assert_eq!(
1500 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid),
1501 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1502 );
1503
1504 assert_eq!(
1506 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint),
1507 PermissionCheckResult {
1508 permit: true,
1509 audit: true,
1510 todo_bug: Some(NonZeroU64::new(1).unwrap())
1511 }
1512 );
1513
1514 assert_eq!(
1516 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans),
1517 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1518 );
1519
1520 assert_eq!(
1522 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint),
1523 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1524 );
1525
1526 assert_eq!(
1528 permission_check.has_permission(
1529 other_sid,
1530 target_sid,
1531 CommonFsNodePermission::Read.for_class(FileClass::Character)
1532 ),
1533 PermissionCheckResult {
1534 permit: true,
1535 audit: true,
1536 todo_bug: Some(NonZeroU64::new(2).unwrap())
1537 }
1538 );
1539
1540 assert_eq!(
1542 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint),
1543 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1544 );
1545
1546 assert_eq!(
1548 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint),
1549 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1550 );
1551
1552 assert_eq!(
1554 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint),
1555 PermissionCheckResult {
1556 permit: true,
1557 audit: true,
1558 todo_bug: Some(NonZeroU64::new(4).unwrap())
1559 }
1560 );
1561
1562 assert_eq!(
1565 permission_check.has_permission(
1566 todo_permissive_sid,
1567 target_sid,
1568 FilePermission::Entrypoint
1569 ),
1570 PermissionCheckResult {
1571 permit: true,
1572 audit: true,
1573 todo_bug: Some(NonZeroU64::new(5).unwrap())
1574 }
1575 );
1576 assert_eq!(
1577 permission_check.has_permission(
1578 todo_permissive_sid,
1579 todo_permissive_sid,
1580 FilePermission::Entrypoint
1581 ),
1582 PermissionCheckResult {
1583 permit: true,
1584 audit: true,
1585 todo_bug: Some(NonZeroU64::new(5).unwrap())
1586 }
1587 );
1588 assert_eq!(
1589 permission_check.has_permission(
1590 todo_permissive_sid,
1591 target_sid,
1592 FilePermission::Entrypoint
1593 ),
1594 PermissionCheckResult {
1595 permit: true,
1596 audit: true,
1597 todo_bug: Some(NonZeroU64::new(5).unwrap())
1598 }
1599 );
1600 }
1601
1602 #[test]
1603 fn handle_unknown() {
1604 let security_server = security_server_with_tests_policy();
1605
1606 let sid = security_server
1607 .security_context_to_sid("user0:object_r:type0:s0".into())
1608 .expect("Resolve Context to SID");
1609
1610 const REJECT_POLICY: &[u8] = include_bytes!(
1614 "../testdata/composite_policies/compiled/handle_unknown_policy-reject.pp"
1615 );
1616 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1617
1618 security_server.set_enforcing(true);
1619
1620 const DENY_POLICY: &[u8] =
1622 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny.pp");
1623 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1624 let permission_check = security_server.as_permission_check();
1625
1626 assert_eq!(
1628 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1629 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1630 );
1631 assert_eq!(
1632 permission_check.has_permission(sid, sid, DirPermission::AddName),
1633 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1634 );
1635
1636 assert_eq!(
1638 permission_check.has_permission(sid, sid, DirPermission::Search),
1639 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1640 );
1641 assert_eq!(
1642 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1643 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1644 );
1645
1646 const ALLOW_POLICY: &[u8] = include_bytes!(
1648 "../testdata/composite_policies/compiled/handle_unknown_policy-allow.pp"
1649 );
1650 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1651 let permission_check = security_server.as_permission_check();
1652
1653 assert_eq!(
1655 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1656 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1657 );
1658 assert_eq!(
1659 permission_check.has_permission(sid, sid, DirPermission::AddName),
1660 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1661 );
1662
1663 assert_eq!(
1665 permission_check.has_permission(sid, sid, DirPermission::Search),
1666 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1667 );
1668 assert_eq!(
1669 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1670 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1671 );
1672 }
1673}