1use crate::access_vector_cache::{
6 AccessVectorCache, CacheStats, KernelXpermsAccessDecision, Query,
7};
8use crate::exceptions_config::ExceptionsConfig;
9use crate::new_policy::HandleUnknown;
10use crate::new_policy::traits::{HasName, HasPolicyId};
11use crate::permission_check::{PerThreadCache, PermissionCheck};
12use crate::policy::parser::PolicyData;
13use crate::policy::{
14 AccessDecision, AccessVector, AccessVectorComputer, ClassId, FsUseLabelAndType, FsUseType,
15 KernelAccessDecision, PermissionId, Policy, SELINUX_AVD_FLAGS_PERMISSIVE, SecurityContext,
16 XpermsBitmap, XpermsKind, parse_policy_by_value,
17};
18use crate::sid_table::SidTable;
19use crate::sync::RwLock;
20use crate::{
21 ClassPermission, FileSystemLabel, FileSystemLabelingScheme, FileSystemMountOptions,
22 FileSystemMountSids, FsNodeClass, InitialSid, KernelClass, KernelPermission, NullessByteStr,
23 ObjectClass, PolicyCap, SeLinuxStatus, SeLinuxStatusPublisher, SecurityId,
24};
25use anyhow::Context as _;
26use std::collections::HashMap;
27use std::ops::DerefMut;
28use std::sync::Arc;
29use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
30
31const ROOT_PATH: &'static str = "/";
32
33struct ActivePolicy {
34 parsed: Arc<Policy>,
36
37 sid_table: SidTable,
39
40 exceptions: ExceptionsConfig,
42}
43
44#[derive(Default)]
45struct SeLinuxBooleans {
46 active: HashMap<String, bool>,
49 pending: HashMap<String, bool>,
51}
52
53impl SeLinuxBooleans {
54 fn reset(&mut self, booleans: Vec<(String, bool)>) {
55 self.active = HashMap::from_iter(booleans);
56 self.pending.clear();
57 }
58 fn names(&self) -> Vec<String> {
59 self.active.keys().cloned().collect()
60 }
61 fn set_pending(&mut self, name: &str, value: bool) -> Result<(), ()> {
62 if !self.active.contains_key(name) {
63 return Err(());
64 }
65 self.pending.insert(name.into(), value);
66 Ok(())
67 }
68 fn get(&self, name: &str) -> Result<(bool, bool), ()> {
69 let active = self.active.get(name).ok_or(())?;
70 let pending = self.pending.get(name).unwrap_or(active);
71 Ok((*active, *pending))
72 }
73 fn commit_pending(&mut self) {
74 self.active.extend(self.pending.drain());
75 }
76}
77
78struct SecurityServerState {
79 active_policy: Option<ActivePolicy>,
81
82 booleans: SeLinuxBooleans,
84
85 status_publisher: Option<Box<dyn SeLinuxStatusPublisher>>,
87}
88
89impl SecurityServerState {
90 fn deny_unknown(&self) -> bool {
91 self.active_policy
92 .as_ref()
93 .map_or(true, |p| p.parsed.handle_unknown() != HandleUnknown::Allow)
94 }
95 fn reject_unknown(&self) -> bool {
96 self.active_policy
97 .as_ref()
98 .map_or(false, |p| p.parsed.handle_unknown() == HandleUnknown::Reject)
99 }
100
101 fn expect_active_policy(&self) -> &ActivePolicy {
102 &self.active_policy.as_ref().expect("policy should be loaded")
103 }
104
105 fn expect_active_policy_mut(&mut self) -> &mut ActivePolicy {
106 self.active_policy.as_mut().expect("policy should be loaded")
107 }
108
109 fn compute_access_decision_raw(
110 &self,
111 source_sid: SecurityId,
112 target_sid: SecurityId,
113 target_class: ObjectClass,
114 ) -> AccessDecision {
115 let Some(active_policy) = self.active_policy.as_ref() else {
116 return AccessDecision::allow(AccessVector::ALL);
118 };
119
120 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
121 let target_context = active_policy.sid_table.sid_to_security_context(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: RwLock<SecurityServerState>,
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
158pub struct SecurityServer {
159 access_vector_cache: AccessVectorCache,
162
163 backend: Arc<SecurityServerBackend>,
165
166 exceptions: Vec<String>,
168}
169
170impl SecurityServer {
171 pub fn new_default() -> Arc<Self> {
173 Self::new(String::new(), Vec::new())
174 }
175
176 pub fn new(options: String, exceptions: Vec<String>) -> Arc<Self> {
178 assert_eq!(options, String::new());
180
181 let backend = Arc::new(SecurityServerBackend {
182 state: RwLock::new(SecurityServerState {
183 active_policy: None,
184 booleans: SeLinuxBooleans::default(),
185 status_publisher: None,
186 }),
187 is_enforcing: AtomicBool::new(false),
188 policy_change_count: AtomicU32::new(0),
189 });
190
191 let access_vector_cache = AccessVectorCache::new(backend.clone());
192
193 Arc::new(Self { access_vector_cache, backend, exceptions })
194 }
195
196 pub fn as_permission_check<'a>(
199 self: &'a Self,
200 local_cache: &'a PerThreadCache,
201 ) -> PermissionCheck<'a> {
202 PermissionCheck::new(self, &self.access_vector_cache, local_cache)
203 }
204
205 pub fn security_context_to_sid(
209 &self,
210 security_context: NullessByteStr<'_>,
211 ) -> Result<SecurityId, anyhow::Error> {
212 self.backend.compute_sid(|active_policy| {
213 active_policy
214 .parsed
215 .parse_security_context(security_context)
216 .map_err(anyhow::Error::from)
217 })
218 }
219
220 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
225 let locked_state = self.backend.state.read();
226 let active_policy = locked_state.active_policy.as_ref()?;
227 let context = active_policy.sid_table.try_sid_to_security_context(sid)?;
228 Some(active_policy.parsed.serialize_security_context(context))
229 }
230
231 pub fn sid_to_security_context_with_nul(&self, sid: SecurityId) -> Option<Vec<u8>> {
233 self.sid_to_security_context(sid).map(|mut context| {
234 context.push(0u8);
235 context
236 })
237 }
238
239 pub fn load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
241 let unvalidated_policy = parse_policy_by_value(binary_policy)?;
244 let parsed = Arc::new(unvalidated_policy.validate()?);
245
246 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
247 let exceptions = ExceptionsConfig::new(&parsed, &exceptions)?;
248
249 self.with_mut_state_and_update_status(|state| {
251 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
252 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
253 } else {
254 SidTable::new(parsed.clone())
255 };
256
257 state.booleans.reset(
260 parsed
261 .conditional_booleans()
262 .iter()
263 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
265 .collect(),
266 );
267
268 state.active_policy = Some(ActivePolicy { parsed, sid_table, exceptions });
269 self.backend.policy_change_count.fetch_add(1, Ordering::Relaxed);
270 });
271
272 Ok(())
273 }
274
275 pub fn has_policy(&self) -> bool {
277 self.backend.state.read().active_policy.is_some()
278 }
279
280 pub fn get_binary_policy(&self) -> Option<PolicyData> {
282 let state = self.backend.state.read();
283 let active_policy = state.active_policy.as_ref()?;
284 Some(active_policy.parsed.serialize())
285 }
286
287 pub fn set_enforcing(&self, enforcing: bool) {
289 self.with_mut_state_and_update_status(|_| {
290 self.backend.is_enforcing.store(enforcing, Ordering::Release);
291 });
292 }
293
294 pub fn is_enforcing(&self) -> bool {
295 self.backend.is_enforcing.load(Ordering::Acquire)
296 }
297
298 pub fn deny_unknown(&self) -> bool {
301 self.backend.state.read().deny_unknown()
302 }
303
304 pub fn reject_unknown(&self) -> bool {
307 self.backend.state.read().reject_unknown()
308 }
309
310 pub fn conditional_booleans(&self) -> Vec<String> {
313 self.backend.state.read().booleans.names()
314 }
315
316 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
318 self.backend.state.read().booleans.get(name)
319 }
320
321 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
323 self.backend.state.write().booleans.set_pending(name, value)
324 }
325
326 pub fn commit_pending_booleans(&self) {
328 self.with_mut_state_and_update_status(|state| {
330 state.booleans.commit_pending();
331 self.backend.policy_change_count.fetch_add(1, Ordering::Relaxed);
332 });
333 }
334
335 pub fn is_policycap_enabled(&self, policy_cap: PolicyCap) -> bool {
337 let locked_state = self.backend.state.read();
338 let Some(policy) = &locked_state.active_policy else {
339 return false;
340 };
341 policy.parsed.has_policycap(policy_cap)
342 }
343
344 pub fn avc_cache_stats(&self) -> CacheStats {
346 self.access_vector_cache.cache_stats()
347 }
348
349 pub fn policy_seqno(&self) -> PolicySeqNo {
351 PolicySeqNo(self.backend.policy_change_count.load(Ordering::Relaxed))
352 }
353
354 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
356 let locked_state = self.backend.state.read();
357 let names = locked_state
358 .expect_active_policy()
359 .parsed
360 .classes()
361 .iter()
362 .map(|class| class.name().to_vec())
363 .collect();
364 Ok(names)
365 }
366
367 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
369 let locked_state = self.backend.state.read();
370 Ok(locked_state
371 .expect_active_policy()
372 .parsed
373 .classes()
374 .get_by_name(name.as_bytes())
375 .ok_or(())?
376 .id())
377 }
378
379 pub fn class_permissions_by_name(
383 &self,
384 name: &str,
385 ) -> Result<Vec<(PermissionId, Vec<u8>)>, ()> {
386 let locked_state = self.backend.state.read();
387 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
388 }
389
390 pub fn resolve_fs_label(
394 &self,
395 fs_type: NullessByteStr<'_>,
396 mount_options: &FileSystemMountOptions,
397 ) -> Result<FileSystemLabel, anyhow::Error> {
398 let mut locked_state = self.backend.state.write();
399 let active_policy = locked_state.expect_active_policy_mut();
400
401 let mount_sids = FileSystemMountSids {
402 context: sid_from_mount_option(active_policy, &mount_options.context)?,
403 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context)?,
404 def_context: sid_from_mount_option(active_policy, &mount_options.def_context)?,
405 root_context: sid_from_mount_option(active_policy, &mount_options.root_context)?,
406 };
407 let label = if let Some(mountpoint_sid) = mount_sids.context {
408 FileSystemLabel {
412 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
413 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
414 mount_sids,
415 }
416 } else if let Some(FsUseLabelAndType { context, use_type }) =
417 active_policy.parsed.fs_use_label_and_type(fs_type)
418 {
419 let fs_sid_from_policy =
421 active_policy.sid_table.security_context_to_sid(&context).unwrap();
422 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
423 FileSystemLabel {
424 sid: fs_sid,
425 scheme: FileSystemLabelingScheme::FsUse {
426 fs_use_type: use_type,
427 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
428 },
429 mount_sids,
430 }
431 } else if let Some(context) =
432 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
433 {
434 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
436 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
437
438 let fs_type = fs_type.as_bytes();
448 let mut supports_seclabel = matches!(fs_type, b"sysfs" | b"tracefs" | b"pstore");
449 supports_seclabel |= matches!(fs_type, b"cgroup" | b"cgroup2")
450 && active_policy.parsed.has_policycap(PolicyCap::CgroupSeclabel);
451 supports_seclabel |= fs_type == b"functionfs"
452 && active_policy.parsed.has_policycap(PolicyCap::FunctionfsSeclabel);
453
454 FileSystemLabel {
455 sid: fs_sid,
456 scheme: FileSystemLabelingScheme::GenFsCon { supports_seclabel },
457 mount_sids,
458 }
459 } else {
460 FileSystemLabel {
462 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
463 scheme: FileSystemLabelingScheme::FsUse {
464 fs_use_type: FsUseType::Xattr,
465 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
466 },
467 mount_sids,
468 }
469 };
470 Ok(label)
471 }
472
473 pub fn genfscon_label_for_fs_and_path(
478 &self,
479 fs_type: NullessByteStr<'_>,
480 node_path: NullessByteStr<'_>,
481 class_id: Option<KernelClass>,
482 ) -> Result<SecurityId, anyhow::Error> {
483 self.backend.compute_sid(|active_policy| {
484 active_policy
485 .parsed
486 .genfscon_label_for_fs_and_path(fs_type, node_path.into(), class_id)
487 .ok_or_else(|| {
488 anyhow::anyhow!("Genfscon label requested for non-genfscon labeled filesystem")
489 })
490 })
491 }
492
493 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
498 let locked_state = self.backend.state.read();
499 let active_policy = locked_state.expect_active_policy();
500 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
501 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
502 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
503 }
504
505 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
512 self.with_mut_state_and_update_status(|state| {
513 assert!(state.status_publisher.is_none());
514 state.status_publisher = Some(status_holder);
515 });
516 }
517
518 fn with_mut_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
522 let mut locked_state = self.backend.state.write();
523 f(locked_state.deref_mut());
524 let new_value = SeLinuxStatus {
525 is_enforcing: self.is_enforcing(),
526 change_count: self.backend.policy_change_count.load(Ordering::Relaxed),
527 deny_unknown: locked_state.deny_unknown(),
528 };
529 if let Some(status_publisher) = &mut locked_state.status_publisher {
530 status_publisher.set_status(new_value);
531 }
532
533 std::mem::drop(locked_state);
536 self.access_vector_cache.reset();
537 }
538
539 pub fn compute_create_sid_raw(
545 &self,
546 source_sid: SecurityId,
547 target_sid: SecurityId,
548 target_class: ClassId,
549 ) -> Result<SecurityId, anyhow::Error> {
550 self.backend.compute_create_sid_raw(source_sid, target_sid, target_class.into())
551 }
552
553 pub fn compute_new_fs_node_sid_raw(
558 &self,
559 source_sid: SecurityId,
560 target_sid: SecurityId,
561 fs_node_class: FsNodeClass,
562 fs_node_name: NullessByteStr<'_>,
563 ) -> Result<SecurityId, anyhow::Error> {
564 self.backend.compute_new_fs_node_sid_raw(
565 source_sid,
566 target_sid,
567 fs_node_class,
568 fs_node_name,
569 )
570 }
571
572 pub fn compute_access_decision_raw(
575 &self,
576 source_sid: SecurityId,
577 target_sid: SecurityId,
578 target_class: ClassId,
579 ) -> AccessDecision {
580 self.backend.compute_access_decision_raw(source_sid, target_sid, target_class.into())
581 }
582}
583
584impl SecurityServerBackend {
585 fn compute_create_sid_raw(
586 &self,
587 source_sid: SecurityId,
588 target_sid: SecurityId,
589 target_class: ObjectClass,
590 ) -> Result<SecurityId, anyhow::Error> {
591 self.compute_sid(|active_policy| {
592 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
593 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
594
595 Ok(active_policy.parsed.compute_create_context(
596 source_context,
597 target_context,
598 target_class,
599 ))
600 })
601 .context("computing new security context from policy")
602 }
603
604 fn compute_new_fs_node_sid_raw(
605 &self,
606 source_sid: SecurityId,
607 target_sid: SecurityId,
608 fs_node_class: FsNodeClass,
609 fs_node_name: NullessByteStr<'_>,
610 ) -> Result<SecurityId, anyhow::Error> {
611 if !fs_node_name.as_bytes().is_empty() {
612 if let Some(sid) = self.compute_new_fs_node_sid_with_name(
613 source_sid,
614 target_sid,
615 fs_node_class,
616 fs_node_name,
617 ) {
618 return Ok(sid);
619 }
620 }
621 self.compute_create_sid_raw(source_sid, target_sid, fs_node_class.into())
622 }
623
624 fn compute_sid(
626 &self,
627 compute_context: impl Fn(&ActivePolicy) -> Result<SecurityContext, anyhow::Error>,
628 ) -> Result<SecurityId, anyhow::Error> {
629 let readable_state = self.state.read();
632 let policy_change_count = self.policy_change_count.load(Ordering::Relaxed);
633 let policy_state = readable_state
634 .active_policy
635 .as_ref()
636 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
637 let context = compute_context(policy_state)?;
638 if let Some(sid) = policy_state.sid_table.security_context_to_existing_sid(&context) {
639 return Ok(sid);
640 }
641 std::mem::drop(readable_state);
642
643 let mut writable_state = self.state.write();
648 let needs_recompute =
649 policy_change_count != self.policy_change_count.load(Ordering::Relaxed);
650 let policy_state = writable_state.active_policy.as_mut().unwrap();
651 let context = if needs_recompute { compute_context(policy_state)? } else { context };
652 policy_state.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
653 }
654
655 fn compute_access_decision_raw(
656 &self,
657 source_sid: SecurityId,
658 target_sid: SecurityId,
659 target_class: ObjectClass,
660 ) -> AccessDecision {
661 let locked_state = self.state.read();
662
663 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class)
664 }
665}
666
667impl Query for SecurityServerBackend {
668 fn compute_access_decision(
669 &self,
670 source_sid: SecurityId,
671 target_sid: SecurityId,
672 target_class: KernelClass,
673 ) -> KernelAccessDecision {
674 let locked_state = self.state.read();
675 let decision =
676 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class.into());
677 locked_state.access_decision_to_kernel_access_decision(target_class, decision)
678 }
679
680 fn compute_create_sid(
681 &self,
682 source_sid: SecurityId,
683 target_sid: SecurityId,
684 target_class: KernelClass,
685 ) -> Result<SecurityId, anyhow::Error> {
686 self.compute_create_sid_raw(source_sid, target_sid, target_class.into())
687 }
688
689 fn compute_new_fs_node_sid_with_name(
690 &self,
691 source_sid: SecurityId,
692 target_sid: SecurityId,
693 fs_node_class: FsNodeClass,
694 fs_node_name: NullessByteStr<'_>,
695 ) -> Option<SecurityId> {
696 let mut locked_state = self.state.write();
697
698 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
700
701 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
702 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
703
704 let new_file_context = active_policy.parsed.compute_create_context_with_name(
705 source_context,
706 target_context,
707 fs_node_class,
708 fs_node_name,
709 )?;
710
711 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
712 }
713
714 fn compute_xperms_access_decision(
715 &self,
716 xperms_kind: XpermsKind,
717 source_sid: SecurityId,
718 target_sid: SecurityId,
719 permission: KernelPermission,
720 xperms_prefix: u8,
721 ) -> KernelXpermsAccessDecision {
722 let locked_state = self.state.read();
723
724 let active_policy = match &locked_state.active_policy {
725 Some(active_policy) => active_policy,
726 None => {
728 return KernelXpermsAccessDecision {
729 allow: XpermsBitmap::ALL,
730 audit: XpermsBitmap::NONE,
731 permissive: false,
732 has_todo: false,
733 };
734 }
735 };
736
737 let base_decision_raw = locked_state.compute_access_decision_raw(
740 source_sid,
741 target_sid,
742 permission.class().into(),
743 );
744 let base_decision = locked_state
745 .access_decision_to_kernel_access_decision(permission.class(), base_decision_raw);
746 let permission_access_vector = permission.as_access_vector();
747 let base_permit =
748 base_decision.allow & permission_access_vector == permission_access_vector;
749 let base_audit = base_decision.audit & permission_access_vector == permission_access_vector;
750
751 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
753 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
754 let xperms_decision = active_policy.parsed.compute_xperms_access_decision(
755 xperms_kind,
756 &source_context,
757 &target_context,
758 permission.class(),
759 xperms_prefix,
760 );
761
762 let allow = if !base_permit { XpermsBitmap::NONE } else { xperms_decision.allow };
764 let audit = if base_audit {
765 XpermsBitmap::ALL
766 } else {
767 (xperms_decision.allow & xperms_decision.auditallow)
768 | (!xperms_decision.allow & xperms_decision.auditdeny)
769 };
770 let permissive = (base_decision.flags & SELINUX_AVD_FLAGS_PERMISSIVE) != 0;
771 let has_todo = base_decision.todo_bug.is_some();
772 KernelXpermsAccessDecision { allow, audit, permissive, has_todo }
773 }
774}
775
776impl AccessVectorComputer for SecurityServerBackend {
777 fn access_decision_to_kernel_access_decision(
778 &self,
779 class: KernelClass,
780 av: AccessDecision,
781 ) -> KernelAccessDecision {
782 self.state.read().access_decision_to_kernel_access_decision(class, av)
783 }
784}
785
786impl AccessVectorComputer for SecurityServerState {
787 fn access_decision_to_kernel_access_decision(
788 &self,
789 class: KernelClass,
790 av: AccessDecision,
791 ) -> KernelAccessDecision {
792 match &self.active_policy {
793 Some(policy) => policy.parsed.access_decision_to_kernel_access_decision(class, av),
794 None => KernelAccessDecision {
795 allow: AccessVector::ALL,
796 audit: AccessVector::NONE,
797 flags: 0,
798 todo_bug: None,
799 },
800 }
801 }
802}
803
804fn sid_from_mount_option(
807 active_policy: &mut ActivePolicy,
808 mount_option: &Option<Vec<u8>>,
809) -> Result<Option<SecurityId>, anyhow::Error> {
810 let Some(label) = mount_option else {
811 return Ok(None);
812 };
813 let context = active_policy.parsed.parse_security_context(label.into())?;
814 let sid = active_policy.sid_table.security_context_to_sid(&context)?;
815 Ok(Some(sid))
816}
817
818#[cfg(test)]
819mod tests {
820 use super::*;
821 use crate::permission_check::PermissionCheckResult;
822 use crate::{
823 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
824 ProcessPermission,
825 };
826 use std::num::NonZeroU32;
827
828 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
829 const TESTS_BINARY_POLICY: &[u8] =
830 include_bytes!("../testdata/micro_policies/security_server_tests_policy");
831 const MINIMAL_BINARY_POLICY: &[u8] =
832 include_bytes!("../testdata/composite_policies/compiled/minimal_policy");
833
834 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
835 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
836 let security_server = SecurityServer::new_default();
837 assert_eq!(
838 Ok(()),
839 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
840 );
841 security_server
842 }
843
844 #[test]
845 fn compute_access_vector_allows_all() {
846 let security_server = SecurityServer::new_default();
847 let sid1 = InitialSid::Kernel.into();
848 let sid2 = InitialSid::Unlabeled.into();
849 assert_eq!(
850 security_server
851 .backend
852 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
853 .allow,
854 AccessVector::ALL
855 );
856 }
857
858 #[test]
859 fn loaded_policy_can_be_retrieved() {
860 let security_server = security_server_with_tests_policy();
861 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_ref());
862 }
863
864 #[test]
865 fn loaded_policy_is_validated() {
866 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
867 let security_server = SecurityServer::new_default();
868 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
869 }
870
871 #[test]
872 fn enforcing_mode_is_reported() {
873 let security_server = SecurityServer::new_default();
874 assert!(!security_server.is_enforcing());
875
876 security_server.set_enforcing(true);
877 assert!(security_server.is_enforcing());
878 }
879
880 #[test]
881 fn without_policy_conditional_booleans_are_empty() {
882 let security_server = SecurityServer::new_default();
883 assert!(security_server.conditional_booleans().is_empty());
884 }
885
886 #[test]
887 fn conditional_booleans_can_be_queried() {
888 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
889 let security_server = SecurityServer::new_default();
890 assert_eq!(
891 Ok(()),
892 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
893 );
894
895 let booleans = security_server.conditional_booleans();
896 assert!(!booleans.is_empty());
897 let boolean = booleans[0].as_str();
898
899 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
900 assert!(security_server.get_boolean(boolean).is_ok());
901 }
902
903 #[test]
904 fn conditional_booleans_can_be_changed() {
905 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
906 let security_server = SecurityServer::new_default();
907 assert_eq!(
908 Ok(()),
909 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
910 );
911
912 let booleans = security_server.conditional_booleans();
913 assert!(!booleans.is_empty());
914 let boolean = booleans[0].as_str();
915
916 let (active, pending) = security_server.get_boolean(boolean).unwrap();
917 assert_eq!(active, pending, "Initially active and pending values should match");
918
919 security_server.set_pending_boolean(boolean, !active).unwrap();
920 let (active, pending) = security_server.get_boolean(boolean).unwrap();
921 assert!(active != pending, "Before commit pending should differ from active");
922
923 security_server.commit_pending_booleans();
924 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
925 assert_eq!(final_active, pending, "Pending value should be active after commit");
926 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
927 }
928
929 #[test]
930 fn parse_security_context_no_policy() {
931 let security_server = SecurityServer::new_default();
932 let error = security_server
933 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
934 .expect_err("expected error");
935 let error_string = format!("{:?}", error);
936 assert!(error_string.contains("no policy"));
937 }
938
939 #[test]
940 fn compute_new_fs_node_sid_no_defaults() {
941 let security_server = SecurityServer::new_default();
942 let policy_bytes =
943 include_bytes!("../testdata/micro_policies/file_no_defaults_policy").to_vec();
944 security_server.load_policy(policy_bytes).expect("binary policy loads");
945
946 let source_sid = security_server
947 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
948 .expect("creating SID from security context should succeed");
949 let target_sid = security_server
950 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
951 .expect("creating SID from security context should succeed");
952
953 let computed_sid = security_server
954 .as_permission_check(&Default::default())
955 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
956 .expect("new sid computed");
957 let computed_context = security_server
958 .sid_to_security_context(computed_sid)
959 .expect("computed sid associated with context");
960
961 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
964 }
965
966 #[test]
967 fn compute_new_fs_node_sid_source_defaults() {
968 let security_server = SecurityServer::new_default();
969 let policy_bytes =
970 include_bytes!("../testdata/micro_policies/file_source_defaults_policy").to_vec();
971 security_server.load_policy(policy_bytes).expect("binary policy loads");
972
973 let source_sid = security_server
974 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
975 .expect("creating SID from security context should succeed");
976 let target_sid = security_server
977 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
978 .expect("creating SID from security context should succeed");
979
980 let computed_sid = security_server
981 .as_permission_check(&Default::default())
982 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
983 .expect("new sid computed");
984 let computed_context = security_server
985 .sid_to_security_context(computed_sid)
986 .expect("computed sid associated with context");
987
988 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
991 }
992
993 #[test]
994 fn compute_new_fs_node_sid_target_defaults() {
995 let security_server = SecurityServer::new_default();
996 let policy_bytes =
997 include_bytes!("../testdata/micro_policies/file_target_defaults_policy").to_vec();
998 security_server.load_policy(policy_bytes).expect("binary policy loads");
999
1000 let source_sid = security_server
1001 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
1002 .expect("creating SID from security context should succeed");
1003 let target_sid = security_server
1004 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
1005 .expect("creating SID from security context should succeed");
1006
1007 let computed_sid = security_server
1008 .as_permission_check(&Default::default())
1009 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1010 .expect("new sid computed");
1011 let computed_context = security_server
1012 .sid_to_security_context(computed_sid)
1013 .expect("computed sid associated with context");
1014
1015 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
1017 }
1018
1019 #[test]
1020 fn compute_new_fs_node_sid_range_source_low_default() {
1021 let security_server = SecurityServer::new_default();
1022 let policy_bytes =
1023 include_bytes!("../testdata/micro_policies/file_range_source_low_policy").to_vec();
1024 security_server.load_policy(policy_bytes).expect("binary policy loads");
1025
1026 let source_sid = security_server
1027 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1028 .expect("creating SID from security context should succeed");
1029 let target_sid = security_server
1030 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
1031 .expect("creating SID from security context should succeed");
1032
1033 let computed_sid = security_server
1034 .as_permission_check(&Default::default())
1035 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1036 .expect("new sid computed");
1037 let computed_context = security_server
1038 .sid_to_security_context(computed_sid)
1039 .expect("computed sid associated with context");
1040
1041 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1043 }
1044
1045 #[test]
1046 fn compute_new_fs_node_sid_range_source_low_high_default() {
1047 let security_server = SecurityServer::new_default();
1048 let policy_bytes =
1049 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy").to_vec();
1050 security_server.load_policy(policy_bytes).expect("binary policy loads");
1051
1052 let source_sid = security_server
1053 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1054 .expect("creating SID from security context should succeed");
1055 let target_sid = security_server
1056 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
1057 .expect("creating SID from security context should succeed");
1058
1059 let computed_sid = security_server
1060 .as_permission_check(&Default::default())
1061 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1062 .expect("new sid computed");
1063 let computed_context = security_server
1064 .sid_to_security_context(computed_sid)
1065 .expect("computed sid associated with context");
1066
1067 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1069 }
1070
1071 #[test]
1072 fn compute_new_fs_node_sid_range_source_high_default() {
1073 let security_server = SecurityServer::new_default();
1074 let policy_bytes =
1075 include_bytes!("../testdata/micro_policies/file_range_source_high_policy").to_vec();
1076 security_server.load_policy(policy_bytes).expect("binary policy loads");
1077
1078 let source_sid = security_server
1079 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1080 .expect("creating SID from security context should succeed");
1081 let target_sid = security_server
1082 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
1083 .expect("creating SID from security context should succeed");
1084
1085 let computed_sid = security_server
1086 .as_permission_check(&Default::default())
1087 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1088 .expect("new sid computed");
1089 let computed_context = security_server
1090 .sid_to_security_context(computed_sid)
1091 .expect("computed sid associated with context");
1092
1093 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1095 }
1096
1097 #[test]
1098 fn compute_new_fs_node_sid_range_target_low_default() {
1099 let security_server = SecurityServer::new_default();
1100 let policy_bytes =
1101 include_bytes!("../testdata/micro_policies/file_range_target_low_policy").to_vec();
1102 security_server.load_policy(policy_bytes).expect("binary policy loads");
1103
1104 let source_sid = security_server
1105 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1106 .expect("creating SID from security context should succeed");
1107 let target_sid = security_server
1108 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1109 .expect("creating SID from security context should succeed");
1110
1111 let computed_sid = security_server
1112 .as_permission_check(&Default::default())
1113 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1114 .expect("new sid computed");
1115 let computed_context = security_server
1116 .sid_to_security_context(computed_sid)
1117 .expect("computed sid associated with context");
1118
1119 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1121 }
1122
1123 #[test]
1124 fn compute_new_fs_node_sid_range_target_low_high_default() {
1125 let security_server = SecurityServer::new_default();
1126 let policy_bytes =
1127 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy").to_vec();
1128 security_server.load_policy(policy_bytes).expect("binary policy loads");
1129
1130 let source_sid = security_server
1131 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1132 .expect("creating SID from security context should succeed");
1133 let target_sid = security_server
1134 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1135 .expect("creating SID from security context should succeed");
1136
1137 let computed_sid = security_server
1138 .as_permission_check(&Default::default())
1139 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1140 .expect("new sid computed");
1141 let computed_context = security_server
1142 .sid_to_security_context(computed_sid)
1143 .expect("computed sid associated with context");
1144
1145 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1147 }
1148
1149 #[test]
1150 fn compute_new_fs_node_sid_range_target_high_default() {
1151 let security_server = SecurityServer::new_default();
1152 let policy_bytes =
1153 include_bytes!("../testdata/micro_policies/file_range_target_high_policy").to_vec();
1154 security_server.load_policy(policy_bytes).expect("binary policy loads");
1155
1156 let source_sid = security_server
1157 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1158 .expect("creating SID from security context should succeed");
1159 let target_sid = security_server
1160 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1161 .expect("creating SID from security context should succeed");
1162
1163 let computed_sid = security_server
1164 .as_permission_check(&Default::default())
1165 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1166 .expect("new sid computed");
1167 let computed_context = security_server
1168 .sid_to_security_context(computed_sid)
1169 .expect("computed sid associated with context");
1170
1171 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1173 }
1174
1175 #[test]
1176 fn compute_new_fs_node_sid_with_name() {
1177 let security_server = SecurityServer::new_default();
1178 let policy_bytes =
1179 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy")
1180 .to_vec();
1181 security_server.load_policy(policy_bytes).expect("binary policy loads");
1182
1183 let source_sid = security_server
1184 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1185 .expect("creating SID from security context should succeed");
1186 let target_sid = security_server
1187 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1188 .expect("creating SID from security context should succeed");
1189
1190 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1191 let computed_sid = security_server
1192 .as_permission_check(&Default::default())
1193 .compute_new_fs_node_sid(
1194 source_sid,
1195 target_sid,
1196 FileClass::File.into(),
1197 SPECIAL_FILE_NAME.into(),
1198 )
1199 .expect("new sid computed");
1200 let computed_context = security_server
1201 .sid_to_security_context(computed_sid)
1202 .expect("computed sid associated with context");
1203
1204 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1206
1207 let computed_sid = security_server
1208 .as_permission_check(&Default::default())
1209 .compute_new_fs_node_sid(
1210 source_sid,
1211 target_sid,
1212 FileClass::ChrFile.into(),
1213 SPECIAL_FILE_NAME.into(),
1214 )
1215 .expect("new sid computed");
1216 let computed_context = security_server
1217 .sid_to_security_context(computed_sid)
1218 .expect("computed sid associated with context");
1219
1220 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1223
1224 const OTHER_FILE_NAME: &[u8] = b"other_file";
1225 let computed_sid = security_server
1226 .as_permission_check(&Default::default())
1227 .compute_new_fs_node_sid(
1228 source_sid,
1229 target_sid,
1230 FileClass::File.into(),
1231 OTHER_FILE_NAME.into(),
1232 )
1233 .expect("new sid computed");
1234 let computed_context = security_server
1235 .sid_to_security_context(computed_sid)
1236 .expect("computed sid associated with context");
1237
1238 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1241 }
1242
1243 #[test]
1244 fn permissions_are_fresh_after_different_policy_load() {
1245 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1246 let allow_fork_bytes =
1247 include_bytes!("../testdata/composite_policies/compiled/allow_fork_policy").to_vec();
1248 let context = b"source_u:object_r:source_t:s0:c0";
1249
1250 let security_server = SecurityServer::new_default();
1251 security_server.set_enforcing(true);
1252
1253 let local_cache = Default::default();
1254 let permission_check = security_server.as_permission_check(&local_cache);
1255
1256 assert_eq!(
1258 Ok(()),
1259 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1260 );
1261 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1262
1263 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1265
1266 assert_eq!(
1268 Ok(()),
1269 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1270 );
1271
1272 let permission_check = security_server.as_permission_check(&local_cache);
1274
1275 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1277 }
1278
1279 #[test]
1280 fn unknown_sids_are_effectively_unlabeled() {
1281 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1282 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy"
1283 )
1284 .to_vec();
1285 let with_additional_domain_policy_bytes =
1286 include_bytes!("../testdata/composite_policies/compiled/with_additional_domain_policy")
1287 .to_vec();
1288 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1289 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1290
1291 let security_server = SecurityServer::new_default();
1292 security_server.set_enforcing(true);
1293
1294 assert_eq!(
1297 Ok(()),
1298 security_server
1299 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1300 .map_err(|e| format!("{:?}", e))
1301 );
1302 let allowed_type_sid =
1303 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1304 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1305
1306 assert_eq!(
1309 Ok(()),
1310 security_server
1311 .load_policy(with_additional_domain_policy_bytes.clone())
1312 .map_err(|e| format!("{:?}", e))
1313 );
1314 let additional_type_sid =
1315 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1316 assert_eq!(
1317 allowed_type_sid,
1318 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1319 );
1320
1321 let local_cache = Default::default();
1322 let permission_check = security_server.as_permission_check(&local_cache);
1323
1324 assert!(
1328 !permission_check
1329 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1330 .granted
1331 );
1332 assert!(
1333 !permission_check
1334 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1335 .granted
1336 );
1337 assert!(
1338 !permission_check
1339 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1340 .granted
1341 );
1342 assert!(
1343 !permission_check
1344 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1345 .granted
1346 );
1347
1348 assert_eq!(
1350 Ok(()),
1351 security_server
1352 .load_policy(with_unlabeled_access_domain_policy_bytes)
1353 .map_err(|e| format!("{:?}", e))
1354 );
1355
1356 let permission_check = security_server.as_permission_check(&local_cache);
1358
1359 assert!(
1363 permission_check
1364 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1365 .granted
1366 );
1367 assert!(
1368 !permission_check
1369 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1370 .granted
1371 );
1372
1373 assert!(
1378 !permission_check
1379 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1380 .granted
1381 );
1382 assert!(
1383 permission_check
1384 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1385 .granted
1386 );
1387
1388 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1390
1391 assert_eq!(
1394 Ok(()),
1395 security_server
1396 .load_policy(with_additional_domain_policy_bytes)
1397 .map_err(|e| format!("{:?}", e))
1398 );
1399 assert_eq!(
1400 additional_type_context.to_vec(),
1401 security_server.sid_to_security_context(additional_type_sid).unwrap()
1402 );
1403 }
1404
1405 #[test]
1406 fn permission_check_permissive() {
1407 let security_server = security_server_with_tests_policy();
1408 security_server.set_enforcing(false);
1409 assert!(!security_server.is_enforcing());
1410
1411 let sid =
1412 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1413 let local_cache = Default::default();
1414 let permission_check = security_server.as_permission_check(&local_cache);
1415
1416 assert_eq!(
1419 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1420 PermissionCheckResult {
1421 granted: true,
1422 audit: false,
1423 permissive: false,
1424 todo_bug: None
1425 }
1426 );
1427
1428 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1432 assert_eq!(
1433 result,
1434 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1435 );
1436 assert!(result.permit());
1437
1438 let result = permission_check.has_permission(
1442 sid,
1443 sid,
1444 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1445 );
1446 assert_eq!(
1447 result,
1448 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1449 );
1450 assert!(result.permit());
1451 }
1452
1453 #[test]
1454 fn permission_check_enforcing() {
1455 let security_server = security_server_with_tests_policy();
1456 security_server.set_enforcing(true);
1457 assert!(security_server.is_enforcing());
1458
1459 let sid =
1460 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1461 let local_cache = Default::default();
1462 let permission_check = security_server.as_permission_check(&local_cache);
1463
1464 let result = permission_check.has_permission(sid, sid, ProcessPermission::Fork);
1466 assert_eq!(
1467 result,
1468 PermissionCheckResult {
1469 granted: true,
1470 audit: false,
1471 permissive: false,
1472 todo_bug: None
1473 }
1474 );
1475 assert!(result.permit());
1476
1477 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1480 assert_eq!(
1481 result,
1482 PermissionCheckResult {
1483 granted: false,
1484 audit: true,
1485 permissive: false,
1486 todo_bug: None
1487 }
1488 );
1489 assert!(!result.permit());
1490
1491 let result = permission_check.has_permission(
1494 sid,
1495 sid,
1496 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1497 );
1498 assert_eq!(
1499 result,
1500 PermissionCheckResult {
1501 granted: false,
1502 audit: true,
1503 permissive: false,
1504 todo_bug: None
1505 }
1506 );
1507 assert!(!result.permit());
1508 }
1509
1510 #[test]
1511 fn permissive_domain() {
1512 let security_server = security_server_with_tests_policy();
1513 security_server.set_enforcing(true);
1514 assert!(security_server.is_enforcing());
1515
1516 let permissive_sid = security_server
1517 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1518 .unwrap();
1519 let non_permissive_sid = security_server
1520 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1521 .unwrap();
1522
1523 let local_cache = Default::default();
1524 let permission_check = security_server.as_permission_check(&local_cache);
1525
1526 let result = permission_check.has_permission(
1528 permissive_sid,
1529 permissive_sid,
1530 ProcessPermission::GetSched,
1531 );
1532 assert_eq!(
1533 result,
1534 PermissionCheckResult { granted: true, audit: false, permissive: true, todo_bug: None }
1535 );
1536 assert!(result.permit());
1537 let result = permission_check.has_permission(
1538 non_permissive_sid,
1539 non_permissive_sid,
1540 ProcessPermission::GetSched,
1541 );
1542 assert_eq!(
1543 result,
1544 PermissionCheckResult {
1545 granted: true,
1546 audit: false,
1547 permissive: false,
1548 todo_bug: None
1549 }
1550 );
1551 assert!(result.permit());
1552
1553 let result = permission_check.has_permission(
1556 permissive_sid,
1557 non_permissive_sid,
1558 ProcessPermission::GetSched,
1559 );
1560 assert_eq!(
1561 result,
1562 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1563 );
1564 assert!(result.permit());
1565 let result = permission_check.has_permission(
1566 non_permissive_sid,
1567 permissive_sid,
1568 ProcessPermission::GetSched,
1569 );
1570 assert_eq!(
1571 result,
1572 PermissionCheckResult {
1573 granted: false,
1574 audit: true,
1575 permissive: false,
1576 todo_bug: None
1577 }
1578 );
1579 assert!(!result.permit());
1580
1581 let result = permission_check.has_permission(
1586 permissive_sid,
1587 non_permissive_sid,
1588 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1589 );
1590 assert_eq!(
1591 result,
1592 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1593 );
1594 assert!(result.permit());
1595 let result = permission_check.has_permission(
1596 non_permissive_sid,
1597 non_permissive_sid,
1598 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1599 );
1600 assert_eq!(
1601 result,
1602 PermissionCheckResult {
1603 granted: false,
1604 audit: true,
1605 permissive: false,
1606 todo_bug: None
1607 }
1608 );
1609 assert!(!result.permit());
1610 }
1611
1612 #[test]
1613 fn auditallow_and_dontaudit() {
1614 let security_server = security_server_with_tests_policy();
1615 security_server.set_enforcing(true);
1616 assert!(security_server.is_enforcing());
1617
1618 let audit_sid = security_server
1619 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1620 .unwrap();
1621
1622 let local_cache = Default::default();
1623 let permission_check = security_server.as_permission_check(&local_cache);
1624
1625 let result = permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork);
1627 assert_eq!(
1628 result,
1629 PermissionCheckResult { granted: true, audit: true, permissive: false, todo_bug: None }
1630 );
1631 assert!(result.permit());
1632
1633 let result =
1635 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched);
1636 assert_eq!(
1637 result,
1638 PermissionCheckResult {
1639 granted: true,
1640 audit: false,
1641 permissive: false,
1642 todo_bug: None
1643 }
1644 );
1645 assert!(result.permit());
1646
1647 let result =
1649 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched);
1650 assert_eq!(
1651 result,
1652 PermissionCheckResult {
1653 granted: false,
1654 audit: false,
1655 permissive: false,
1656 todo_bug: None
1657 }
1658 );
1659 assert!(!result.permit());
1660
1661 let result =
1663 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid);
1664 assert_eq!(
1665 result,
1666 PermissionCheckResult {
1667 granted: false,
1668 audit: true,
1669 permissive: false,
1670 todo_bug: None
1671 }
1672 );
1673 assert!(!result.permit());
1674 }
1675
1676 #[test]
1677 fn access_checks_with_exceptions_config() {
1678 const EXCEPTIONS_CONFIG: &[&str] = &[
1679 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1681 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1682 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1683 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1684 "todo_permissive b/005 test_exception_todo_permissive_t",
1685 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1687 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1688 "todo_permissive b/103 test_undefined_source_t",
1689 ];
1690 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1691 let security_server = SecurityServer::new(String::new(), exceptions_config);
1692 security_server.set_enforcing(true);
1693
1694 const EXCEPTIONS_POLICY: &[u8] =
1695 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy");
1696 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1697
1698 let source_sid = security_server
1699 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1700 .unwrap();
1701 let target_sid = security_server
1702 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1703 .unwrap();
1704 let other_sid = security_server
1705 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1706 .unwrap();
1707 let permissive_sid = security_server
1708 .security_context_to_sid(
1709 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1710 )
1711 .unwrap();
1712 let unmatched_sid = security_server
1713 .security_context_to_sid(
1714 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1715 )
1716 .unwrap();
1717 let todo_permissive_sid = security_server
1718 .security_context_to_sid(
1719 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1720 )
1721 .unwrap();
1722
1723 let local_cache = Default::default();
1724 let permission_check = security_server.as_permission_check(&local_cache);
1725
1726 let result =
1728 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid);
1729 assert_eq!(
1730 result,
1731 PermissionCheckResult {
1732 granted: false,
1733 audit: true,
1734 permissive: false,
1735 todo_bug: None
1736 }
1737 );
1738 assert!(!result.permit());
1739
1740 let result =
1742 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint);
1743 assert_eq!(
1744 result,
1745 PermissionCheckResult {
1746 granted: true,
1747 audit: true,
1748 permissive: false,
1749 todo_bug: Some(NonZeroU32::new(1).unwrap())
1750 }
1751 );
1752 assert!(result.permit());
1753
1754 let result =
1756 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans);
1757 assert_eq!(
1758 result,
1759 PermissionCheckResult {
1760 granted: true,
1761 audit: false,
1762 permissive: false,
1763 todo_bug: None,
1764 }
1765 );
1766 assert!(result.permit());
1767
1768 let result =
1770 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint);
1771 assert_eq!(
1772 result,
1773 PermissionCheckResult {
1774 granted: false,
1775 audit: true,
1776 permissive: false,
1777 todo_bug: None
1778 }
1779 );
1780 assert!(!result.permit());
1781
1782 let result = permission_check.has_permission(
1784 other_sid,
1785 target_sid,
1786 CommonFsNodePermission::Read.for_class(FileClass::ChrFile),
1787 );
1788 assert_eq!(
1789 result,
1790 PermissionCheckResult {
1791 granted: true,
1792 audit: true,
1793 permissive: false,
1794 todo_bug: Some(NonZeroU32::new(2).unwrap())
1795 }
1796 );
1797 assert!(result.permit());
1798
1799 let result =
1801 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint);
1802 assert_eq!(
1803 result,
1804 PermissionCheckResult {
1805 granted: false,
1806 audit: true,
1807 permissive: false,
1808 todo_bug: None
1809 }
1810 );
1811 assert!(!result.permit());
1812
1813 let result =
1815 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint);
1816 assert_eq!(
1817 result,
1818 PermissionCheckResult {
1819 granted: false,
1820 audit: true,
1821 permissive: false,
1822 todo_bug: None
1823 }
1824 );
1825 assert!(!result.permit());
1826
1827 let result =
1829 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint);
1830 assert_eq!(
1831 result,
1832 PermissionCheckResult {
1833 granted: true,
1834 audit: true,
1835 permissive: true,
1836 todo_bug: Some(NonZeroU32::new(4).unwrap())
1837 }
1838 );
1839 assert!(result.permit());
1840
1841 let result = permission_check.has_permission(
1844 todo_permissive_sid,
1845 target_sid,
1846 FilePermission::Entrypoint,
1847 );
1848 assert_eq!(
1849 result,
1850 PermissionCheckResult {
1851 granted: true,
1852 audit: true,
1853 permissive: false,
1854 todo_bug: Some(NonZeroU32::new(5).unwrap())
1855 }
1856 );
1857 assert!(result.permit());
1858 let result = permission_check.has_permission(
1859 todo_permissive_sid,
1860 todo_permissive_sid,
1861 FilePermission::Entrypoint,
1862 );
1863 assert_eq!(
1864 result,
1865 PermissionCheckResult {
1866 granted: true,
1867 audit: true,
1868 permissive: false,
1869 todo_bug: Some(NonZeroU32::new(5).unwrap())
1870 }
1871 );
1872 assert!(result.permit());
1873 let result = permission_check.has_permission(
1874 todo_permissive_sid,
1875 target_sid,
1876 FilePermission::Entrypoint,
1877 );
1878 assert_eq!(
1879 result,
1880 PermissionCheckResult {
1881 granted: true,
1882 audit: true,
1883 permissive: false,
1884 todo_bug: Some(NonZeroU32::new(5).unwrap())
1885 }
1886 );
1887 assert!(result.permit());
1888 }
1889
1890 #[test]
1891 fn handle_unknown() {
1892 let security_server = security_server_with_tests_policy();
1893
1894 let sid = security_server
1895 .security_context_to_sid("user0:object_r:type0:s0".into())
1896 .expect("Resolve Context to SID");
1897
1898 const REJECT_POLICY: &[u8] =
1902 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-reject");
1903 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1904
1905 security_server.set_enforcing(true);
1906
1907 const DENY_POLICY: &[u8] =
1909 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny");
1910 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1911 let local_cache = Default::default();
1912 let permission_check = security_server.as_permission_check(&local_cache);
1913
1914 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1916 assert_eq!(
1917 result,
1918 PermissionCheckResult {
1919 granted: false,
1920 audit: true,
1921 permissive: false,
1922 todo_bug: None
1923 }
1924 );
1925 assert!(!result.permit());
1926 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1927 assert_eq!(
1928 result,
1929 PermissionCheckResult {
1930 granted: false,
1931 audit: true,
1932 permissive: false,
1933 todo_bug: None
1934 }
1935 );
1936 assert!(!result.permit());
1937
1938 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1940 assert_eq!(
1941 result,
1942 PermissionCheckResult {
1943 granted: true,
1944 audit: false,
1945 permissive: false,
1946 todo_bug: None
1947 }
1948 );
1949 assert!(result.permit());
1950 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1951 assert_eq!(
1952 result,
1953 PermissionCheckResult {
1954 granted: false,
1955 audit: true,
1956 permissive: false,
1957 todo_bug: None
1958 }
1959 );
1960 assert!(!result.permit());
1961
1962 const ALLOW_POLICY: &[u8] =
1964 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-allow");
1965 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1966 let local_cache2 = Default::default();
1967 let permission_check = security_server.as_permission_check(&local_cache2);
1968
1969 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1971 assert_eq!(
1972 result,
1973 PermissionCheckResult {
1974 granted: true,
1975 audit: false,
1976 permissive: false,
1977 todo_bug: None
1978 }
1979 );
1980 assert!(result.permit());
1981 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
1982 assert_eq!(
1983 result,
1984 PermissionCheckResult {
1985 granted: true,
1986 audit: false,
1987 permissive: false,
1988 todo_bug: None
1989 }
1990 );
1991 assert!(result.permit());
1992
1993 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1995 assert_eq!(
1996 result,
1997 PermissionCheckResult {
1998 granted: true,
1999 audit: false,
2000 permissive: false,
2001 todo_bug: None
2002 }
2003 );
2004 assert!(result.permit());
2005
2006 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
2007 assert_eq!(
2008 result,
2009 PermissionCheckResult {
2010 granted: false,
2011 audit: true,
2012 permissive: false,
2013 todo_bug: None
2014 }
2015 );
2016 assert!(!result.permit());
2017 }
2018}