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 ClassPermission, FileSystemLabel, FileSystemLabelingScheme, FileSystemMountOptions,
20 FsNodeClass, InitialSid, KernelPermission, NullessByteStr, ObjectClass, SeLinuxStatus,
21 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: Vec<String>,
132}
133
134impl SecurityServer {
135 pub fn new_default() -> Arc<Self> {
137 Self::new(String::new(), Vec::new())
138 }
139
140 pub fn new(options: String, exceptions: Vec<String>) -> Arc<Self> {
142 assert_eq!(options, String::new());
144
145 let avc_manager = AvcManager::new();
146 let state = Mutex::new(SecurityServerState {
147 active_policy: None,
148 booleans: SeLinuxBooleans::default(),
149 status_publisher: None,
150 enforcing: false,
151 policy_change_count: 0,
152 });
153
154 let security_server = Arc::new(Self { avc_manager, state, exceptions: exceptions });
155
156 security_server.as_ref().avc_manager.set_security_server(Arc::downgrade(&security_server));
159
160 security_server
161 }
162
163 pub fn as_permission_check<'a>(self: &'a Self) -> PermissionCheck<'a> {
166 PermissionCheck::new(self, self.avc_manager.get_shared_cache())
167 }
168
169 pub fn security_context_to_sid(
173 &self,
174 security_context: NullessByteStr<'_>,
175 ) -> Result<SecurityId, anyhow::Error> {
176 let mut locked_state = self.state.lock();
177 let active_policy = locked_state
178 .active_policy
179 .as_mut()
180 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
181 let context = active_policy
182 .parsed
183 .parse_security_context(security_context)
184 .map_err(anyhow::Error::from)?;
185 active_policy.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
186 }
187
188 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
193 let locked_state = self.state.lock();
194 let active_policy = locked_state.active_policy.as_ref()?;
195 let context = active_policy.sid_table.try_sid_to_security_context(sid)?;
196 Some(active_policy.parsed.serialize_security_context(context))
197 }
198
199 pub fn load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
201 let (parsed, binary) = parse_policy_by_value(binary_policy)?;
204 let parsed = Arc::new(parsed.validate()?);
205
206 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
207 let exceptions = ExceptionsConfig::new(&parsed, &exceptions)?;
208
209 self.with_state_and_update_status(|state| {
211 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
212 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
213 } else {
214 SidTable::new(parsed.clone())
215 };
216
217 state.booleans.reset(
220 parsed
221 .conditional_booleans()
222 .iter()
223 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
225 .collect(),
226 );
227
228 state.active_policy = Some(ActivePolicy { parsed, binary, sid_table, exceptions });
229 state.policy_change_count += 1;
230 });
231
232 self.avc_manager.reset();
235
236 Ok(())
237 }
238
239 pub fn get_binary_policy(&self) -> Option<Vec<u8>> {
241 self.state.lock().active_policy.as_ref().map(|p| p.binary.clone())
242 }
243
244 pub fn has_policy(&self) -> bool {
246 self.state.lock().active_policy.is_some()
247 }
248
249 pub fn set_enforcing(&self, enforcing: bool) {
251 self.with_state_and_update_status(|state| state.enforcing = enforcing);
252 }
253
254 pub fn is_enforcing(&self) -> bool {
255 self.state.lock().enforcing
256 }
257
258 pub fn deny_unknown(&self) -> bool {
261 self.state.lock().deny_unknown()
262 }
263
264 pub fn reject_unknown(&self) -> bool {
267 self.state.lock().reject_unknown()
268 }
269
270 pub fn conditional_booleans(&self) -> Vec<String> {
273 self.state.lock().booleans.names()
274 }
275
276 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
278 self.state.lock().booleans.get(name)
279 }
280
281 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
283 self.state.lock().booleans.set_pending(name, value)
284 }
285
286 pub fn commit_pending_booleans(&self) {
288 self.with_state_and_update_status(|state| {
290 state.booleans.commit_pending();
291 state.policy_change_count += 1;
292 });
293 }
294
295 pub fn avc_cache_stats(&self) -> CacheStats {
297 self.avc_manager.get_shared_cache().cache_stats()
298 }
299
300 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
302 let locked_state = self.state.lock();
303 let names = locked_state
304 .expect_active_policy()
305 .parsed
306 .classes()
307 .iter()
308 .map(|class| class.class_name.to_vec())
309 .collect();
310 Ok(names)
311 }
312
313 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
315 let locked_state = self.state.lock();
316 Ok(locked_state
317 .expect_active_policy()
318 .parsed
319 .classes()
320 .iter()
321 .find(|class| class.class_name == name.as_bytes())
322 .ok_or(())?
323 .class_id)
324 }
325
326 pub fn class_permissions_by_name(
330 &self,
331 name: &str,
332 ) -> Result<Vec<(ClassPermissionId, Vec<u8>)>, ()> {
333 let locked_state = self.state.lock();
334 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
335 }
336
337 pub fn resolve_fs_label(
341 &self,
342 fs_type: NullessByteStr<'_>,
343 mount_options: &FileSystemMountOptions,
344 ) -> FileSystemLabel {
345 let mut locked_state = self.state.lock();
346 let active_policy = locked_state.expect_active_policy_mut();
347
348 let mount_sids = FileSystemMountSids {
349 context: sid_from_mount_option(active_policy, &mount_options.context),
350 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context),
351 def_context: sid_from_mount_option(active_policy, &mount_options.def_context),
352 root_context: sid_from_mount_option(active_policy, &mount_options.root_context),
353 };
354 if let Some(mountpoint_sid) = mount_sids.context {
355 FileSystemLabel {
359 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
360 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
361 mount_sids,
362 }
363 } else if let Some(FsUseLabelAndType { context, use_type }) =
364 active_policy.parsed.fs_use_label_and_type(fs_type)
365 {
366 let fs_sid_from_policy =
368 active_policy.sid_table.security_context_to_sid(&context).unwrap();
369 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
370 FileSystemLabel {
371 sid: fs_sid,
372 scheme: FileSystemLabelingScheme::FsUse {
373 fs_use_type: use_type,
374 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
375 },
376 mount_sids,
377 }
378 } else if let Some(context) =
379 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
380 {
381 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
383 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
384 FileSystemLabel { sid: fs_sid, scheme: FileSystemLabelingScheme::GenFsCon, mount_sids }
385 } else {
386 FileSystemLabel {
388 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
389 scheme: FileSystemLabelingScheme::FsUse {
390 fs_use_type: FsUseType::Xattr,
391 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
392 },
393 mount_sids,
394 }
395 }
396 }
397
398 pub fn genfscon_label_for_fs_and_path(
402 &self,
403 fs_type: NullessByteStr<'_>,
404 node_path: NullessByteStr<'_>,
405 class_id: Option<ClassId>,
406 ) -> Option<SecurityId> {
407 let mut locked_state = self.state.lock();
408 let active_policy = locked_state.expect_active_policy_mut();
409 let security_context = active_policy.parsed.genfscon_label_for_fs_and_path(
410 fs_type,
411 node_path.into(),
412 class_id,
413 )?;
414 Some(active_policy.sid_table.security_context_to_sid(&security_context).unwrap())
415 }
416
417 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
422 let locked_state = self.state.lock();
423 let active_policy = locked_state.expect_active_policy();
424 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
425 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
426 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
427 }
428
429 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
436 self.with_state_and_update_status(|state| {
437 assert!(state.status_publisher.is_none());
438 state.status_publisher = Some(status_holder);
439 });
440 }
441
442 #[allow(dead_code)]
446 pub(super) fn get_shared_avc(&self) -> &impl Query {
447 self.avc_manager.get_shared_cache()
448 }
449
450 #[allow(dead_code)]
456 pub(super) fn new_thread_local_avc(&self) -> impl QueryMut {
457 self.avc_manager.new_thread_local_cache()
458 }
459
460 fn with_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
463 let mut locked_state = self.state.lock();
464 f(locked_state.deref_mut());
465 let new_value = SeLinuxStatus {
466 is_enforcing: locked_state.enforcing,
467 change_count: locked_state.policy_change_count,
468 deny_unknown: locked_state.deny_unknown(),
469 };
470 if let Some(status_publisher) = &mut locked_state.status_publisher {
471 status_publisher.set_status(new_value);
472 }
473 }
474
475 pub fn compute_create_sid(
480 &self,
481 source_sid: SecurityId,
482 target_sid: SecurityId,
483 target_class: impl Into<ObjectClass>,
484 ) -> Result<SecurityId, anyhow::Error> {
485 let mut locked_state = self.state.lock();
486 let active_policy = locked_state.expect_active_policy_mut();
487
488 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
489 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
490
491 let security_context = active_policy.parsed.compute_create_context(
492 source_context,
493 target_context,
494 target_class.into(),
495 );
496
497 active_policy
498 .sid_table
499 .security_context_to_sid(&security_context)
500 .map_err(anyhow::Error::from)
501 .context("computing new security context from policy")
502 }
503}
504
505impl Query for SecurityServer {
506 fn compute_access_decision(
507 &self,
508 source_sid: SecurityId,
509 target_sid: SecurityId,
510 target_class: ObjectClass,
511 ) -> AccessDecision {
512 let locked_state = self.state.lock();
513
514 let active_policy = match &locked_state.active_policy {
515 Some(active_policy) => active_policy,
516 None => return AccessDecision::allow(AccessVector::ALL),
518 };
519
520 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
521 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
522
523 let mut decision = active_policy.parsed.compute_access_decision(
524 &source_context,
525 &target_context,
526 target_class,
527 );
528
529 decision.todo_bug = active_policy.exceptions.lookup(
530 source_context.type_(),
531 target_context.type_(),
532 target_class,
533 );
534
535 decision
536 }
537
538 fn compute_new_fs_node_sid(
539 &self,
540 source_sid: SecurityId,
541 target_sid: SecurityId,
542 fs_node_class: FsNodeClass,
543 ) -> Result<SecurityId, anyhow::Error> {
544 self.compute_create_sid(source_sid, target_sid, fs_node_class)
545 }
546
547 fn compute_new_fs_node_sid_with_name(
548 &self,
549 source_sid: SecurityId,
550 target_sid: SecurityId,
551 fs_node_class: FsNodeClass,
552 fs_node_name: NullessByteStr<'_>,
553 ) -> Option<SecurityId> {
554 let mut locked_state = self.state.lock();
555
556 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
558
559 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
560 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
561
562 let new_file_context = active_policy.parsed.compute_create_context_with_name(
563 source_context,
564 target_context,
565 fs_node_class,
566 fs_node_name,
567 )?;
568
569 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
570 }
571
572 fn compute_ioctl_access_decision(
573 &self,
574 source_sid: SecurityId,
575 target_sid: SecurityId,
576 target_class: ObjectClass,
577 ioctl_prefix: u8,
578 ) -> IoctlAccessDecision {
579 let locked_state = self.state.lock();
580
581 let active_policy = match &locked_state.active_policy {
582 Some(active_policy) => active_policy,
583 None => return IoctlAccessDecision::ALLOW_ALL,
585 };
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 active_policy.parsed.compute_ioctl_access_decision(
591 &source_context,
592 &target_context,
593 target_class,
594 ioctl_prefix,
595 )
596 }
597}
598
599impl AccessVectorComputer for SecurityServer {
600 fn access_vector_from_permissions<
601 P: ClassPermission + Into<KernelPermission> + Clone + 'static,
602 >(
603 &self,
604 permissions: &[P],
605 ) -> Option<AccessVector> {
606 match &self.state.lock().active_policy {
607 Some(policy) => policy.parsed.access_vector_from_permissions(permissions),
608 None => Some(AccessVector::NONE),
609 }
610 }
611}
612
613fn sid_from_mount_option(
616 active_policy: &mut ActivePolicy,
617 mount_option: &Option<Vec<u8>>,
618) -> Option<SecurityId> {
619 if let Some(label) = mount_option.as_ref() {
620 Some(
621 if let Some(context) = active_policy.parsed.parse_security_context(label.into()).ok() {
622 active_policy.sid_table.security_context_to_sid(&context).unwrap()
623 } else {
624 InitialSid::Unlabeled.into()
626 },
627 )
628 } else {
629 None
630 }
631}
632
633#[cfg(test)]
634mod tests {
635 use super::*;
636 use crate::permission_check::PermissionCheckResult;
637 use crate::{
638 CommonFsNodePermission, DirPermission, FileClass, FilePermission, KernelClass,
639 ProcessPermission,
640 };
641 use std::num::NonZeroU64;
642
643 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
644 const TESTS_BINARY_POLICY: &[u8] =
645 include_bytes!("../testdata/micro_policies/security_server_tests_policy.pp");
646 const MINIMAL_BINARY_POLICY: &[u8] =
647 include_bytes!("../testdata/composite_policies/compiled/minimal_policy.pp");
648
649 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
650 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
651 let security_server = SecurityServer::new_default();
652 assert_eq!(
653 Ok(()),
654 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
655 );
656 security_server
657 }
658
659 #[test]
660 fn compute_access_vector_allows_all() {
661 let security_server = SecurityServer::new_default();
662 let sid1 = InitialSid::Kernel.into();
663 let sid2 = InitialSid::Unlabeled.into();
664 assert_eq!(
665 security_server.compute_access_decision(sid1, sid2, KernelClass::Process.into()).allow,
666 AccessVector::ALL
667 );
668 }
669
670 #[test]
671 fn loaded_policy_can_be_retrieved() {
672 let security_server = security_server_with_tests_policy();
673 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_slice());
674 }
675
676 #[test]
677 fn loaded_policy_is_validated() {
678 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
679 let security_server = SecurityServer::new_default();
680 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
681 }
682
683 #[test]
684 fn enforcing_mode_is_reported() {
685 let security_server = SecurityServer::new_default();
686 assert!(!security_server.is_enforcing());
687
688 security_server.set_enforcing(true);
689 assert!(security_server.is_enforcing());
690 }
691
692 #[test]
693 fn without_policy_conditional_booleans_are_empty() {
694 let security_server = SecurityServer::new_default();
695 assert!(security_server.conditional_booleans().is_empty());
696 }
697
698 #[test]
699 fn conditional_booleans_can_be_queried() {
700 let policy_bytes = TESTSUITE_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
707 let booleans = security_server.conditional_booleans();
708 assert!(!booleans.is_empty());
709 let boolean = booleans[0].as_str();
710
711 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
712 assert!(security_server.get_boolean(boolean).is_ok());
713 }
714
715 #[test]
716 fn conditional_booleans_can_be_changed() {
717 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
718 let security_server = SecurityServer::new_default();
719 assert_eq!(
720 Ok(()),
721 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
722 );
723
724 let booleans = security_server.conditional_booleans();
725 assert!(!booleans.is_empty());
726 let boolean = booleans[0].as_str();
727
728 let (active, pending) = security_server.get_boolean(boolean).unwrap();
729 assert_eq!(active, pending, "Initially active and pending values should match");
730
731 security_server.set_pending_boolean(boolean, !active).unwrap();
732 let (active, pending) = security_server.get_boolean(boolean).unwrap();
733 assert!(active != pending, "Before commit pending should differ from active");
734
735 security_server.commit_pending_booleans();
736 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
737 assert_eq!(final_active, pending, "Pending value should be active after commit");
738 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
739 }
740
741 #[test]
742 fn parse_security_context_no_policy() {
743 let security_server = SecurityServer::new_default();
744 let error = security_server
745 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
746 .expect_err("expected error");
747 let error_string = format!("{:?}", error);
748 assert!(error_string.contains("no policy"));
749 }
750
751 #[test]
752 fn compute_new_fs_node_sid_no_defaults() {
753 let security_server = SecurityServer::new_default();
754 let policy_bytes =
755 include_bytes!("../testdata/micro_policies/file_no_defaults_policy.pp").to_vec();
756 security_server.load_policy(policy_bytes).expect("binary policy loads");
757
758 let source_sid = security_server
759 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
760 .expect("creating SID from security context should succeed");
761 let target_sid = security_server
762 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
763 .expect("creating SID from security context should succeed");
764
765 let computed_sid = security_server
766 .as_permission_check()
767 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
768 .expect("new sid computed");
769 let computed_context = security_server
770 .sid_to_security_context(computed_sid)
771 .expect("computed sid associated with context");
772
773 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
776 }
777
778 #[test]
779 fn compute_new_fs_node_sid_source_defaults() {
780 let security_server = SecurityServer::new_default();
781 let policy_bytes =
782 include_bytes!("../testdata/micro_policies/file_source_defaults_policy.pp").to_vec();
783 security_server.load_policy(policy_bytes).expect("binary policy loads");
784
785 let source_sid = security_server
786 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
787 .expect("creating SID from security context should succeed");
788 let target_sid = security_server
789 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
790 .expect("creating SID from security context should succeed");
791
792 let computed_sid = security_server
793 .as_permission_check()
794 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
795 .expect("new sid computed");
796 let computed_context = security_server
797 .sid_to_security_context(computed_sid)
798 .expect("computed sid associated with context");
799
800 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
803 }
804
805 #[test]
806 fn compute_new_fs_node_sid_target_defaults() {
807 let security_server = SecurityServer::new_default();
808 let policy_bytes =
809 include_bytes!("../testdata/micro_policies/file_target_defaults_policy.pp").to_vec();
810 security_server.load_policy(policy_bytes).expect("binary policy loads");
811
812 let source_sid = security_server
813 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
814 .expect("creating SID from security context should succeed");
815 let target_sid = security_server
816 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
817 .expect("creating SID from security context should succeed");
818
819 let computed_sid = security_server
820 .as_permission_check()
821 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
822 .expect("new sid computed");
823 let computed_context = security_server
824 .sid_to_security_context(computed_sid)
825 .expect("computed sid associated with context");
826
827 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
829 }
830
831 #[test]
832 fn compute_new_fs_node_sid_range_source_low_default() {
833 let security_server = SecurityServer::new_default();
834 let policy_bytes =
835 include_bytes!("../testdata/micro_policies/file_range_source_low_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-s1: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".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:object_r:file_t:s0");
855 }
856
857 #[test]
858 fn compute_new_fs_node_sid_range_source_low_high_default() {
859 let security_server = SecurityServer::new_default();
860 let policy_bytes =
861 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy.pp")
862 .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-s1: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".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"user_u:object_r:file_t:s0-s1:c0");
882 }
883
884 #[test]
885 fn compute_new_fs_node_sid_range_source_high_default() {
886 let security_server = SecurityServer::new_default();
887 let policy_bytes =
888 include_bytes!("../testdata/micro_policies/file_range_source_high_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:s0".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:s1:c0");
908 }
909
910 #[test]
911 fn compute_new_fs_node_sid_range_target_low_default() {
912 let security_server = SecurityServer::new_default();
913 let policy_bytes =
914 include_bytes!("../testdata/micro_policies/file_range_target_low_policy.pp").to_vec();
915 security_server.load_policy(policy_bytes).expect("binary policy loads");
916
917 let source_sid = security_server
918 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
919 .expect("creating SID from security context should succeed");
920 let target_sid = security_server
921 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
922 .expect("creating SID from security context should succeed");
923
924 let computed_sid = security_server
925 .as_permission_check()
926 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
927 .expect("new sid computed");
928 let computed_context = security_server
929 .sid_to_security_context(computed_sid)
930 .expect("computed sid associated with context");
931
932 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
934 }
935
936 #[test]
937 fn compute_new_fs_node_sid_range_target_low_high_default() {
938 let security_server = SecurityServer::new_default();
939 let policy_bytes =
940 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy.pp")
941 .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:s1".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-s1:c0".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:s0-s1:c0");
961 }
962
963 #[test]
964 fn compute_new_fs_node_sid_range_target_high_default() {
965 let security_server = SecurityServer::new_default();
966 let policy_bytes =
967 include_bytes!("../testdata/micro_policies/file_range_target_high_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:s0".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:s1:c0");
987 }
988
989 #[test]
990 fn compute_new_fs_node_sid_with_name() {
991 let security_server = SecurityServer::new_default();
992 let policy_bytes =
993 include_bytes!("../testdata/composite_policies/compiled/type_transition_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"source_u:source_r:source_t:s0".into())
999 .expect("creating SID from security context should succeed");
1000 let target_sid = security_server
1001 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1002 .expect("creating SID from security context should succeed");
1003
1004 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1005 let computed_sid = security_server
1006 .as_permission_check()
1007 .compute_new_fs_node_sid(
1008 source_sid,
1009 target_sid,
1010 FileClass::File.into(),
1011 SPECIAL_FILE_NAME.into(),
1012 )
1013 .expect("new sid computed");
1014 let computed_context = security_server
1015 .sid_to_security_context(computed_sid)
1016 .expect("computed sid associated with context");
1017
1018 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1020
1021 let computed_sid = security_server
1022 .as_permission_check()
1023 .compute_new_fs_node_sid(
1024 source_sid,
1025 target_sid,
1026 FileClass::Character.into(),
1027 SPECIAL_FILE_NAME.into(),
1028 )
1029 .expect("new sid computed");
1030 let computed_context = security_server
1031 .sid_to_security_context(computed_sid)
1032 .expect("computed sid associated with context");
1033
1034 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1037
1038 const OTHER_FILE_NAME: &[u8] = b"other_file";
1039 let computed_sid = security_server
1040 .as_permission_check()
1041 .compute_new_fs_node_sid(
1042 source_sid,
1043 target_sid,
1044 FileClass::File.into(),
1045 OTHER_FILE_NAME.into(),
1046 )
1047 .expect("new sid computed");
1048 let computed_context = security_server
1049 .sid_to_security_context(computed_sid)
1050 .expect("computed sid associated with context");
1051
1052 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1055 }
1056
1057 #[test]
1058 fn permissions_are_fresh_after_different_policy_load() {
1059 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1060 let allow_fork_bytes =
1061 include_bytes!("../testdata/composite_policies/compiled/allow_fork.pp").to_vec();
1062 let context = b"source_u:object_r:source_t:s0:c0";
1063
1064 let security_server = SecurityServer::new_default();
1065 security_server.set_enforcing(true);
1066
1067 let permission_check = security_server.as_permission_check();
1068
1069 assert_eq!(
1071 Ok(()),
1072 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1073 );
1074 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1075
1076 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1078
1079 assert_eq!(
1081 Ok(()),
1082 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1083 );
1084
1085 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1087 }
1088
1089 #[test]
1090 fn unknown_sids_are_effectively_unlabeled() {
1091 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1092 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy.pp"
1093 )
1094 .to_vec();
1095 let with_additional_domain_policy_bytes = include_bytes!(
1096 "../testdata/composite_policies/compiled/with_additional_domain_policy.pp"
1097 )
1098 .to_vec();
1099 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1100 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1101
1102 let security_server = SecurityServer::new_default();
1103 security_server.set_enforcing(true);
1104
1105 assert_eq!(
1108 Ok(()),
1109 security_server
1110 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1111 .map_err(|e| format!("{:?}", e))
1112 );
1113 let allowed_type_sid =
1114 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1115 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1116
1117 assert_eq!(
1120 Ok(()),
1121 security_server
1122 .load_policy(with_additional_domain_policy_bytes.clone())
1123 .map_err(|e| format!("{:?}", e))
1124 );
1125 let additional_type_sid =
1126 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1127 assert_eq!(
1128 allowed_type_sid,
1129 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1130 );
1131
1132 let permission_check = security_server.as_permission_check();
1133
1134 assert!(
1138 !permission_check
1139 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1140 .permit
1141 );
1142 assert!(
1143 !permission_check
1144 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1145 .permit
1146 );
1147 assert!(
1148 !permission_check
1149 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1150 .permit
1151 );
1152 assert!(
1153 !permission_check
1154 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1155 .permit
1156 );
1157
1158 assert_eq!(
1160 Ok(()),
1161 security_server
1162 .load_policy(with_unlabeled_access_domain_policy_bytes)
1163 .map_err(|e| format!("{:?}", e))
1164 );
1165
1166 assert!(
1170 permission_check
1171 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1172 .permit
1173 );
1174 assert!(
1175 !permission_check
1176 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1177 .permit
1178 );
1179
1180 assert!(
1185 !permission_check
1186 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1187 .permit
1188 );
1189 assert!(
1190 permission_check
1191 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1192 .permit
1193 );
1194
1195 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1197
1198 assert_eq!(
1201 Ok(()),
1202 security_server
1203 .load_policy(with_additional_domain_policy_bytes)
1204 .map_err(|e| format!("{:?}", e))
1205 );
1206 assert_eq!(
1207 additional_type_context.to_vec(),
1208 security_server.sid_to_security_context(additional_type_sid).unwrap()
1209 );
1210 }
1211
1212 #[test]
1213 fn permission_check_permissive() {
1214 let security_server = security_server_with_tests_policy();
1215 security_server.set_enforcing(false);
1216 assert!(!security_server.is_enforcing());
1217
1218 let sid =
1219 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1220 let permission_check = security_server.as_permission_check();
1221
1222 assert_eq!(
1225 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1226 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1227 );
1228
1229 assert_eq!(
1233 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1234 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1235 );
1236
1237 assert_eq!(
1241 permission_check.has_permission(
1242 sid,
1243 sid,
1244 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1245 ),
1246 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1247 );
1248 }
1249
1250 #[test]
1251 fn permission_check_enforcing() {
1252 let security_server = security_server_with_tests_policy();
1253 security_server.set_enforcing(true);
1254 assert!(security_server.is_enforcing());
1255
1256 let sid =
1257 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1258 let permission_check = security_server.as_permission_check();
1259
1260 assert_eq!(
1262 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1263 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1264 );
1265
1266 assert_eq!(
1269 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1270 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1271 );
1272
1273 assert_eq!(
1276 permission_check.has_permission(
1277 sid,
1278 sid,
1279 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1280 ),
1281 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1282 );
1283 }
1284
1285 #[test]
1286 fn permissive_domain() {
1287 let security_server = security_server_with_tests_policy();
1288 security_server.set_enforcing(true);
1289 assert!(security_server.is_enforcing());
1290
1291 let permissive_sid = security_server
1292 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1293 .unwrap();
1294 let non_permissive_sid = security_server
1295 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1296 .unwrap();
1297
1298 let permission_check = security_server.as_permission_check();
1299
1300 assert_eq!(
1302 permission_check.has_permission(
1303 permissive_sid,
1304 permissive_sid,
1305 ProcessPermission::GetSched
1306 ),
1307 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1308 );
1309 assert_eq!(
1310 permission_check.has_permission(
1311 non_permissive_sid,
1312 non_permissive_sid,
1313 ProcessPermission::GetSched
1314 ),
1315 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1316 );
1317
1318 assert_eq!(
1321 permission_check.has_permission(
1322 permissive_sid,
1323 non_permissive_sid,
1324 ProcessPermission::GetSched
1325 ),
1326 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1327 );
1328 assert_eq!(
1329 permission_check.has_permission(
1330 non_permissive_sid,
1331 permissive_sid,
1332 ProcessPermission::GetSched
1333 ),
1334 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1335 );
1336
1337 assert_eq!(
1342 permission_check.has_permission(
1343 permissive_sid,
1344 non_permissive_sid,
1345 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1346 ),
1347 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1348 );
1349 assert_eq!(
1350 permission_check.has_permission(
1351 non_permissive_sid,
1352 non_permissive_sid,
1353 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1354 ),
1355 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1356 );
1357 }
1358
1359 #[test]
1360 fn auditallow_and_dontaudit() {
1361 let security_server = security_server_with_tests_policy();
1362 security_server.set_enforcing(true);
1363 assert!(security_server.is_enforcing());
1364
1365 let audit_sid = security_server
1366 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1367 .unwrap();
1368
1369 let permission_check = security_server.as_permission_check();
1370
1371 assert_eq!(
1373 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork),
1374 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1375 );
1376
1377 assert_eq!(
1379 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched),
1380 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1381 );
1382
1383 assert_eq!(
1385 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched),
1386 PermissionCheckResult { permit: false, audit: false, todo_bug: None }
1387 );
1388
1389 assert_eq!(
1391 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid),
1392 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1393 );
1394 }
1395
1396 #[test]
1397 fn access_checks_with_exceptions_config() {
1398 const EXCEPTIONS_CONFIG: &[&str] = &[
1399 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1401 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1402 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1403 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1404 "todo_permissive b/005 test_exception_todo_permissive_t",
1405 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1407 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1408 "todo_permissive b/103 test_undefined_source_t",
1409 ];
1410 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1411 let security_server = SecurityServer::new(String::new(), exceptions_config);
1412 security_server.set_enforcing(true);
1413
1414 const EXCEPTIONS_POLICY: &[u8] =
1415 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1416 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1417
1418 let source_sid = security_server
1419 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1420 .unwrap();
1421 let target_sid = security_server
1422 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1423 .unwrap();
1424 let other_sid = security_server
1425 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1426 .unwrap();
1427 let permissive_sid = security_server
1428 .security_context_to_sid(
1429 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1430 )
1431 .unwrap();
1432 let unmatched_sid = security_server
1433 .security_context_to_sid(
1434 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1435 )
1436 .unwrap();
1437 let todo_permissive_sid = security_server
1438 .security_context_to_sid(
1439 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1440 )
1441 .unwrap();
1442
1443 let permission_check = security_server.as_permission_check();
1444
1445 assert_eq!(
1447 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid),
1448 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1449 );
1450
1451 assert_eq!(
1453 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint),
1454 PermissionCheckResult {
1455 permit: true,
1456 audit: true,
1457 todo_bug: Some(NonZeroU64::new(1).unwrap())
1458 }
1459 );
1460
1461 assert_eq!(
1463 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans),
1464 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1465 );
1466
1467 assert_eq!(
1469 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint),
1470 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1471 );
1472
1473 assert_eq!(
1475 permission_check.has_permission(
1476 other_sid,
1477 target_sid,
1478 CommonFsNodePermission::Read.for_class(FileClass::Character)
1479 ),
1480 PermissionCheckResult {
1481 permit: true,
1482 audit: true,
1483 todo_bug: Some(NonZeroU64::new(2).unwrap())
1484 }
1485 );
1486
1487 assert_eq!(
1489 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint),
1490 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1491 );
1492
1493 assert_eq!(
1495 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint),
1496 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1497 );
1498
1499 assert_eq!(
1501 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint),
1502 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1503 );
1504
1505 assert_eq!(
1508 permission_check.has_permission(
1509 todo_permissive_sid,
1510 target_sid,
1511 FilePermission::Entrypoint
1512 ),
1513 PermissionCheckResult {
1514 permit: true,
1515 audit: true,
1516 todo_bug: Some(NonZeroU64::new(5).unwrap())
1517 }
1518 );
1519 assert_eq!(
1520 permission_check.has_permission(
1521 todo_permissive_sid,
1522 todo_permissive_sid,
1523 FilePermission::Entrypoint
1524 ),
1525 PermissionCheckResult {
1526 permit: true,
1527 audit: true,
1528 todo_bug: Some(NonZeroU64::new(5).unwrap())
1529 }
1530 );
1531 assert_eq!(
1532 permission_check.has_permission(
1533 todo_permissive_sid,
1534 target_sid,
1535 FilePermission::Entrypoint
1536 ),
1537 PermissionCheckResult {
1538 permit: true,
1539 audit: true,
1540 todo_bug: Some(NonZeroU64::new(5).unwrap())
1541 }
1542 );
1543 }
1544
1545 #[test]
1546 fn handle_unknown() {
1547 let security_server = security_server_with_tests_policy();
1548
1549 let sid = security_server
1550 .security_context_to_sid("user0:object_r:type0:s0".into())
1551 .expect("Resolve Context to SID");
1552
1553 const REJECT_POLICY: &[u8] = include_bytes!(
1557 "../testdata/composite_policies/compiled/handle_unknown_policy-reject.pp"
1558 );
1559 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1560
1561 security_server.set_enforcing(true);
1562
1563 const DENY_POLICY: &[u8] =
1565 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny.pp");
1566 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1567 let permission_check = security_server.as_permission_check();
1568
1569 assert_eq!(
1571 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1572 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1573 );
1574 assert_eq!(
1575 permission_check.has_permission(sid, sid, DirPermission::AddName),
1576 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1577 );
1578
1579 assert_eq!(
1581 permission_check.has_permission(sid, sid, DirPermission::Search),
1582 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1583 );
1584 assert_eq!(
1585 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1586 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1587 );
1588
1589 const ALLOW_POLICY: &[u8] = include_bytes!(
1591 "../testdata/composite_policies/compiled/handle_unknown_policy-allow.pp"
1592 );
1593 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1594 let permission_check = security_server.as_permission_check();
1595
1596 assert_eq!(
1598 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1599 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1600 );
1601 assert_eq!(
1602 permission_check.has_permission(sid, sid, DirPermission::AddName),
1603 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1604 );
1605
1606 assert_eq!(
1608 permission_check.has_permission(sid, sid, DirPermission::Search),
1609 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1610 );
1611 assert_eq!(
1612 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1613 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1614 );
1615 }
1616}