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