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 ) -> FileSystemLabel {
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 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 }
464
465 pub fn genfscon_label_for_fs_and_path(
470 &self,
471 fs_type: NullessByteStr<'_>,
472 node_path: NullessByteStr<'_>,
473 class_id: Option<KernelClass>,
474 ) -> Result<SecurityId, anyhow::Error> {
475 self.backend.compute_sid(|active_policy| {
476 active_policy
477 .parsed
478 .genfscon_label_for_fs_and_path(fs_type, node_path.into(), class_id)
479 .ok_or_else(|| {
480 anyhow::anyhow!("Genfscon label requested for non-genfscon labeled filesystem")
481 })
482 })
483 }
484
485 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
490 let locked_state = self.backend.state.read();
491 let active_policy = locked_state.expect_active_policy();
492 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
493 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
494 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
495 }
496
497 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
504 self.with_mut_state_and_update_status(|state| {
505 assert!(state.status_publisher.is_none());
506 state.status_publisher = Some(status_holder);
507 });
508 }
509
510 fn with_mut_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
514 let mut locked_state = self.backend.state.write();
515 f(locked_state.deref_mut());
516 let new_value = SeLinuxStatus {
517 is_enforcing: self.is_enforcing(),
518 change_count: self.backend.policy_change_count.load(Ordering::Relaxed),
519 deny_unknown: locked_state.deny_unknown(),
520 };
521 if let Some(status_publisher) = &mut locked_state.status_publisher {
522 status_publisher.set_status(new_value);
523 }
524
525 std::mem::drop(locked_state);
528 self.access_vector_cache.reset();
529 }
530
531 pub fn compute_create_sid_raw(
537 &self,
538 source_sid: SecurityId,
539 target_sid: SecurityId,
540 target_class: ClassId,
541 ) -> Result<SecurityId, anyhow::Error> {
542 self.backend.compute_create_sid_raw(source_sid, target_sid, target_class.into())
543 }
544
545 pub fn compute_access_decision_raw(
548 &self,
549 source_sid: SecurityId,
550 target_sid: SecurityId,
551 target_class: ClassId,
552 ) -> AccessDecision {
553 self.backend.compute_access_decision_raw(source_sid, target_sid, target_class.into())
554 }
555}
556
557impl SecurityServerBackend {
558 fn compute_create_sid_raw(
559 &self,
560 source_sid: SecurityId,
561 target_sid: SecurityId,
562 target_class: ObjectClass,
563 ) -> Result<SecurityId, anyhow::Error> {
564 self.compute_sid(|active_policy| {
565 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
566 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
567
568 Ok(active_policy.parsed.compute_create_context(
569 source_context,
570 target_context,
571 target_class,
572 ))
573 })
574 .context("computing new security context from policy")
575 }
576
577 fn compute_sid(
579 &self,
580 compute_context: impl Fn(&ActivePolicy) -> Result<SecurityContext, anyhow::Error>,
581 ) -> Result<SecurityId, anyhow::Error> {
582 let readable_state = self.state.read();
585 let policy_change_count = self.policy_change_count.load(Ordering::Relaxed);
586 let policy_state = readable_state
587 .active_policy
588 .as_ref()
589 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
590 let context = compute_context(policy_state)?;
591 if let Some(sid) = policy_state.sid_table.security_context_to_existing_sid(&context) {
592 return Ok(sid);
593 }
594 std::mem::drop(readable_state);
595
596 let mut writable_state = self.state.write();
601 let needs_recompute =
602 policy_change_count != self.policy_change_count.load(Ordering::Relaxed);
603 let policy_state = writable_state.active_policy.as_mut().unwrap();
604 let context = if needs_recompute { compute_context(policy_state)? } else { context };
605 policy_state.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
606 }
607
608 fn compute_access_decision_raw(
609 &self,
610 source_sid: SecurityId,
611 target_sid: SecurityId,
612 target_class: ObjectClass,
613 ) -> AccessDecision {
614 let locked_state = self.state.read();
615
616 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class)
617 }
618}
619
620impl Query for SecurityServerBackend {
621 fn compute_access_decision(
622 &self,
623 source_sid: SecurityId,
624 target_sid: SecurityId,
625 target_class: KernelClass,
626 ) -> KernelAccessDecision {
627 let locked_state = self.state.read();
628 let decision =
629 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class.into());
630 locked_state.access_decision_to_kernel_access_decision(target_class, decision)
631 }
632
633 fn compute_create_sid(
634 &self,
635 source_sid: SecurityId,
636 target_sid: SecurityId,
637 target_class: KernelClass,
638 ) -> Result<SecurityId, anyhow::Error> {
639 self.compute_create_sid_raw(source_sid, target_sid, target_class.into())
640 }
641
642 fn compute_new_fs_node_sid_with_name(
643 &self,
644 source_sid: SecurityId,
645 target_sid: SecurityId,
646 fs_node_class: FsNodeClass,
647 fs_node_name: NullessByteStr<'_>,
648 ) -> Option<SecurityId> {
649 let mut locked_state = self.state.write();
650
651 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
653
654 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
655 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
656
657 let new_file_context = active_policy.parsed.compute_create_context_with_name(
658 source_context,
659 target_context,
660 fs_node_class,
661 fs_node_name,
662 )?;
663
664 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
665 }
666
667 fn compute_xperms_access_decision(
668 &self,
669 xperms_kind: XpermsKind,
670 source_sid: SecurityId,
671 target_sid: SecurityId,
672 permission: KernelPermission,
673 xperms_prefix: u8,
674 ) -> KernelXpermsAccessDecision {
675 let locked_state = self.state.read();
676
677 let active_policy = match &locked_state.active_policy {
678 Some(active_policy) => active_policy,
679 None => {
681 return KernelXpermsAccessDecision {
682 allow: XpermsBitmap::ALL,
683 audit: XpermsBitmap::NONE,
684 permissive: false,
685 has_todo: false,
686 };
687 }
688 };
689
690 let base_decision_raw = locked_state.compute_access_decision_raw(
693 source_sid,
694 target_sid,
695 permission.class().into(),
696 );
697 let base_decision = locked_state
698 .access_decision_to_kernel_access_decision(permission.class(), base_decision_raw);
699 let permission_access_vector = permission.as_access_vector();
700 let base_permit =
701 base_decision.allow & permission_access_vector == permission_access_vector;
702 let base_audit = base_decision.audit & permission_access_vector == permission_access_vector;
703
704 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
706 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
707 let xperms_decision = active_policy.parsed.compute_xperms_access_decision(
708 xperms_kind,
709 &source_context,
710 &target_context,
711 permission.class(),
712 xperms_prefix,
713 );
714
715 let allow = if !base_permit { XpermsBitmap::NONE } else { xperms_decision.allow };
717 let audit = if base_audit {
718 XpermsBitmap::ALL
719 } else {
720 (xperms_decision.allow & xperms_decision.auditallow)
721 | (!xperms_decision.allow & xperms_decision.auditdeny)
722 };
723 let permissive = (base_decision.flags & SELINUX_AVD_FLAGS_PERMISSIVE) != 0;
724 let has_todo = base_decision.todo_bug.is_some();
725 KernelXpermsAccessDecision { allow, audit, permissive, has_todo }
726 }
727}
728
729impl AccessVectorComputer for SecurityServerBackend {
730 fn access_decision_to_kernel_access_decision(
731 &self,
732 class: KernelClass,
733 av: AccessDecision,
734 ) -> KernelAccessDecision {
735 self.state.read().access_decision_to_kernel_access_decision(class, av)
736 }
737}
738
739impl AccessVectorComputer for SecurityServerState {
740 fn access_decision_to_kernel_access_decision(
741 &self,
742 class: KernelClass,
743 av: AccessDecision,
744 ) -> KernelAccessDecision {
745 match &self.active_policy {
746 Some(policy) => policy.parsed.access_decision_to_kernel_access_decision(class, av),
747 None => KernelAccessDecision {
748 allow: AccessVector::ALL,
749 audit: AccessVector::NONE,
750 flags: 0,
751 todo_bug: None,
752 },
753 }
754 }
755}
756
757fn sid_from_mount_option(
760 active_policy: &mut ActivePolicy,
761 mount_option: &Option<Vec<u8>>,
762) -> Option<SecurityId> {
763 if let Some(label) = mount_option.as_ref() {
764 Some(
765 if let Some(context) = active_policy.parsed.parse_security_context(label.into()).ok() {
766 active_policy.sid_table.security_context_to_sid(&context).unwrap()
767 } else {
768 InitialSid::Unlabeled.into()
770 },
771 )
772 } else {
773 None
774 }
775}
776
777#[cfg(test)]
778mod tests {
779 use super::*;
780 use crate::permission_check::PermissionCheckResult;
781 use crate::{
782 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
783 ProcessPermission,
784 };
785 use std::num::NonZeroU32;
786
787 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
788 const TESTS_BINARY_POLICY: &[u8] =
789 include_bytes!("../testdata/micro_policies/security_server_tests_policy");
790 const MINIMAL_BINARY_POLICY: &[u8] =
791 include_bytes!("../testdata/composite_policies/compiled/minimal_policy");
792
793 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
794 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
795 let security_server = SecurityServer::new_default();
796 assert_eq!(
797 Ok(()),
798 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
799 );
800 security_server
801 }
802
803 #[test]
804 fn compute_access_vector_allows_all() {
805 let security_server = SecurityServer::new_default();
806 let sid1 = InitialSid::Kernel.into();
807 let sid2 = InitialSid::Unlabeled.into();
808 assert_eq!(
809 security_server
810 .backend
811 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
812 .allow,
813 AccessVector::ALL
814 );
815 }
816
817 #[test]
818 fn loaded_policy_can_be_retrieved() {
819 let security_server = security_server_with_tests_policy();
820 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_slice());
821 }
822
823 #[test]
824 fn loaded_policy_is_validated() {
825 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
826 let security_server = SecurityServer::new_default();
827 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
828 }
829
830 #[test]
831 fn enforcing_mode_is_reported() {
832 let security_server = SecurityServer::new_default();
833 assert!(!security_server.is_enforcing());
834
835 security_server.set_enforcing(true);
836 assert!(security_server.is_enforcing());
837 }
838
839 #[test]
840 fn without_policy_conditional_booleans_are_empty() {
841 let security_server = SecurityServer::new_default();
842 assert!(security_server.conditional_booleans().is_empty());
843 }
844
845 #[test]
846 fn conditional_booleans_can_be_queried() {
847 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
848 let security_server = SecurityServer::new_default();
849 assert_eq!(
850 Ok(()),
851 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
852 );
853
854 let booleans = security_server.conditional_booleans();
855 assert!(!booleans.is_empty());
856 let boolean = booleans[0].as_str();
857
858 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
859 assert!(security_server.get_boolean(boolean).is_ok());
860 }
861
862 #[test]
863 fn conditional_booleans_can_be_changed() {
864 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
865 let security_server = SecurityServer::new_default();
866 assert_eq!(
867 Ok(()),
868 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
869 );
870
871 let booleans = security_server.conditional_booleans();
872 assert!(!booleans.is_empty());
873 let boolean = booleans[0].as_str();
874
875 let (active, pending) = security_server.get_boolean(boolean).unwrap();
876 assert_eq!(active, pending, "Initially active and pending values should match");
877
878 security_server.set_pending_boolean(boolean, !active).unwrap();
879 let (active, pending) = security_server.get_boolean(boolean).unwrap();
880 assert!(active != pending, "Before commit pending should differ from active");
881
882 security_server.commit_pending_booleans();
883 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
884 assert_eq!(final_active, pending, "Pending value should be active after commit");
885 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
886 }
887
888 #[test]
889 fn parse_security_context_no_policy() {
890 let security_server = SecurityServer::new_default();
891 let error = security_server
892 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
893 .expect_err("expected error");
894 let error_string = format!("{:?}", error);
895 assert!(error_string.contains("no policy"));
896 }
897
898 #[test]
899 fn compute_new_fs_node_sid_no_defaults() {
900 let security_server = SecurityServer::new_default();
901 let policy_bytes =
902 include_bytes!("../testdata/micro_policies/file_no_defaults_policy").to_vec();
903 security_server.load_policy(policy_bytes).expect("binary policy loads");
904
905 let source_sid = security_server
906 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
907 .expect("creating SID from security context should succeed");
908 let target_sid = security_server
909 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
910 .expect("creating SID from security context should succeed");
911
912 let computed_sid = security_server
913 .as_permission_check(&Default::default())
914 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
915 .expect("new sid computed");
916 let computed_context = security_server
917 .sid_to_security_context(computed_sid)
918 .expect("computed sid associated with context");
919
920 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
923 }
924
925 #[test]
926 fn compute_new_fs_node_sid_source_defaults() {
927 let security_server = SecurityServer::new_default();
928 let policy_bytes =
929 include_bytes!("../testdata/micro_policies/file_source_defaults_policy").to_vec();
930 security_server.load_policy(policy_bytes).expect("binary policy loads");
931
932 let source_sid = security_server
933 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
934 .expect("creating SID from security context should succeed");
935 let target_sid = security_server
936 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
937 .expect("creating SID from security context should succeed");
938
939 let computed_sid = security_server
940 .as_permission_check(&Default::default())
941 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
942 .expect("new sid computed");
943 let computed_context = security_server
944 .sid_to_security_context(computed_sid)
945 .expect("computed sid associated with context");
946
947 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
950 }
951
952 #[test]
953 fn compute_new_fs_node_sid_target_defaults() {
954 let security_server = SecurityServer::new_default();
955 let policy_bytes =
956 include_bytes!("../testdata/micro_policies/file_target_defaults_policy").to_vec();
957 security_server.load_policy(policy_bytes).expect("binary policy loads");
958
959 let source_sid = security_server
960 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
961 .expect("creating SID from security context should succeed");
962 let target_sid = security_server
963 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
964 .expect("creating SID from security context should succeed");
965
966 let computed_sid = security_server
967 .as_permission_check(&Default::default())
968 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
969 .expect("new sid computed");
970 let computed_context = security_server
971 .sid_to_security_context(computed_sid)
972 .expect("computed sid associated with context");
973
974 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
976 }
977
978 #[test]
979 fn compute_new_fs_node_sid_range_source_low_default() {
980 let security_server = SecurityServer::new_default();
981 let policy_bytes =
982 include_bytes!("../testdata/micro_policies/file_range_source_low_policy").to_vec();
983 security_server.load_policy(policy_bytes).expect("binary policy loads");
984
985 let source_sid = security_server
986 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
987 .expect("creating SID from security context should succeed");
988 let target_sid = security_server
989 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
990 .expect("creating SID from security context should succeed");
991
992 let computed_sid = security_server
993 .as_permission_check(&Default::default())
994 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
995 .expect("new sid computed");
996 let computed_context = security_server
997 .sid_to_security_context(computed_sid)
998 .expect("computed sid associated with context");
999
1000 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1002 }
1003
1004 #[test]
1005 fn compute_new_fs_node_sid_range_source_low_high_default() {
1006 let security_server = SecurityServer::new_default();
1007 let policy_bytes =
1008 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy").to_vec();
1009 security_server.load_policy(policy_bytes).expect("binary policy loads");
1010
1011 let source_sid = security_server
1012 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1013 .expect("creating SID from security context should succeed");
1014 let target_sid = security_server
1015 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
1016 .expect("creating SID from security context should succeed");
1017
1018 let computed_sid = security_server
1019 .as_permission_check(&Default::default())
1020 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1021 .expect("new sid computed");
1022 let computed_context = security_server
1023 .sid_to_security_context(computed_sid)
1024 .expect("computed sid associated with context");
1025
1026 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1028 }
1029
1030 #[test]
1031 fn compute_new_fs_node_sid_range_source_high_default() {
1032 let security_server = SecurityServer::new_default();
1033 let policy_bytes =
1034 include_bytes!("../testdata/micro_policies/file_range_source_high_policy").to_vec();
1035 security_server.load_policy(policy_bytes).expect("binary policy loads");
1036
1037 let source_sid = security_server
1038 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1039 .expect("creating SID from security context should succeed");
1040 let target_sid = security_server
1041 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
1042 .expect("creating SID from security context should succeed");
1043
1044 let computed_sid = security_server
1045 .as_permission_check(&Default::default())
1046 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1047 .expect("new sid computed");
1048 let computed_context = security_server
1049 .sid_to_security_context(computed_sid)
1050 .expect("computed sid associated with context");
1051
1052 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1054 }
1055
1056 #[test]
1057 fn compute_new_fs_node_sid_range_target_low_default() {
1058 let security_server = SecurityServer::new_default();
1059 let policy_bytes =
1060 include_bytes!("../testdata/micro_policies/file_range_target_low_policy").to_vec();
1061 security_server.load_policy(policy_bytes).expect("binary policy loads");
1062
1063 let source_sid = security_server
1064 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1065 .expect("creating SID from security context should succeed");
1066 let target_sid = security_server
1067 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1068 .expect("creating SID from security context should succeed");
1069
1070 let computed_sid = security_server
1071 .as_permission_check(&Default::default())
1072 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1073 .expect("new sid computed");
1074 let computed_context = security_server
1075 .sid_to_security_context(computed_sid)
1076 .expect("computed sid associated with context");
1077
1078 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1080 }
1081
1082 #[test]
1083 fn compute_new_fs_node_sid_range_target_low_high_default() {
1084 let security_server = SecurityServer::new_default();
1085 let policy_bytes =
1086 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy").to_vec();
1087 security_server.load_policy(policy_bytes).expect("binary policy loads");
1088
1089 let source_sid = security_server
1090 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1091 .expect("creating SID from security context should succeed");
1092 let target_sid = security_server
1093 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1094 .expect("creating SID from security context should succeed");
1095
1096 let computed_sid = security_server
1097 .as_permission_check(&Default::default())
1098 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1099 .expect("new sid computed");
1100 let computed_context = security_server
1101 .sid_to_security_context(computed_sid)
1102 .expect("computed sid associated with context");
1103
1104 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1106 }
1107
1108 #[test]
1109 fn compute_new_fs_node_sid_range_target_high_default() {
1110 let security_server = SecurityServer::new_default();
1111 let policy_bytes =
1112 include_bytes!("../testdata/micro_policies/file_range_target_high_policy").to_vec();
1113 security_server.load_policy(policy_bytes).expect("binary policy loads");
1114
1115 let source_sid = security_server
1116 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1117 .expect("creating SID from security context should succeed");
1118 let target_sid = security_server
1119 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1120 .expect("creating SID from security context should succeed");
1121
1122 let computed_sid = security_server
1123 .as_permission_check(&Default::default())
1124 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1125 .expect("new sid computed");
1126 let computed_context = security_server
1127 .sid_to_security_context(computed_sid)
1128 .expect("computed sid associated with context");
1129
1130 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1132 }
1133
1134 #[test]
1135 fn compute_new_fs_node_sid_with_name() {
1136 let security_server = SecurityServer::new_default();
1137 let policy_bytes =
1138 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy")
1139 .to_vec();
1140 security_server.load_policy(policy_bytes).expect("binary policy loads");
1141
1142 let source_sid = security_server
1143 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1144 .expect("creating SID from security context should succeed");
1145 let target_sid = security_server
1146 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1147 .expect("creating SID from security context should succeed");
1148
1149 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1150 let computed_sid = security_server
1151 .as_permission_check(&Default::default())
1152 .compute_new_fs_node_sid(
1153 source_sid,
1154 target_sid,
1155 FileClass::File.into(),
1156 SPECIAL_FILE_NAME.into(),
1157 )
1158 .expect("new sid computed");
1159 let computed_context = security_server
1160 .sid_to_security_context(computed_sid)
1161 .expect("computed sid associated with context");
1162
1163 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1165
1166 let computed_sid = security_server
1167 .as_permission_check(&Default::default())
1168 .compute_new_fs_node_sid(
1169 source_sid,
1170 target_sid,
1171 FileClass::ChrFile.into(),
1172 SPECIAL_FILE_NAME.into(),
1173 )
1174 .expect("new sid computed");
1175 let computed_context = security_server
1176 .sid_to_security_context(computed_sid)
1177 .expect("computed sid associated with context");
1178
1179 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1182
1183 const OTHER_FILE_NAME: &[u8] = b"other_file";
1184 let computed_sid = security_server
1185 .as_permission_check(&Default::default())
1186 .compute_new_fs_node_sid(
1187 source_sid,
1188 target_sid,
1189 FileClass::File.into(),
1190 OTHER_FILE_NAME.into(),
1191 )
1192 .expect("new sid computed");
1193 let computed_context = security_server
1194 .sid_to_security_context(computed_sid)
1195 .expect("computed sid associated with context");
1196
1197 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1200 }
1201
1202 #[test]
1203 fn permissions_are_fresh_after_different_policy_load() {
1204 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1205 let allow_fork_bytes =
1206 include_bytes!("../testdata/composite_policies/compiled/allow_fork_policy").to_vec();
1207 let context = b"source_u:object_r:source_t:s0:c0";
1208
1209 let security_server = SecurityServer::new_default();
1210 security_server.set_enforcing(true);
1211
1212 let local_cache = Default::default();
1213 let permission_check = security_server.as_permission_check(&local_cache);
1214
1215 assert_eq!(
1217 Ok(()),
1218 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1219 );
1220 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1221
1222 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1224
1225 assert_eq!(
1227 Ok(()),
1228 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1229 );
1230
1231 let permission_check = security_server.as_permission_check(&local_cache);
1233
1234 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1236 }
1237
1238 #[test]
1239 fn unknown_sids_are_effectively_unlabeled() {
1240 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1241 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy"
1242 )
1243 .to_vec();
1244 let with_additional_domain_policy_bytes =
1245 include_bytes!("../testdata/composite_policies/compiled/with_additional_domain_policy")
1246 .to_vec();
1247 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1248 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1249
1250 let security_server = SecurityServer::new_default();
1251 security_server.set_enforcing(true);
1252
1253 assert_eq!(
1256 Ok(()),
1257 security_server
1258 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1259 .map_err(|e| format!("{:?}", e))
1260 );
1261 let allowed_type_sid =
1262 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1263 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1264
1265 assert_eq!(
1268 Ok(()),
1269 security_server
1270 .load_policy(with_additional_domain_policy_bytes.clone())
1271 .map_err(|e| format!("{:?}", e))
1272 );
1273 let additional_type_sid =
1274 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1275 assert_eq!(
1276 allowed_type_sid,
1277 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1278 );
1279
1280 let local_cache = Default::default();
1281 let permission_check = security_server.as_permission_check(&local_cache);
1282
1283 assert!(
1287 !permission_check
1288 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1289 .granted
1290 );
1291 assert!(
1292 !permission_check
1293 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1294 .granted
1295 );
1296 assert!(
1297 !permission_check
1298 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1299 .granted
1300 );
1301 assert!(
1302 !permission_check
1303 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1304 .granted
1305 );
1306
1307 assert_eq!(
1309 Ok(()),
1310 security_server
1311 .load_policy(with_unlabeled_access_domain_policy_bytes)
1312 .map_err(|e| format!("{:?}", e))
1313 );
1314
1315 let permission_check = security_server.as_permission_check(&local_cache);
1317
1318 assert!(
1322 permission_check
1323 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1324 .granted
1325 );
1326 assert!(
1327 !permission_check
1328 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1329 .granted
1330 );
1331
1332 assert!(
1337 !permission_check
1338 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1339 .granted
1340 );
1341 assert!(
1342 permission_check
1343 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1344 .granted
1345 );
1346
1347 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1349
1350 assert_eq!(
1353 Ok(()),
1354 security_server
1355 .load_policy(with_additional_domain_policy_bytes)
1356 .map_err(|e| format!("{:?}", e))
1357 );
1358 assert_eq!(
1359 additional_type_context.to_vec(),
1360 security_server.sid_to_security_context(additional_type_sid).unwrap()
1361 );
1362 }
1363
1364 #[test]
1365 fn permission_check_permissive() {
1366 let security_server = security_server_with_tests_policy();
1367 security_server.set_enforcing(false);
1368 assert!(!security_server.is_enforcing());
1369
1370 let sid =
1371 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1372 let local_cache = Default::default();
1373 let permission_check = security_server.as_permission_check(&local_cache);
1374
1375 assert_eq!(
1378 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1379 PermissionCheckResult {
1380 granted: true,
1381 audit: false,
1382 permissive: false,
1383 todo_bug: None
1384 }
1385 );
1386
1387 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1391 assert_eq!(
1392 result,
1393 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1394 );
1395 assert!(result.permit());
1396
1397 let result = permission_check.has_permission(
1401 sid,
1402 sid,
1403 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1404 );
1405 assert_eq!(
1406 result,
1407 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1408 );
1409 assert!(result.permit());
1410 }
1411
1412 #[test]
1413 fn permission_check_enforcing() {
1414 let security_server = security_server_with_tests_policy();
1415 security_server.set_enforcing(true);
1416 assert!(security_server.is_enforcing());
1417
1418 let sid =
1419 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1420 let local_cache = Default::default();
1421 let permission_check = security_server.as_permission_check(&local_cache);
1422
1423 let result = permission_check.has_permission(sid, sid, ProcessPermission::Fork);
1425 assert_eq!(
1426 result,
1427 PermissionCheckResult {
1428 granted: true,
1429 audit: false,
1430 permissive: false,
1431 todo_bug: None
1432 }
1433 );
1434 assert!(result.permit());
1435
1436 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
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 let result = permission_check.has_permission(
1453 sid,
1454 sid,
1455 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1456 );
1457 assert_eq!(
1458 result,
1459 PermissionCheckResult {
1460 granted: false,
1461 audit: true,
1462 permissive: false,
1463 todo_bug: None
1464 }
1465 );
1466 assert!(!result.permit());
1467 }
1468
1469 #[test]
1470 fn permissive_domain() {
1471 let security_server = security_server_with_tests_policy();
1472 security_server.set_enforcing(true);
1473 assert!(security_server.is_enforcing());
1474
1475 let permissive_sid = security_server
1476 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1477 .unwrap();
1478 let non_permissive_sid = security_server
1479 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1480 .unwrap();
1481
1482 let local_cache = Default::default();
1483 let permission_check = security_server.as_permission_check(&local_cache);
1484
1485 let result = permission_check.has_permission(
1487 permissive_sid,
1488 permissive_sid,
1489 ProcessPermission::GetSched,
1490 );
1491 assert_eq!(
1492 result,
1493 PermissionCheckResult { granted: true, audit: false, permissive: true, todo_bug: None }
1494 );
1495 assert!(result.permit());
1496 let result = permission_check.has_permission(
1497 non_permissive_sid,
1498 non_permissive_sid,
1499 ProcessPermission::GetSched,
1500 );
1501 assert_eq!(
1502 result,
1503 PermissionCheckResult {
1504 granted: true,
1505 audit: false,
1506 permissive: false,
1507 todo_bug: None
1508 }
1509 );
1510 assert!(result.permit());
1511
1512 let result = permission_check.has_permission(
1515 permissive_sid,
1516 non_permissive_sid,
1517 ProcessPermission::GetSched,
1518 );
1519 assert_eq!(
1520 result,
1521 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1522 );
1523 assert!(result.permit());
1524 let result = permission_check.has_permission(
1525 non_permissive_sid,
1526 permissive_sid,
1527 ProcessPermission::GetSched,
1528 );
1529 assert_eq!(
1530 result,
1531 PermissionCheckResult {
1532 granted: false,
1533 audit: true,
1534 permissive: false,
1535 todo_bug: None
1536 }
1537 );
1538 assert!(!result.permit());
1539
1540 let result = permission_check.has_permission(
1545 permissive_sid,
1546 non_permissive_sid,
1547 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1548 );
1549 assert_eq!(
1550 result,
1551 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1552 );
1553 assert!(result.permit());
1554 let result = permission_check.has_permission(
1555 non_permissive_sid,
1556 non_permissive_sid,
1557 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1558 );
1559 assert_eq!(
1560 result,
1561 PermissionCheckResult {
1562 granted: false,
1563 audit: true,
1564 permissive: false,
1565 todo_bug: None
1566 }
1567 );
1568 assert!(!result.permit());
1569 }
1570
1571 #[test]
1572 fn auditallow_and_dontaudit() {
1573 let security_server = security_server_with_tests_policy();
1574 security_server.set_enforcing(true);
1575 assert!(security_server.is_enforcing());
1576
1577 let audit_sid = security_server
1578 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1579 .unwrap();
1580
1581 let local_cache = Default::default();
1582 let permission_check = security_server.as_permission_check(&local_cache);
1583
1584 let result = permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork);
1586 assert_eq!(
1587 result,
1588 PermissionCheckResult { granted: true, audit: true, permissive: false, todo_bug: None }
1589 );
1590 assert!(result.permit());
1591
1592 let result =
1594 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched);
1595 assert_eq!(
1596 result,
1597 PermissionCheckResult {
1598 granted: true,
1599 audit: false,
1600 permissive: false,
1601 todo_bug: None
1602 }
1603 );
1604 assert!(result.permit());
1605
1606 let result =
1608 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched);
1609 assert_eq!(
1610 result,
1611 PermissionCheckResult {
1612 granted: false,
1613 audit: false,
1614 permissive: false,
1615 todo_bug: None
1616 }
1617 );
1618 assert!(!result.permit());
1619
1620 let result =
1622 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid);
1623 assert_eq!(
1624 result,
1625 PermissionCheckResult {
1626 granted: false,
1627 audit: true,
1628 permissive: false,
1629 todo_bug: None
1630 }
1631 );
1632 assert!(!result.permit());
1633 }
1634
1635 #[test]
1636 fn access_checks_with_exceptions_config() {
1637 const EXCEPTIONS_CONFIG: &[&str] = &[
1638 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1640 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1641 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1642 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1643 "todo_permissive b/005 test_exception_todo_permissive_t",
1644 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1646 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1647 "todo_permissive b/103 test_undefined_source_t",
1648 ];
1649 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1650 let security_server = SecurityServer::new(String::new(), exceptions_config);
1651 security_server.set_enforcing(true);
1652
1653 const EXCEPTIONS_POLICY: &[u8] =
1654 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy");
1655 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1656
1657 let source_sid = security_server
1658 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1659 .unwrap();
1660 let target_sid = security_server
1661 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1662 .unwrap();
1663 let other_sid = security_server
1664 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1665 .unwrap();
1666 let permissive_sid = security_server
1667 .security_context_to_sid(
1668 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1669 )
1670 .unwrap();
1671 let unmatched_sid = security_server
1672 .security_context_to_sid(
1673 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1674 )
1675 .unwrap();
1676 let todo_permissive_sid = security_server
1677 .security_context_to_sid(
1678 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1679 )
1680 .unwrap();
1681
1682 let local_cache = Default::default();
1683 let permission_check = security_server.as_permission_check(&local_cache);
1684
1685 let result =
1687 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid);
1688 assert_eq!(
1689 result,
1690 PermissionCheckResult {
1691 granted: false,
1692 audit: true,
1693 permissive: false,
1694 todo_bug: None
1695 }
1696 );
1697 assert!(!result.permit());
1698
1699 let result =
1701 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint);
1702 assert_eq!(
1703 result,
1704 PermissionCheckResult {
1705 granted: true,
1706 audit: true,
1707 permissive: false,
1708 todo_bug: Some(NonZeroU32::new(1).unwrap())
1709 }
1710 );
1711 assert!(result.permit());
1712
1713 let result =
1715 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans);
1716 assert_eq!(
1717 result,
1718 PermissionCheckResult {
1719 granted: true,
1720 audit: false,
1721 permissive: false,
1722 todo_bug: None,
1723 }
1724 );
1725 assert!(result.permit());
1726
1727 let result =
1729 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint);
1730 assert_eq!(
1731 result,
1732 PermissionCheckResult {
1733 granted: false,
1734 audit: true,
1735 permissive: false,
1736 todo_bug: None
1737 }
1738 );
1739 assert!(!result.permit());
1740
1741 let result = permission_check.has_permission(
1743 other_sid,
1744 target_sid,
1745 CommonFsNodePermission::Read.for_class(FileClass::ChrFile),
1746 );
1747 assert_eq!(
1748 result,
1749 PermissionCheckResult {
1750 granted: true,
1751 audit: true,
1752 permissive: false,
1753 todo_bug: Some(NonZeroU32::new(2).unwrap())
1754 }
1755 );
1756 assert!(result.permit());
1757
1758 let result =
1760 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint);
1761 assert_eq!(
1762 result,
1763 PermissionCheckResult {
1764 granted: false,
1765 audit: true,
1766 permissive: false,
1767 todo_bug: None
1768 }
1769 );
1770 assert!(!result.permit());
1771
1772 let result =
1774 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint);
1775 assert_eq!(
1776 result,
1777 PermissionCheckResult {
1778 granted: false,
1779 audit: true,
1780 permissive: false,
1781 todo_bug: None
1782 }
1783 );
1784 assert!(!result.permit());
1785
1786 let result =
1788 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint);
1789 assert_eq!(
1790 result,
1791 PermissionCheckResult {
1792 granted: true,
1793 audit: true,
1794 permissive: true,
1795 todo_bug: Some(NonZeroU32::new(4).unwrap())
1796 }
1797 );
1798 assert!(result.permit());
1799
1800 let result = permission_check.has_permission(
1803 todo_permissive_sid,
1804 target_sid,
1805 FilePermission::Entrypoint,
1806 );
1807 assert_eq!(
1808 result,
1809 PermissionCheckResult {
1810 granted: true,
1811 audit: true,
1812 permissive: false,
1813 todo_bug: Some(NonZeroU32::new(5).unwrap())
1814 }
1815 );
1816 assert!(result.permit());
1817 let result = permission_check.has_permission(
1818 todo_permissive_sid,
1819 todo_permissive_sid,
1820 FilePermission::Entrypoint,
1821 );
1822 assert_eq!(
1823 result,
1824 PermissionCheckResult {
1825 granted: true,
1826 audit: true,
1827 permissive: false,
1828 todo_bug: Some(NonZeroU32::new(5).unwrap())
1829 }
1830 );
1831 assert!(result.permit());
1832 let result = permission_check.has_permission(
1833 todo_permissive_sid,
1834 target_sid,
1835 FilePermission::Entrypoint,
1836 );
1837 assert_eq!(
1838 result,
1839 PermissionCheckResult {
1840 granted: true,
1841 audit: true,
1842 permissive: false,
1843 todo_bug: Some(NonZeroU32::new(5).unwrap())
1844 }
1845 );
1846 assert!(result.permit());
1847 }
1848
1849 #[test]
1850 fn handle_unknown() {
1851 let security_server = security_server_with_tests_policy();
1852
1853 let sid = security_server
1854 .security_context_to_sid("user0:object_r:type0:s0".into())
1855 .expect("Resolve Context to SID");
1856
1857 const REJECT_POLICY: &[u8] =
1861 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-reject");
1862 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1863
1864 security_server.set_enforcing(true);
1865
1866 const DENY_POLICY: &[u8] =
1868 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny");
1869 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1870 let local_cache = Default::default();
1871 let permission_check = security_server.as_permission_check(&local_cache);
1872
1873 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1875 assert_eq!(
1876 result,
1877 PermissionCheckResult {
1878 granted: false,
1879 audit: true,
1880 permissive: false,
1881 todo_bug: None
1882 }
1883 );
1884 assert!(!result.permit());
1885 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1886 assert_eq!(
1887 result,
1888 PermissionCheckResult {
1889 granted: false,
1890 audit: true,
1891 permissive: false,
1892 todo_bug: None
1893 }
1894 );
1895 assert!(!result.permit());
1896
1897 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1899 assert_eq!(
1900 result,
1901 PermissionCheckResult {
1902 granted: true,
1903 audit: false,
1904 permissive: false,
1905 todo_bug: None
1906 }
1907 );
1908 assert!(result.permit());
1909 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1910 assert_eq!(
1911 result,
1912 PermissionCheckResult {
1913 granted: false,
1914 audit: true,
1915 permissive: false,
1916 todo_bug: None
1917 }
1918 );
1919 assert!(!result.permit());
1920
1921 const ALLOW_POLICY: &[u8] =
1923 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-allow");
1924 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1925 let local_cache2 = Default::default();
1926 let permission_check = security_server.as_permission_check(&local_cache2);
1927
1928 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1930 assert_eq!(
1931 result,
1932 PermissionCheckResult {
1933 granted: true,
1934 audit: false,
1935 permissive: false,
1936 todo_bug: None
1937 }
1938 );
1939 assert!(result.permit());
1940 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1941 assert_eq!(
1942 result,
1943 PermissionCheckResult {
1944 granted: true,
1945 audit: false,
1946 permissive: false,
1947 todo_bug: None
1948 }
1949 );
1950 assert!(result.permit());
1951
1952 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1954 assert_eq!(
1955 result,
1956 PermissionCheckResult {
1957 granted: true,
1958 audit: false,
1959 permissive: false,
1960 todo_bug: None
1961 }
1962 );
1963 assert!(result.permit());
1964
1965 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1966 assert_eq!(
1967 result,
1968 PermissionCheckResult {
1969 granted: false,
1970 audit: true,
1971 permissive: false,
1972 todo_bug: None
1973 }
1974 );
1975 assert!(!result.permit());
1976 }
1977}