1use crate::access_vector_cache::{
6 CacheStats, HasCacheStats, Manager as AvcManager, Query, QueryMut, Reset,
7};
8use crate::exceptions_config::ExceptionsConfig;
9use crate::permission_check::PermissionCheck;
10use crate::policy::metadata::HandleUnknown;
11use crate::policy::parser::ByValue;
12use crate::policy::{
13 parse_policy_by_value, AccessDecision, AccessVector, AccessVectorComputer, ClassId,
14 ClassPermissionId, FsUseLabelAndType, FsUseType, IoctlAccessDecision, Policy,
15};
16use crate::sid_table::SidTable;
17use crate::sync::Mutex;
18use crate::{
19 AbstractObjectClass, ClassPermission, FileSystemLabel, FileSystemLabelingScheme,
20 FileSystemMountOptions, FsNodeClass, InitialSid, NullessByteStr, ObjectClass, Permission,
21 SeLinuxStatus, SeLinuxStatusPublisher, SecurityId,
22};
23
24use crate::FileSystemMountSids;
25use anyhow::Context as _;
26use std::collections::HashMap;
27use std::ops::DerefMut;
28use std::sync::Arc;
29
30const ROOT_PATH: &'static str = "/";
31
32struct ActivePolicy {
33 parsed: Arc<Policy<ByValue<Vec<u8>>>>,
35
36 binary: Vec<u8>,
38
39 sid_table: SidTable,
41
42 exceptions: ExceptionsConfig,
44}
45
46#[derive(Default)]
47struct SeLinuxBooleans {
48 active: HashMap<String, bool>,
51 pending: HashMap<String, bool>,
53}
54
55impl SeLinuxBooleans {
56 fn reset(&mut self, booleans: Vec<(String, bool)>) {
57 self.active = HashMap::from_iter(booleans);
58 self.pending.clear();
59 }
60 fn names(&self) -> Vec<String> {
61 self.active.keys().cloned().collect()
62 }
63 fn set_pending(&mut self, name: &str, value: bool) -> Result<(), ()> {
64 if !self.active.contains_key(name) {
65 return Err(());
66 }
67 self.pending.insert(name.into(), value);
68 Ok(())
69 }
70 fn get(&self, name: &str) -> Result<(bool, bool), ()> {
71 let active = self.active.get(name).ok_or(())?;
72 let pending = self.pending.get(name).unwrap_or(active);
73 Ok((*active, *pending))
74 }
75 fn commit_pending(&mut self) {
76 self.active.extend(self.pending.drain());
77 }
78}
79
80struct SecurityServerState {
81 active_policy: Option<ActivePolicy>,
83
84 booleans: SeLinuxBooleans,
86
87 status_publisher: Option<Box<dyn SeLinuxStatusPublisher>>,
89
90 enforcing: bool,
92
93 policy_change_count: u32,
97}
98
99impl SecurityServerState {
100 fn deny_unknown(&self) -> bool {
101 self.active_policy
102 .as_ref()
103 .map_or(true, |p| p.parsed.handle_unknown() != HandleUnknown::Allow)
104 }
105 fn reject_unknown(&self) -> bool {
106 self.active_policy
107 .as_ref()
108 .map_or(false, |p| p.parsed.handle_unknown() == HandleUnknown::Reject)
109 }
110
111 fn expect_active_policy(&self) -> &ActivePolicy {
112 &self.active_policy.as_ref().expect("policy should be loaded")
113 }
114
115 fn expect_active_policy_mut(&mut self) -> &mut ActivePolicy {
116 self.active_policy.as_mut().expect("policy should be loaded")
117 }
118}
119
120pub struct SecurityServer {
121 avc_manager: AvcManager<SecurityServer>,
126
127 state: Mutex<SecurityServerState>,
129
130 exceptions_config: String,
132}
133
134impl SecurityServer {
135 pub fn new() -> Arc<Self> {
136 Self::new_with_exceptions(String::new())
137 }
138
139 pub fn new_with_exceptions(exceptions_config: String) -> Arc<Self> {
140 let avc_manager = AvcManager::new();
141 let state = Mutex::new(SecurityServerState {
142 active_policy: None,
143 booleans: SeLinuxBooleans::default(),
144 status_publisher: None,
145 enforcing: false,
146 policy_change_count: 0,
147 });
148
149 let security_server = Arc::new(Self { avc_manager, state, exceptions_config });
150
151 security_server.as_ref().avc_manager.set_security_server(Arc::downgrade(&security_server));
154
155 security_server
156 }
157
158 pub fn as_permission_check<'a>(self: &'a Self) -> PermissionCheck<'a> {
161 PermissionCheck::new(self, self.avc_manager.get_shared_cache())
162 }
163
164 pub fn security_context_to_sid(
168 &self,
169 security_context: NullessByteStr<'_>,
170 ) -> Result<SecurityId, anyhow::Error> {
171 let mut locked_state = self.state.lock();
172 let active_policy = locked_state
173 .active_policy
174 .as_mut()
175 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
176 let context = active_policy
177 .parsed
178 .parse_security_context(security_context)
179 .map_err(anyhow::Error::from)?;
180 active_policy.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
181 }
182
183 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
188 let locked_state = self.state.lock();
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 load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
196 let (parsed, binary) = parse_policy_by_value(binary_policy)?;
199 let parsed = Arc::new(parsed.validate()?);
200
201 let exceptions = ExceptionsConfig::new(&parsed, &self.exceptions_config)?;
202
203 self.with_state_and_update_status(|state| {
205 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
206 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
207 } else {
208 SidTable::new(parsed.clone())
209 };
210
211 state.booleans.reset(
214 parsed
215 .conditional_booleans()
216 .iter()
217 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
219 .collect(),
220 );
221
222 state.active_policy = Some(ActivePolicy { parsed, binary, sid_table, exceptions });
223 state.policy_change_count += 1;
224 });
225
226 self.avc_manager.reset();
229
230 Ok(())
231 }
232
233 pub fn get_binary_policy(&self) -> Vec<u8> {
235 self.state.lock().active_policy.as_ref().map_or(Vec::new(), |p| p.binary.clone())
236 }
237
238 pub fn has_policy(&self) -> bool {
240 self.state.lock().active_policy.is_some()
241 }
242
243 pub fn set_enforcing(&self, enforcing: bool) {
245 self.with_state_and_update_status(|state| state.enforcing = enforcing);
246 }
247
248 pub fn is_enforcing(&self) -> bool {
249 self.state.lock().enforcing
250 }
251
252 pub fn deny_unknown(&self) -> bool {
255 self.state.lock().deny_unknown()
256 }
257
258 pub fn reject_unknown(&self) -> bool {
261 self.state.lock().reject_unknown()
262 }
263
264 pub fn conditional_booleans(&self) -> Vec<String> {
267 self.state.lock().booleans.names()
268 }
269
270 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
272 self.state.lock().booleans.get(name)
273 }
274
275 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
277 self.state.lock().booleans.set_pending(name, value)
278 }
279
280 pub fn commit_pending_booleans(&self) {
282 self.with_state_and_update_status(|state| {
284 state.booleans.commit_pending();
285 state.policy_change_count += 1;
286 });
287 }
288
289 pub fn avc_cache_stats(&self) -> CacheStats {
291 self.avc_manager.get_shared_cache().cache_stats()
292 }
293
294 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
296 let locked_state = self.state.lock();
297 let names = locked_state
298 .expect_active_policy()
299 .parsed
300 .classes()
301 .iter()
302 .map(|class| class.class_name.to_vec())
303 .collect();
304 Ok(names)
305 }
306
307 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
309 let locked_state = self.state.lock();
310 Ok(locked_state
311 .expect_active_policy()
312 .parsed
313 .classes()
314 .iter()
315 .find(|class| class.class_name == name.as_bytes())
316 .ok_or(())?
317 .class_id)
318 }
319
320 pub fn class_permissions_by_name(
324 &self,
325 name: &str,
326 ) -> Result<Vec<(ClassPermissionId, Vec<u8>)>, ()> {
327 let locked_state = self.state.lock();
328 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
329 }
330
331 pub fn resolve_fs_label(
335 &self,
336 fs_type: NullessByteStr<'_>,
337 mount_options: &FileSystemMountOptions,
338 ) -> FileSystemLabel {
339 let mut locked_state = self.state.lock();
340 let active_policy = locked_state.expect_active_policy_mut();
341
342 let mount_sids = FileSystemMountSids {
343 context: sid_from_mount_option(active_policy, &mount_options.context),
344 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context),
345 def_context: sid_from_mount_option(active_policy, &mount_options.def_context),
346 root_context: sid_from_mount_option(active_policy, &mount_options.root_context),
347 };
348 if let Some(mountpoint_sid) = mount_sids.context {
349 FileSystemLabel {
353 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
354 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
355 mount_sids,
356 }
357 } else if let Some(FsUseLabelAndType { context, use_type }) =
358 active_policy.parsed.fs_use_label_and_type(fs_type)
359 {
360 let fs_sid_from_policy =
362 active_policy.sid_table.security_context_to_sid(&context).unwrap();
363 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
364 FileSystemLabel {
365 sid: fs_sid,
366 scheme: FileSystemLabelingScheme::FsUse {
367 fs_use_type: use_type,
368 computed_def_sid: mount_sids
369 .def_context
370 .unwrap_or_else(|| SecurityId::initial(InitialSid::File)),
371 },
372 mount_sids,
373 }
374 } else if let Some(context) =
375 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
376 {
377 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
379 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
380 FileSystemLabel { sid: fs_sid, scheme: FileSystemLabelingScheme::GenFsCon, mount_sids }
381 } else {
382 let unrecognized_filesystem_type_sid = SecurityId::initial(InitialSid::File);
386 let unrecognized_filesystem_type_fs_use_type = FsUseType::Xattr;
387
388 FileSystemLabel {
389 sid: mount_sids.fs_context.unwrap_or(unrecognized_filesystem_type_sid),
390 scheme: FileSystemLabelingScheme::FsUse {
391 fs_use_type: unrecognized_filesystem_type_fs_use_type,
392 computed_def_sid: mount_sids
393 .def_context
394 .unwrap_or(unrecognized_filesystem_type_sid),
395 },
396 mount_sids,
397 }
398 }
399 }
400
401 pub fn genfscon_label_for_fs_and_path(
405 &self,
406 fs_type: NullessByteStr<'_>,
407 node_path: NullessByteStr<'_>,
408 class_id: Option<ClassId>,
409 ) -> Option<SecurityId> {
410 let mut locked_state = self.state.lock();
411 let active_policy = locked_state.expect_active_policy_mut();
412 let security_context = active_policy.parsed.genfscon_label_for_fs_and_path(
413 fs_type,
414 node_path.into(),
415 class_id,
416 )?;
417 Some(active_policy.sid_table.security_context_to_sid(&security_context).unwrap())
418 }
419
420 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
425 let locked_state = self.state.lock();
426 let active_policy = locked_state.expect_active_policy();
427 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
428 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
429 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
430 }
431
432 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
439 self.with_state_and_update_status(|state| {
440 assert!(state.status_publisher.is_none());
441 state.status_publisher = Some(status_holder);
442 });
443 }
444
445 #[allow(dead_code)]
449 pub(super) fn get_shared_avc(&self) -> &impl Query {
450 self.avc_manager.get_shared_cache()
451 }
452
453 #[allow(dead_code)]
459 pub(super) fn new_thread_local_avc(&self) -> impl QueryMut {
460 self.avc_manager.new_thread_local_cache()
461 }
462
463 fn with_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
466 let mut locked_state = self.state.lock();
467 f(locked_state.deref_mut());
468 let new_value = SeLinuxStatus {
469 is_enforcing: locked_state.enforcing,
470 change_count: locked_state.policy_change_count,
471 deny_unknown: locked_state.deny_unknown(),
472 };
473 if let Some(status_publisher) = &mut locked_state.status_publisher {
474 status_publisher.set_status(new_value);
475 }
476 }
477
478 pub fn compute_new_sid(
483 &self,
484 source_sid: SecurityId,
485 target_sid: SecurityId,
486 target_class: ObjectClass,
487 ) -> Result<SecurityId, anyhow::Error> {
488 let mut locked_state = self.state.lock();
489 let active_policy = locked_state.expect_active_policy_mut();
490
491 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
493 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
494
495 active_policy
496 .sid_table
497 .security_context_to_sid(&active_policy.parsed.new_security_context(
498 source_context,
499 target_context,
500 &target_class,
501 ))
502 .map_err(anyhow::Error::from)
503 .context("computing new security context from policy")
504 }
505}
506
507impl Query for SecurityServer {
508 fn compute_access_decision(
509 &self,
510 source_sid: SecurityId,
511 target_sid: SecurityId,
512 target_class: AbstractObjectClass,
513 ) -> AccessDecision {
514 let locked_state = self.state.lock();
515
516 let active_policy = match &locked_state.active_policy {
517 Some(active_policy) => active_policy,
518 None => return AccessDecision::allow(AccessVector::ALL),
520 };
521
522 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
523 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
524
525 match target_class {
526 AbstractObjectClass::System(target_class) => {
527 let mut decision = active_policy.parsed.compute_access_decision(
528 &source_context,
529 &target_context,
530 &target_class,
531 );
532 decision.todo_bug = active_policy.exceptions.lookup(
533 source_context.type_(),
534 target_context.type_(),
535 target_class,
536 );
537 decision
538 }
539 AbstractObjectClass::Custom(target_class) => active_policy
540 .parsed
541 .compute_access_decision_custom(&source_context, &target_context, &target_class),
542 _ => AccessDecision::allow(AccessVector::NONE),
544 }
545 }
546
547 fn compute_new_fs_node_sid(
548 &self,
549 source_sid: SecurityId,
550 target_sid: SecurityId,
551 fs_node_class: FsNodeClass,
552 ) -> Result<SecurityId, anyhow::Error> {
553 let mut locked_state = self.state.lock();
554
555 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
557
558 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
559 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
560
561 let new_file_context = active_policy.parsed.new_file_security_context(
563 source_context,
564 target_context,
565 &fs_node_class,
566 );
567
568 active_policy
569 .sid_table
570 .security_context_to_sid(&new_file_context)
571 .map_err(anyhow::Error::from)
572 .context("computing new file security context from policy")
573 }
574
575 fn compute_new_fs_node_sid_with_name(
576 &self,
577 source_sid: SecurityId,
578 target_sid: SecurityId,
579 fs_node_class: FsNodeClass,
580 fs_node_name: NullessByteStr<'_>,
581 ) -> Option<SecurityId> {
582 let mut locked_state = self.state.lock();
583
584 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
586
587 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
588 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
589
590 let new_file_context = active_policy.parsed.new_file_security_context_by_name(
591 source_context,
592 target_context,
593 &fs_node_class,
594 fs_node_name,
595 )?;
596
597 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
598 }
599
600 fn compute_ioctl_access_decision(
601 &self,
602 source_sid: SecurityId,
603 target_sid: SecurityId,
604 target_class: AbstractObjectClass,
605 ioctl_prefix: u8,
606 ) -> IoctlAccessDecision {
607 let locked_state = self.state.lock();
608
609 let active_policy = match &locked_state.active_policy {
610 Some(active_policy) => active_policy,
611 None => return IoctlAccessDecision::ALLOW_ALL,
613 };
614
615 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
616 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
617
618 match target_class {
619 AbstractObjectClass::System(target_class) => {
620 active_policy.parsed.compute_ioctl_access_decision(
621 &source_context,
622 &target_context,
623 &target_class,
624 ioctl_prefix,
625 )
626 }
627 AbstractObjectClass::Custom(target_class) => {
628 active_policy.parsed.compute_ioctl_access_decision_custom(
629 &source_context,
630 &target_context,
631 &target_class,
632 ioctl_prefix,
633 )
634 }
635 _ => IoctlAccessDecision::DENY_ALL,
637 }
638 }
639}
640
641impl AccessVectorComputer for SecurityServer {
642 fn access_vector_from_permissions<P: ClassPermission + Into<Permission> + Clone + 'static>(
643 &self,
644 permissions: &[P],
645 ) -> Option<AccessVector> {
646 match &self.state.lock().active_policy {
647 Some(policy) => policy.parsed.access_vector_from_permissions(permissions),
648 None => Some(AccessVector::NONE),
649 }
650 }
651}
652
653fn sid_from_mount_option(
656 active_policy: &mut ActivePolicy,
657 mount_option: &Option<Vec<u8>>,
658) -> Option<SecurityId> {
659 if let Some(label) = mount_option.as_ref() {
660 Some(
661 if let Some(context) = active_policy.parsed.parse_security_context(label.into()).ok() {
662 active_policy.sid_table.security_context_to_sid(&context).unwrap()
663 } else {
664 SecurityId::initial(InitialSid::Unlabeled)
666 },
667 )
668 } else {
669 None
670 }
671}
672
673#[cfg(test)]
674mod tests {
675 use super::*;
676 use crate::permission_check::PermissionCheckResult;
677 use crate::{
678 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ProcessPermission,
679 };
680 use std::num::NonZeroU64;
681
682 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
683 const TESTS_BINARY_POLICY: &[u8] =
684 include_bytes!("../testdata/micro_policies/security_server_tests_policy.pp");
685 const MINIMAL_BINARY_POLICY: &[u8] =
686 include_bytes!("../testdata/composite_policies/compiled/minimal_policy.pp");
687
688 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
689 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
690 let security_server = SecurityServer::new();
691 assert_eq!(
692 Ok(()),
693 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
694 );
695 security_server
696 }
697
698 #[test]
699 fn compute_access_vector_allows_all() {
700 let security_server = SecurityServer::new();
701 let sid1 = SecurityId::initial(InitialSid::Kernel);
702 let sid2 = SecurityId::initial(InitialSid::Unlabeled);
703 assert_eq!(
704 security_server.compute_access_decision(sid1, sid2, ObjectClass::Process.into()).allow,
705 AccessVector::ALL
706 );
707 }
708
709 #[test]
710 fn loaded_policy_can_be_retrieved() {
711 let security_server = security_server_with_tests_policy();
712 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().as_slice());
713 }
714
715 #[test]
716 fn loaded_policy_is_validated() {
717 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
718 let security_server = SecurityServer::new();
719 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
720 }
721
722 #[test]
723 fn enforcing_mode_is_reported() {
724 let security_server = SecurityServer::new();
725 assert!(!security_server.is_enforcing());
726
727 security_server.set_enforcing(true);
728 assert!(security_server.is_enforcing());
729 }
730
731 #[test]
732 fn without_policy_conditional_booleans_are_empty() {
733 let security_server = SecurityServer::new();
734 assert!(security_server.conditional_booleans().is_empty());
735 }
736
737 #[test]
738 fn conditional_booleans_can_be_queried() {
739 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
740 let security_server = SecurityServer::new();
741 assert_eq!(
742 Ok(()),
743 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
744 );
745
746 let booleans = security_server.conditional_booleans();
747 assert!(!booleans.is_empty());
748 let boolean = booleans[0].as_str();
749
750 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
751 assert!(security_server.get_boolean(boolean).is_ok());
752 }
753
754 #[test]
755 fn conditional_booleans_can_be_changed() {
756 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
757 let security_server = SecurityServer::new();
758 assert_eq!(
759 Ok(()),
760 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
761 );
762
763 let booleans = security_server.conditional_booleans();
764 assert!(!booleans.is_empty());
765 let boolean = booleans[0].as_str();
766
767 let (active, pending) = security_server.get_boolean(boolean).unwrap();
768 assert_eq!(active, pending, "Initially active and pending values should match");
769
770 security_server.set_pending_boolean(boolean, !active).unwrap();
771 let (active, pending) = security_server.get_boolean(boolean).unwrap();
772 assert!(active != pending, "Before commit pending should differ from active");
773
774 security_server.commit_pending_booleans();
775 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
776 assert_eq!(final_active, pending, "Pending value should be active after commit");
777 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
778 }
779
780 #[test]
781 fn parse_security_context_no_policy() {
782 let security_server = SecurityServer::new();
783 let error = security_server
784 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
785 .expect_err("expected error");
786 let error_string = format!("{:?}", error);
787 assert!(error_string.contains("no policy"));
788 }
789
790 #[test]
791 fn compute_new_fs_node_sid_no_defaults() {
792 let security_server = SecurityServer::new();
793 let policy_bytes =
794 include_bytes!("../testdata/micro_policies/file_no_defaults_policy.pp").to_vec();
795 security_server.load_policy(policy_bytes).expect("binary policy loads");
796
797 let source_sid = security_server
798 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
799 .expect("creating SID from security context should succeed");
800 let target_sid = security_server
801 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
802 .expect("creating SID from security context should succeed");
803
804 let computed_sid = security_server
805 .as_permission_check()
806 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
807 .expect("new sid computed");
808 let computed_context = security_server
809 .sid_to_security_context(computed_sid)
810 .expect("computed sid associated with context");
811
812 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
815 }
816
817 #[test]
818 fn compute_new_fs_node_sid_source_defaults() {
819 let security_server = SecurityServer::new();
820 let policy_bytes =
821 include_bytes!("../testdata/micro_policies/file_source_defaults_policy.pp").to_vec();
822 security_server.load_policy(policy_bytes).expect("binary policy loads");
823
824 let source_sid = security_server
825 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
826 .expect("creating SID from security context should succeed");
827 let target_sid = security_server
828 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
829 .expect("creating SID from security context should succeed");
830
831 let computed_sid = security_server
832 .as_permission_check()
833 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
834 .expect("new sid computed");
835 let computed_context = security_server
836 .sid_to_security_context(computed_sid)
837 .expect("computed sid associated with context");
838
839 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
842 }
843
844 #[test]
845 fn compute_new_fs_node_sid_target_defaults() {
846 let security_server = SecurityServer::new();
847 let policy_bytes =
848 include_bytes!("../testdata/micro_policies/file_target_defaults_policy.pp").to_vec();
849 security_server.load_policy(policy_bytes).expect("binary policy loads");
850
851 let source_sid = security_server
852 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
853 .expect("creating SID from security context should succeed");
854 let target_sid = security_server
855 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
856 .expect("creating SID from security context should succeed");
857
858 let computed_sid = security_server
859 .as_permission_check()
860 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
861 .expect("new sid computed");
862 let computed_context = security_server
863 .sid_to_security_context(computed_sid)
864 .expect("computed sid associated with context");
865
866 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
868 }
869
870 #[test]
871 fn compute_new_fs_node_sid_range_source_low_default() {
872 let security_server = SecurityServer::new();
873 let policy_bytes =
874 include_bytes!("../testdata/micro_policies/file_range_source_low_policy.pp").to_vec();
875 security_server.load_policy(policy_bytes).expect("binary policy loads");
876
877 let source_sid = security_server
878 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
879 .expect("creating SID from security context should succeed");
880 let target_sid = security_server
881 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
882 .expect("creating SID from security context should succeed");
883
884 let computed_sid = security_server
885 .as_permission_check()
886 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
887 .expect("new sid computed");
888 let computed_context = security_server
889 .sid_to_security_context(computed_sid)
890 .expect("computed sid associated with context");
891
892 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
894 }
895
896 #[test]
897 fn compute_new_fs_node_sid_range_source_low_high_default() {
898 let security_server = SecurityServer::new();
899 let policy_bytes =
900 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy.pp")
901 .to_vec();
902 security_server.load_policy(policy_bytes).expect("binary policy loads");
903
904 let source_sid = security_server
905 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
906 .expect("creating SID from security context should succeed");
907 let target_sid = security_server
908 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
909 .expect("creating SID from security context should succeed");
910
911 let computed_sid = security_server
912 .as_permission_check()
913 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
914 .expect("new sid computed");
915 let computed_context = security_server
916 .sid_to_security_context(computed_sid)
917 .expect("computed sid associated with context");
918
919 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
921 }
922
923 #[test]
924 fn compute_new_fs_node_sid_range_source_high_default() {
925 let security_server = SecurityServer::new();
926 let policy_bytes =
927 include_bytes!("../testdata/micro_policies/file_range_source_high_policy.pp").to_vec();
928 security_server.load_policy(policy_bytes).expect("binary policy loads");
929
930 let source_sid = security_server
931 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
932 .expect("creating SID from security context should succeed");
933 let target_sid = security_server
934 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
935 .expect("creating SID from security context should succeed");
936
937 let computed_sid = security_server
938 .as_permission_check()
939 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
940 .expect("new sid computed");
941 let computed_context = security_server
942 .sid_to_security_context(computed_sid)
943 .expect("computed sid associated with context");
944
945 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
947 }
948
949 #[test]
950 fn compute_new_fs_node_sid_range_target_low_default() {
951 let security_server = SecurityServer::new();
952 let policy_bytes =
953 include_bytes!("../testdata/micro_policies/file_range_target_low_policy.pp").to_vec();
954 security_server.load_policy(policy_bytes).expect("binary policy loads");
955
956 let source_sid = security_server
957 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
958 .expect("creating SID from security context should succeed");
959 let target_sid = security_server
960 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
961 .expect("creating SID from security context should succeed");
962
963 let computed_sid = security_server
964 .as_permission_check()
965 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
966 .expect("new sid computed");
967 let computed_context = security_server
968 .sid_to_security_context(computed_sid)
969 .expect("computed sid associated with context");
970
971 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
973 }
974
975 #[test]
976 fn compute_new_fs_node_sid_range_target_low_high_default() {
977 let security_server = SecurityServer::new();
978 let policy_bytes =
979 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy.pp")
980 .to_vec();
981 security_server.load_policy(policy_bytes).expect("binary policy loads");
982
983 let source_sid = security_server
984 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
985 .expect("creating SID from security context should succeed");
986 let target_sid = security_server
987 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
988 .expect("creating SID from security context should succeed");
989
990 let computed_sid = security_server
991 .as_permission_check()
992 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
993 .expect("new sid computed");
994 let computed_context = security_server
995 .sid_to_security_context(computed_sid)
996 .expect("computed sid associated with context");
997
998 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1000 }
1001
1002 #[test]
1003 fn compute_new_fs_node_sid_range_target_high_default() {
1004 let security_server = SecurityServer::new();
1005 let policy_bytes =
1006 include_bytes!("../testdata/micro_policies/file_range_target_high_policy.pp").to_vec();
1007 security_server.load_policy(policy_bytes).expect("binary policy loads");
1008
1009 let source_sid = security_server
1010 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1011 .expect("creating SID from security context should succeed");
1012 let target_sid = security_server
1013 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1014 .expect("creating SID from security context should succeed");
1015
1016 let computed_sid = security_server
1017 .as_permission_check()
1018 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1019 .expect("new sid computed");
1020 let computed_context = security_server
1021 .sid_to_security_context(computed_sid)
1022 .expect("computed sid associated with context");
1023
1024 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1026 }
1027
1028 #[test]
1029 fn compute_new_fs_node_sid_with_name() {
1030 let security_server = SecurityServer::new();
1031 let policy_bytes =
1032 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy.pp")
1033 .to_vec();
1034 security_server.load_policy(policy_bytes).expect("binary policy loads");
1035
1036 let source_sid = security_server
1037 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1038 .expect("creating SID from security context should succeed");
1039 let target_sid = security_server
1040 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1041 .expect("creating SID from security context should succeed");
1042
1043 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1044 let computed_sid = security_server
1045 .as_permission_check()
1046 .compute_new_fs_node_sid(
1047 source_sid,
1048 target_sid,
1049 FileClass::File.into(),
1050 SPECIAL_FILE_NAME.into(),
1051 )
1052 .expect("new sid computed");
1053 let computed_context = security_server
1054 .sid_to_security_context(computed_sid)
1055 .expect("computed sid associated with context");
1056
1057 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1059
1060 let computed_sid = security_server
1061 .as_permission_check()
1062 .compute_new_fs_node_sid(
1063 source_sid,
1064 target_sid,
1065 FileClass::Character.into(),
1066 SPECIAL_FILE_NAME.into(),
1067 )
1068 .expect("new sid computed");
1069 let computed_context = security_server
1070 .sid_to_security_context(computed_sid)
1071 .expect("computed sid associated with context");
1072
1073 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1076
1077 const OTHER_FILE_NAME: &[u8] = b"other_file";
1078 let computed_sid = security_server
1079 .as_permission_check()
1080 .compute_new_fs_node_sid(
1081 source_sid,
1082 target_sid,
1083 FileClass::File.into(),
1084 OTHER_FILE_NAME.into(),
1085 )
1086 .expect("new sid computed");
1087 let computed_context = security_server
1088 .sid_to_security_context(computed_sid)
1089 .expect("computed sid associated with context");
1090
1091 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1094 }
1095
1096 #[test]
1097 fn permissions_are_fresh_after_different_policy_load() {
1098 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1099 let allow_fork_bytes =
1100 include_bytes!("../testdata/composite_policies/compiled/allow_fork.pp").to_vec();
1101 let context = b"source_u:object_r:source_t:s0:c0";
1102
1103 let security_server = SecurityServer::new();
1104 security_server.set_enforcing(true);
1105
1106 let permission_check = security_server.as_permission_check();
1107
1108 assert_eq!(
1110 Ok(()),
1111 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1112 );
1113 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1114
1115 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1117
1118 assert_eq!(
1120 Ok(()),
1121 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1122 );
1123
1124 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1126 }
1127
1128 #[test]
1129 fn unknown_sids_are_effectively_unlabeled() {
1130 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1131 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy.pp"
1132 )
1133 .to_vec();
1134 let with_additional_domain_policy_bytes = include_bytes!(
1135 "../testdata/composite_policies/compiled/with_additional_domain_policy.pp"
1136 )
1137 .to_vec();
1138 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1139 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1140
1141 let security_server = SecurityServer::new();
1142 security_server.set_enforcing(true);
1143
1144 assert_eq!(
1147 Ok(()),
1148 security_server
1149 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1150 .map_err(|e| format!("{:?}", e))
1151 );
1152 let allowed_type_sid =
1153 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1154 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1155
1156 assert_eq!(
1159 Ok(()),
1160 security_server
1161 .load_policy(with_additional_domain_policy_bytes.clone())
1162 .map_err(|e| format!("{:?}", e))
1163 );
1164 let additional_type_sid =
1165 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1166 assert_eq!(
1167 allowed_type_sid,
1168 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1169 );
1170
1171 let permission_check = security_server.as_permission_check();
1172
1173 assert!(
1177 !permission_check
1178 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1179 .permit
1180 );
1181 assert!(
1182 !permission_check
1183 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1184 .permit
1185 );
1186 assert!(
1187 !permission_check
1188 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1189 .permit
1190 );
1191 assert!(
1192 !permission_check
1193 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1194 .permit
1195 );
1196
1197 assert_eq!(
1199 Ok(()),
1200 security_server
1201 .load_policy(with_unlabeled_access_domain_policy_bytes)
1202 .map_err(|e| format!("{:?}", e))
1203 );
1204
1205 assert!(
1209 permission_check
1210 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1211 .permit
1212 );
1213 assert!(
1214 !permission_check
1215 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1216 .permit
1217 );
1218
1219 assert!(
1224 !permission_check
1225 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1226 .permit
1227 );
1228 assert!(
1229 permission_check
1230 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1231 .permit
1232 );
1233
1234 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1236
1237 assert_eq!(
1240 Ok(()),
1241 security_server
1242 .load_policy(with_additional_domain_policy_bytes)
1243 .map_err(|e| format!("{:?}", e))
1244 );
1245 assert_eq!(
1246 additional_type_context.to_vec(),
1247 security_server.sid_to_security_context(additional_type_sid).unwrap()
1248 );
1249 }
1250
1251 #[test]
1252 fn permission_check_permissive() {
1253 let security_server = security_server_with_tests_policy();
1254 security_server.set_enforcing(false);
1255 assert!(!security_server.is_enforcing());
1256
1257 let sid =
1258 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1259 let permission_check = security_server.as_permission_check();
1260
1261 assert_eq!(
1264 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1265 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1266 );
1267
1268 assert_eq!(
1272 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1273 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1274 );
1275
1276 assert_eq!(
1280 permission_check.has_permission(
1281 sid,
1282 sid,
1283 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1284 ),
1285 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1286 );
1287 }
1288
1289 #[test]
1290 fn permission_check_enforcing() {
1291 let security_server = security_server_with_tests_policy();
1292 security_server.set_enforcing(true);
1293 assert!(security_server.is_enforcing());
1294
1295 let sid =
1296 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1297 let permission_check = security_server.as_permission_check();
1298
1299 assert_eq!(
1301 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1302 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1303 );
1304
1305 assert_eq!(
1308 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1309 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1310 );
1311
1312 assert_eq!(
1315 permission_check.has_permission(
1316 sid,
1317 sid,
1318 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1319 ),
1320 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1321 );
1322 }
1323
1324 #[test]
1325 fn permissive_domain() {
1326 let security_server = security_server_with_tests_policy();
1327 security_server.set_enforcing(true);
1328 assert!(security_server.is_enforcing());
1329
1330 let permissive_sid = security_server
1331 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1332 .unwrap();
1333 let non_permissive_sid = security_server
1334 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1335 .unwrap();
1336
1337 let permission_check = security_server.as_permission_check();
1338
1339 assert_eq!(
1341 permission_check.has_permission(
1342 permissive_sid,
1343 permissive_sid,
1344 ProcessPermission::GetSched
1345 ),
1346 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1347 );
1348 assert_eq!(
1349 permission_check.has_permission(
1350 non_permissive_sid,
1351 non_permissive_sid,
1352 ProcessPermission::GetSched
1353 ),
1354 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1355 );
1356
1357 assert_eq!(
1360 permission_check.has_permission(
1361 permissive_sid,
1362 non_permissive_sid,
1363 ProcessPermission::GetSched
1364 ),
1365 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1366 );
1367 assert_eq!(
1368 permission_check.has_permission(
1369 non_permissive_sid,
1370 permissive_sid,
1371 ProcessPermission::GetSched
1372 ),
1373 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1374 );
1375
1376 assert_eq!(
1381 permission_check.has_permission(
1382 permissive_sid,
1383 non_permissive_sid,
1384 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1385 ),
1386 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1387 );
1388 assert_eq!(
1389 permission_check.has_permission(
1390 non_permissive_sid,
1391 non_permissive_sid,
1392 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1393 ),
1394 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1395 );
1396 }
1397
1398 #[test]
1399 fn auditallow_and_dontaudit() {
1400 let security_server = security_server_with_tests_policy();
1401 security_server.set_enforcing(true);
1402 assert!(security_server.is_enforcing());
1403
1404 let audit_sid = security_server
1405 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1406 .unwrap();
1407
1408 let permission_check = security_server.as_permission_check();
1409
1410 assert_eq!(
1412 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork),
1413 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1414 );
1415
1416 assert_eq!(
1418 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched),
1419 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1420 );
1421
1422 assert_eq!(
1424 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched),
1425 PermissionCheckResult { permit: false, audit: false, todo_bug: None }
1426 );
1427
1428 assert_eq!(
1430 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid),
1431 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1432 );
1433 }
1434
1435 #[test]
1436 fn access_checks_with_exceptions_config() {
1437 const EXCEPTIONS_CONFIG: &str = "
1438 // These statement should all be resolved.
1439 todo_deny b/001 test_exception_source_t test_exception_target_t file
1440 todo_deny b/002 test_exception_other_t test_exception_target_t chr_file
1441 todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode
1442 todo_deny b/004 test_exception_permissive_t test_exception_target_t file
1443
1444 // These statements should not be resolved.
1445 todo_deny b/101 test_undefined_source_t test_exception_target_t file
1446 todo_deny b/102 test_exception_source_t test_undefined_target_t file
1447 ";
1448 let security_server = SecurityServer::new_with_exceptions(EXCEPTIONS_CONFIG.into());
1449 security_server.set_enforcing(true);
1450
1451 const EXCEPTIONS_POLICY: &[u8] =
1452 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1453 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1454
1455 let source_sid = security_server
1456 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1457 .unwrap();
1458 let target_sid = security_server
1459 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1460 .unwrap();
1461 let other_sid = security_server
1462 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1463 .unwrap();
1464 let permissive_sid = security_server
1465 .security_context_to_sid(
1466 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1467 )
1468 .unwrap();
1469 let unmatched_sid = security_server
1470 .security_context_to_sid(
1471 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1472 )
1473 .unwrap();
1474
1475 let permission_check = security_server.as_permission_check();
1476
1477 assert_eq!(
1479 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid),
1480 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1481 );
1482
1483 assert_eq!(
1485 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint),
1486 PermissionCheckResult {
1487 permit: true,
1488 audit: true,
1489 todo_bug: Some(NonZeroU64::new(1).unwrap())
1490 }
1491 );
1492
1493 assert_eq!(
1495 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans),
1496 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1497 );
1498
1499 assert_eq!(
1501 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint),
1502 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1503 );
1504
1505 assert_eq!(
1507 permission_check.has_permission(
1508 other_sid,
1509 target_sid,
1510 CommonFsNodePermission::Read.for_class(FileClass::Character)
1511 ),
1512 PermissionCheckResult {
1513 permit: true,
1514 audit: true,
1515 todo_bug: Some(NonZeroU64::new(2).unwrap())
1516 }
1517 );
1518
1519 assert_eq!(
1521 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint),
1522 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1523 );
1524
1525 assert_eq!(
1527 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint),
1528 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1529 );
1530
1531 assert_eq!(
1533 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint),
1534 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1535 );
1536 }
1537
1538 #[test]
1539 fn handle_unknown() {
1540 let security_server = security_server_with_tests_policy();
1541
1542 let sid = security_server
1543 .security_context_to_sid("user0:object_r:type0:s0".into())
1544 .expect("Resolve Context to SID");
1545
1546 const REJECT_POLICY: &[u8] = include_bytes!(
1550 "../testdata/composite_policies/compiled/handle_unknown_policy-reject.pp"
1551 );
1552 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1553
1554 security_server.set_enforcing(true);
1555
1556 const DENY_POLICY: &[u8] =
1558 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny.pp");
1559 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1560 let permission_check = security_server.as_permission_check();
1561
1562 assert_eq!(
1564 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1565 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1566 );
1567 assert_eq!(
1568 permission_check.has_permission(sid, sid, DirPermission::AddName),
1569 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1570 );
1571
1572 assert_eq!(
1574 permission_check.has_permission(sid, sid, DirPermission::Search),
1575 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1576 );
1577 assert_eq!(
1578 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1579 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1580 );
1581
1582 const ALLOW_POLICY: &[u8] = include_bytes!(
1584 "../testdata/composite_policies/compiled/handle_unknown_policy-allow.pp"
1585 );
1586 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1587 let permission_check = security_server.as_permission_check();
1588
1589 assert_eq!(
1591 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1592 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1593 );
1594 assert_eq!(
1595 permission_check.has_permission(sid, sid, DirPermission::AddName),
1596 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1597 );
1598
1599 assert_eq!(
1601 permission_check.has_permission(sid, sid, DirPermission::Search),
1602 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1603 );
1604 assert_eq!(
1605 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1606 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1607 );
1608 }
1609}