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