1use crate::access_vector_cache::{
6 AccessVectorCache, CacheStats, KernelXpermsAccessDecision, Query,
7};
8use crate::exceptions_config::ExceptionsConfig;
9use crate::permission_check::PermissionCheck;
10use crate::policy::metadata::HandleUnknown;
11use crate::policy::parser::PolicyData;
12use crate::policy::{
13 AccessDecision, AccessVector, AccessVectorComputer, ClassId, ClassPermissionId,
14 FsUseLabelAndType, FsUseType, KernelAccessDecision, Policy, SELINUX_AVD_FLAGS_PERMISSIVE,
15 SecurityContext, XpermsBitmap, XpermsKind, parse_policy_by_value,
16};
17use crate::sid_table::SidTable;
18use crate::sync::RwLock;
19use crate::{
20 ClassPermission, FileSystemLabel, FileSystemLabelingScheme, FileSystemMountOptions,
21 FileSystemMountSids, FsNodeClass, InitialSid, KernelClass, KernelPermission, NullessByteStr,
22 ObjectClass, PolicyCap, SeLinuxStatus, SeLinuxStatusPublisher, SecurityId,
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 fn compute_access_decision_raw(
117 &self,
118 source_sid: SecurityId,
119 target_sid: SecurityId,
120 target_class: ObjectClass,
121 ) -> AccessDecision {
122 let Some(active_policy) = self.active_policy.as_ref() else {
123 return AccessDecision::allow(AccessVector::ALL);
125 };
126
127 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
128 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
129
130 let mut decision = active_policy.parsed.compute_access_decision(
131 &source_context,
132 &target_context,
133 target_class,
134 );
135
136 decision.todo_bug = active_policy.exceptions.lookup(
137 source_context.type_(),
138 target_context.type_(),
139 target_class,
140 );
141
142 decision
143 }
144}
145
146pub(crate) struct SecurityServerBackend {
147 state: RwLock<SecurityServerState>,
149
150 is_enforcing: AtomicBool,
152}
153
154pub struct SecurityServer {
155 access_vector_cache: AccessVectorCache,
158
159 backend: Arc<SecurityServerBackend>,
161
162 exceptions: Vec<String>,
164}
165
166impl SecurityServer {
167 pub fn new_default() -> Arc<Self> {
169 Self::new(String::new(), Vec::new())
170 }
171
172 pub fn new(options: String, exceptions: Vec<String>) -> Arc<Self> {
174 assert_eq!(options, String::new());
176
177 let backend = Arc::new(SecurityServerBackend {
178 state: RwLock::new(SecurityServerState {
179 active_policy: None,
180 booleans: SeLinuxBooleans::default(),
181 status_publisher: None,
182 policy_change_count: 0,
183 }),
184 is_enforcing: AtomicBool::new(false),
185 });
186
187 let access_vector_cache = AccessVectorCache::new(backend.clone());
188
189 Arc::new(Self { access_vector_cache, backend, exceptions })
190 }
191
192 pub fn as_permission_check<'a>(self: &'a Self) -> PermissionCheck<'a> {
195 PermissionCheck::new(self, &self.access_vector_cache)
196 }
197
198 pub fn security_context_to_sid(
202 &self,
203 security_context: NullessByteStr<'_>,
204 ) -> Result<SecurityId, anyhow::Error> {
205 self.backend.compute_sid(|active_policy| {
206 active_policy
207 .parsed
208 .parse_security_context(security_context)
209 .map_err(anyhow::Error::from)
210 })
211 }
212
213 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
218 let locked_state = self.backend.state.read();
219 let active_policy = locked_state.active_policy.as_ref()?;
220 let context = active_policy.sid_table.try_sid_to_security_context(sid)?;
221 Some(active_policy.parsed.serialize_security_context(context))
222 }
223
224 pub fn sid_to_security_context_with_nul(&self, sid: SecurityId) -> Option<Vec<u8>> {
226 self.sid_to_security_context(sid).map(|mut context| {
227 context.push(0u8);
228 context
229 })
230 }
231
232 pub fn load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
234 let unvalidated_policy = parse_policy_by_value(binary_policy)?;
237 let parsed = Arc::new(unvalidated_policy.validate()?);
238 let binary = parsed.binary().clone();
239
240 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
241 let exceptions = ExceptionsConfig::new(&parsed, &exceptions)?;
242
243 self.with_mut_state_and_update_status(|state| {
245 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
246 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
247 } else {
248 SidTable::new(parsed.clone())
249 };
250
251 state.booleans.reset(
254 parsed
255 .conditional_booleans()
256 .iter()
257 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
259 .collect(),
260 );
261
262 state.active_policy = Some(ActivePolicy { parsed, binary, sid_table, exceptions });
263 state.policy_change_count += 1;
264 });
265
266 Ok(())
267 }
268
269 pub fn get_binary_policy(&self) -> Option<PolicyData> {
271 self.backend.state.read().active_policy.as_ref().map(|p| p.binary.clone())
272 }
273
274 pub fn set_enforcing(&self, enforcing: bool) {
276 self.with_mut_state_and_update_status(|_| {
277 self.backend.is_enforcing.store(enforcing, Ordering::Release);
278 });
279 }
280
281 pub fn is_enforcing(&self) -> bool {
282 self.backend.is_enforcing.load(Ordering::Acquire)
283 }
284
285 pub fn deny_unknown(&self) -> bool {
288 self.backend.state.read().deny_unknown()
289 }
290
291 pub fn reject_unknown(&self) -> bool {
294 self.backend.state.read().reject_unknown()
295 }
296
297 pub fn conditional_booleans(&self) -> Vec<String> {
300 self.backend.state.read().booleans.names()
301 }
302
303 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
305 self.backend.state.read().booleans.get(name)
306 }
307
308 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
310 self.backend.state.write().booleans.set_pending(name, value)
311 }
312
313 pub fn commit_pending_booleans(&self) {
315 self.with_mut_state_and_update_status(|state| {
317 state.booleans.commit_pending();
318 state.policy_change_count += 1;
319 });
320 }
321
322 pub fn is_policycap_enabled(&self, policy_cap: PolicyCap) -> bool {
324 let locked_state = self.backend.state.read();
325 let Some(policy) = &locked_state.active_policy else {
326 return false;
327 };
328 policy.parsed.has_policycap(policy_cap)
329 }
330
331 pub fn avc_cache_stats(&self) -> CacheStats {
333 self.access_vector_cache.cache_stats()
334 }
335
336 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
338 let locked_state = self.backend.state.read();
339 let names = locked_state
340 .expect_active_policy()
341 .parsed
342 .classes()
343 .iter()
344 .map(|class| class.class_name.to_vec())
345 .collect();
346 Ok(names)
347 }
348
349 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
351 let locked_state = self.backend.state.read();
352 Ok(locked_state
353 .expect_active_policy()
354 .parsed
355 .classes()
356 .iter()
357 .find(|class| *(class.class_name) == *(name.as_bytes()))
358 .ok_or(())?
359 .class_id)
360 }
361
362 pub fn class_permissions_by_name(
366 &self,
367 name: &str,
368 ) -> Result<Vec<(ClassPermissionId, Vec<u8>)>, ()> {
369 let locked_state = self.backend.state.read();
370 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
371 }
372
373 pub fn resolve_fs_label(
377 &self,
378 fs_type: NullessByteStr<'_>,
379 mount_options: &FileSystemMountOptions,
380 ) -> FileSystemLabel {
381 let mut locked_state = self.backend.state.write();
382 let active_policy = locked_state.expect_active_policy_mut();
383
384 let mount_sids = FileSystemMountSids {
385 context: sid_from_mount_option(active_policy, &mount_options.context),
386 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context),
387 def_context: sid_from_mount_option(active_policy, &mount_options.def_context),
388 root_context: sid_from_mount_option(active_policy, &mount_options.root_context),
389 };
390 if let Some(mountpoint_sid) = mount_sids.context {
391 FileSystemLabel {
395 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
396 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
397 mount_sids,
398 }
399 } else if let Some(FsUseLabelAndType { context, use_type }) =
400 active_policy.parsed.fs_use_label_and_type(fs_type)
401 {
402 let fs_sid_from_policy =
404 active_policy.sid_table.security_context_to_sid(&context).unwrap();
405 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
406 FileSystemLabel {
407 sid: fs_sid,
408 scheme: FileSystemLabelingScheme::FsUse {
409 fs_use_type: use_type,
410 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
411 },
412 mount_sids,
413 }
414 } else if let Some(context) =
415 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
416 {
417 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
419 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
420
421 let fs_type = fs_type.as_bytes();
431 let mut supports_seclabel = matches!(fs_type, b"sysfs" | b"tracefs" | b"pstore");
432 supports_seclabel |= matches!(fs_type, b"cgroup" | b"cgroup2")
433 && active_policy.parsed.has_policycap(PolicyCap::CgroupSeclabel);
434 supports_seclabel |= fs_type == b"functionfs"
435 && active_policy.parsed.has_policycap(PolicyCap::FunctionfsSeclabel);
436
437 FileSystemLabel {
438 sid: fs_sid,
439 scheme: FileSystemLabelingScheme::GenFsCon { supports_seclabel },
440 mount_sids,
441 }
442 } else {
443 FileSystemLabel {
445 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
446 scheme: FileSystemLabelingScheme::FsUse {
447 fs_use_type: FsUseType::Xattr,
448 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
449 },
450 mount_sids,
451 }
452 }
453 }
454
455 pub fn genfscon_label_for_fs_and_path(
460 &self,
461 fs_type: NullessByteStr<'_>,
462 node_path: NullessByteStr<'_>,
463 class_id: Option<KernelClass>,
464 ) -> Result<SecurityId, anyhow::Error> {
465 self.backend.compute_sid(|active_policy| {
466 active_policy
467 .parsed
468 .genfscon_label_for_fs_and_path(fs_type, node_path.into(), class_id)
469 .ok_or_else(|| {
470 anyhow::anyhow!("Genfscon label requested for non-genfscon labeled filesystem")
471 })
472 })
473 }
474
475 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
480 let locked_state = self.backend.state.read();
481 let active_policy = locked_state.expect_active_policy();
482 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
483 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
484 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
485 }
486
487 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
494 self.with_mut_state_and_update_status(|state| {
495 assert!(state.status_publisher.is_none());
496 state.status_publisher = Some(status_holder);
497 });
498 }
499
500 fn with_mut_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
504 let mut locked_state = self.backend.state.write();
505 f(locked_state.deref_mut());
506 let new_value = SeLinuxStatus {
507 is_enforcing: self.is_enforcing(),
508 change_count: locked_state.policy_change_count,
509 deny_unknown: locked_state.deny_unknown(),
510 };
511 if let Some(status_publisher) = &mut locked_state.status_publisher {
512 status_publisher.set_status(new_value);
513 }
514
515 std::mem::drop(locked_state);
518 self.access_vector_cache.reset();
519 }
520
521 pub fn compute_create_sid_raw(
527 &self,
528 source_sid: SecurityId,
529 target_sid: SecurityId,
530 target_class: ClassId,
531 ) -> Result<SecurityId, anyhow::Error> {
532 self.backend.compute_create_sid_raw(source_sid, target_sid, target_class.into())
533 }
534
535 pub fn compute_access_decision_raw(
538 &self,
539 source_sid: SecurityId,
540 target_sid: SecurityId,
541 target_class: ClassId,
542 ) -> AccessDecision {
543 self.backend.compute_access_decision_raw(source_sid, target_sid, target_class.into())
544 }
545}
546
547impl SecurityServerBackend {
548 fn compute_create_sid_raw(
549 &self,
550 source_sid: SecurityId,
551 target_sid: SecurityId,
552 target_class: ObjectClass,
553 ) -> Result<SecurityId, anyhow::Error> {
554 self.compute_sid(|active_policy| {
555 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
556 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
557
558 Ok(active_policy.parsed.compute_create_context(
559 source_context,
560 target_context,
561 target_class,
562 ))
563 })
564 .context("computing new security context from policy")
565 }
566
567 fn compute_sid(
569 &self,
570 compute_context: impl Fn(&ActivePolicy) -> Result<SecurityContext, anyhow::Error>,
571 ) -> Result<SecurityId, anyhow::Error> {
572 let readable_state = self.state.read();
575 let policy_change_count = readable_state.policy_change_count;
576 let policy_state = readable_state
577 .active_policy
578 .as_ref()
579 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
580 let context = compute_context(policy_state)?;
581 if let Some(sid) = policy_state.sid_table.security_context_to_existing_sid(&context) {
582 return Ok(sid);
583 }
584 std::mem::drop(readable_state);
585
586 let mut writable_state = self.state.write();
591 let needs_recompute = policy_change_count != writable_state.policy_change_count;
592 let policy_state = writable_state.active_policy.as_mut().unwrap();
593 let context = if needs_recompute { compute_context(policy_state)? } else { context };
594 policy_state.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
595 }
596
597 fn compute_access_decision_raw(
598 &self,
599 source_sid: SecurityId,
600 target_sid: SecurityId,
601 target_class: ObjectClass,
602 ) -> AccessDecision {
603 let locked_state = self.state.read();
604
605 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class)
606 }
607}
608
609impl Query for SecurityServerBackend {
610 fn compute_access_decision(
611 &self,
612 source_sid: SecurityId,
613 target_sid: SecurityId,
614 target_class: KernelClass,
615 ) -> KernelAccessDecision {
616 let locked_state = self.state.read();
617 let decision =
618 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class.into());
619 locked_state.access_decision_to_kernel_access_decision(target_class, decision)
620 }
621
622 fn compute_create_sid(
623 &self,
624 source_sid: SecurityId,
625 target_sid: SecurityId,
626 target_class: KernelClass,
627 ) -> Result<SecurityId, anyhow::Error> {
628 self.compute_create_sid_raw(source_sid, target_sid, target_class.into())
629 }
630
631 fn compute_new_fs_node_sid_with_name(
632 &self,
633 source_sid: SecurityId,
634 target_sid: SecurityId,
635 fs_node_class: FsNodeClass,
636 fs_node_name: NullessByteStr<'_>,
637 ) -> Option<SecurityId> {
638 let mut locked_state = self.state.write();
639
640 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
642
643 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
644 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
645
646 let new_file_context = active_policy.parsed.compute_create_context_with_name(
647 source_context,
648 target_context,
649 fs_node_class,
650 fs_node_name,
651 )?;
652
653 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
654 }
655
656 fn compute_xperms_access_decision(
657 &self,
658 xperms_kind: XpermsKind,
659 source_sid: SecurityId,
660 target_sid: SecurityId,
661 permission: KernelPermission,
662 xperms_prefix: u8,
663 ) -> KernelXpermsAccessDecision {
664 let locked_state = self.state.read();
665
666 let active_policy = match &locked_state.active_policy {
667 Some(active_policy) => active_policy,
668 None => {
670 return KernelXpermsAccessDecision {
671 allow: XpermsBitmap::ALL,
672 audit: XpermsBitmap::NONE,
673 permissive: false,
674 has_todo: false,
675 };
676 }
677 };
678
679 let base_decision_raw = locked_state.compute_access_decision_raw(
682 source_sid,
683 target_sid,
684 permission.class().into(),
685 );
686 let base_decision = locked_state
687 .access_decision_to_kernel_access_decision(permission.class(), base_decision_raw);
688 let permission_access_vector = permission.as_access_vector();
689 let base_permit =
690 base_decision.allow & permission_access_vector == permission_access_vector;
691 let base_audit = base_decision.audit & permission_access_vector == permission_access_vector;
692
693 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
695 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
696 let xperms_decision = active_policy.parsed.compute_xperms_access_decision(
697 xperms_kind,
698 &source_context,
699 &target_context,
700 permission.class(),
701 xperms_prefix,
702 );
703
704 let allow = if !base_permit { XpermsBitmap::NONE } else { xperms_decision.allow };
706 let audit = if base_audit {
707 XpermsBitmap::ALL
708 } else {
709 (xperms_decision.allow & xperms_decision.auditallow)
710 | (!xperms_decision.allow & xperms_decision.auditdeny)
711 };
712 let permissive = (base_decision.flags & SELINUX_AVD_FLAGS_PERMISSIVE) != 0;
713 let has_todo = base_decision.todo_bug.is_some();
714 KernelXpermsAccessDecision { allow, audit, permissive, has_todo }
715 }
716}
717
718impl AccessVectorComputer for SecurityServerBackend {
719 fn access_decision_to_kernel_access_decision(
720 &self,
721 class: KernelClass,
722 av: AccessDecision,
723 ) -> KernelAccessDecision {
724 self.state.read().access_decision_to_kernel_access_decision(class, av)
725 }
726}
727
728impl AccessVectorComputer for SecurityServerState {
729 fn access_decision_to_kernel_access_decision(
730 &self,
731 class: KernelClass,
732 av: AccessDecision,
733 ) -> KernelAccessDecision {
734 match &self.active_policy {
735 Some(policy) => policy.parsed.access_decision_to_kernel_access_decision(class, av),
736 None => KernelAccessDecision {
737 allow: AccessVector::ALL,
738 audit: AccessVector::NONE,
739 flags: 0,
740 todo_bug: None,
741 },
742 }
743 }
744}
745
746fn sid_from_mount_option(
749 active_policy: &mut ActivePolicy,
750 mount_option: &Option<Vec<u8>>,
751) -> Option<SecurityId> {
752 if let Some(label) = mount_option.as_ref() {
753 Some(
754 if let Some(context) = active_policy.parsed.parse_security_context(label.into()).ok() {
755 active_policy.sid_table.security_context_to_sid(&context).unwrap()
756 } else {
757 InitialSid::Unlabeled.into()
759 },
760 )
761 } else {
762 None
763 }
764}
765
766#[cfg(test)]
767mod tests {
768 use super::*;
769 use crate::permission_check::PermissionCheckResult;
770 use crate::{
771 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
772 ProcessPermission,
773 };
774 use std::num::NonZeroU64;
775
776 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
777 const TESTS_BINARY_POLICY: &[u8] =
778 include_bytes!("../testdata/micro_policies/security_server_tests_policy.pp");
779 const MINIMAL_BINARY_POLICY: &[u8] =
780 include_bytes!("../testdata/composite_policies/compiled/minimal_policy.pp");
781
782 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
783 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
784 let security_server = SecurityServer::new_default();
785 assert_eq!(
786 Ok(()),
787 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
788 );
789 security_server
790 }
791
792 #[test]
793 fn compute_access_vector_allows_all() {
794 let security_server = SecurityServer::new_default();
795 let sid1 = InitialSid::Kernel.into();
796 let sid2 = InitialSid::Unlabeled.into();
797 assert_eq!(
798 security_server
799 .backend
800 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
801 .allow,
802 AccessVector::ALL
803 );
804 }
805
806 #[test]
807 fn loaded_policy_can_be_retrieved() {
808 let security_server = security_server_with_tests_policy();
809 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_slice());
810 }
811
812 #[test]
813 fn loaded_policy_is_validated() {
814 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
815 let security_server = SecurityServer::new_default();
816 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
817 }
818
819 #[test]
820 fn enforcing_mode_is_reported() {
821 let security_server = SecurityServer::new_default();
822 assert!(!security_server.is_enforcing());
823
824 security_server.set_enforcing(true);
825 assert!(security_server.is_enforcing());
826 }
827
828 #[test]
829 fn without_policy_conditional_booleans_are_empty() {
830 let security_server = SecurityServer::new_default();
831 assert!(security_server.conditional_booleans().is_empty());
832 }
833
834 #[test]
835 fn conditional_booleans_can_be_queried() {
836 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
837 let security_server = SecurityServer::new_default();
838 assert_eq!(
839 Ok(()),
840 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
841 );
842
843 let booleans = security_server.conditional_booleans();
844 assert!(!booleans.is_empty());
845 let boolean = booleans[0].as_str();
846
847 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
848 assert!(security_server.get_boolean(boolean).is_ok());
849 }
850
851 #[test]
852 fn conditional_booleans_can_be_changed() {
853 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
854 let security_server = SecurityServer::new_default();
855 assert_eq!(
856 Ok(()),
857 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
858 );
859
860 let booleans = security_server.conditional_booleans();
861 assert!(!booleans.is_empty());
862 let boolean = booleans[0].as_str();
863
864 let (active, pending) = security_server.get_boolean(boolean).unwrap();
865 assert_eq!(active, pending, "Initially active and pending values should match");
866
867 security_server.set_pending_boolean(boolean, !active).unwrap();
868 let (active, pending) = security_server.get_boolean(boolean).unwrap();
869 assert!(active != pending, "Before commit pending should differ from active");
870
871 security_server.commit_pending_booleans();
872 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
873 assert_eq!(final_active, pending, "Pending value should be active after commit");
874 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
875 }
876
877 #[test]
878 fn parse_security_context_no_policy() {
879 let security_server = SecurityServer::new_default();
880 let error = security_server
881 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
882 .expect_err("expected error");
883 let error_string = format!("{:?}", error);
884 assert!(error_string.contains("no policy"));
885 }
886
887 #[test]
888 fn compute_new_fs_node_sid_no_defaults() {
889 let security_server = SecurityServer::new_default();
890 let policy_bytes =
891 include_bytes!("../testdata/micro_policies/file_no_defaults_policy.pp").to_vec();
892 security_server.load_policy(policy_bytes).expect("binary policy loads");
893
894 let source_sid = security_server
895 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
896 .expect("creating SID from security context should succeed");
897 let target_sid = security_server
898 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
899 .expect("creating SID from security context should succeed");
900
901 let computed_sid = security_server
902 .as_permission_check()
903 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
904 .expect("new sid computed");
905 let computed_context = security_server
906 .sid_to_security_context(computed_sid)
907 .expect("computed sid associated with context");
908
909 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
912 }
913
914 #[test]
915 fn compute_new_fs_node_sid_source_defaults() {
916 let security_server = SecurityServer::new_default();
917 let policy_bytes =
918 include_bytes!("../testdata/micro_policies/file_source_defaults_policy.pp").to_vec();
919 security_server.load_policy(policy_bytes).expect("binary policy loads");
920
921 let source_sid = security_server
922 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
923 .expect("creating SID from security context should succeed");
924 let target_sid = security_server
925 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
926 .expect("creating SID from security context should succeed");
927
928 let computed_sid = security_server
929 .as_permission_check()
930 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
931 .expect("new sid computed");
932 let computed_context = security_server
933 .sid_to_security_context(computed_sid)
934 .expect("computed sid associated with context");
935
936 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
939 }
940
941 #[test]
942 fn compute_new_fs_node_sid_target_defaults() {
943 let security_server = SecurityServer::new_default();
944 let policy_bytes =
945 include_bytes!("../testdata/micro_policies/file_target_defaults_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-s2: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:s1-s3:c0".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"file_u:object_r:file_t:s0");
965 }
966
967 #[test]
968 fn compute_new_fs_node_sid_range_source_low_default() {
969 let security_server = SecurityServer::new_default();
970 let policy_bytes =
971 include_bytes!("../testdata/micro_policies/file_range_source_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:s0-s1:c0".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:s1".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_source_low_high_default() {
995 let security_server = SecurityServer::new_default();
996 let policy_bytes =
997 include_bytes!("../testdata/micro_policies/file_range_source_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:s0-s1:c0".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:s1".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_source_high_default() {
1022 let security_server = SecurityServer::new_default();
1023 let policy_bytes =
1024 include_bytes!("../testdata/micro_policies/file_range_source_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-s1:c0".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".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_range_target_low_default() {
1048 let security_server = SecurityServer::new_default();
1049 let policy_bytes =
1050 include_bytes!("../testdata/micro_policies/file_range_target_low_policy.pp").to_vec();
1051 security_server.load_policy(policy_bytes).expect("binary policy loads");
1052
1053 let source_sid = security_server
1054 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1055 .expect("creating SID from security context should succeed");
1056 let target_sid = security_server
1057 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1058 .expect("creating SID from security context should succeed");
1059
1060 let computed_sid = security_server
1061 .as_permission_check()
1062 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1063 .expect("new sid computed");
1064 let computed_context = security_server
1065 .sid_to_security_context(computed_sid)
1066 .expect("computed sid associated with context");
1067
1068 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1070 }
1071
1072 #[test]
1073 fn compute_new_fs_node_sid_range_target_low_high_default() {
1074 let security_server = SecurityServer::new_default();
1075 let policy_bytes =
1076 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy.pp")
1077 .to_vec();
1078 security_server.load_policy(policy_bytes).expect("binary policy loads");
1079
1080 let source_sid = security_server
1081 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1082 .expect("creating SID from security context should succeed");
1083 let target_sid = security_server
1084 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1085 .expect("creating SID from security context should succeed");
1086
1087 let computed_sid = security_server
1088 .as_permission_check()
1089 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1090 .expect("new sid computed");
1091 let computed_context = security_server
1092 .sid_to_security_context(computed_sid)
1093 .expect("computed sid associated with context");
1094
1095 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1097 }
1098
1099 #[test]
1100 fn compute_new_fs_node_sid_range_target_high_default() {
1101 let security_server = SecurityServer::new_default();
1102 let policy_bytes =
1103 include_bytes!("../testdata/micro_policies/file_range_target_high_policy.pp").to_vec();
1104 security_server.load_policy(policy_bytes).expect("binary policy loads");
1105
1106 let source_sid = security_server
1107 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1108 .expect("creating SID from security context should succeed");
1109 let target_sid = security_server
1110 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1111 .expect("creating SID from security context should succeed");
1112
1113 let computed_sid = security_server
1114 .as_permission_check()
1115 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1116 .expect("new sid computed");
1117 let computed_context = security_server
1118 .sid_to_security_context(computed_sid)
1119 .expect("computed sid associated with context");
1120
1121 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1123 }
1124
1125 #[test]
1126 fn compute_new_fs_node_sid_with_name() {
1127 let security_server = SecurityServer::new_default();
1128 let policy_bytes =
1129 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy.pp")
1130 .to_vec();
1131 security_server.load_policy(policy_bytes).expect("binary policy loads");
1132
1133 let source_sid = security_server
1134 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1135 .expect("creating SID from security context should succeed");
1136 let target_sid = security_server
1137 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1138 .expect("creating SID from security context should succeed");
1139
1140 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1141 let computed_sid = security_server
1142 .as_permission_check()
1143 .compute_new_fs_node_sid(
1144 source_sid,
1145 target_sid,
1146 FileClass::File.into(),
1147 SPECIAL_FILE_NAME.into(),
1148 )
1149 .expect("new sid computed");
1150 let computed_context = security_server
1151 .sid_to_security_context(computed_sid)
1152 .expect("computed sid associated with context");
1153
1154 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1156
1157 let computed_sid = security_server
1158 .as_permission_check()
1159 .compute_new_fs_node_sid(
1160 source_sid,
1161 target_sid,
1162 FileClass::ChrFile.into(),
1163 SPECIAL_FILE_NAME.into(),
1164 )
1165 .expect("new sid computed");
1166 let computed_context = security_server
1167 .sid_to_security_context(computed_sid)
1168 .expect("computed sid associated with context");
1169
1170 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1173
1174 const OTHER_FILE_NAME: &[u8] = b"other_file";
1175 let computed_sid = security_server
1176 .as_permission_check()
1177 .compute_new_fs_node_sid(
1178 source_sid,
1179 target_sid,
1180 FileClass::File.into(),
1181 OTHER_FILE_NAME.into(),
1182 )
1183 .expect("new sid computed");
1184 let computed_context = security_server
1185 .sid_to_security_context(computed_sid)
1186 .expect("computed sid associated with context");
1187
1188 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1191 }
1192
1193 #[test]
1194 fn permissions_are_fresh_after_different_policy_load() {
1195 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1196 let allow_fork_bytes =
1197 include_bytes!("../testdata/composite_policies/compiled/allow_fork.pp").to_vec();
1198 let context = b"source_u:object_r:source_t:s0:c0";
1199
1200 let security_server = SecurityServer::new_default();
1201 security_server.set_enforcing(true);
1202
1203 let permission_check = security_server.as_permission_check();
1204
1205 assert_eq!(
1207 Ok(()),
1208 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1209 );
1210 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1211
1212 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1214
1215 assert_eq!(
1217 Ok(()),
1218 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1219 );
1220
1221 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1223 }
1224
1225 #[test]
1226 fn unknown_sids_are_effectively_unlabeled() {
1227 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1228 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy.pp"
1229 )
1230 .to_vec();
1231 let with_additional_domain_policy_bytes = include_bytes!(
1232 "../testdata/composite_policies/compiled/with_additional_domain_policy.pp"
1233 )
1234 .to_vec();
1235 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1236 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1237
1238 let security_server = SecurityServer::new_default();
1239 security_server.set_enforcing(true);
1240
1241 assert_eq!(
1244 Ok(()),
1245 security_server
1246 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1247 .map_err(|e| format!("{:?}", e))
1248 );
1249 let allowed_type_sid =
1250 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1251 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1252
1253 assert_eq!(
1256 Ok(()),
1257 security_server
1258 .load_policy(with_additional_domain_policy_bytes.clone())
1259 .map_err(|e| format!("{:?}", e))
1260 );
1261 let additional_type_sid =
1262 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1263 assert_eq!(
1264 allowed_type_sid,
1265 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1266 );
1267
1268 let permission_check = security_server.as_permission_check();
1269
1270 assert!(
1274 !permission_check
1275 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1276 .granted
1277 );
1278 assert!(
1279 !permission_check
1280 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1281 .granted
1282 );
1283 assert!(
1284 !permission_check
1285 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1286 .granted
1287 );
1288 assert!(
1289 !permission_check
1290 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1291 .granted
1292 );
1293
1294 assert_eq!(
1296 Ok(()),
1297 security_server
1298 .load_policy(with_unlabeled_access_domain_policy_bytes)
1299 .map_err(|e| format!("{:?}", e))
1300 );
1301
1302 assert!(
1306 permission_check
1307 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1308 .granted
1309 );
1310 assert!(
1311 !permission_check
1312 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1313 .granted
1314 );
1315
1316 assert!(
1321 !permission_check
1322 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1323 .granted
1324 );
1325 assert!(
1326 permission_check
1327 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1328 .granted
1329 );
1330
1331 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1333
1334 assert_eq!(
1337 Ok(()),
1338 security_server
1339 .load_policy(with_additional_domain_policy_bytes)
1340 .map_err(|e| format!("{:?}", e))
1341 );
1342 assert_eq!(
1343 additional_type_context.to_vec(),
1344 security_server.sid_to_security_context(additional_type_sid).unwrap()
1345 );
1346 }
1347
1348 #[test]
1349 fn permission_check_permissive() {
1350 let security_server = security_server_with_tests_policy();
1351 security_server.set_enforcing(false);
1352 assert!(!security_server.is_enforcing());
1353
1354 let sid =
1355 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1356 let permission_check = security_server.as_permission_check();
1357
1358 assert_eq!(
1361 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1362 PermissionCheckResult {
1363 granted: true,
1364 audit: false,
1365 permissive: false,
1366 todo_bug: None
1367 }
1368 );
1369
1370 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1374 assert_eq!(
1375 result,
1376 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1377 );
1378 assert!(result.permit());
1379
1380 let result = permission_check.has_permission(
1384 sid,
1385 sid,
1386 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1387 );
1388 assert_eq!(
1389 result,
1390 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1391 );
1392 assert!(result.permit());
1393 }
1394
1395 #[test]
1396 fn permission_check_enforcing() {
1397 let security_server = security_server_with_tests_policy();
1398 security_server.set_enforcing(true);
1399 assert!(security_server.is_enforcing());
1400
1401 let sid =
1402 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1403 let permission_check = security_server.as_permission_check();
1404
1405 let result = permission_check.has_permission(sid, sid, ProcessPermission::Fork);
1407 assert_eq!(
1408 result,
1409 PermissionCheckResult {
1410 granted: true,
1411 audit: false,
1412 permissive: false,
1413 todo_bug: None
1414 }
1415 );
1416 assert!(result.permit());
1417
1418 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1421 assert_eq!(
1422 result,
1423 PermissionCheckResult {
1424 granted: false,
1425 audit: true,
1426 permissive: false,
1427 todo_bug: None
1428 }
1429 );
1430 assert!(!result.permit());
1431
1432 let result = permission_check.has_permission(
1435 sid,
1436 sid,
1437 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1438 );
1439 assert_eq!(
1440 result,
1441 PermissionCheckResult {
1442 granted: false,
1443 audit: true,
1444 permissive: false,
1445 todo_bug: None
1446 }
1447 );
1448 assert!(!result.permit());
1449 }
1450
1451 #[test]
1452 fn permissive_domain() {
1453 let security_server = security_server_with_tests_policy();
1454 security_server.set_enforcing(true);
1455 assert!(security_server.is_enforcing());
1456
1457 let permissive_sid = security_server
1458 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1459 .unwrap();
1460 let non_permissive_sid = security_server
1461 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1462 .unwrap();
1463
1464 let permission_check = security_server.as_permission_check();
1465
1466 let result = permission_check.has_permission(
1468 permissive_sid,
1469 permissive_sid,
1470 ProcessPermission::GetSched,
1471 );
1472 assert_eq!(
1473 result,
1474 PermissionCheckResult { granted: true, audit: false, permissive: true, todo_bug: None }
1475 );
1476 assert!(result.permit());
1477 let result = permission_check.has_permission(
1478 non_permissive_sid,
1479 non_permissive_sid,
1480 ProcessPermission::GetSched,
1481 );
1482 assert_eq!(
1483 result,
1484 PermissionCheckResult {
1485 granted: true,
1486 audit: false,
1487 permissive: false,
1488 todo_bug: None
1489 }
1490 );
1491 assert!(result.permit());
1492
1493 let result = permission_check.has_permission(
1496 permissive_sid,
1497 non_permissive_sid,
1498 ProcessPermission::GetSched,
1499 );
1500 assert_eq!(
1501 result,
1502 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1503 );
1504 assert!(result.permit());
1505 let result = permission_check.has_permission(
1506 non_permissive_sid,
1507 permissive_sid,
1508 ProcessPermission::GetSched,
1509 );
1510 assert_eq!(
1511 result,
1512 PermissionCheckResult {
1513 granted: false,
1514 audit: true,
1515 permissive: false,
1516 todo_bug: None
1517 }
1518 );
1519 assert!(!result.permit());
1520
1521 let result = permission_check.has_permission(
1526 permissive_sid,
1527 non_permissive_sid,
1528 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1529 );
1530 assert_eq!(
1531 result,
1532 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1533 );
1534 assert!(result.permit());
1535 let result = permission_check.has_permission(
1536 non_permissive_sid,
1537 non_permissive_sid,
1538 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1539 );
1540 assert_eq!(
1541 result,
1542 PermissionCheckResult {
1543 granted: false,
1544 audit: true,
1545 permissive: false,
1546 todo_bug: None
1547 }
1548 );
1549 assert!(!result.permit());
1550 }
1551
1552 #[test]
1553 fn auditallow_and_dontaudit() {
1554 let security_server = security_server_with_tests_policy();
1555 security_server.set_enforcing(true);
1556 assert!(security_server.is_enforcing());
1557
1558 let audit_sid = security_server
1559 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1560 .unwrap();
1561
1562 let permission_check = security_server.as_permission_check();
1563
1564 let result = permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork);
1566 assert_eq!(
1567 result,
1568 PermissionCheckResult { granted: true, audit: true, permissive: false, todo_bug: None }
1569 );
1570 assert!(result.permit());
1571
1572 let result =
1574 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched);
1575 assert_eq!(
1576 result,
1577 PermissionCheckResult {
1578 granted: true,
1579 audit: false,
1580 permissive: false,
1581 todo_bug: None
1582 }
1583 );
1584 assert!(result.permit());
1585
1586 let result =
1588 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched);
1589 assert_eq!(
1590 result,
1591 PermissionCheckResult {
1592 granted: false,
1593 audit: false,
1594 permissive: false,
1595 todo_bug: None
1596 }
1597 );
1598 assert!(!result.permit());
1599
1600 let result =
1602 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid);
1603 assert_eq!(
1604 result,
1605 PermissionCheckResult {
1606 granted: false,
1607 audit: true,
1608 permissive: false,
1609 todo_bug: None
1610 }
1611 );
1612 assert!(!result.permit());
1613 }
1614
1615 #[test]
1616 fn access_checks_with_exceptions_config() {
1617 const EXCEPTIONS_CONFIG: &[&str] = &[
1618 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1620 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1621 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1622 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1623 "todo_permissive b/005 test_exception_todo_permissive_t",
1624 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1626 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1627 "todo_permissive b/103 test_undefined_source_t",
1628 ];
1629 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1630 let security_server = SecurityServer::new(String::new(), exceptions_config);
1631 security_server.set_enforcing(true);
1632
1633 const EXCEPTIONS_POLICY: &[u8] =
1634 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1635 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1636
1637 let source_sid = security_server
1638 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1639 .unwrap();
1640 let target_sid = security_server
1641 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1642 .unwrap();
1643 let other_sid = security_server
1644 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1645 .unwrap();
1646 let permissive_sid = security_server
1647 .security_context_to_sid(
1648 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1649 )
1650 .unwrap();
1651 let unmatched_sid = security_server
1652 .security_context_to_sid(
1653 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1654 )
1655 .unwrap();
1656 let todo_permissive_sid = security_server
1657 .security_context_to_sid(
1658 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1659 )
1660 .unwrap();
1661
1662 let permission_check = security_server.as_permission_check();
1663
1664 let result =
1666 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid);
1667 assert_eq!(
1668 result,
1669 PermissionCheckResult {
1670 granted: false,
1671 audit: true,
1672 permissive: false,
1673 todo_bug: None
1674 }
1675 );
1676 assert!(!result.permit());
1677
1678 let result =
1680 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint);
1681 assert_eq!(
1682 result,
1683 PermissionCheckResult {
1684 granted: true,
1685 audit: true,
1686 permissive: false,
1687 todo_bug: Some(NonZeroU64::new(1).unwrap())
1688 }
1689 );
1690 assert!(result.permit());
1691
1692 let result =
1694 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans);
1695 assert_eq!(
1696 result,
1697 PermissionCheckResult {
1698 granted: true,
1699 audit: false,
1700 permissive: false,
1701 todo_bug: None
1702 }
1703 );
1704 assert!(result.permit());
1705
1706 let result =
1708 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint);
1709 assert_eq!(
1710 result,
1711 PermissionCheckResult {
1712 granted: false,
1713 audit: true,
1714 permissive: false,
1715 todo_bug: None
1716 }
1717 );
1718 assert!(!result.permit());
1719
1720 let result = permission_check.has_permission(
1722 other_sid,
1723 target_sid,
1724 CommonFsNodePermission::Read.for_class(FileClass::ChrFile),
1725 );
1726 assert_eq!(
1727 result,
1728 PermissionCheckResult {
1729 granted: true,
1730 audit: true,
1731 permissive: false,
1732 todo_bug: Some(NonZeroU64::new(2).unwrap())
1733 }
1734 );
1735 assert!(result.permit());
1736
1737 let result =
1739 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint);
1740 assert_eq!(
1741 result,
1742 PermissionCheckResult {
1743 granted: false,
1744 audit: true,
1745 permissive: false,
1746 todo_bug: None
1747 }
1748 );
1749 assert!(!result.permit());
1750
1751 let result =
1753 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint);
1754 assert_eq!(
1755 result,
1756 PermissionCheckResult {
1757 granted: false,
1758 audit: true,
1759 permissive: false,
1760 todo_bug: None
1761 }
1762 );
1763 assert!(!result.permit());
1764
1765 let result =
1767 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint);
1768 assert_eq!(
1769 result,
1770 PermissionCheckResult {
1771 granted: true,
1772 audit: true,
1773 permissive: true,
1774 todo_bug: Some(NonZeroU64::new(4).unwrap())
1775 }
1776 );
1777 assert!(result.permit());
1778
1779 let result = permission_check.has_permission(
1782 todo_permissive_sid,
1783 target_sid,
1784 FilePermission::Entrypoint,
1785 );
1786 assert_eq!(
1787 result,
1788 PermissionCheckResult {
1789 granted: true,
1790 audit: true,
1791 permissive: false,
1792 todo_bug: Some(NonZeroU64::new(5).unwrap())
1793 }
1794 );
1795 assert!(result.permit());
1796 let result = permission_check.has_permission(
1797 todo_permissive_sid,
1798 todo_permissive_sid,
1799 FilePermission::Entrypoint,
1800 );
1801 assert_eq!(
1802 result,
1803 PermissionCheckResult {
1804 granted: true,
1805 audit: true,
1806 permissive: false,
1807 todo_bug: Some(NonZeroU64::new(5).unwrap())
1808 }
1809 );
1810 assert!(result.permit());
1811 let result = permission_check.has_permission(
1812 todo_permissive_sid,
1813 target_sid,
1814 FilePermission::Entrypoint,
1815 );
1816 assert_eq!(
1817 result,
1818 PermissionCheckResult {
1819 granted: true,
1820 audit: true,
1821 permissive: false,
1822 todo_bug: Some(NonZeroU64::new(5).unwrap())
1823 }
1824 );
1825 assert!(result.permit());
1826 }
1827
1828 #[test]
1829 fn handle_unknown() {
1830 let security_server = security_server_with_tests_policy();
1831
1832 let sid = security_server
1833 .security_context_to_sid("user0:object_r:type0:s0".into())
1834 .expect("Resolve Context to SID");
1835
1836 const REJECT_POLICY: &[u8] = include_bytes!(
1840 "../testdata/composite_policies/compiled/handle_unknown_policy-reject.pp"
1841 );
1842 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1843
1844 security_server.set_enforcing(true);
1845
1846 const DENY_POLICY: &[u8] =
1848 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny.pp");
1849 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1850 let permission_check = security_server.as_permission_check();
1851
1852 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1854 assert_eq!(
1855 result,
1856 PermissionCheckResult {
1857 granted: false,
1858 audit: true,
1859 permissive: false,
1860 todo_bug: None
1861 }
1862 );
1863 assert!(!result.permit());
1864 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1865 assert_eq!(
1866 result,
1867 PermissionCheckResult {
1868 granted: false,
1869 audit: true,
1870 permissive: false,
1871 todo_bug: None
1872 }
1873 );
1874 assert!(!result.permit());
1875
1876 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1878 assert_eq!(
1879 result,
1880 PermissionCheckResult {
1881 granted: true,
1882 audit: false,
1883 permissive: false,
1884 todo_bug: None
1885 }
1886 );
1887 assert!(result.permit());
1888 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1889 assert_eq!(
1890 result,
1891 PermissionCheckResult {
1892 granted: false,
1893 audit: true,
1894 permissive: false,
1895 todo_bug: None
1896 }
1897 );
1898 assert!(!result.permit());
1899
1900 const ALLOW_POLICY: &[u8] = include_bytes!(
1902 "../testdata/composite_policies/compiled/handle_unknown_policy-allow.pp"
1903 );
1904 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1905 let permission_check = security_server.as_permission_check();
1906
1907 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1909 assert_eq!(
1910 result,
1911 PermissionCheckResult {
1912 granted: true,
1913 audit: false,
1914 permissive: false,
1915 todo_bug: None
1916 }
1917 );
1918 assert!(result.permit());
1919 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1920 assert_eq!(
1921 result,
1922 PermissionCheckResult {
1923 granted: true,
1924 audit: false,
1925 permissive: false,
1926 todo_bug: None
1927 }
1928 );
1929 assert!(result.permit());
1930
1931 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1933 assert_eq!(
1934 result,
1935 PermissionCheckResult {
1936 granted: true,
1937 audit: false,
1938 permissive: false,
1939 todo_bug: None
1940 }
1941 );
1942 assert!(result.permit());
1943 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1944 assert_eq!(
1945 result,
1946 PermissionCheckResult {
1947 granted: false,
1948 audit: true,
1949 permissive: false,
1950 todo_bug: None
1951 }
1952 );
1953 assert!(!result.permit());
1954 }
1955}