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