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