1use crate::access_vector_cache::{
6 AccessVectorCache, CacheStats, KernelXpermsAccessDecision, Query,
7};
8use crate::exceptions_config::ExceptionsConfig;
9use crate::permission_check::{PerThreadCache, 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, AtomicU32, 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
91impl SecurityServerState {
92 fn deny_unknown(&self) -> bool {
93 self.active_policy
94 .as_ref()
95 .map_or(true, |p| p.parsed.handle_unknown() != HandleUnknown::Allow)
96 }
97 fn reject_unknown(&self) -> bool {
98 self.active_policy
99 .as_ref()
100 .map_or(false, |p| p.parsed.handle_unknown() == HandleUnknown::Reject)
101 }
102
103 fn expect_active_policy(&self) -> &ActivePolicy {
104 &self.active_policy.as_ref().expect("policy should be loaded")
105 }
106
107 fn expect_active_policy_mut(&mut self) -> &mut ActivePolicy {
108 self.active_policy.as_mut().expect("policy should be loaded")
109 }
110
111 fn compute_access_decision_raw(
112 &self,
113 source_sid: SecurityId,
114 target_sid: SecurityId,
115 target_class: ObjectClass,
116 ) -> AccessDecision {
117 let Some(active_policy) = self.active_policy.as_ref() else {
118 return AccessDecision::allow(AccessVector::ALL);
120 };
121
122 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
123 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
124
125 let mut decision = active_policy.parsed.compute_access_decision(
126 &source_context,
127 &target_context,
128 target_class,
129 );
130
131 decision.todo_bug = active_policy.exceptions.lookup(
132 source_context.type_(),
133 target_context.type_(),
134 target_class,
135 );
136
137 decision
138 }
139}
140
141pub(crate) struct SecurityServerBackend {
142 state: RwLock<SecurityServerState>,
144
145 is_enforcing: AtomicBool,
148
149 policy_change_count: AtomicU32,
154}
155
156pub struct SecurityServer {
157 access_vector_cache: AccessVectorCache,
160
161 backend: Arc<SecurityServerBackend>,
163
164 exceptions: Vec<String>,
166}
167
168impl SecurityServer {
169 pub fn new_default() -> Arc<Self> {
171 Self::new(String::new(), Vec::new())
172 }
173
174 pub fn new(options: String, exceptions: Vec<String>) -> Arc<Self> {
176 assert_eq!(options, String::new());
178
179 let backend = Arc::new(SecurityServerBackend {
180 state: RwLock::new(SecurityServerState {
181 active_policy: None,
182 booleans: SeLinuxBooleans::default(),
183 status_publisher: None,
184 }),
185 is_enforcing: AtomicBool::new(false),
186 policy_change_count: AtomicU32::new(0),
187 });
188
189 let access_vector_cache = AccessVectorCache::new(backend.clone());
190
191 Arc::new(Self { access_vector_cache, backend, exceptions })
192 }
193
194 pub fn as_permission_check<'a>(
197 self: &'a Self,
198 local_cache: &'a PerThreadCache,
199 ) -> PermissionCheck<'a> {
200 PermissionCheck::new(self, &self.access_vector_cache, local_cache)
201 }
202
203 pub fn security_context_to_sid(
207 &self,
208 security_context: NullessByteStr<'_>,
209 ) -> Result<SecurityId, anyhow::Error> {
210 self.backend.compute_sid(|active_policy| {
211 active_policy
212 .parsed
213 .parse_security_context(security_context)
214 .map_err(anyhow::Error::from)
215 })
216 }
217
218 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
223 let locked_state = self.backend.state.read();
224 let active_policy = locked_state.active_policy.as_ref()?;
225 let context = active_policy.sid_table.try_sid_to_security_context(sid)?;
226 Some(active_policy.parsed.serialize_security_context(context))
227 }
228
229 pub fn sid_to_security_context_with_nul(&self, sid: SecurityId) -> Option<Vec<u8>> {
231 self.sid_to_security_context(sid).map(|mut context| {
232 context.push(0u8);
233 context
234 })
235 }
236
237 pub fn load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
239 let unvalidated_policy = parse_policy_by_value(binary_policy)?;
242 let parsed = Arc::new(unvalidated_policy.validate()?);
243 let binary = parsed.binary().clone();
244
245 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
246 let exceptions = ExceptionsConfig::new(&parsed, &exceptions)?;
247
248 self.with_mut_state_and_update_status(|state| {
250 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
251 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
252 } else {
253 SidTable::new(parsed.clone())
254 };
255
256 state.booleans.reset(
259 parsed
260 .conditional_booleans()
261 .iter()
262 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
264 .collect(),
265 );
266
267 state.active_policy = Some(ActivePolicy { parsed, binary, sid_table, exceptions });
268 self.backend.policy_change_count.fetch_add(1, Ordering::Relaxed);
269 });
270
271 Ok(())
272 }
273
274 pub fn get_binary_policy(&self) -> Option<PolicyData> {
276 self.backend.state.read().active_policy.as_ref().map(|p| p.binary.clone())
277 }
278
279 pub fn set_enforcing(&self, enforcing: bool) {
281 self.with_mut_state_and_update_status(|_| {
282 self.backend.is_enforcing.store(enforcing, Ordering::Release);
283 });
284 }
285
286 pub fn is_enforcing(&self) -> bool {
287 self.backend.is_enforcing.load(Ordering::Acquire)
288 }
289
290 pub fn deny_unknown(&self) -> bool {
293 self.backend.state.read().deny_unknown()
294 }
295
296 pub fn reject_unknown(&self) -> bool {
299 self.backend.state.read().reject_unknown()
300 }
301
302 pub fn conditional_booleans(&self) -> Vec<String> {
305 self.backend.state.read().booleans.names()
306 }
307
308 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
310 self.backend.state.read().booleans.get(name)
311 }
312
313 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
315 self.backend.state.write().booleans.set_pending(name, value)
316 }
317
318 pub fn commit_pending_booleans(&self) {
320 self.with_mut_state_and_update_status(|state| {
322 state.booleans.commit_pending();
323 self.backend.policy_change_count.fetch_add(1, Ordering::Relaxed);
324 });
325 }
326
327 pub fn is_policycap_enabled(&self, policy_cap: PolicyCap) -> bool {
329 let locked_state = self.backend.state.read();
330 let Some(policy) = &locked_state.active_policy else {
331 return false;
332 };
333 policy.parsed.has_policycap(policy_cap)
334 }
335
336 pub fn avc_cache_stats(&self) -> CacheStats {
338 self.access_vector_cache.cache_stats()
339 }
340
341 pub fn policy_change_count(&self) -> u32 {
343 self.backend.policy_change_count.load(Ordering::Relaxed)
344 }
345
346 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
348 let locked_state = self.backend.state.read();
349 let names = locked_state
350 .expect_active_policy()
351 .parsed
352 .classes()
353 .iter()
354 .map(|class| class.class_name.to_vec())
355 .collect();
356 Ok(names)
357 }
358
359 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
361 let locked_state = self.backend.state.read();
362 Ok(locked_state
363 .expect_active_policy()
364 .parsed
365 .classes()
366 .iter()
367 .find(|class| *(class.class_name) == *(name.as_bytes()))
368 .ok_or(())?
369 .class_id)
370 }
371
372 pub fn class_permissions_by_name(
376 &self,
377 name: &str,
378 ) -> Result<Vec<(ClassPermissionId, Vec<u8>)>, ()> {
379 let locked_state = self.backend.state.read();
380 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
381 }
382
383 pub fn resolve_fs_label(
387 &self,
388 fs_type: NullessByteStr<'_>,
389 mount_options: &FileSystemMountOptions,
390 ) -> Result<FileSystemLabel, anyhow::Error> {
391 let mut locked_state = self.backend.state.write();
392 let active_policy = locked_state.expect_active_policy_mut();
393
394 let mount_sids = FileSystemMountSids {
395 context: sid_from_mount_option(active_policy, &mount_options.context)?,
396 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context)?,
397 def_context: sid_from_mount_option(active_policy, &mount_options.def_context)?,
398 root_context: sid_from_mount_option(active_policy, &mount_options.root_context)?,
399 };
400 let label = if let Some(mountpoint_sid) = mount_sids.context {
401 FileSystemLabel {
405 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
406 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
407 mount_sids,
408 }
409 } else if let Some(FsUseLabelAndType { context, use_type }) =
410 active_policy.parsed.fs_use_label_and_type(fs_type)
411 {
412 let fs_sid_from_policy =
414 active_policy.sid_table.security_context_to_sid(&context).unwrap();
415 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
416 FileSystemLabel {
417 sid: fs_sid,
418 scheme: FileSystemLabelingScheme::FsUse {
419 fs_use_type: use_type,
420 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
421 },
422 mount_sids,
423 }
424 } else if let Some(context) =
425 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
426 {
427 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
429 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
430
431 let fs_type = fs_type.as_bytes();
441 let mut supports_seclabel = matches!(fs_type, b"sysfs" | b"tracefs" | b"pstore");
442 supports_seclabel |= matches!(fs_type, b"cgroup" | b"cgroup2")
443 && active_policy.parsed.has_policycap(PolicyCap::CgroupSeclabel);
444 supports_seclabel |= fs_type == b"functionfs"
445 && active_policy.parsed.has_policycap(PolicyCap::FunctionfsSeclabel);
446
447 FileSystemLabel {
448 sid: fs_sid,
449 scheme: FileSystemLabelingScheme::GenFsCon { supports_seclabel },
450 mount_sids,
451 }
452 } else {
453 FileSystemLabel {
455 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
456 scheme: FileSystemLabelingScheme::FsUse {
457 fs_use_type: FsUseType::Xattr,
458 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
459 },
460 mount_sids,
461 }
462 };
463 Ok(label)
464 }
465
466 pub fn genfscon_label_for_fs_and_path(
471 &self,
472 fs_type: NullessByteStr<'_>,
473 node_path: NullessByteStr<'_>,
474 class_id: Option<KernelClass>,
475 ) -> Result<SecurityId, anyhow::Error> {
476 self.backend.compute_sid(|active_policy| {
477 active_policy
478 .parsed
479 .genfscon_label_for_fs_and_path(fs_type, node_path.into(), class_id)
480 .ok_or_else(|| {
481 anyhow::anyhow!("Genfscon label requested for non-genfscon labeled filesystem")
482 })
483 })
484 }
485
486 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
491 let locked_state = self.backend.state.read();
492 let active_policy = locked_state.expect_active_policy();
493 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
494 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
495 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
496 }
497
498 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
505 self.with_mut_state_and_update_status(|state| {
506 assert!(state.status_publisher.is_none());
507 state.status_publisher = Some(status_holder);
508 });
509 }
510
511 fn with_mut_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
515 let mut locked_state = self.backend.state.write();
516 f(locked_state.deref_mut());
517 let new_value = SeLinuxStatus {
518 is_enforcing: self.is_enforcing(),
519 change_count: self.backend.policy_change_count.load(Ordering::Relaxed),
520 deny_unknown: locked_state.deny_unknown(),
521 };
522 if let Some(status_publisher) = &mut locked_state.status_publisher {
523 status_publisher.set_status(new_value);
524 }
525
526 std::mem::drop(locked_state);
529 self.access_vector_cache.reset();
530 }
531
532 pub fn compute_create_sid_raw(
538 &self,
539 source_sid: SecurityId,
540 target_sid: SecurityId,
541 target_class: ClassId,
542 ) -> Result<SecurityId, anyhow::Error> {
543 self.backend.compute_create_sid_raw(source_sid, target_sid, target_class.into())
544 }
545
546 pub fn compute_access_decision_raw(
549 &self,
550 source_sid: SecurityId,
551 target_sid: SecurityId,
552 target_class: ClassId,
553 ) -> AccessDecision {
554 self.backend.compute_access_decision_raw(source_sid, target_sid, target_class.into())
555 }
556}
557
558impl SecurityServerBackend {
559 fn compute_create_sid_raw(
560 &self,
561 source_sid: SecurityId,
562 target_sid: SecurityId,
563 target_class: ObjectClass,
564 ) -> Result<SecurityId, anyhow::Error> {
565 self.compute_sid(|active_policy| {
566 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
567 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
568
569 Ok(active_policy.parsed.compute_create_context(
570 source_context,
571 target_context,
572 target_class,
573 ))
574 })
575 .context("computing new security context from policy")
576 }
577
578 fn compute_sid(
580 &self,
581 compute_context: impl Fn(&ActivePolicy) -> Result<SecurityContext, anyhow::Error>,
582 ) -> Result<SecurityId, anyhow::Error> {
583 let readable_state = self.state.read();
586 let policy_change_count = self.policy_change_count.load(Ordering::Relaxed);
587 let policy_state = readable_state
588 .active_policy
589 .as_ref()
590 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
591 let context = compute_context(policy_state)?;
592 if let Some(sid) = policy_state.sid_table.security_context_to_existing_sid(&context) {
593 return Ok(sid);
594 }
595 std::mem::drop(readable_state);
596
597 let mut writable_state = self.state.write();
602 let needs_recompute =
603 policy_change_count != self.policy_change_count.load(Ordering::Relaxed);
604 let policy_state = writable_state.active_policy.as_mut().unwrap();
605 let context = if needs_recompute { compute_context(policy_state)? } else { context };
606 policy_state.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
607 }
608
609 fn compute_access_decision_raw(
610 &self,
611 source_sid: SecurityId,
612 target_sid: SecurityId,
613 target_class: ObjectClass,
614 ) -> AccessDecision {
615 let locked_state = self.state.read();
616
617 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class)
618 }
619}
620
621impl Query for SecurityServerBackend {
622 fn compute_access_decision(
623 &self,
624 source_sid: SecurityId,
625 target_sid: SecurityId,
626 target_class: KernelClass,
627 ) -> KernelAccessDecision {
628 let locked_state = self.state.read();
629 let decision =
630 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class.into());
631 locked_state.access_decision_to_kernel_access_decision(target_class, decision)
632 }
633
634 fn compute_create_sid(
635 &self,
636 source_sid: SecurityId,
637 target_sid: SecurityId,
638 target_class: KernelClass,
639 ) -> Result<SecurityId, anyhow::Error> {
640 self.compute_create_sid_raw(source_sid, target_sid, target_class.into())
641 }
642
643 fn compute_new_fs_node_sid_with_name(
644 &self,
645 source_sid: SecurityId,
646 target_sid: SecurityId,
647 fs_node_class: FsNodeClass,
648 fs_node_name: NullessByteStr<'_>,
649 ) -> Option<SecurityId> {
650 let mut locked_state = self.state.write();
651
652 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
654
655 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
656 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
657
658 let new_file_context = active_policy.parsed.compute_create_context_with_name(
659 source_context,
660 target_context,
661 fs_node_class,
662 fs_node_name,
663 )?;
664
665 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
666 }
667
668 fn compute_xperms_access_decision(
669 &self,
670 xperms_kind: XpermsKind,
671 source_sid: SecurityId,
672 target_sid: SecurityId,
673 permission: KernelPermission,
674 xperms_prefix: u8,
675 ) -> KernelXpermsAccessDecision {
676 let locked_state = self.state.read();
677
678 let active_policy = match &locked_state.active_policy {
679 Some(active_policy) => active_policy,
680 None => {
682 return KernelXpermsAccessDecision {
683 allow: XpermsBitmap::ALL,
684 audit: XpermsBitmap::NONE,
685 permissive: false,
686 has_todo: false,
687 };
688 }
689 };
690
691 let base_decision_raw = locked_state.compute_access_decision_raw(
694 source_sid,
695 target_sid,
696 permission.class().into(),
697 );
698 let base_decision = locked_state
699 .access_decision_to_kernel_access_decision(permission.class(), base_decision_raw);
700 let permission_access_vector = permission.as_access_vector();
701 let base_permit =
702 base_decision.allow & permission_access_vector == permission_access_vector;
703 let base_audit = base_decision.audit & permission_access_vector == permission_access_vector;
704
705 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
707 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
708 let xperms_decision = active_policy.parsed.compute_xperms_access_decision(
709 xperms_kind,
710 &source_context,
711 &target_context,
712 permission.class(),
713 xperms_prefix,
714 );
715
716 let allow = if !base_permit { XpermsBitmap::NONE } else { xperms_decision.allow };
718 let audit = if base_audit {
719 XpermsBitmap::ALL
720 } else {
721 (xperms_decision.allow & xperms_decision.auditallow)
722 | (!xperms_decision.allow & xperms_decision.auditdeny)
723 };
724 let permissive = (base_decision.flags & SELINUX_AVD_FLAGS_PERMISSIVE) != 0;
725 let has_todo = base_decision.todo_bug.is_some();
726 KernelXpermsAccessDecision { allow, audit, permissive, has_todo }
727 }
728}
729
730impl AccessVectorComputer for SecurityServerBackend {
731 fn access_decision_to_kernel_access_decision(
732 &self,
733 class: KernelClass,
734 av: AccessDecision,
735 ) -> KernelAccessDecision {
736 self.state.read().access_decision_to_kernel_access_decision(class, av)
737 }
738}
739
740impl AccessVectorComputer for SecurityServerState {
741 fn access_decision_to_kernel_access_decision(
742 &self,
743 class: KernelClass,
744 av: AccessDecision,
745 ) -> KernelAccessDecision {
746 match &self.active_policy {
747 Some(policy) => policy.parsed.access_decision_to_kernel_access_decision(class, av),
748 None => KernelAccessDecision {
749 allow: AccessVector::ALL,
750 audit: AccessVector::NONE,
751 flags: 0,
752 todo_bug: None,
753 },
754 }
755 }
756}
757
758fn sid_from_mount_option(
761 active_policy: &mut ActivePolicy,
762 mount_option: &Option<Vec<u8>>,
763) -> Result<Option<SecurityId>, anyhow::Error> {
764 let Some(label) = mount_option else {
765 return Ok(None);
766 };
767 let context = active_policy.parsed.parse_security_context(label.into())?;
768 let sid = active_policy.sid_table.security_context_to_sid(&context)?;
769 Ok(Some(sid))
770}
771
772#[cfg(test)]
773mod tests {
774 use super::*;
775 use crate::permission_check::PermissionCheckResult;
776 use crate::{
777 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
778 ProcessPermission,
779 };
780 use std::num::NonZeroU32;
781
782 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
783 const TESTS_BINARY_POLICY: &[u8] =
784 include_bytes!("../testdata/micro_policies/security_server_tests_policy");
785 const MINIMAL_BINARY_POLICY: &[u8] =
786 include_bytes!("../testdata/composite_policies/compiled/minimal_policy");
787
788 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
789 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
790 let security_server = SecurityServer::new_default();
791 assert_eq!(
792 Ok(()),
793 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
794 );
795 security_server
796 }
797
798 #[test]
799 fn compute_access_vector_allows_all() {
800 let security_server = SecurityServer::new_default();
801 let sid1 = InitialSid::Kernel.into();
802 let sid2 = InitialSid::Unlabeled.into();
803 assert_eq!(
804 security_server
805 .backend
806 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
807 .allow,
808 AccessVector::ALL
809 );
810 }
811
812 #[test]
813 fn loaded_policy_can_be_retrieved() {
814 let security_server = security_server_with_tests_policy();
815 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_slice());
816 }
817
818 #[test]
819 fn loaded_policy_is_validated() {
820 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
821 let security_server = SecurityServer::new_default();
822 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
823 }
824
825 #[test]
826 fn enforcing_mode_is_reported() {
827 let security_server = SecurityServer::new_default();
828 assert!(!security_server.is_enforcing());
829
830 security_server.set_enforcing(true);
831 assert!(security_server.is_enforcing());
832 }
833
834 #[test]
835 fn without_policy_conditional_booleans_are_empty() {
836 let security_server = SecurityServer::new_default();
837 assert!(security_server.conditional_booleans().is_empty());
838 }
839
840 #[test]
841 fn conditional_booleans_can_be_queried() {
842 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
843 let security_server = SecurityServer::new_default();
844 assert_eq!(
845 Ok(()),
846 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
847 );
848
849 let booleans = security_server.conditional_booleans();
850 assert!(!booleans.is_empty());
851 let boolean = booleans[0].as_str();
852
853 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
854 assert!(security_server.get_boolean(boolean).is_ok());
855 }
856
857 #[test]
858 fn conditional_booleans_can_be_changed() {
859 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
860 let security_server = SecurityServer::new_default();
861 assert_eq!(
862 Ok(()),
863 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
864 );
865
866 let booleans = security_server.conditional_booleans();
867 assert!(!booleans.is_empty());
868 let boolean = booleans[0].as_str();
869
870 let (active, pending) = security_server.get_boolean(boolean).unwrap();
871 assert_eq!(active, pending, "Initially active and pending values should match");
872
873 security_server.set_pending_boolean(boolean, !active).unwrap();
874 let (active, pending) = security_server.get_boolean(boolean).unwrap();
875 assert!(active != pending, "Before commit pending should differ from active");
876
877 security_server.commit_pending_booleans();
878 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
879 assert_eq!(final_active, pending, "Pending value should be active after commit");
880 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
881 }
882
883 #[test]
884 fn parse_security_context_no_policy() {
885 let security_server = SecurityServer::new_default();
886 let error = security_server
887 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
888 .expect_err("expected error");
889 let error_string = format!("{:?}", error);
890 assert!(error_string.contains("no policy"));
891 }
892
893 #[test]
894 fn compute_new_fs_node_sid_no_defaults() {
895 let security_server = SecurityServer::new_default();
896 let policy_bytes =
897 include_bytes!("../testdata/micro_policies/file_no_defaults_policy").to_vec();
898 security_server.load_policy(policy_bytes).expect("binary policy loads");
899
900 let source_sid = security_server
901 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
902 .expect("creating SID from security context should succeed");
903 let target_sid = security_server
904 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
905 .expect("creating SID from security context should succeed");
906
907 let computed_sid = security_server
908 .as_permission_check(&Default::default())
909 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
910 .expect("new sid computed");
911 let computed_context = security_server
912 .sid_to_security_context(computed_sid)
913 .expect("computed sid associated with context");
914
915 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
918 }
919
920 #[test]
921 fn compute_new_fs_node_sid_source_defaults() {
922 let security_server = SecurityServer::new_default();
923 let policy_bytes =
924 include_bytes!("../testdata/micro_policies/file_source_defaults_policy").to_vec();
925 security_server.load_policy(policy_bytes).expect("binary policy loads");
926
927 let source_sid = security_server
928 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
929 .expect("creating SID from security context should succeed");
930 let target_sid = security_server
931 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
932 .expect("creating SID from security context should succeed");
933
934 let computed_sid = security_server
935 .as_permission_check(&Default::default())
936 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
937 .expect("new sid computed");
938 let computed_context = security_server
939 .sid_to_security_context(computed_sid)
940 .expect("computed sid associated with context");
941
942 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
945 }
946
947 #[test]
948 fn compute_new_fs_node_sid_target_defaults() {
949 let security_server = SecurityServer::new_default();
950 let policy_bytes =
951 include_bytes!("../testdata/micro_policies/file_target_defaults_policy").to_vec();
952 security_server.load_policy(policy_bytes).expect("binary policy loads");
953
954 let source_sid = security_server
955 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
956 .expect("creating SID from security context should succeed");
957 let target_sid = security_server
958 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
959 .expect("creating SID from security context should succeed");
960
961 let computed_sid = security_server
962 .as_permission_check(&Default::default())
963 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
964 .expect("new sid computed");
965 let computed_context = security_server
966 .sid_to_security_context(computed_sid)
967 .expect("computed sid associated with context");
968
969 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
971 }
972
973 #[test]
974 fn compute_new_fs_node_sid_range_source_low_default() {
975 let security_server = SecurityServer::new_default();
976 let policy_bytes =
977 include_bytes!("../testdata/micro_policies/file_range_source_low_policy").to_vec();
978 security_server.load_policy(policy_bytes).expect("binary policy loads");
979
980 let source_sid = security_server
981 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
982 .expect("creating SID from security context should succeed");
983 let target_sid = security_server
984 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
985 .expect("creating SID from security context should succeed");
986
987 let computed_sid = security_server
988 .as_permission_check(&Default::default())
989 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
990 .expect("new sid computed");
991 let computed_context = security_server
992 .sid_to_security_context(computed_sid)
993 .expect("computed sid associated with context");
994
995 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
997 }
998
999 #[test]
1000 fn compute_new_fs_node_sid_range_source_low_high_default() {
1001 let security_server = SecurityServer::new_default();
1002 let policy_bytes =
1003 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy").to_vec();
1004 security_server.load_policy(policy_bytes).expect("binary policy loads");
1005
1006 let source_sid = security_server
1007 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1008 .expect("creating SID from security context should succeed");
1009 let target_sid = security_server
1010 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
1011 .expect("creating SID from security context should succeed");
1012
1013 let computed_sid = security_server
1014 .as_permission_check(&Default::default())
1015 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1016 .expect("new sid computed");
1017 let computed_context = security_server
1018 .sid_to_security_context(computed_sid)
1019 .expect("computed sid associated with context");
1020
1021 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1023 }
1024
1025 #[test]
1026 fn compute_new_fs_node_sid_range_source_high_default() {
1027 let security_server = SecurityServer::new_default();
1028 let policy_bytes =
1029 include_bytes!("../testdata/micro_policies/file_range_source_high_policy").to_vec();
1030 security_server.load_policy(policy_bytes).expect("binary policy loads");
1031
1032 let source_sid = security_server
1033 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1034 .expect("creating SID from security context should succeed");
1035 let target_sid = security_server
1036 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
1037 .expect("creating SID from security context should succeed");
1038
1039 let computed_sid = security_server
1040 .as_permission_check(&Default::default())
1041 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1042 .expect("new sid computed");
1043 let computed_context = security_server
1044 .sid_to_security_context(computed_sid)
1045 .expect("computed sid associated with context");
1046
1047 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1049 }
1050
1051 #[test]
1052 fn compute_new_fs_node_sid_range_target_low_default() {
1053 let security_server = SecurityServer::new_default();
1054 let policy_bytes =
1055 include_bytes!("../testdata/micro_policies/file_range_target_low_policy").to_vec();
1056 security_server.load_policy(policy_bytes).expect("binary policy loads");
1057
1058 let source_sid = security_server
1059 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1060 .expect("creating SID from security context should succeed");
1061 let target_sid = security_server
1062 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1063 .expect("creating SID from security context should succeed");
1064
1065 let computed_sid = security_server
1066 .as_permission_check(&Default::default())
1067 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1068 .expect("new sid computed");
1069 let computed_context = security_server
1070 .sid_to_security_context(computed_sid)
1071 .expect("computed sid associated with context");
1072
1073 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1075 }
1076
1077 #[test]
1078 fn compute_new_fs_node_sid_range_target_low_high_default() {
1079 let security_server = SecurityServer::new_default();
1080 let policy_bytes =
1081 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy").to_vec();
1082 security_server.load_policy(policy_bytes).expect("binary policy loads");
1083
1084 let source_sid = security_server
1085 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1086 .expect("creating SID from security context should succeed");
1087 let target_sid = security_server
1088 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1089 .expect("creating SID from security context should succeed");
1090
1091 let computed_sid = security_server
1092 .as_permission_check(&Default::default())
1093 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1094 .expect("new sid computed");
1095 let computed_context = security_server
1096 .sid_to_security_context(computed_sid)
1097 .expect("computed sid associated with context");
1098
1099 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1101 }
1102
1103 #[test]
1104 fn compute_new_fs_node_sid_range_target_high_default() {
1105 let security_server = SecurityServer::new_default();
1106 let policy_bytes =
1107 include_bytes!("../testdata/micro_policies/file_range_target_high_policy").to_vec();
1108 security_server.load_policy(policy_bytes).expect("binary policy loads");
1109
1110 let source_sid = security_server
1111 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1112 .expect("creating SID from security context should succeed");
1113 let target_sid = security_server
1114 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1115 .expect("creating SID from security context should succeed");
1116
1117 let computed_sid = security_server
1118 .as_permission_check(&Default::default())
1119 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1120 .expect("new sid computed");
1121 let computed_context = security_server
1122 .sid_to_security_context(computed_sid)
1123 .expect("computed sid associated with context");
1124
1125 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1127 }
1128
1129 #[test]
1130 fn compute_new_fs_node_sid_with_name() {
1131 let security_server = SecurityServer::new_default();
1132 let policy_bytes =
1133 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy")
1134 .to_vec();
1135 security_server.load_policy(policy_bytes).expect("binary policy loads");
1136
1137 let source_sid = security_server
1138 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1139 .expect("creating SID from security context should succeed");
1140 let target_sid = security_server
1141 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1142 .expect("creating SID from security context should succeed");
1143
1144 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1145 let computed_sid = security_server
1146 .as_permission_check(&Default::default())
1147 .compute_new_fs_node_sid(
1148 source_sid,
1149 target_sid,
1150 FileClass::File.into(),
1151 SPECIAL_FILE_NAME.into(),
1152 )
1153 .expect("new sid computed");
1154 let computed_context = security_server
1155 .sid_to_security_context(computed_sid)
1156 .expect("computed sid associated with context");
1157
1158 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1160
1161 let computed_sid = security_server
1162 .as_permission_check(&Default::default())
1163 .compute_new_fs_node_sid(
1164 source_sid,
1165 target_sid,
1166 FileClass::ChrFile.into(),
1167 SPECIAL_FILE_NAME.into(),
1168 )
1169 .expect("new sid computed");
1170 let computed_context = security_server
1171 .sid_to_security_context(computed_sid)
1172 .expect("computed sid associated with context");
1173
1174 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1177
1178 const OTHER_FILE_NAME: &[u8] = b"other_file";
1179 let computed_sid = security_server
1180 .as_permission_check(&Default::default())
1181 .compute_new_fs_node_sid(
1182 source_sid,
1183 target_sid,
1184 FileClass::File.into(),
1185 OTHER_FILE_NAME.into(),
1186 )
1187 .expect("new sid computed");
1188 let computed_context = security_server
1189 .sid_to_security_context(computed_sid)
1190 .expect("computed sid associated with context");
1191
1192 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1195 }
1196
1197 #[test]
1198 fn permissions_are_fresh_after_different_policy_load() {
1199 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1200 let allow_fork_bytes =
1201 include_bytes!("../testdata/composite_policies/compiled/allow_fork_policy").to_vec();
1202 let context = b"source_u:object_r:source_t:s0:c0";
1203
1204 let security_server = SecurityServer::new_default();
1205 security_server.set_enforcing(true);
1206
1207 let local_cache = Default::default();
1208 let permission_check = security_server.as_permission_check(&local_cache);
1209
1210 assert_eq!(
1212 Ok(()),
1213 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1214 );
1215 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1216
1217 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1219
1220 assert_eq!(
1222 Ok(()),
1223 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1224 );
1225
1226 let permission_check = security_server.as_permission_check(&local_cache);
1228
1229 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1231 }
1232
1233 #[test]
1234 fn unknown_sids_are_effectively_unlabeled() {
1235 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1236 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy"
1237 )
1238 .to_vec();
1239 let with_additional_domain_policy_bytes =
1240 include_bytes!("../testdata/composite_policies/compiled/with_additional_domain_policy")
1241 .to_vec();
1242 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1243 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1244
1245 let security_server = SecurityServer::new_default();
1246 security_server.set_enforcing(true);
1247
1248 assert_eq!(
1251 Ok(()),
1252 security_server
1253 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1254 .map_err(|e| format!("{:?}", e))
1255 );
1256 let allowed_type_sid =
1257 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1258 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1259
1260 assert_eq!(
1263 Ok(()),
1264 security_server
1265 .load_policy(with_additional_domain_policy_bytes.clone())
1266 .map_err(|e| format!("{:?}", e))
1267 );
1268 let additional_type_sid =
1269 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1270 assert_eq!(
1271 allowed_type_sid,
1272 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1273 );
1274
1275 let local_cache = Default::default();
1276 let permission_check = security_server.as_permission_check(&local_cache);
1277
1278 assert!(
1282 !permission_check
1283 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1284 .granted
1285 );
1286 assert!(
1287 !permission_check
1288 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1289 .granted
1290 );
1291 assert!(
1292 !permission_check
1293 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1294 .granted
1295 );
1296 assert!(
1297 !permission_check
1298 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1299 .granted
1300 );
1301
1302 assert_eq!(
1304 Ok(()),
1305 security_server
1306 .load_policy(with_unlabeled_access_domain_policy_bytes)
1307 .map_err(|e| format!("{:?}", e))
1308 );
1309
1310 let permission_check = security_server.as_permission_check(&local_cache);
1312
1313 assert!(
1317 permission_check
1318 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1319 .granted
1320 );
1321 assert!(
1322 !permission_check
1323 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1324 .granted
1325 );
1326
1327 assert!(
1332 !permission_check
1333 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1334 .granted
1335 );
1336 assert!(
1337 permission_check
1338 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1339 .granted
1340 );
1341
1342 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1344
1345 assert_eq!(
1348 Ok(()),
1349 security_server
1350 .load_policy(with_additional_domain_policy_bytes)
1351 .map_err(|e| format!("{:?}", e))
1352 );
1353 assert_eq!(
1354 additional_type_context.to_vec(),
1355 security_server.sid_to_security_context(additional_type_sid).unwrap()
1356 );
1357 }
1358
1359 #[test]
1360 fn permission_check_permissive() {
1361 let security_server = security_server_with_tests_policy();
1362 security_server.set_enforcing(false);
1363 assert!(!security_server.is_enforcing());
1364
1365 let sid =
1366 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1367 let local_cache = Default::default();
1368 let permission_check = security_server.as_permission_check(&local_cache);
1369
1370 assert_eq!(
1373 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1374 PermissionCheckResult {
1375 granted: true,
1376 audit: false,
1377 permissive: false,
1378 todo_bug: None
1379 }
1380 );
1381
1382 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1386 assert_eq!(
1387 result,
1388 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1389 );
1390 assert!(result.permit());
1391
1392 let result = permission_check.has_permission(
1396 sid,
1397 sid,
1398 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1399 );
1400 assert_eq!(
1401 result,
1402 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1403 );
1404 assert!(result.permit());
1405 }
1406
1407 #[test]
1408 fn permission_check_enforcing() {
1409 let security_server = security_server_with_tests_policy();
1410 security_server.set_enforcing(true);
1411 assert!(security_server.is_enforcing());
1412
1413 let sid =
1414 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1415 let local_cache = Default::default();
1416 let permission_check = security_server.as_permission_check(&local_cache);
1417
1418 let result = permission_check.has_permission(sid, sid, ProcessPermission::Fork);
1420 assert_eq!(
1421 result,
1422 PermissionCheckResult {
1423 granted: true,
1424 audit: false,
1425 permissive: false,
1426 todo_bug: None
1427 }
1428 );
1429 assert!(result.permit());
1430
1431 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1434 assert_eq!(
1435 result,
1436 PermissionCheckResult {
1437 granted: false,
1438 audit: true,
1439 permissive: false,
1440 todo_bug: None
1441 }
1442 );
1443 assert!(!result.permit());
1444
1445 let result = permission_check.has_permission(
1448 sid,
1449 sid,
1450 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1451 );
1452 assert_eq!(
1453 result,
1454 PermissionCheckResult {
1455 granted: false,
1456 audit: true,
1457 permissive: false,
1458 todo_bug: None
1459 }
1460 );
1461 assert!(!result.permit());
1462 }
1463
1464 #[test]
1465 fn permissive_domain() {
1466 let security_server = security_server_with_tests_policy();
1467 security_server.set_enforcing(true);
1468 assert!(security_server.is_enforcing());
1469
1470 let permissive_sid = security_server
1471 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1472 .unwrap();
1473 let non_permissive_sid = security_server
1474 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1475 .unwrap();
1476
1477 let local_cache = Default::default();
1478 let permission_check = security_server.as_permission_check(&local_cache);
1479
1480 let result = permission_check.has_permission(
1482 permissive_sid,
1483 permissive_sid,
1484 ProcessPermission::GetSched,
1485 );
1486 assert_eq!(
1487 result,
1488 PermissionCheckResult { granted: true, audit: false, permissive: true, todo_bug: None }
1489 );
1490 assert!(result.permit());
1491 let result = permission_check.has_permission(
1492 non_permissive_sid,
1493 non_permissive_sid,
1494 ProcessPermission::GetSched,
1495 );
1496 assert_eq!(
1497 result,
1498 PermissionCheckResult {
1499 granted: true,
1500 audit: false,
1501 permissive: false,
1502 todo_bug: None
1503 }
1504 );
1505 assert!(result.permit());
1506
1507 let result = permission_check.has_permission(
1510 permissive_sid,
1511 non_permissive_sid,
1512 ProcessPermission::GetSched,
1513 );
1514 assert_eq!(
1515 result,
1516 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1517 );
1518 assert!(result.permit());
1519 let result = permission_check.has_permission(
1520 non_permissive_sid,
1521 permissive_sid,
1522 ProcessPermission::GetSched,
1523 );
1524 assert_eq!(
1525 result,
1526 PermissionCheckResult {
1527 granted: false,
1528 audit: true,
1529 permissive: false,
1530 todo_bug: None
1531 }
1532 );
1533 assert!(!result.permit());
1534
1535 let result = permission_check.has_permission(
1540 permissive_sid,
1541 non_permissive_sid,
1542 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1543 );
1544 assert_eq!(
1545 result,
1546 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1547 );
1548 assert!(result.permit());
1549 let result = permission_check.has_permission(
1550 non_permissive_sid,
1551 non_permissive_sid,
1552 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1553 );
1554 assert_eq!(
1555 result,
1556 PermissionCheckResult {
1557 granted: false,
1558 audit: true,
1559 permissive: false,
1560 todo_bug: None
1561 }
1562 );
1563 assert!(!result.permit());
1564 }
1565
1566 #[test]
1567 fn auditallow_and_dontaudit() {
1568 let security_server = security_server_with_tests_policy();
1569 security_server.set_enforcing(true);
1570 assert!(security_server.is_enforcing());
1571
1572 let audit_sid = security_server
1573 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1574 .unwrap();
1575
1576 let local_cache = Default::default();
1577 let permission_check = security_server.as_permission_check(&local_cache);
1578
1579 let result = permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork);
1581 assert_eq!(
1582 result,
1583 PermissionCheckResult { granted: true, audit: true, permissive: false, todo_bug: None }
1584 );
1585 assert!(result.permit());
1586
1587 let result =
1589 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched);
1590 assert_eq!(
1591 result,
1592 PermissionCheckResult {
1593 granted: true,
1594 audit: false,
1595 permissive: false,
1596 todo_bug: None
1597 }
1598 );
1599 assert!(result.permit());
1600
1601 let result =
1603 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched);
1604 assert_eq!(
1605 result,
1606 PermissionCheckResult {
1607 granted: false,
1608 audit: false,
1609 permissive: false,
1610 todo_bug: None
1611 }
1612 );
1613 assert!(!result.permit());
1614
1615 let result =
1617 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid);
1618 assert_eq!(
1619 result,
1620 PermissionCheckResult {
1621 granted: false,
1622 audit: true,
1623 permissive: false,
1624 todo_bug: None
1625 }
1626 );
1627 assert!(!result.permit());
1628 }
1629
1630 #[test]
1631 fn access_checks_with_exceptions_config() {
1632 const EXCEPTIONS_CONFIG: &[&str] = &[
1633 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1635 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1636 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1637 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1638 "todo_permissive b/005 test_exception_todo_permissive_t",
1639 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1641 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1642 "todo_permissive b/103 test_undefined_source_t",
1643 ];
1644 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1645 let security_server = SecurityServer::new(String::new(), exceptions_config);
1646 security_server.set_enforcing(true);
1647
1648 const EXCEPTIONS_POLICY: &[u8] =
1649 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy");
1650 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1651
1652 let source_sid = security_server
1653 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1654 .unwrap();
1655 let target_sid = security_server
1656 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1657 .unwrap();
1658 let other_sid = security_server
1659 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1660 .unwrap();
1661 let permissive_sid = security_server
1662 .security_context_to_sid(
1663 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1664 )
1665 .unwrap();
1666 let unmatched_sid = security_server
1667 .security_context_to_sid(
1668 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1669 )
1670 .unwrap();
1671 let todo_permissive_sid = security_server
1672 .security_context_to_sid(
1673 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1674 )
1675 .unwrap();
1676
1677 let local_cache = Default::default();
1678 let permission_check = security_server.as_permission_check(&local_cache);
1679
1680 let result =
1682 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid);
1683 assert_eq!(
1684 result,
1685 PermissionCheckResult {
1686 granted: false,
1687 audit: true,
1688 permissive: false,
1689 todo_bug: None
1690 }
1691 );
1692 assert!(!result.permit());
1693
1694 let result =
1696 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint);
1697 assert_eq!(
1698 result,
1699 PermissionCheckResult {
1700 granted: true,
1701 audit: true,
1702 permissive: false,
1703 todo_bug: Some(NonZeroU32::new(1).unwrap())
1704 }
1705 );
1706 assert!(result.permit());
1707
1708 let result =
1710 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans);
1711 assert_eq!(
1712 result,
1713 PermissionCheckResult {
1714 granted: true,
1715 audit: false,
1716 permissive: false,
1717 todo_bug: None,
1718 }
1719 );
1720 assert!(result.permit());
1721
1722 let result =
1724 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint);
1725 assert_eq!(
1726 result,
1727 PermissionCheckResult {
1728 granted: false,
1729 audit: true,
1730 permissive: false,
1731 todo_bug: None
1732 }
1733 );
1734 assert!(!result.permit());
1735
1736 let result = permission_check.has_permission(
1738 other_sid,
1739 target_sid,
1740 CommonFsNodePermission::Read.for_class(FileClass::ChrFile),
1741 );
1742 assert_eq!(
1743 result,
1744 PermissionCheckResult {
1745 granted: true,
1746 audit: true,
1747 permissive: false,
1748 todo_bug: Some(NonZeroU32::new(2).unwrap())
1749 }
1750 );
1751 assert!(result.permit());
1752
1753 let result =
1755 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint);
1756 assert_eq!(
1757 result,
1758 PermissionCheckResult {
1759 granted: false,
1760 audit: true,
1761 permissive: false,
1762 todo_bug: None
1763 }
1764 );
1765 assert!(!result.permit());
1766
1767 let result =
1769 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint);
1770 assert_eq!(
1771 result,
1772 PermissionCheckResult {
1773 granted: false,
1774 audit: true,
1775 permissive: false,
1776 todo_bug: None
1777 }
1778 );
1779 assert!(!result.permit());
1780
1781 let result =
1783 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint);
1784 assert_eq!(
1785 result,
1786 PermissionCheckResult {
1787 granted: true,
1788 audit: true,
1789 permissive: true,
1790 todo_bug: Some(NonZeroU32::new(4).unwrap())
1791 }
1792 );
1793 assert!(result.permit());
1794
1795 let result = permission_check.has_permission(
1798 todo_permissive_sid,
1799 target_sid,
1800 FilePermission::Entrypoint,
1801 );
1802 assert_eq!(
1803 result,
1804 PermissionCheckResult {
1805 granted: true,
1806 audit: true,
1807 permissive: false,
1808 todo_bug: Some(NonZeroU32::new(5).unwrap())
1809 }
1810 );
1811 assert!(result.permit());
1812 let result = permission_check.has_permission(
1813 todo_permissive_sid,
1814 todo_permissive_sid,
1815 FilePermission::Entrypoint,
1816 );
1817 assert_eq!(
1818 result,
1819 PermissionCheckResult {
1820 granted: true,
1821 audit: true,
1822 permissive: false,
1823 todo_bug: Some(NonZeroU32::new(5).unwrap())
1824 }
1825 );
1826 assert!(result.permit());
1827 let result = permission_check.has_permission(
1828 todo_permissive_sid,
1829 target_sid,
1830 FilePermission::Entrypoint,
1831 );
1832 assert_eq!(
1833 result,
1834 PermissionCheckResult {
1835 granted: true,
1836 audit: true,
1837 permissive: false,
1838 todo_bug: Some(NonZeroU32::new(5).unwrap())
1839 }
1840 );
1841 assert!(result.permit());
1842 }
1843
1844 #[test]
1845 fn handle_unknown() {
1846 let security_server = security_server_with_tests_policy();
1847
1848 let sid = security_server
1849 .security_context_to_sid("user0:object_r:type0:s0".into())
1850 .expect("Resolve Context to SID");
1851
1852 const REJECT_POLICY: &[u8] =
1856 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-reject");
1857 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1858
1859 security_server.set_enforcing(true);
1860
1861 const DENY_POLICY: &[u8] =
1863 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny");
1864 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1865 let local_cache = Default::default();
1866 let permission_check = security_server.as_permission_check(&local_cache);
1867
1868 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1870 assert_eq!(
1871 result,
1872 PermissionCheckResult {
1873 granted: false,
1874 audit: true,
1875 permissive: false,
1876 todo_bug: None
1877 }
1878 );
1879 assert!(!result.permit());
1880 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1881 assert_eq!(
1882 result,
1883 PermissionCheckResult {
1884 granted: false,
1885 audit: true,
1886 permissive: false,
1887 todo_bug: None
1888 }
1889 );
1890 assert!(!result.permit());
1891
1892 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1894 assert_eq!(
1895 result,
1896 PermissionCheckResult {
1897 granted: true,
1898 audit: false,
1899 permissive: false,
1900 todo_bug: None
1901 }
1902 );
1903 assert!(result.permit());
1904 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1905 assert_eq!(
1906 result,
1907 PermissionCheckResult {
1908 granted: false,
1909 audit: true,
1910 permissive: false,
1911 todo_bug: None
1912 }
1913 );
1914 assert!(!result.permit());
1915
1916 const ALLOW_POLICY: &[u8] =
1918 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-allow");
1919 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1920 let local_cache2 = Default::default();
1921 let permission_check = security_server.as_permission_check(&local_cache2);
1922
1923 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1925 assert_eq!(
1926 result,
1927 PermissionCheckResult {
1928 granted: true,
1929 audit: false,
1930 permissive: false,
1931 todo_bug: None
1932 }
1933 );
1934 assert!(result.permit());
1935 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1936 assert_eq!(
1937 result,
1938 PermissionCheckResult {
1939 granted: true,
1940 audit: false,
1941 permissive: false,
1942 todo_bug: None
1943 }
1944 );
1945 assert!(result.permit());
1946
1947 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1949 assert_eq!(
1950 result,
1951 PermissionCheckResult {
1952 granted: true,
1953 audit: false,
1954 permissive: false,
1955 todo_bug: None
1956 }
1957 );
1958 assert!(result.permit());
1959
1960 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1961 assert_eq!(
1962 result,
1963 PermissionCheckResult {
1964 granted: false,
1965 audit: true,
1966 permissive: false,
1967 todo_bug: None
1968 }
1969 );
1970 assert!(!result.permit());
1971 }
1972}