1use crate::exceptions_config::ExceptionsConfig;
6use crate::kernel::{
7 AccessVectorCache, CacheStats, KernelAccessDecision, KernelXpermsAccessDecision, PolicyIndex,
8 Query,
9};
10use crate::permission_check::{PerThreadCache, PermissionCheck};
11use crate::policy::{
12 AccessDecision, AccessVector, ClassId, FsUseLabelAndType, FsUseType, HandleUnknown,
13 HasName as _, HasPolicyId as _, PermissionId, Policy, PolicyData, SELINUX_AVD_FLAGS_PERMISSIVE,
14 SecurityContext, XpermsBitmap, XpermsKind,
15};
16use crate::sid_table::{PortableSidTable, SidTable};
17use crate::sync::{LockDepMutex, SeLinuxSecurityServerStateLock, SeLinuxStatusLock};
18use crate::{
19 ClassPermission, FileSystemLabel, FileSystemLabelingScheme, FileSystemMountOptions,
20 FileSystemMountSids, InitialSid, KernelClass, KernelPermission, NullessByteStr, ObjectClass,
21 PolicyCap, SeLinuxStatus, SeLinuxStatusPublisher, SecurityId,
22};
23use anyhow::Context as _;
24use fuchsia_rcu::{RcuDroppable, RcuOptionArc, RcuReadScope};
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
32#[derive(RcuDroppable)]
33struct ActivePolicy {
34 parsed: PolicyIndex,
36
37 sid_table: SidTable,
39
40 exceptions: ExceptionsConfig,
42
43 binary_policy_size: usize,
45}
46
47impl ActivePolicy {
48 fn compute_access_decision_raw(
49 &self,
50 scope: &RcuReadScope,
51 source_sid: SecurityId,
52 target_sid: SecurityId,
53 target_class: ObjectClass,
54 ) -> AccessDecision {
55 let (source_context, target_context) =
56 self.sid_table.sids_to_security_contexts(scope, source_sid, target_sid);
57 self.compute_access_decision_for_contexts(source_context, target_context, target_class)
58 }
59
60 fn compute_access_decision_for_contexts(
61 &self,
62 source_context: &SecurityContext,
63 target_context: &SecurityContext,
64 target_class: ObjectClass,
65 ) -> AccessDecision {
66 let mut decision =
67 self.parsed.compute_access_decision(source_context, target_context, target_class);
68
69 decision.todo_bug =
70 self.exceptions.lookup(source_context.type_(), target_context.type_(), target_class);
71
72 decision
73 }
74}
75
76#[derive(Default)]
77struct SeLinuxBooleans {
78 active: HashMap<String, bool>,
81 pending: HashMap<String, bool>,
83}
84
85impl SeLinuxBooleans {
86 fn reset(&mut self, booleans: Vec<(String, bool)>) {
87 self.active = HashMap::from_iter(booleans);
88 self.pending.clear();
89 }
90 fn names(&self) -> Vec<String> {
91 self.active.keys().cloned().collect()
92 }
93 fn set_pending(&mut self, name: &str, value: bool) -> Result<(), ()> {
94 if !self.active.contains_key(name) {
95 return Err(());
96 }
97 self.pending.insert(name.into(), value);
98 Ok(())
99 }
100 fn get(&self, name: &str) -> Result<(bool, bool), ()> {
101 let active = self.active.get(name).ok_or(())?;
102 let pending = self.pending.get(name).unwrap_or(active);
103 Ok((*active, *pending))
104 }
105 fn commit_pending(&mut self) {
106 self.active.extend(self.pending.drain());
107 }
108}
109
110#[derive(Default)]
111struct SecurityServerState {
112 booleans: SeLinuxBooleans,
114
115 status_publisher: Option<Box<dyn SeLinuxStatusPublisher>>,
117}
118
119pub(crate) struct SecurityServerBackend {
120 active_policy: RcuOptionArc<ActivePolicy>,
122
123 portable_sids: LockDepMutex<PortableSidTable, SeLinuxSecurityServerStateLock>,
127}
128
129#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
131pub struct PolicySeqNo(u32);
132
133impl PolicySeqNo {
134 pub const INITIAL: Self = Self(0);
135
136 #[cfg(test)]
137 pub const OTHER: Self = Self(1);
138}
139
140pub struct SecurityServer {
141 state: LockDepMutex<SecurityServerState, SeLinuxStatusLock>,
144
145 access_vector_cache: AccessVectorCache,
148
149 backend: Arc<SecurityServerBackend>,
151
152 is_enforcing: AtomicBool,
155
156 policy_change_count: AtomicU32,
161
162 exceptions: Vec<String>,
164
165 allow_unimplemented: bool,
167}
168
169impl SecurityServer {
170 pub fn new_default() -> Arc<Self> {
172 Self::new(String::new(), Vec::new())
173 }
174
175 pub fn new(options: String, exceptions: Vec<String>) -> Arc<Self> {
177 let mut allow_unimplemented = false;
178 for option in options.split(',').map(str::trim).filter(|s| !s.is_empty()) {
179 match option {
180 "allow_unimplemented" => allow_unimplemented = true,
181 _ => {}
182 }
183 }
184
185 let backend = Arc::new(SecurityServerBackend {
186 active_policy: RcuOptionArc::default(),
187 portable_sids: LockDepMutex::new(PortableSidTable::default()),
188 });
189
190 let access_vector_cache = AccessVectorCache::new(backend.clone());
191
192 Arc::new(Self {
193 state: LockDepMutex::new(SecurityServerState::default()),
194 access_vector_cache,
195 backend,
196 is_enforcing: AtomicBool::new(false),
197 policy_change_count: AtomicU32::new(0),
198 exceptions,
199 allow_unimplemented,
200 })
201 }
202
203 pub fn as_permission_check<'a>(
206 self: &'a Self,
207 local_cache: &'a PerThreadCache,
208 ) -> PermissionCheck<'a> {
209 PermissionCheck::new(self, &self.access_vector_cache, local_cache)
210 }
211
212 pub fn security_context_to_sid(
216 &self,
217 security_context: NullessByteStr<'_>,
218 ) -> Result<SecurityId, anyhow::Error> {
219 self.backend.compute_sid(|_scope, active_policy| {
220 active_policy
221 .parsed
222 .parse_security_context(security_context)
223 .map_err(anyhow::Error::from)
224 })
225 }
226
227 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
234 let scope = RcuReadScope::new();
235 let active_policy = self.backend.active_policy.as_ref(&scope)?;
236 let context = active_policy.sid_table.sid_to_security_context(&scope, sid);
237 Some(active_policy.parsed.serialize_security_context(context))
238 }
239
240 pub fn sid_to_security_context_with_nul(&self, sid: SecurityId) -> Option<Vec<u8>> {
242 self.sid_to_security_context(sid).map(|mut context| {
243 context.push(0u8);
244 context
245 })
246 }
247
248 pub fn load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
250 let binary_policy_size = binary_policy.len();
253 let policy = Policy::parse(&binary_policy)?;
254 policy.validate()?;
255 if !self.allow_unimplemented {
256 validate_no_unsupported_policy_features_used(&policy)?;
257 }
258
259 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
260 let exceptions = ExceptionsConfig::new(&policy, &exceptions)?;
261 let parsed = PolicyIndex::new(policy)?;
262
263 self.with_mut_state_and_reset_cache(|state| {
265 state.booleans.reset(
268 parsed
269 .conditional_booleans()
270 .iter()
271 .map(|boolean| {
273 (String::from_utf8(boolean.name().to_vec()).unwrap(), boolean.active())
274 })
275 .collect(),
276 );
277
278 let portable_sids = self.backend.portable_sids.lock();
279 let sid_table = SidTable::new(&parsed, &portable_sids);
280 self.backend.active_policy.update(Some(Arc::new(ActivePolicy {
281 parsed,
282 sid_table,
283 exceptions,
284 binary_policy_size,
285 })));
286 });
287
288 Ok(())
289 }
290
291 pub fn has_policy(&self) -> bool {
293 let scope = RcuReadScope::new();
294 self.backend.active_policy.as_ref(&scope).is_some()
295 }
296
297 pub fn binary_policy_size(&self) -> Option<usize> {
299 let scope = RcuReadScope::new();
300 let active_policy = self.backend.active_policy.as_ref(&scope)?;
301 Some(active_policy.binary_policy_size)
302 }
303
304 pub fn get_binary_policy(&self) -> Option<PolicyData> {
306 let scope = RcuReadScope::new();
307 let active_policy = self.backend.active_policy.as_ref(&scope)?;
308 let mut bytes = Vec::with_capacity(active_policy.binary_policy_size);
309 active_policy
310 .parsed
311 .serialize(&mut bytes)
312 .expect("Serializing an ActivePolicy should not fail.");
313 Some(Arc::from(bytes))
314 }
315
316 pub fn set_enforcing(&self, enforcing: bool) {
318 self.with_mut_state_and_update_status(|_| {
319 self.is_enforcing.store(enforcing, Ordering::Release);
320 });
321 }
322
323 pub fn is_enforcing(&self) -> bool {
324 self.is_enforcing.load(Ordering::Acquire)
325 }
326
327 pub fn deny_unknown(&self) -> bool {
330 let scope = RcuReadScope::new();
331 self.backend
332 .active_policy
333 .as_ref(&scope)
334 .is_none_or(|p| p.parsed.handle_unknown() != HandleUnknown::Allow)
335 }
336
337 pub fn reject_unknown(&self) -> bool {
340 let scope = RcuReadScope::new();
341 self.backend
342 .active_policy
343 .as_ref(&scope)
344 .is_some_and(|p| p.parsed.handle_unknown() == HandleUnknown::Reject)
345 }
346
347 pub fn conditional_booleans(&self) -> Vec<String> {
350 self.state.lock().booleans.names()
351 }
352
353 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
355 self.state.lock().booleans.get(name)
356 }
357
358 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
360 self.state.lock().booleans.set_pending(name, value)
361 }
362
363 pub fn commit_pending_booleans(&self) {
365 self.with_mut_state_and_reset_cache(|state| {
367 state.booleans.commit_pending();
368 });
369 }
370
371 pub fn is_policycap_enabled(&self, policy_cap: PolicyCap) -> bool {
373 let scope = RcuReadScope::new();
374 let Some(policy) = self.backend.active_policy.as_ref(&scope) else {
375 return false;
376 };
377 policy.parsed.has_policycap(policy_cap)
378 }
379
380 pub fn avc_cache_stats(&self) -> CacheStats {
382 self.access_vector_cache.cache_stats()
383 }
384
385 pub fn policy_seqno(&self) -> PolicySeqNo {
391 PolicySeqNo(self.policy_change_count.load(Ordering::Relaxed))
392 }
393
394 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
396 let scope = RcuReadScope::new();
397 let names = self
398 .backend
399 .expect_active_policy(&scope)
400 .parsed
401 .classes()
402 .iter()
403 .map(|class| class.name().to_vec())
404 .collect();
405 Ok(names)
406 }
407
408 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
410 let scope = RcuReadScope::new();
411 Ok(self
412 .backend
413 .expect_active_policy(&scope)
414 .parsed
415 .classes()
416 .get_by_name(name.as_bytes())
417 .ok_or(())?
418 .id())
419 }
420
421 pub fn class_permissions_by_name(
425 &self,
426 name: &str,
427 ) -> Result<Vec<(PermissionId, Vec<u8>)>, ()> {
428 let scope = RcuReadScope::new();
429 self.backend.expect_active_policy(&scope).parsed.find_class_permissions_by_name(name)
430 }
431
432 pub fn resolve_fs_label(
436 &self,
437 fs_type: NullessByteStr<'_>,
438 mount_options: &FileSystemMountOptions,
439 ) -> Result<FileSystemLabel, anyhow::Error> {
440 let mut portable_sids = self.backend.portable_sids.lock();
443 let scope = RcuReadScope::new();
444 let active_policy = self.backend.expect_active_policy(&scope);
445
446 let mut resolve_sid = |context: &SecurityContext| -> Result<SecurityId, anyhow::Error> {
447 unsafe {
449 active_policy
450 .sid_table
451 .security_context_to_sid(
452 &scope,
453 &active_policy.parsed,
454 &mut portable_sids,
455 context,
456 )
457 .map_err(anyhow::Error::from)
458 }
459 };
460
461 let mut sid_from_mount_option =
462 |mount_option: &Option<Vec<u8>>| -> Result<Option<SecurityId>, anyhow::Error> {
463 let Some(label) = mount_option else {
464 return Ok(None);
465 };
466 let context = active_policy.parsed.parse_security_context(label.into())?;
467 resolve_sid(&context).map(Some)
468 };
469
470 let mount_sids = FileSystemMountSids {
471 context: sid_from_mount_option(&mount_options.context)?,
472 fs_context: sid_from_mount_option(&mount_options.fs_context)?,
473 def_context: sid_from_mount_option(&mount_options.def_context)?,
474 root_context: sid_from_mount_option(&mount_options.root_context)?,
475 };
476
477 let label = if let Some(mountpoint_sid) = mount_sids.context {
478 FileSystemLabel {
482 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
483 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
484 mount_sids,
485 }
486 } else if let Some(FsUseLabelAndType { context, use_type }) =
487 active_policy.parsed.fs_use_label_and_type(fs_type)
488 {
489 let fs_sid_from_policy = resolve_sid(&context)?;
491 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
492 FileSystemLabel {
493 sid: fs_sid,
494 scheme: FileSystemLabelingScheme::FsUse {
495 fs_use_type: use_type,
496 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
497 },
498 mount_sids,
499 }
500 } else if let Some(context) =
501 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
502 {
503 let genfscon_sid = resolve_sid(&context)?;
505 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
506
507 let fs_type = fs_type.as_bytes();
512 let mut supports_seclabel = matches!(fs_type, b"sysfs" | b"tracefs" | b"pstore");
513 supports_seclabel |= matches!(fs_type, b"cgroup" | b"cgroup2")
514 && active_policy.parsed.has_policycap(PolicyCap::CgroupSeclabel);
515 supports_seclabel |= fs_type == b"functionfs"
516 && active_policy.parsed.has_policycap(PolicyCap::FunctionfsSeclabel);
517
518 FileSystemLabel {
519 sid: fs_sid,
520 scheme: FileSystemLabelingScheme::GenFsCon { supports_seclabel },
521 mount_sids,
522 }
523 } else {
524 FileSystemLabel {
526 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
527 scheme: FileSystemLabelingScheme::FsUse {
528 fs_use_type: FsUseType::Xattr,
529 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
530 },
531 mount_sids,
532 }
533 };
534 Ok(label)
535 }
536
537 pub fn genfscon_label_for_fs_and_path(
542 &self,
543 fs_type: NullessByteStr<'_>,
544 node_path: NullessByteStr<'_>,
545 class_id: Option<KernelClass>,
546 ) -> Result<SecurityId, anyhow::Error> {
547 self.backend.compute_sid(|_scope, active_policy| {
548 active_policy
549 .parsed
550 .genfscon_label_for_fs_and_path(fs_type, node_path.into(), class_id)
551 .ok_or_else(|| {
552 anyhow::anyhow!("Genfscon label requested for non-genfscon labeled filesystem")
553 })
554 })
555 }
556
557 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
562 let scope = RcuReadScope::new();
563 let active_policy = self.backend.expect_active_policy(&scope);
564 let (bounded_context, parent_context) =
565 active_policy.sid_table.sids_to_security_contexts(&scope, bounded_sid, parent_sid);
566 active_policy.parsed.is_bounded_by(bounded_context.type_(), parent_context.type_())
567 }
568
569 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
576 self.with_mut_state_and_update_status(|state| {
577 assert!(state.status_publisher.is_none());
578 state.status_publisher = Some(status_holder);
579 });
580 }
581
582 fn with_mut_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
586 let mut locked_state = self.state.lock();
587 f(locked_state.deref_mut());
588 self.update_status(&mut locked_state);
589 }
590
591 fn with_mut_state_and_reset_cache(&self, f: impl FnOnce(&mut SecurityServerState)) {
595 let mut locked_state = self.state.lock();
596 f(locked_state.deref_mut());
597
598 self.access_vector_cache.reset();
601
602 self.policy_change_count.fetch_add(1, Ordering::Release);
606 self.update_status(&mut locked_state);
607 }
608
609 fn update_status(&self, state: &mut SecurityServerState) {
610 let new_value = SeLinuxStatus {
611 is_enforcing: self.is_enforcing(),
612 change_count: self.policy_change_count.load(Ordering::Relaxed),
613 deny_unknown: self.deny_unknown(),
614 };
615 if let Some(status_publisher) = &mut state.status_publisher {
616 status_publisher.set_status(new_value);
617 }
618 }
619
620 pub fn compute_create_sid_raw(
626 &self,
627 source_sid: SecurityId,
628 target_sid: SecurityId,
629 target_class: ClassId,
630 name: &[u8],
631 ) -> Result<SecurityId, anyhow::Error> {
632 self.backend.compute_create_sid_raw(source_sid, target_sid, target_class.into(), name)
633 }
634
635 pub fn compute_access_decision_raw(
638 &self,
639 source_sid: SecurityId,
640 target_sid: SecurityId,
641 target_class: ClassId,
642 ) -> AccessDecision {
643 self.backend.compute_access_decision_raw(source_sid, target_sid, target_class.into())
644 }
645}
646
647impl SecurityServerBackend {
648 fn expect_active_policy<'a>(&self, scope: &'a RcuReadScope) -> &'a ActivePolicy {
649 self.active_policy.as_ref(scope).expect("policy should be loaded")
650 }
651
652 fn compute_create_sid_raw(
653 &self,
654 source_sid: SecurityId,
655 target_sid: SecurityId,
656 target_class: ObjectClass,
657 name: &[u8],
658 ) -> Result<SecurityId, anyhow::Error> {
659 self.compute_sid(|scope, active_policy| {
660 let (source_context, target_context) =
661 active_policy.sid_table.sids_to_security_contexts(scope, source_sid, target_sid);
662
663 Ok(active_policy.parsed.compute_create_context(
664 source_context,
665 target_context,
666 target_class,
667 name,
668 ))
669 })
670 .context("computing new security context from policy")
671 }
672
673 fn compute_sid(
675 &self,
676 compute_context: impl Fn(&RcuReadScope, &ActivePolicy) -> Result<SecurityContext, anyhow::Error>,
677 ) -> Result<SecurityId, anyhow::Error> {
678 let scope = RcuReadScope::new();
681 let active_policy =
682 self.active_policy.as_ref(&scope).ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
683 let context = compute_context(&scope, active_policy)?;
684 if let Some(sid) =
685 active_policy.sid_table.security_context_to_existing_sid(&scope, &context)
686 {
687 return Ok(sid);
688 }
689
690 let mut portable_sids = self.portable_sids.lock();
695 let current_policy =
696 self.active_policy.as_ref(&scope).expect("policy cannot be unloaded once loaded");
697 let context = if !std::ptr::eq(active_policy, current_policy) {
698 compute_context(&scope, current_policy)?
699 } else {
700 context
701 };
702 unsafe {
704 current_policy
705 .sid_table
706 .security_context_to_sid(
707 &scope,
708 ¤t_policy.parsed,
709 &mut portable_sids,
710 &context,
711 )
712 .map_err(anyhow::Error::from)
713 }
714 }
715
716 fn compute_access_decision_raw(
717 &self,
718 source_sid: SecurityId,
719 target_sid: SecurityId,
720 target_class: ObjectClass,
721 ) -> AccessDecision {
722 let scope = RcuReadScope::new();
723 let Some(active_policy) = self.active_policy.as_ref(&scope) else {
724 return AccessDecision::allow(AccessVector::ALL);
726 };
727 active_policy.compute_access_decision_raw(&scope, source_sid, target_sid, target_class)
728 }
729}
730
731impl Query for SecurityServerBackend {
732 fn compute_access_decision(
733 &self,
734 source_sid: SecurityId,
735 target_sid: SecurityId,
736 target_class: KernelClass,
737 ) -> KernelAccessDecision {
738 let scope = RcuReadScope::new();
739 let Some(active_policy) = self.active_policy.as_ref(&scope) else {
740 return KernelAccessDecision {
741 allow: AccessVector::ALL,
742 audit: AccessVector::NONE,
743 flags: 0,
744 todo_bug: None,
745 };
746 };
747 let decision = active_policy.compute_access_decision_raw(
748 &scope,
749 source_sid,
750 target_sid,
751 target_class.into(),
752 );
753 active_policy.parsed.access_decision_to_kernel_access_decision(target_class, decision)
754 }
755
756 fn compute_create_sid(
757 &self,
758 source_sid: SecurityId,
759 target_sid: SecurityId,
760 target_class: KernelClass,
761 name: &[u8],
762 ) -> Result<SecurityId, anyhow::Error> {
763 self.compute_create_sid_raw(source_sid, target_sid, target_class.into(), name)
764 }
765
766 fn compute_xperms_access_decision(
767 &self,
768 xperms_kind: XpermsKind,
769 source_sid: SecurityId,
770 target_sid: SecurityId,
771 permission: KernelPermission,
772 xperms_prefix: u8,
773 ) -> KernelXpermsAccessDecision {
774 let scope = RcuReadScope::new();
775 let Some(active_policy) = self.active_policy.as_ref(&scope) else {
776 return KernelXpermsAccessDecision {
778 allow: XpermsBitmap::ALL,
779 audit: XpermsBitmap::NONE,
780 permissive: false,
781 has_todo: false,
782 };
783 };
784
785 let (source_context, target_context) =
786 active_policy.sid_table.sids_to_security_contexts(&scope, source_sid, target_sid);
787
788 let base_decision_raw = active_policy.compute_access_decision_for_contexts(
790 source_context,
791 target_context,
792 permission.class().into(),
793 );
794 let base_decision = active_policy
795 .parsed
796 .access_decision_to_kernel_access_decision(permission.class(), base_decision_raw);
797 let permission_access_vector = permission.as_access_vector();
798 let base_permit =
799 base_decision.allow & permission_access_vector == permission_access_vector;
800 let base_audit = base_decision.audit & permission_access_vector == permission_access_vector;
801
802 let xperms_decision = active_policy.parsed.compute_xperms_access_decision(
804 xperms_kind,
805 source_context,
806 target_context,
807 permission.class(),
808 xperms_prefix,
809 );
810
811 let allow = if !base_permit { XpermsBitmap::NONE } else { xperms_decision.allow };
813 let audit = if base_audit {
814 XpermsBitmap::ALL
815 } else {
816 (xperms_decision.allow & xperms_decision.auditallow)
817 | (!xperms_decision.allow & xperms_decision.auditdeny)
818 };
819 let permissive = (base_decision.flags & SELINUX_AVD_FLAGS_PERMISSIVE) != 0;
820 let has_todo = base_decision.todo_bug.is_some();
821 KernelXpermsAccessDecision { allow, audit, permissive, has_todo }
822 }
823}
824
825fn check_policy_feature_is_empty<T>(name: &'static str, items: &[T]) -> Result<(), anyhow::Error> {
826 if !items.is_empty() {
827 anyhow::bail!("Policy contains unsupported feature: {name} ({})", items.len());
828 }
829 Ok(())
830}
831
832fn validate_no_unsupported_policy_features_used(policy: &Policy) -> Result<(), anyhow::Error> {
833 let ocontexts = policy.object_contexts();
834 check_policy_feature_is_empty("ports", ocontexts.ports())?;
835 check_policy_feature_is_empty("network_interfaces", ocontexts.network_interfaces())?;
836 check_policy_feature_is_empty("nodes", ocontexts.ipv4_nodes())?;
837 check_policy_feature_is_empty("ipv6_nodes", ocontexts.ipv6_nodes())?;
838 check_policy_feature_is_empty(
839 "infiniband_partition_keys",
840 ocontexts.infiniband_partition_keys(),
841 )?;
842 check_policy_feature_is_empty("infiniband_end_ports", ocontexts.infiniband_end_ports())?;
843 check_policy_feature_is_empty("filesystems", ocontexts.filesystems())?;
844
845 Ok(())
846}
847
848#[cfg(test)]
849mod tests {
850 use super::*;
851 use crate::permission_check::PermissionCheckResult;
852 use crate::{
853 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
854 ProcessPermission,
855 };
856 use std::num::NonZeroU32;
857
858 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
859 const TESTS_BINARY_POLICY: &[u8] =
860 include_bytes!("../testdata/micro_policies/security_server_tests_policy");
861 const MINIMAL_BINARY_POLICY: &[u8] =
862 include_bytes!("../testdata/composite_policies/compiled/minimal_policy");
863
864 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
865 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
866 let security_server = SecurityServer::new_default();
867 assert_eq!(
868 Ok(()),
869 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
870 );
871 security_server
872 }
873
874 #[test]
875 fn test_unsupported_policy_features_check() {
876 let default_server = SecurityServer::new_default();
877 let testsuite_server = SecurityServer::new("allow_unimplemented".into(), vec![]);
878
879 assert!(default_server.load_policy(MINIMAL_BINARY_POLICY.to_vec()).is_ok());
880 assert!(testsuite_server.load_policy(MINIMAL_BINARY_POLICY.to_vec()).is_ok());
881 assert!(testsuite_server.load_policy(TESTSUITE_BINARY_POLICY.to_vec()).is_ok());
882 }
883
884 #[test]
885 fn compute_access_vector_allows_all() {
886 let security_server = SecurityServer::new_default();
887 let sid1 = InitialSid::Kernel.into();
888 let sid2 = InitialSid::Unlabeled.into();
889 assert_eq!(
890 security_server
891 .backend
892 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
893 .allow,
894 AccessVector::ALL
895 );
896 }
897
898 #[test]
899 fn loaded_policy_can_be_retrieved() {
900 let security_server = security_server_with_tests_policy();
901 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_ref());
902 }
903
904 #[test]
905 fn loaded_policy_is_validated() {
906 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
907 let security_server = SecurityServer::new_default();
908 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
909 }
910
911 #[test]
912 fn enforcing_mode_is_reported() {
913 let security_server = SecurityServer::new_default();
914 assert!(!security_server.is_enforcing());
915
916 security_server.set_enforcing(true);
917 assert!(security_server.is_enforcing());
918 }
919
920 #[test]
921 fn without_policy_conditional_booleans_are_empty() {
922 let security_server = SecurityServer::new_default();
923 assert!(security_server.conditional_booleans().is_empty());
924 }
925
926 #[test]
927 fn conditional_booleans_can_be_queried() {
928 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
929 let security_server = SecurityServer::new("allow_unimplemented".into(), vec![]);
930 assert_eq!(
931 Ok(()),
932 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
933 );
934
935 let booleans = security_server.conditional_booleans();
936 assert!(!booleans.is_empty());
937 let boolean = booleans[0].as_str();
938
939 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
940 assert!(security_server.get_boolean(boolean).is_ok());
941 }
942
943 #[test]
944 fn conditional_booleans_can_be_changed() {
945 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
946 let security_server = SecurityServer::new("allow_unimplemented".into(), vec![]);
947 assert_eq!(
948 Ok(()),
949 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
950 );
951
952 let booleans = security_server.conditional_booleans();
953 assert!(!booleans.is_empty());
954 let boolean = booleans[0].as_str();
955
956 let (active, pending) = security_server.get_boolean(boolean).unwrap();
957 assert_eq!(active, pending, "Initially active and pending values should match");
958
959 security_server.set_pending_boolean(boolean, !active).unwrap();
960 let (active, pending) = security_server.get_boolean(boolean).unwrap();
961 assert!(active != pending, "Before commit pending should differ from active");
962
963 security_server.commit_pending_booleans();
964 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
965 assert_eq!(final_active, pending, "Pending value should be active after commit");
966 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
967 }
968
969 #[test]
970 fn parse_security_context_no_policy() {
971 let security_server = SecurityServer::new_default();
972 let error = security_server
973 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
974 .expect_err("expected error");
975 let error_string = format!("{:?}", error);
976 assert!(error_string.contains("no policy"));
977 }
978
979 #[test]
980 fn compute_sid_recomputes_when_policy_reloaded() {
981 let security_server = security_server_with_tests_policy();
982 let compute_calls = std::cell::Cell::new(0usize);
983
984 let sid = security_server
985 .backend
986 .compute_sid(|_scope, active_policy| {
987 let call_index = compute_calls.get();
988 compute_calls.set(call_index + 1);
989 let context = active_policy
990 .parsed
991 .parse_security_context(b"user0:object_r:type0:s0".into())
992 .map_err(anyhow::Error::from)?;
993 if call_index == 0 {
994 security_server
997 .load_policy(TESTS_BINARY_POLICY.to_vec())
998 .expect("policy reload succeeds");
999 }
1000 Ok(context)
1001 })
1002 .expect("compute_sid succeeds across policy reload");
1003
1004 assert_eq!(compute_calls.get(), 2);
1005 assert_eq!(
1006 security_server.sid_to_security_context(sid),
1007 Some(b"user0:object_r:type0:s0".to_vec())
1008 );
1009 }
1010
1011 #[test]
1012 fn compute_create_sid_no_defaults() {
1013 let security_server = SecurityServer::new_default();
1014 let policy_bytes =
1015 include_bytes!("../testdata/micro_policies/file_no_defaults_policy").to_vec();
1016 security_server.load_policy(policy_bytes).expect("binary policy loads");
1017
1018 let source_sid = security_server
1019 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
1020 .expect("creating SID from security context should succeed");
1021 let target_sid = security_server
1022 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
1023 .expect("creating SID from security context should succeed");
1024
1025 let computed_sid = security_server
1026 .as_permission_check(&Default::default())
1027 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1028 .expect("new sid computed");
1029 let computed_context = security_server
1030 .sid_to_security_context(computed_sid)
1031 .expect("computed sid associated with context");
1032
1033 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1036 }
1037
1038 #[test]
1039 fn compute_create_sid_source_defaults() {
1040 let security_server = SecurityServer::new_default();
1041 let policy_bytes =
1042 include_bytes!("../testdata/micro_policies/file_source_defaults_policy").to_vec();
1043 security_server.load_policy(policy_bytes).expect("binary policy loads");
1044
1045 let source_sid = security_server
1046 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
1047 .expect("creating SID from security context should succeed");
1048 let target_sid = security_server
1049 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
1050 .expect("creating SID from security context should succeed");
1051
1052 let computed_sid = security_server
1053 .as_permission_check(&Default::default())
1054 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1055 .expect("new sid computed");
1056 let computed_context = security_server
1057 .sid_to_security_context(computed_sid)
1058 .expect("computed sid associated with context");
1059
1060 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
1063 }
1064
1065 #[test]
1066 fn compute_create_sid_target_defaults() {
1067 let security_server = SecurityServer::new_default();
1068 let policy_bytes =
1069 include_bytes!("../testdata/micro_policies/file_target_defaults_policy").to_vec();
1070 security_server.load_policy(policy_bytes).expect("binary policy loads");
1071
1072 let source_sid = security_server
1073 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
1074 .expect("creating SID from security context should succeed");
1075 let target_sid = security_server
1076 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
1077 .expect("creating SID from security context should succeed");
1078
1079 let computed_sid = security_server
1080 .as_permission_check(&Default::default())
1081 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1082 .expect("new sid computed");
1083 let computed_context = security_server
1084 .sid_to_security_context(computed_sid)
1085 .expect("computed sid associated with context");
1086
1087 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
1089 }
1090
1091 #[test]
1092 fn compute_create_sid_range_source_low_default() {
1093 let security_server = SecurityServer::new_default();
1094 let policy_bytes =
1095 include_bytes!("../testdata/micro_policies/file_range_source_low_policy").to_vec();
1096 security_server.load_policy(policy_bytes).expect("binary policy loads");
1097
1098 let source_sid = security_server
1099 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1100 .expect("creating SID from security context should succeed");
1101 let target_sid = security_server
1102 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
1103 .expect("creating SID from security context should succeed");
1104
1105 let computed_sid = security_server
1106 .as_permission_check(&Default::default())
1107 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1108 .expect("new sid computed");
1109 let computed_context = security_server
1110 .sid_to_security_context(computed_sid)
1111 .expect("computed sid associated with context");
1112
1113 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1115 }
1116
1117 #[test]
1118 fn compute_create_sid_range_source_low_high_default() {
1119 let security_server = SecurityServer::new_default();
1120 let policy_bytes =
1121 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy").to_vec();
1122 security_server.load_policy(policy_bytes).expect("binary policy loads");
1123
1124 let source_sid = security_server
1125 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1126 .expect("creating SID from security context should succeed");
1127 let target_sid = security_server
1128 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
1129 .expect("creating SID from security context should succeed");
1130
1131 let computed_sid = security_server
1132 .as_permission_check(&Default::default())
1133 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1134 .expect("new sid computed");
1135 let computed_context = security_server
1136 .sid_to_security_context(computed_sid)
1137 .expect("computed sid associated with context");
1138
1139 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1141 }
1142
1143 #[test]
1144 fn compute_create_sid_range_source_high_default() {
1145 let security_server = SecurityServer::new_default();
1146 let policy_bytes =
1147 include_bytes!("../testdata/micro_policies/file_range_source_high_policy").to_vec();
1148 security_server.load_policy(policy_bytes).expect("binary policy loads");
1149
1150 let source_sid = security_server
1151 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1152 .expect("creating SID from security context should succeed");
1153 let target_sid = security_server
1154 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
1155 .expect("creating SID from security context should succeed");
1156
1157 let computed_sid = security_server
1158 .as_permission_check(&Default::default())
1159 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1160 .expect("new sid computed");
1161 let computed_context = security_server
1162 .sid_to_security_context(computed_sid)
1163 .expect("computed sid associated with context");
1164
1165 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1167 }
1168
1169 #[test]
1170 fn compute_create_sid_range_target_low_default() {
1171 let security_server = SecurityServer::new_default();
1172 let policy_bytes =
1173 include_bytes!("../testdata/micro_policies/file_range_target_low_policy").to_vec();
1174 security_server.load_policy(policy_bytes).expect("binary policy loads");
1175
1176 let source_sid = security_server
1177 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1178 .expect("creating SID from security context should succeed");
1179 let target_sid = security_server
1180 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1181 .expect("creating SID from security context should succeed");
1182
1183 let computed_sid = security_server
1184 .as_permission_check(&Default::default())
1185 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1186 .expect("new sid computed");
1187 let computed_context = security_server
1188 .sid_to_security_context(computed_sid)
1189 .expect("computed sid associated with context");
1190
1191 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1193 }
1194
1195 #[test]
1196 fn compute_create_sid_range_target_low_high_default() {
1197 let security_server = SecurityServer::new_default();
1198 let policy_bytes =
1199 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy").to_vec();
1200 security_server.load_policy(policy_bytes).expect("binary policy loads");
1201
1202 let source_sid = security_server
1203 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1204 .expect("creating SID from security context should succeed");
1205 let target_sid = security_server
1206 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1207 .expect("creating SID from security context should succeed");
1208
1209 let computed_sid = security_server
1210 .as_permission_check(&Default::default())
1211 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1212 .expect("new sid computed");
1213 let computed_context = security_server
1214 .sid_to_security_context(computed_sid)
1215 .expect("computed sid associated with context");
1216
1217 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1219 }
1220
1221 #[test]
1222 fn compute_create_sid_range_target_high_default() {
1223 let security_server = SecurityServer::new_default();
1224 let policy_bytes =
1225 include_bytes!("../testdata/micro_policies/file_range_target_high_policy").to_vec();
1226 security_server.load_policy(policy_bytes).expect("binary policy loads");
1227
1228 let source_sid = security_server
1229 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1230 .expect("creating SID from security context should succeed");
1231 let target_sid = security_server
1232 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1233 .expect("creating SID from security context should succeed");
1234
1235 let computed_sid = security_server
1236 .as_permission_check(&Default::default())
1237 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1238 .expect("new sid computed");
1239 let computed_context = security_server
1240 .sid_to_security_context(computed_sid)
1241 .expect("computed sid associated with context");
1242
1243 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1245 }
1246
1247 #[test]
1248 fn compute_create_sid_with_name() {
1249 let security_server = SecurityServer::new_default();
1250 let policy_bytes =
1251 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy")
1252 .to_vec();
1253 security_server.load_policy(policy_bytes).expect("binary policy loads");
1254
1255 let source_sid = security_server
1256 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1257 .expect("creating SID from security context should succeed");
1258 let target_sid = security_server
1259 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1260 .expect("creating SID from security context should succeed");
1261
1262 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1263 let computed_sid = security_server
1264 .as_permission_check(&Default::default())
1265 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), SPECIAL_FILE_NAME)
1266 .expect("new sid computed");
1267 let computed_context = security_server
1268 .sid_to_security_context(computed_sid)
1269 .expect("computed sid associated with context");
1270
1271 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1273
1274 let computed_sid = security_server
1275 .as_permission_check(&Default::default())
1276 .compute_create_sid(
1277 source_sid,
1278 target_sid,
1279 FileClass::ChrFile.into(),
1280 SPECIAL_FILE_NAME,
1281 )
1282 .expect("new sid computed");
1283 let computed_context = security_server
1284 .sid_to_security_context(computed_sid)
1285 .expect("computed sid associated with context");
1286
1287 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1290
1291 const OTHER_FILE_NAME: &[u8] = b"other_file";
1292 let computed_sid = security_server
1293 .as_permission_check(&Default::default())
1294 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), OTHER_FILE_NAME)
1295 .expect("new sid computed");
1296 let computed_context = security_server
1297 .sid_to_security_context(computed_sid)
1298 .expect("computed sid associated with context");
1299
1300 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1303 }
1304
1305 #[test]
1306 fn permissions_are_fresh_after_different_policy_load() {
1307 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1308 let allow_fork_bytes =
1309 include_bytes!("../testdata/composite_policies/compiled/allow_fork_policy").to_vec();
1310 let context = b"source_u:object_r:source_t:s0:c0";
1311
1312 let security_server = SecurityServer::new_default();
1313 security_server.set_enforcing(true);
1314
1315 let local_cache = Default::default();
1316 let permission_check = security_server.as_permission_check(&local_cache);
1317
1318 assert_eq!(
1320 Ok(()),
1321 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1322 );
1323 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1324
1325 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1327
1328 assert_eq!(
1330 Ok(()),
1331 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1332 );
1333
1334 let permission_check = security_server.as_permission_check(&local_cache);
1336
1337 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1339 }
1340
1341 #[test]
1342 fn unknown_sids_are_effectively_unlabeled() {
1343 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1344 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy"
1345 )
1346 .to_vec();
1347 let with_additional_domain_policy_bytes =
1348 include_bytes!("../testdata/composite_policies/compiled/with_additional_domain_policy")
1349 .to_vec();
1350 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1351 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1352
1353 let security_server = SecurityServer::new_default();
1354 security_server.set_enforcing(true);
1355
1356 assert_eq!(
1359 Ok(()),
1360 security_server
1361 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1362 .map_err(|e| format!("{:?}", e))
1363 );
1364 let allowed_type_sid =
1365 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1366 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1367
1368 assert_eq!(
1371 Ok(()),
1372 security_server
1373 .load_policy(with_additional_domain_policy_bytes.clone())
1374 .map_err(|e| format!("{:?}", e))
1375 );
1376 let additional_type_sid =
1377 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1378 assert_eq!(
1379 allowed_type_sid,
1380 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1381 );
1382
1383 let local_cache = Default::default();
1384 let permission_check = security_server.as_permission_check(&local_cache);
1385
1386 assert!(
1390 !permission_check
1391 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1392 .granted
1393 );
1394 assert!(
1395 !permission_check
1396 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1397 .granted
1398 );
1399 assert!(
1400 !permission_check
1401 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1402 .granted
1403 );
1404 assert!(
1405 !permission_check
1406 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1407 .granted
1408 );
1409
1410 assert_eq!(
1412 Ok(()),
1413 security_server
1414 .load_policy(with_unlabeled_access_domain_policy_bytes)
1415 .map_err(|e| format!("{:?}", e))
1416 );
1417
1418 let permission_check = security_server.as_permission_check(&local_cache);
1420
1421 assert!(
1425 permission_check
1426 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1427 .granted
1428 );
1429 assert!(
1430 !permission_check
1431 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1432 .granted
1433 );
1434
1435 assert!(
1440 !permission_check
1441 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1442 .granted
1443 );
1444 assert!(
1445 permission_check
1446 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1447 .granted
1448 );
1449
1450 let unlabeled_context =
1453 security_server.sid_to_security_context(InitialSid::Unlabeled.into()).unwrap();
1454 assert_eq!(
1455 unlabeled_context,
1456 security_server.sid_to_security_context(additional_type_sid).unwrap()
1457 );
1458
1459 assert_eq!(
1462 Ok(()),
1463 security_server
1464 .load_policy(with_additional_domain_policy_bytes)
1465 .map_err(|e| format!("{:?}", e))
1466 );
1467 assert_eq!(
1468 additional_type_context.to_vec(),
1469 security_server.sid_to_security_context(additional_type_sid).unwrap()
1470 );
1471 }
1472
1473 #[test]
1474 fn permission_check_permissive() {
1475 let security_server = security_server_with_tests_policy();
1476 security_server.set_enforcing(false);
1477 assert!(!security_server.is_enforcing());
1478
1479 let sid =
1480 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1481 let local_cache = Default::default();
1482 let permission_check = security_server.as_permission_check(&local_cache);
1483
1484 assert_eq!(
1487 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1488 PermissionCheckResult {
1489 granted: true,
1490 audit: false,
1491 permissive: false,
1492 todo_bug: None
1493 }
1494 );
1495
1496 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1500 assert_eq!(
1501 result,
1502 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1503 );
1504 assert!(result.permit());
1505
1506 let result = permission_check.has_permission(
1510 sid,
1511 sid,
1512 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1513 );
1514 assert_eq!(
1515 result,
1516 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1517 );
1518 assert!(result.permit());
1519 }
1520
1521 #[test]
1522 fn permission_check_enforcing() {
1523 let security_server = security_server_with_tests_policy();
1524 security_server.set_enforcing(true);
1525 assert!(security_server.is_enforcing());
1526
1527 let sid =
1528 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1529 let local_cache = Default::default();
1530 let permission_check = security_server.as_permission_check(&local_cache);
1531
1532 let result = permission_check.has_permission(sid, sid, ProcessPermission::Fork);
1534 assert_eq!(
1535 result,
1536 PermissionCheckResult {
1537 granted: true,
1538 audit: false,
1539 permissive: false,
1540 todo_bug: None
1541 }
1542 );
1543 assert!(result.permit());
1544
1545 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1548 assert_eq!(
1549 result,
1550 PermissionCheckResult {
1551 granted: false,
1552 audit: true,
1553 permissive: false,
1554 todo_bug: None
1555 }
1556 );
1557 assert!(!result.permit());
1558
1559 let result = permission_check.has_permission(
1562 sid,
1563 sid,
1564 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1565 );
1566 assert_eq!(
1567 result,
1568 PermissionCheckResult {
1569 granted: false,
1570 audit: true,
1571 permissive: false,
1572 todo_bug: None
1573 }
1574 );
1575 assert!(!result.permit());
1576 }
1577
1578 #[test]
1579 fn permissive_domain() {
1580 let security_server = security_server_with_tests_policy();
1581 security_server.set_enforcing(true);
1582 assert!(security_server.is_enforcing());
1583
1584 let permissive_sid = security_server
1585 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1586 .unwrap();
1587 let non_permissive_sid = security_server
1588 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1589 .unwrap();
1590
1591 let local_cache = Default::default();
1592 let permission_check = security_server.as_permission_check(&local_cache);
1593
1594 let result = permission_check.has_permission(
1596 permissive_sid,
1597 permissive_sid,
1598 ProcessPermission::GetSched,
1599 );
1600 assert_eq!(
1601 result,
1602 PermissionCheckResult { granted: true, audit: false, permissive: true, todo_bug: None }
1603 );
1604 assert!(result.permit());
1605 let result = permission_check.has_permission(
1606 non_permissive_sid,
1607 non_permissive_sid,
1608 ProcessPermission::GetSched,
1609 );
1610 assert_eq!(
1611 result,
1612 PermissionCheckResult {
1613 granted: true,
1614 audit: false,
1615 permissive: false,
1616 todo_bug: None
1617 }
1618 );
1619 assert!(result.permit());
1620
1621 let result = permission_check.has_permission(
1624 permissive_sid,
1625 non_permissive_sid,
1626 ProcessPermission::GetSched,
1627 );
1628 assert_eq!(
1629 result,
1630 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1631 );
1632 assert!(result.permit());
1633 let result = permission_check.has_permission(
1634 non_permissive_sid,
1635 permissive_sid,
1636 ProcessPermission::GetSched,
1637 );
1638 assert_eq!(
1639 result,
1640 PermissionCheckResult {
1641 granted: false,
1642 audit: true,
1643 permissive: false,
1644 todo_bug: None
1645 }
1646 );
1647 assert!(!result.permit());
1648
1649 let result = permission_check.has_permission(
1654 permissive_sid,
1655 non_permissive_sid,
1656 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1657 );
1658 assert_eq!(
1659 result,
1660 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1661 );
1662 assert!(result.permit());
1663 let result = permission_check.has_permission(
1664 non_permissive_sid,
1665 non_permissive_sid,
1666 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1667 );
1668 assert_eq!(
1669 result,
1670 PermissionCheckResult {
1671 granted: false,
1672 audit: true,
1673 permissive: false,
1674 todo_bug: None
1675 }
1676 );
1677 assert!(!result.permit());
1678 }
1679
1680 #[test]
1681 fn auditallow_and_dontaudit() {
1682 let security_server = security_server_with_tests_policy();
1683 security_server.set_enforcing(true);
1684 assert!(security_server.is_enforcing());
1685
1686 let audit_sid = security_server
1687 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1688 .unwrap();
1689
1690 let local_cache = Default::default();
1691 let permission_check = security_server.as_permission_check(&local_cache);
1692
1693 let result = permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork);
1695 assert_eq!(
1696 result,
1697 PermissionCheckResult { granted: true, audit: true, permissive: false, todo_bug: None }
1698 );
1699 assert!(result.permit());
1700
1701 let result =
1703 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched);
1704 assert_eq!(
1705 result,
1706 PermissionCheckResult {
1707 granted: true,
1708 audit: false,
1709 permissive: false,
1710 todo_bug: None
1711 }
1712 );
1713 assert!(result.permit());
1714
1715 let result =
1717 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched);
1718 assert_eq!(
1719 result,
1720 PermissionCheckResult {
1721 granted: false,
1722 audit: false,
1723 permissive: false,
1724 todo_bug: None
1725 }
1726 );
1727 assert!(!result.permit());
1728
1729 let result =
1731 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid);
1732 assert_eq!(
1733 result,
1734 PermissionCheckResult {
1735 granted: false,
1736 audit: true,
1737 permissive: false,
1738 todo_bug: None
1739 }
1740 );
1741 assert!(!result.permit());
1742 }
1743
1744 #[test]
1745 fn access_checks_with_exceptions_config() {
1746 const EXCEPTIONS_CONFIG: &[&str] = &[
1747 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1749 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1750 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1751 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1752 "todo_permissive b/005 test_exception_todo_permissive_t",
1753 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1755 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1756 "todo_permissive b/103 test_undefined_source_t",
1757 ];
1758 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1759 let security_server = SecurityServer::new(String::new(), exceptions_config);
1760 security_server.set_enforcing(true);
1761
1762 const EXCEPTIONS_POLICY: &[u8] =
1763 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy");
1764 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1765
1766 let source_sid = security_server
1767 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1768 .unwrap();
1769 let target_sid = security_server
1770 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1771 .unwrap();
1772 let other_sid = security_server
1773 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1774 .unwrap();
1775 let permissive_sid = security_server
1776 .security_context_to_sid(
1777 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1778 )
1779 .unwrap();
1780 let unmatched_sid = security_server
1781 .security_context_to_sid(
1782 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1783 )
1784 .unwrap();
1785 let todo_permissive_sid = security_server
1786 .security_context_to_sid(
1787 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1788 )
1789 .unwrap();
1790
1791 let local_cache = Default::default();
1792 let permission_check = security_server.as_permission_check(&local_cache);
1793
1794 let result =
1796 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid);
1797 assert_eq!(
1798 result,
1799 PermissionCheckResult {
1800 granted: false,
1801 audit: true,
1802 permissive: false,
1803 todo_bug: None
1804 }
1805 );
1806 assert!(!result.permit());
1807
1808 let result =
1810 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint);
1811 assert_eq!(
1812 result,
1813 PermissionCheckResult {
1814 granted: true,
1815 audit: true,
1816 permissive: false,
1817 todo_bug: Some(NonZeroU32::new(1).unwrap())
1818 }
1819 );
1820 assert!(result.permit());
1821
1822 let result =
1824 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans);
1825 assert_eq!(
1826 result,
1827 PermissionCheckResult {
1828 granted: true,
1829 audit: false,
1830 permissive: false,
1831 todo_bug: None,
1832 }
1833 );
1834 assert!(result.permit());
1835
1836 let result =
1838 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint);
1839 assert_eq!(
1840 result,
1841 PermissionCheckResult {
1842 granted: false,
1843 audit: true,
1844 permissive: false,
1845 todo_bug: None
1846 }
1847 );
1848 assert!(!result.permit());
1849
1850 let result = permission_check.has_permission(
1852 other_sid,
1853 target_sid,
1854 CommonFsNodePermission::Read.for_class(FileClass::ChrFile),
1855 );
1856 assert_eq!(
1857 result,
1858 PermissionCheckResult {
1859 granted: true,
1860 audit: true,
1861 permissive: false,
1862 todo_bug: Some(NonZeroU32::new(2).unwrap())
1863 }
1864 );
1865 assert!(result.permit());
1866
1867 let result =
1869 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint);
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
1881 let result =
1883 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint);
1884 assert_eq!(
1885 result,
1886 PermissionCheckResult {
1887 granted: false,
1888 audit: true,
1889 permissive: false,
1890 todo_bug: None
1891 }
1892 );
1893 assert!(!result.permit());
1894
1895 let result =
1897 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint);
1898 assert_eq!(
1899 result,
1900 PermissionCheckResult {
1901 granted: true,
1902 audit: true,
1903 permissive: true,
1904 todo_bug: Some(NonZeroU32::new(4).unwrap())
1905 }
1906 );
1907 assert!(result.permit());
1908
1909 let result = permission_check.has_permission(
1912 todo_permissive_sid,
1913 target_sid,
1914 FilePermission::Entrypoint,
1915 );
1916 assert_eq!(
1917 result,
1918 PermissionCheckResult {
1919 granted: true,
1920 audit: true,
1921 permissive: false,
1922 todo_bug: Some(NonZeroU32::new(5).unwrap())
1923 }
1924 );
1925 assert!(result.permit());
1926 let result = permission_check.has_permission(
1927 todo_permissive_sid,
1928 todo_permissive_sid,
1929 FilePermission::Entrypoint,
1930 );
1931 assert_eq!(
1932 result,
1933 PermissionCheckResult {
1934 granted: true,
1935 audit: true,
1936 permissive: false,
1937 todo_bug: Some(NonZeroU32::new(5).unwrap())
1938 }
1939 );
1940 assert!(result.permit());
1941 let result = permission_check.has_permission(
1942 todo_permissive_sid,
1943 target_sid,
1944 FilePermission::Entrypoint,
1945 );
1946 assert_eq!(
1947 result,
1948 PermissionCheckResult {
1949 granted: true,
1950 audit: true,
1951 permissive: false,
1952 todo_bug: Some(NonZeroU32::new(5).unwrap())
1953 }
1954 );
1955 assert!(result.permit());
1956 }
1957
1958 #[test]
1959 fn handle_unknown() {
1960 let security_server = security_server_with_tests_policy();
1961
1962 let sid = security_server
1963 .security_context_to_sid("user0:object_r:type0:s0".into())
1964 .expect("Resolve Context to SID");
1965
1966 const REJECT_POLICY: &[u8] =
1970 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-reject");
1971 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1972
1973 security_server.set_enforcing(true);
1974
1975 const DENY_POLICY: &[u8] =
1977 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny");
1978 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1979 let local_cache = Default::default();
1980 let permission_check = security_server.as_permission_check(&local_cache);
1981
1982 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1984 assert_eq!(
1985 result,
1986 PermissionCheckResult {
1987 granted: false,
1988 audit: true,
1989 permissive: false,
1990 todo_bug: None
1991 }
1992 );
1993 assert!(!result.permit());
1994 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1995 assert_eq!(
1996 result,
1997 PermissionCheckResult {
1998 granted: false,
1999 audit: true,
2000 permissive: false,
2001 todo_bug: None
2002 }
2003 );
2004 assert!(!result.permit());
2005
2006 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
2008 assert_eq!(
2009 result,
2010 PermissionCheckResult {
2011 granted: true,
2012 audit: false,
2013 permissive: false,
2014 todo_bug: None
2015 }
2016 );
2017 assert!(result.permit());
2018 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
2019 assert_eq!(
2020 result,
2021 PermissionCheckResult {
2022 granted: false,
2023 audit: true,
2024 permissive: false,
2025 todo_bug: None
2026 }
2027 );
2028 assert!(!result.permit());
2029
2030 const ALLOW_POLICY: &[u8] =
2032 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-allow");
2033 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
2034 let local_cache2 = Default::default();
2035 let permission_check = security_server.as_permission_check(&local_cache2);
2036
2037 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
2039 assert_eq!(
2040 result,
2041 PermissionCheckResult {
2042 granted: true,
2043 audit: false,
2044 permissive: false,
2045 todo_bug: None
2046 }
2047 );
2048 assert!(result.permit());
2049 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
2050 assert_eq!(
2051 result,
2052 PermissionCheckResult {
2053 granted: true,
2054 audit: false,
2055 permissive: false,
2056 todo_bug: None
2057 }
2058 );
2059 assert!(result.permit());
2060
2061 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
2063 assert_eq!(
2064 result,
2065 PermissionCheckResult {
2066 granted: true,
2067 audit: false,
2068 permissive: false,
2069 todo_bug: None
2070 }
2071 );
2072 assert!(result.permit());
2073
2074 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
2075 assert_eq!(
2076 result,
2077 PermissionCheckResult {
2078 granted: false,
2079 audit: true,
2080 permissive: false,
2081 todo_bug: None
2082 }
2083 );
2084 assert!(!result.permit());
2085 }
2086}