1use crate::access_vector_cache::{
6 AccessVectorCache, CacheStats, KernelXpermsAccessDecision, Query,
7};
8use crate::exceptions_config::ExceptionsConfig;
9use crate::new_policy::traits::{HasName, HasPolicyId};
10use crate::new_policy::{HandleUnknown, NewPolicy};
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, InitialSid, KernelClass, KernelPermission, NullessByteStr, ObjectClass,
23 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
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: RwLock::new(SecurityServerState {
198 active_policy: None,
199 booleans: SeLinuxBooleans::default(),
200 status_publisher: None,
201 }),
202 is_enforcing: AtomicBool::new(false),
203 policy_change_count: AtomicU32::new(0),
204 });
205
206 let access_vector_cache = AccessVectorCache::new(backend.clone());
207
208 Arc::new(Self { access_vector_cache, backend, exceptions, allow_unimplemented })
209 }
210
211 pub fn as_permission_check<'a>(
214 self: &'a Self,
215 local_cache: &'a PerThreadCache,
216 ) -> PermissionCheck<'a> {
217 PermissionCheck::new(self, &self.access_vector_cache, local_cache)
218 }
219
220 pub fn security_context_to_sid(
224 &self,
225 security_context: NullessByteStr<'_>,
226 ) -> Result<SecurityId, anyhow::Error> {
227 self.backend.compute_sid(|active_policy| {
228 active_policy
229 .parsed
230 .parse_security_context(security_context)
231 .map_err(anyhow::Error::from)
232 })
233 }
234
235 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
242 let locked_state = self.backend.state.read();
243 let active_policy = locked_state.active_policy.as_ref()?;
244 let context = active_policy.sid_table.sid_to_security_context(sid);
245 Some(active_policy.parsed.serialize_security_context(context))
246 }
247
248 pub fn sid_to_security_context_with_nul(&self, sid: SecurityId) -> Option<Vec<u8>> {
250 self.sid_to_security_context(sid).map(|mut context| {
251 context.push(0u8);
252 context
253 })
254 }
255
256 pub fn load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
258 let unvalidated_policy = parse_policy_by_value(binary_policy)?;
261 let parsed = Arc::new(unvalidated_policy.validate()?);
262 if !self.allow_unimplemented {
263 validate_no_unsupported_policy_features_used(&parsed)?;
264 }
265
266 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
267 let exceptions = ExceptionsConfig::new(&parsed, &exceptions)?;
268
269 self.with_mut_state_and_update_status(|state| {
271 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
272 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
273 } else {
274 SidTable::new(parsed.clone())
275 };
276
277 state.booleans.reset(
280 parsed
281 .conditional_booleans()
282 .iter()
283 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
285 .collect(),
286 );
287
288 state.active_policy = Some(ActivePolicy { parsed, sid_table, exceptions });
289 self.backend.policy_change_count.fetch_add(1, Ordering::Relaxed);
290 });
291
292 Ok(())
293 }
294
295 pub fn has_policy(&self) -> bool {
297 self.backend.state.read().active_policy.is_some()
298 }
299
300 pub fn get_binary_policy(&self) -> Option<PolicyData> {
302 let state = self.backend.state.read();
303 let active_policy = state.active_policy.as_ref()?;
304 Some(active_policy.parsed.serialize())
305 }
306
307 pub fn set_enforcing(&self, enforcing: bool) {
309 self.with_mut_state_and_update_status(|_| {
310 self.backend.is_enforcing.store(enforcing, Ordering::Release);
311 });
312 }
313
314 pub fn is_enforcing(&self) -> bool {
315 self.backend.is_enforcing.load(Ordering::Acquire)
316 }
317
318 pub fn deny_unknown(&self) -> bool {
321 self.backend.state.read().deny_unknown()
322 }
323
324 pub fn reject_unknown(&self) -> bool {
327 self.backend.state.read().reject_unknown()
328 }
329
330 pub fn conditional_booleans(&self) -> Vec<String> {
333 self.backend.state.read().booleans.names()
334 }
335
336 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
338 self.backend.state.read().booleans.get(name)
339 }
340
341 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
343 self.backend.state.write().booleans.set_pending(name, value)
344 }
345
346 pub fn commit_pending_booleans(&self) {
348 self.with_mut_state_and_update_status(|state| {
350 state.booleans.commit_pending();
351 self.backend.policy_change_count.fetch_add(1, Ordering::Relaxed);
352 });
353 }
354
355 pub fn is_policycap_enabled(&self, policy_cap: PolicyCap) -> bool {
357 let locked_state = self.backend.state.read();
358 let Some(policy) = &locked_state.active_policy else {
359 return false;
360 };
361 policy.parsed.has_policycap(policy_cap)
362 }
363
364 pub fn avc_cache_stats(&self) -> CacheStats {
366 self.access_vector_cache.cache_stats()
367 }
368
369 pub fn policy_seqno(&self) -> PolicySeqNo {
371 PolicySeqNo(self.backend.policy_change_count.load(Ordering::Relaxed))
372 }
373
374 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
376 let locked_state = self.backend.state.read();
377 let names = locked_state
378 .expect_active_policy()
379 .parsed
380 .classes()
381 .iter()
382 .map(|class| class.name().to_vec())
383 .collect();
384 Ok(names)
385 }
386
387 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
389 let locked_state = self.backend.state.read();
390 Ok(locked_state
391 .expect_active_policy()
392 .parsed
393 .classes()
394 .get_by_name(name.as_bytes())
395 .ok_or(())?
396 .id())
397 }
398
399 pub fn class_permissions_by_name(
403 &self,
404 name: &str,
405 ) -> Result<Vec<(PermissionId, Vec<u8>)>, ()> {
406 let locked_state = self.backend.state.read();
407 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
408 }
409
410 pub fn resolve_fs_label(
414 &self,
415 fs_type: NullessByteStr<'_>,
416 mount_options: &FileSystemMountOptions,
417 ) -> Result<FileSystemLabel, anyhow::Error> {
418 let mut locked_state = self.backend.state.write();
419 let active_policy = locked_state.expect_active_policy_mut();
420
421 let mount_sids = FileSystemMountSids {
422 context: sid_from_mount_option(active_policy, &mount_options.context)?,
423 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context)?,
424 def_context: sid_from_mount_option(active_policy, &mount_options.def_context)?,
425 root_context: sid_from_mount_option(active_policy, &mount_options.root_context)?,
426 };
427 let label = if let Some(mountpoint_sid) = mount_sids.context {
428 FileSystemLabel {
432 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
433 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
434 mount_sids,
435 }
436 } else if let Some(FsUseLabelAndType { context, use_type }) =
437 active_policy.parsed.fs_use_label_and_type(fs_type)
438 {
439 let fs_sid_from_policy =
441 active_policy.sid_table.security_context_to_sid(&context).unwrap();
442 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
443 FileSystemLabel {
444 sid: fs_sid,
445 scheme: FileSystemLabelingScheme::FsUse {
446 fs_use_type: use_type,
447 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
448 },
449 mount_sids,
450 }
451 } else if let Some(context) =
452 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
453 {
454 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
456 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
457
458 let fs_type = fs_type.as_bytes();
468 let mut supports_seclabel = matches!(fs_type, b"sysfs" | b"tracefs" | b"pstore");
469 supports_seclabel |= matches!(fs_type, b"cgroup" | b"cgroup2")
470 && active_policy.parsed.has_policycap(PolicyCap::CgroupSeclabel);
471 supports_seclabel |= fs_type == b"functionfs"
472 && active_policy.parsed.has_policycap(PolicyCap::FunctionfsSeclabel);
473
474 FileSystemLabel {
475 sid: fs_sid,
476 scheme: FileSystemLabelingScheme::GenFsCon { supports_seclabel },
477 mount_sids,
478 }
479 } else {
480 FileSystemLabel {
482 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
483 scheme: FileSystemLabelingScheme::FsUse {
484 fs_use_type: FsUseType::Xattr,
485 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
486 },
487 mount_sids,
488 }
489 };
490 Ok(label)
491 }
492
493 pub fn genfscon_label_for_fs_and_path(
498 &self,
499 fs_type: NullessByteStr<'_>,
500 node_path: NullessByteStr<'_>,
501 class_id: Option<KernelClass>,
502 ) -> Result<SecurityId, anyhow::Error> {
503 self.backend.compute_sid(|active_policy| {
504 active_policy
505 .parsed
506 .genfscon_label_for_fs_and_path(fs_type, node_path.into(), class_id)
507 .ok_or_else(|| {
508 anyhow::anyhow!("Genfscon label requested for non-genfscon labeled filesystem")
509 })
510 })
511 }
512
513 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
518 let locked_state = self.backend.state.read();
519 let active_policy = locked_state.expect_active_policy();
520 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
521 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
522 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
523 }
524
525 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
532 self.with_mut_state_and_update_status(|state| {
533 assert!(state.status_publisher.is_none());
534 state.status_publisher = Some(status_holder);
535 });
536 }
537
538 fn with_mut_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
542 let mut locked_state = self.backend.state.write();
543 f(locked_state.deref_mut());
544 let new_value = SeLinuxStatus {
545 is_enforcing: self.is_enforcing(),
546 change_count: self.backend.policy_change_count.load(Ordering::Relaxed),
547 deny_unknown: locked_state.deny_unknown(),
548 };
549 if let Some(status_publisher) = &mut locked_state.status_publisher {
550 status_publisher.set_status(new_value);
551 }
552
553 std::mem::drop(locked_state);
556 self.access_vector_cache.reset();
557 }
558
559 pub fn compute_create_sid_raw(
565 &self,
566 source_sid: SecurityId,
567 target_sid: SecurityId,
568 target_class: ClassId,
569 name: &[u8],
570 ) -> Result<SecurityId, anyhow::Error> {
571 self.backend.compute_create_sid_raw(source_sid, target_sid, target_class.into(), name)
572 }
573
574 pub fn compute_access_decision_raw(
577 &self,
578 source_sid: SecurityId,
579 target_sid: SecurityId,
580 target_class: ClassId,
581 ) -> AccessDecision {
582 self.backend.compute_access_decision_raw(source_sid, target_sid, target_class.into())
583 }
584}
585
586impl SecurityServerBackend {
587 fn compute_create_sid_raw(
588 &self,
589 source_sid: SecurityId,
590 target_sid: SecurityId,
591 target_class: ObjectClass,
592 name: &[u8],
593 ) -> Result<SecurityId, anyhow::Error> {
594 self.compute_sid(|active_policy| {
595 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
596 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
597
598 Ok(active_policy.parsed.compute_create_context(
599 source_context,
600 target_context,
601 target_class,
602 name,
603 ))
604 })
605 .context("computing new security context from policy")
606 }
607
608 fn compute_sid(
610 &self,
611 compute_context: impl Fn(&ActivePolicy) -> Result<SecurityContext, anyhow::Error>,
612 ) -> Result<SecurityId, anyhow::Error> {
613 let readable_state = self.state.read();
616 let policy_change_count = self.policy_change_count.load(Ordering::Relaxed);
617 let policy_state = readable_state
618 .active_policy
619 .as_ref()
620 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
621 let context = compute_context(policy_state)?;
622 if let Some(sid) = policy_state.sid_table.security_context_to_existing_sid(&context) {
623 return Ok(sid);
624 }
625 std::mem::drop(readable_state);
626
627 let mut writable_state = self.state.write();
632 let needs_recompute =
633 policy_change_count != self.policy_change_count.load(Ordering::Relaxed);
634 let policy_state = writable_state.active_policy.as_mut().unwrap();
635 let context = if needs_recompute { compute_context(policy_state)? } else { context };
636 policy_state.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
637 }
638
639 fn compute_access_decision_raw(
640 &self,
641 source_sid: SecurityId,
642 target_sid: SecurityId,
643 target_class: ObjectClass,
644 ) -> AccessDecision {
645 let locked_state = self.state.read();
646
647 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class)
648 }
649}
650
651impl Query for SecurityServerBackend {
652 fn compute_access_decision(
653 &self,
654 source_sid: SecurityId,
655 target_sid: SecurityId,
656 target_class: KernelClass,
657 ) -> KernelAccessDecision {
658 let locked_state = self.state.read();
659 let decision =
660 locked_state.compute_access_decision_raw(source_sid, target_sid, target_class.into());
661 locked_state.access_decision_to_kernel_access_decision(target_class, decision)
662 }
663
664 fn compute_create_sid(
665 &self,
666 source_sid: SecurityId,
667 target_sid: SecurityId,
668 target_class: KernelClass,
669 name: &[u8],
670 ) -> Result<SecurityId, anyhow::Error> {
671 self.compute_create_sid_raw(source_sid, target_sid, target_class.into(), name)
672 }
673
674 fn compute_xperms_access_decision(
675 &self,
676 xperms_kind: XpermsKind,
677 source_sid: SecurityId,
678 target_sid: SecurityId,
679 permission: KernelPermission,
680 xperms_prefix: u8,
681 ) -> KernelXpermsAccessDecision {
682 let locked_state = self.state.read();
683
684 let active_policy = match &locked_state.active_policy {
685 Some(active_policy) => active_policy,
686 None => {
688 return KernelXpermsAccessDecision {
689 allow: XpermsBitmap::ALL,
690 audit: XpermsBitmap::NONE,
691 permissive: false,
692 has_todo: false,
693 };
694 }
695 };
696
697 let base_decision_raw = locked_state.compute_access_decision_raw(
700 source_sid,
701 target_sid,
702 permission.class().into(),
703 );
704 let base_decision = locked_state
705 .access_decision_to_kernel_access_decision(permission.class(), base_decision_raw);
706 let permission_access_vector = permission.as_access_vector();
707 let base_permit =
708 base_decision.allow & permission_access_vector == permission_access_vector;
709 let base_audit = base_decision.audit & permission_access_vector == permission_access_vector;
710
711 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
713 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
714 let xperms_decision = active_policy.parsed.compute_xperms_access_decision(
715 xperms_kind,
716 &source_context,
717 &target_context,
718 permission.class(),
719 xperms_prefix,
720 );
721
722 let allow = if !base_permit { XpermsBitmap::NONE } else { xperms_decision.allow };
724 let audit = if base_audit {
725 XpermsBitmap::ALL
726 } else {
727 (xperms_decision.allow & xperms_decision.auditallow)
728 | (!xperms_decision.allow & xperms_decision.auditdeny)
729 };
730 let permissive = (base_decision.flags & SELINUX_AVD_FLAGS_PERMISSIVE) != 0;
731 let has_todo = base_decision.todo_bug.is_some();
732 KernelXpermsAccessDecision { allow, audit, permissive, has_todo }
733 }
734}
735
736impl AccessVectorComputer for SecurityServerBackend {
737 fn access_decision_to_kernel_access_decision(
738 &self,
739 class: KernelClass,
740 av: AccessDecision,
741 ) -> KernelAccessDecision {
742 self.state.read().access_decision_to_kernel_access_decision(class, av)
743 }
744}
745
746impl AccessVectorComputer for SecurityServerState {
747 fn access_decision_to_kernel_access_decision(
748 &self,
749 class: KernelClass,
750 av: AccessDecision,
751 ) -> KernelAccessDecision {
752 match &self.active_policy {
753 Some(policy) => policy.parsed.access_decision_to_kernel_access_decision(class, av),
754 None => KernelAccessDecision {
755 allow: AccessVector::ALL,
756 audit: AccessVector::NONE,
757 flags: 0,
758 todo_bug: None,
759 },
760 }
761 }
762}
763
764fn sid_from_mount_option(
767 active_policy: &mut ActivePolicy,
768 mount_option: &Option<Vec<u8>>,
769) -> Result<Option<SecurityId>, anyhow::Error> {
770 let Some(label) = mount_option else {
771 return Ok(None);
772 };
773 let context = active_policy.parsed.parse_security_context(label.into())?;
774 let sid = active_policy.sid_table.security_context_to_sid(&context)?;
775 Ok(Some(sid))
776}
777
778fn check_policy_feature_is_empty<T>(name: &'static str, items: &[T]) -> Result<(), anyhow::Error> {
779 if !items.is_empty() {
780 anyhow::bail!("Policy contains unsupported feature: {name} ({})", items.len());
781 }
782 Ok(())
783}
784
785fn validate_no_unsupported_policy_features_used(policy: &NewPolicy) -> Result<(), anyhow::Error> {
786 let ocontexts = policy.object_contexts();
787 check_policy_feature_is_empty("ports", ocontexts.ports())?;
788 check_policy_feature_is_empty("network_interfaces", ocontexts.network_interfaces())?;
789 check_policy_feature_is_empty("nodes", ocontexts.ipv4_nodes())?;
790 check_policy_feature_is_empty("ipv6_nodes", ocontexts.ipv6_nodes())?;
791 check_policy_feature_is_empty(
792 "infiniband_partition_keys",
793 ocontexts.infiniband_partition_keys(),
794 )?;
795 check_policy_feature_is_empty("infiniband_end_ports", ocontexts.infiniband_end_ports())?;
796 check_policy_feature_is_empty("filesystems", ocontexts.filesystems())?;
797
798 Ok(())
799}
800
801#[cfg(test)]
802mod tests {
803 use super::*;
804 use crate::permission_check::PermissionCheckResult;
805 use crate::{
806 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
807 ProcessPermission,
808 };
809 use std::num::NonZeroU32;
810
811 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
812 const TESTS_BINARY_POLICY: &[u8] =
813 include_bytes!("../testdata/micro_policies/security_server_tests_policy");
814 const MINIMAL_BINARY_POLICY: &[u8] =
815 include_bytes!("../testdata/composite_policies/compiled/minimal_policy");
816
817 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
818 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
819 let security_server = SecurityServer::new_default();
820 assert_eq!(
821 Ok(()),
822 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
823 );
824 security_server
825 }
826
827 #[test]
828 fn test_unsupported_policy_features_check() {
829 let default_server = SecurityServer::new_default();
830 let testsuite_server = SecurityServer::new("allow_unimplemented".into(), vec![]);
831
832 assert!(default_server.load_policy(MINIMAL_BINARY_POLICY.to_vec()).is_ok());
833 assert!(testsuite_server.load_policy(MINIMAL_BINARY_POLICY.to_vec()).is_ok());
834 assert!(testsuite_server.load_policy(TESTSUITE_BINARY_POLICY.to_vec()).is_ok());
835 }
836
837 #[test]
838 fn compute_access_vector_allows_all() {
839 let security_server = SecurityServer::new_default();
840 let sid1 = InitialSid::Kernel.into();
841 let sid2 = InitialSid::Unlabeled.into();
842 assert_eq!(
843 security_server
844 .backend
845 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
846 .allow,
847 AccessVector::ALL
848 );
849 }
850
851 #[test]
852 fn loaded_policy_can_be_retrieved() {
853 let security_server = security_server_with_tests_policy();
854 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_ref());
855 }
856
857 #[test]
858 fn loaded_policy_is_validated() {
859 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
860 let security_server = SecurityServer::new_default();
861 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
862 }
863
864 #[test]
865 fn enforcing_mode_is_reported() {
866 let security_server = SecurityServer::new_default();
867 assert!(!security_server.is_enforcing());
868
869 security_server.set_enforcing(true);
870 assert!(security_server.is_enforcing());
871 }
872
873 #[test]
874 fn without_policy_conditional_booleans_are_empty() {
875 let security_server = SecurityServer::new_default();
876 assert!(security_server.conditional_booleans().is_empty());
877 }
878
879 #[test]
880 fn conditional_booleans_can_be_queried() {
881 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
882 let security_server = SecurityServer::new("allow_unimplemented".into(), vec![]);
883 assert_eq!(
884 Ok(()),
885 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
886 );
887
888 let booleans = security_server.conditional_booleans();
889 assert!(!booleans.is_empty());
890 let boolean = booleans[0].as_str();
891
892 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
893 assert!(security_server.get_boolean(boolean).is_ok());
894 }
895
896 #[test]
897 fn conditional_booleans_can_be_changed() {
898 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
899 let security_server = SecurityServer::new("allow_unimplemented".into(), vec![]);
900 assert_eq!(
901 Ok(()),
902 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
903 );
904
905 let booleans = security_server.conditional_booleans();
906 assert!(!booleans.is_empty());
907 let boolean = booleans[0].as_str();
908
909 let (active, pending) = security_server.get_boolean(boolean).unwrap();
910 assert_eq!(active, pending, "Initially active and pending values should match");
911
912 security_server.set_pending_boolean(boolean, !active).unwrap();
913 let (active, pending) = security_server.get_boolean(boolean).unwrap();
914 assert!(active != pending, "Before commit pending should differ from active");
915
916 security_server.commit_pending_booleans();
917 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
918 assert_eq!(final_active, pending, "Pending value should be active after commit");
919 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
920 }
921
922 #[test]
923 fn parse_security_context_no_policy() {
924 let security_server = SecurityServer::new_default();
925 let error = security_server
926 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
927 .expect_err("expected error");
928 let error_string = format!("{:?}", error);
929 assert!(error_string.contains("no policy"));
930 }
931
932 #[test]
933 fn compute_create_sid_no_defaults() {
934 let security_server = SecurityServer::new_default();
935 let policy_bytes =
936 include_bytes!("../testdata/micro_policies/file_no_defaults_policy").to_vec();
937 security_server.load_policy(policy_bytes).expect("binary policy loads");
938
939 let source_sid = security_server
940 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
941 .expect("creating SID from security context should succeed");
942 let target_sid = security_server
943 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
944 .expect("creating SID from security context should succeed");
945
946 let computed_sid = security_server
947 .as_permission_check(&Default::default())
948 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
949 .expect("new sid computed");
950 let computed_context = security_server
951 .sid_to_security_context(computed_sid)
952 .expect("computed sid associated with context");
953
954 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
957 }
958
959 #[test]
960 fn compute_create_sid_source_defaults() {
961 let security_server = SecurityServer::new_default();
962 let policy_bytes =
963 include_bytes!("../testdata/micro_policies/file_source_defaults_policy").to_vec();
964 security_server.load_policy(policy_bytes).expect("binary policy loads");
965
966 let source_sid = security_server
967 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
968 .expect("creating SID from security context should succeed");
969 let target_sid = security_server
970 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
971 .expect("creating SID from security context should succeed");
972
973 let computed_sid = security_server
974 .as_permission_check(&Default::default())
975 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
976 .expect("new sid computed");
977 let computed_context = security_server
978 .sid_to_security_context(computed_sid)
979 .expect("computed sid associated with context");
980
981 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
984 }
985
986 #[test]
987 fn compute_create_sid_target_defaults() {
988 let security_server = SecurityServer::new_default();
989 let policy_bytes =
990 include_bytes!("../testdata/micro_policies/file_target_defaults_policy").to_vec();
991 security_server.load_policy(policy_bytes).expect("binary policy loads");
992
993 let source_sid = security_server
994 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
995 .expect("creating SID from security context should succeed");
996 let target_sid = security_server
997 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
998 .expect("creating SID from security context should succeed");
999
1000 let computed_sid = security_server
1001 .as_permission_check(&Default::default())
1002 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1003 .expect("new sid computed");
1004 let computed_context = security_server
1005 .sid_to_security_context(computed_sid)
1006 .expect("computed sid associated with context");
1007
1008 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
1010 }
1011
1012 #[test]
1013 fn compute_create_sid_range_source_low_default() {
1014 let security_server = SecurityServer::new_default();
1015 let policy_bytes =
1016 include_bytes!("../testdata/micro_policies/file_range_source_low_policy").to_vec();
1017 security_server.load_policy(policy_bytes).expect("binary policy loads");
1018
1019 let source_sid = security_server
1020 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1021 .expect("creating SID from security context should succeed");
1022 let target_sid = security_server
1023 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
1024 .expect("creating SID from security context should succeed");
1025
1026 let computed_sid = security_server
1027 .as_permission_check(&Default::default())
1028 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1029 .expect("new sid computed");
1030 let computed_context = security_server
1031 .sid_to_security_context(computed_sid)
1032 .expect("computed sid associated with context");
1033
1034 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1036 }
1037
1038 #[test]
1039 fn compute_create_sid_range_source_low_high_default() {
1040 let security_server = SecurityServer::new_default();
1041 let policy_bytes =
1042 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy").to_vec();
1043 security_server.load_policy(policy_bytes).expect("binary policy loads");
1044
1045 let source_sid = security_server
1046 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1047 .expect("creating SID from security context should succeed");
1048 let target_sid = security_server
1049 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
1050 .expect("creating SID from security context should succeed");
1051
1052 let computed_sid = security_server
1053 .as_permission_check(&Default::default())
1054 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1055 .expect("new sid computed");
1056 let computed_context = security_server
1057 .sid_to_security_context(computed_sid)
1058 .expect("computed sid associated with context");
1059
1060 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1062 }
1063
1064 #[test]
1065 fn compute_create_sid_range_source_high_default() {
1066 let security_server = SecurityServer::new_default();
1067 let policy_bytes =
1068 include_bytes!("../testdata/micro_policies/file_range_source_high_policy").to_vec();
1069 security_server.load_policy(policy_bytes).expect("binary policy loads");
1070
1071 let source_sid = security_server
1072 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
1073 .expect("creating SID from security context should succeed");
1074 let target_sid = security_server
1075 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
1076 .expect("creating SID from security context should succeed");
1077
1078 let computed_sid = security_server
1079 .as_permission_check(&Default::default())
1080 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1081 .expect("new sid computed");
1082 let computed_context = security_server
1083 .sid_to_security_context(computed_sid)
1084 .expect("computed sid associated with context");
1085
1086 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1088 }
1089
1090 #[test]
1091 fn compute_create_sid_range_target_low_default() {
1092 let security_server = SecurityServer::new_default();
1093 let policy_bytes =
1094 include_bytes!("../testdata/micro_policies/file_range_target_low_policy").to_vec();
1095 security_server.load_policy(policy_bytes).expect("binary policy loads");
1096
1097 let source_sid = security_server
1098 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1099 .expect("creating SID from security context should succeed");
1100 let target_sid = security_server
1101 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1102 .expect("creating SID from security context should succeed");
1103
1104 let computed_sid = security_server
1105 .as_permission_check(&Default::default())
1106 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1107 .expect("new sid computed");
1108 let computed_context = security_server
1109 .sid_to_security_context(computed_sid)
1110 .expect("computed sid associated with context");
1111
1112 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
1114 }
1115
1116 #[test]
1117 fn compute_create_sid_range_target_low_high_default() {
1118 let security_server = SecurityServer::new_default();
1119 let policy_bytes =
1120 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy").to_vec();
1121 security_server.load_policy(policy_bytes).expect("binary policy loads");
1122
1123 let source_sid = security_server
1124 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
1125 .expect("creating SID from security context should succeed");
1126 let target_sid = security_server
1127 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1128 .expect("creating SID from security context should succeed");
1129
1130 let computed_sid = security_server
1131 .as_permission_check(&Default::default())
1132 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1133 .expect("new sid computed");
1134 let computed_context = security_server
1135 .sid_to_security_context(computed_sid)
1136 .expect("computed sid associated with context");
1137
1138 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
1140 }
1141
1142 #[test]
1143 fn compute_create_sid_range_target_high_default() {
1144 let security_server = SecurityServer::new_default();
1145 let policy_bytes =
1146 include_bytes!("../testdata/micro_policies/file_range_target_high_policy").to_vec();
1147 security_server.load_policy(policy_bytes).expect("binary policy loads");
1148
1149 let source_sid = security_server
1150 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1151 .expect("creating SID from security context should succeed");
1152 let target_sid = security_server
1153 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1154 .expect("creating SID from security context should succeed");
1155
1156 let computed_sid = security_server
1157 .as_permission_check(&Default::default())
1158 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), &[])
1159 .expect("new sid computed");
1160 let computed_context = security_server
1161 .sid_to_security_context(computed_sid)
1162 .expect("computed sid associated with context");
1163
1164 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1166 }
1167
1168 #[test]
1169 fn compute_create_sid_with_name() {
1170 let security_server = SecurityServer::new_default();
1171 let policy_bytes =
1172 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy")
1173 .to_vec();
1174 security_server.load_policy(policy_bytes).expect("binary policy loads");
1175
1176 let source_sid = security_server
1177 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1178 .expect("creating SID from security context should succeed");
1179 let target_sid = security_server
1180 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1181 .expect("creating SID from security context should succeed");
1182
1183 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1184 let computed_sid = security_server
1185 .as_permission_check(&Default::default())
1186 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), SPECIAL_FILE_NAME)
1187 .expect("new sid computed");
1188 let computed_context = security_server
1189 .sid_to_security_context(computed_sid)
1190 .expect("computed sid associated with context");
1191
1192 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1194
1195 let computed_sid = security_server
1196 .as_permission_check(&Default::default())
1197 .compute_create_sid(
1198 source_sid,
1199 target_sid,
1200 FileClass::ChrFile.into(),
1201 SPECIAL_FILE_NAME,
1202 )
1203 .expect("new sid computed");
1204 let computed_context = security_server
1205 .sid_to_security_context(computed_sid)
1206 .expect("computed sid associated with context");
1207
1208 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1211
1212 const OTHER_FILE_NAME: &[u8] = b"other_file";
1213 let computed_sid = security_server
1214 .as_permission_check(&Default::default())
1215 .compute_create_sid(source_sid, target_sid, FileClass::File.into(), OTHER_FILE_NAME)
1216 .expect("new sid computed");
1217 let computed_context = security_server
1218 .sid_to_security_context(computed_sid)
1219 .expect("computed sid associated with context");
1220
1221 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1224 }
1225
1226 #[test]
1227 fn permissions_are_fresh_after_different_policy_load() {
1228 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1229 let allow_fork_bytes =
1230 include_bytes!("../testdata/composite_policies/compiled/allow_fork_policy").to_vec();
1231 let context = b"source_u:object_r:source_t:s0:c0";
1232
1233 let security_server = SecurityServer::new_default();
1234 security_server.set_enforcing(true);
1235
1236 let local_cache = Default::default();
1237 let permission_check = security_server.as_permission_check(&local_cache);
1238
1239 assert_eq!(
1241 Ok(()),
1242 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1243 );
1244 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1245
1246 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1248
1249 assert_eq!(
1251 Ok(()),
1252 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1253 );
1254
1255 let permission_check = security_server.as_permission_check(&local_cache);
1257
1258 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).granted);
1260 }
1261
1262 #[test]
1263 fn unknown_sids_are_effectively_unlabeled() {
1264 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1265 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy"
1266 )
1267 .to_vec();
1268 let with_additional_domain_policy_bytes =
1269 include_bytes!("../testdata/composite_policies/compiled/with_additional_domain_policy")
1270 .to_vec();
1271 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1272 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1273
1274 let security_server = SecurityServer::new_default();
1275 security_server.set_enforcing(true);
1276
1277 assert_eq!(
1280 Ok(()),
1281 security_server
1282 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1283 .map_err(|e| format!("{:?}", e))
1284 );
1285 let allowed_type_sid =
1286 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1287 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1288
1289 assert_eq!(
1292 Ok(()),
1293 security_server
1294 .load_policy(with_additional_domain_policy_bytes.clone())
1295 .map_err(|e| format!("{:?}", e))
1296 );
1297 let additional_type_sid =
1298 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1299 assert_eq!(
1300 allowed_type_sid,
1301 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1302 );
1303
1304 let local_cache = Default::default();
1305 let permission_check = security_server.as_permission_check(&local_cache);
1306
1307 assert!(
1311 !permission_check
1312 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1313 .granted
1314 );
1315 assert!(
1316 !permission_check
1317 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1318 .granted
1319 );
1320 assert!(
1321 !permission_check
1322 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1323 .granted
1324 );
1325 assert!(
1326 !permission_check
1327 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1328 .granted
1329 );
1330
1331 assert_eq!(
1333 Ok(()),
1334 security_server
1335 .load_policy(with_unlabeled_access_domain_policy_bytes)
1336 .map_err(|e| format!("{:?}", e))
1337 );
1338
1339 let permission_check = security_server.as_permission_check(&local_cache);
1341
1342 assert!(
1346 permission_check
1347 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1348 .granted
1349 );
1350 assert!(
1351 !permission_check
1352 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1353 .granted
1354 );
1355
1356 assert!(
1361 !permission_check
1362 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1363 .granted
1364 );
1365 assert!(
1366 permission_check
1367 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1368 .granted
1369 );
1370
1371 let unlabeled_context =
1374 security_server.sid_to_security_context(InitialSid::Unlabeled.into()).unwrap();
1375 assert_eq!(
1376 unlabeled_context,
1377 security_server.sid_to_security_context(additional_type_sid).unwrap()
1378 );
1379
1380 assert_eq!(
1383 Ok(()),
1384 security_server
1385 .load_policy(with_additional_domain_policy_bytes)
1386 .map_err(|e| format!("{:?}", e))
1387 );
1388 assert_eq!(
1389 additional_type_context.to_vec(),
1390 security_server.sid_to_security_context(additional_type_sid).unwrap()
1391 );
1392 }
1393
1394 #[test]
1395 fn permission_check_permissive() {
1396 let security_server = security_server_with_tests_policy();
1397 security_server.set_enforcing(false);
1398 assert!(!security_server.is_enforcing());
1399
1400 let sid =
1401 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1402 let local_cache = Default::default();
1403 let permission_check = security_server.as_permission_check(&local_cache);
1404
1405 assert_eq!(
1408 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1409 PermissionCheckResult {
1410 granted: true,
1411 audit: false,
1412 permissive: false,
1413 todo_bug: None
1414 }
1415 );
1416
1417 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1421 assert_eq!(
1422 result,
1423 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1424 );
1425 assert!(result.permit());
1426
1427 let result = permission_check.has_permission(
1431 sid,
1432 sid,
1433 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1434 );
1435 assert_eq!(
1436 result,
1437 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1438 );
1439 assert!(result.permit());
1440 }
1441
1442 #[test]
1443 fn permission_check_enforcing() {
1444 let security_server = security_server_with_tests_policy();
1445 security_server.set_enforcing(true);
1446 assert!(security_server.is_enforcing());
1447
1448 let sid =
1449 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1450 let local_cache = Default::default();
1451 let permission_check = security_server.as_permission_check(&local_cache);
1452
1453 let result = permission_check.has_permission(sid, sid, ProcessPermission::Fork);
1455 assert_eq!(
1456 result,
1457 PermissionCheckResult {
1458 granted: true,
1459 audit: false,
1460 permissive: false,
1461 todo_bug: None
1462 }
1463 );
1464 assert!(result.permit());
1465
1466 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit);
1469 assert_eq!(
1470 result,
1471 PermissionCheckResult {
1472 granted: false,
1473 audit: true,
1474 permissive: false,
1475 todo_bug: None
1476 }
1477 );
1478 assert!(!result.permit());
1479
1480 let result = permission_check.has_permission(
1483 sid,
1484 sid,
1485 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1486 );
1487 assert_eq!(
1488 result,
1489 PermissionCheckResult {
1490 granted: false,
1491 audit: true,
1492 permissive: false,
1493 todo_bug: None
1494 }
1495 );
1496 assert!(!result.permit());
1497 }
1498
1499 #[test]
1500 fn permissive_domain() {
1501 let security_server = security_server_with_tests_policy();
1502 security_server.set_enforcing(true);
1503 assert!(security_server.is_enforcing());
1504
1505 let permissive_sid = security_server
1506 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1507 .unwrap();
1508 let non_permissive_sid = security_server
1509 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1510 .unwrap();
1511
1512 let local_cache = Default::default();
1513 let permission_check = security_server.as_permission_check(&local_cache);
1514
1515 let result = permission_check.has_permission(
1517 permissive_sid,
1518 permissive_sid,
1519 ProcessPermission::GetSched,
1520 );
1521 assert_eq!(
1522 result,
1523 PermissionCheckResult { granted: true, audit: false, permissive: true, todo_bug: None }
1524 );
1525 assert!(result.permit());
1526 let result = permission_check.has_permission(
1527 non_permissive_sid,
1528 non_permissive_sid,
1529 ProcessPermission::GetSched,
1530 );
1531 assert_eq!(
1532 result,
1533 PermissionCheckResult {
1534 granted: true,
1535 audit: false,
1536 permissive: false,
1537 todo_bug: None
1538 }
1539 );
1540 assert!(result.permit());
1541
1542 let result = permission_check.has_permission(
1545 permissive_sid,
1546 non_permissive_sid,
1547 ProcessPermission::GetSched,
1548 );
1549 assert_eq!(
1550 result,
1551 PermissionCheckResult { granted: false, audit: true, permissive: true, todo_bug: None }
1552 );
1553 assert!(result.permit());
1554 let result = permission_check.has_permission(
1555 non_permissive_sid,
1556 permissive_sid,
1557 ProcessPermission::GetSched,
1558 );
1559 assert_eq!(
1560 result,
1561 PermissionCheckResult {
1562 granted: false,
1563 audit: true,
1564 permissive: false,
1565 todo_bug: None
1566 }
1567 );
1568 assert!(!result.permit());
1569
1570 let result = permission_check.has_permission(
1575 permissive_sid,
1576 non_permissive_sid,
1577 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1578 );
1579 assert_eq!(
1580 result,
1581 PermissionCheckResult { granted: false, audit: true, 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 CommonFsNodePermission::GetAttr.for_class(FileClass::BlkFile),
1588 );
1589 assert_eq!(
1590 result,
1591 PermissionCheckResult {
1592 granted: false,
1593 audit: true,
1594 permissive: false,
1595 todo_bug: None
1596 }
1597 );
1598 assert!(!result.permit());
1599 }
1600
1601 #[test]
1602 fn auditallow_and_dontaudit() {
1603 let security_server = security_server_with_tests_policy();
1604 security_server.set_enforcing(true);
1605 assert!(security_server.is_enforcing());
1606
1607 let audit_sid = security_server
1608 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1609 .unwrap();
1610
1611 let local_cache = Default::default();
1612 let permission_check = security_server.as_permission_check(&local_cache);
1613
1614 let result = permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork);
1616 assert_eq!(
1617 result,
1618 PermissionCheckResult { granted: true, audit: true, permissive: false, todo_bug: None }
1619 );
1620 assert!(result.permit());
1621
1622 let result =
1624 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched);
1625 assert_eq!(
1626 result,
1627 PermissionCheckResult {
1628 granted: true,
1629 audit: false,
1630 permissive: false,
1631 todo_bug: None
1632 }
1633 );
1634 assert!(result.permit());
1635
1636 let result =
1638 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched);
1639 assert_eq!(
1640 result,
1641 PermissionCheckResult {
1642 granted: false,
1643 audit: false,
1644 permissive: false,
1645 todo_bug: None
1646 }
1647 );
1648 assert!(!result.permit());
1649
1650 let result =
1652 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid);
1653 assert_eq!(
1654 result,
1655 PermissionCheckResult {
1656 granted: false,
1657 audit: true,
1658 permissive: false,
1659 todo_bug: None
1660 }
1661 );
1662 assert!(!result.permit());
1663 }
1664
1665 #[test]
1666 fn access_checks_with_exceptions_config() {
1667 const EXCEPTIONS_CONFIG: &[&str] = &[
1668 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1670 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1671 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1672 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1673 "todo_permissive b/005 test_exception_todo_permissive_t",
1674 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1676 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1677 "todo_permissive b/103 test_undefined_source_t",
1678 ];
1679 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1680 let security_server = SecurityServer::new(String::new(), exceptions_config);
1681 security_server.set_enforcing(true);
1682
1683 const EXCEPTIONS_POLICY: &[u8] =
1684 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy");
1685 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1686
1687 let source_sid = security_server
1688 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1689 .unwrap();
1690 let target_sid = security_server
1691 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1692 .unwrap();
1693 let other_sid = security_server
1694 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1695 .unwrap();
1696 let permissive_sid = security_server
1697 .security_context_to_sid(
1698 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1699 )
1700 .unwrap();
1701 let unmatched_sid = security_server
1702 .security_context_to_sid(
1703 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1704 )
1705 .unwrap();
1706 let todo_permissive_sid = security_server
1707 .security_context_to_sid(
1708 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1709 )
1710 .unwrap();
1711
1712 let local_cache = Default::default();
1713 let permission_check = security_server.as_permission_check(&local_cache);
1714
1715 let result =
1717 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid);
1718 assert_eq!(
1719 result,
1720 PermissionCheckResult {
1721 granted: false,
1722 audit: true,
1723 permissive: false,
1724 todo_bug: None
1725 }
1726 );
1727 assert!(!result.permit());
1728
1729 let result =
1731 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint);
1732 assert_eq!(
1733 result,
1734 PermissionCheckResult {
1735 granted: true,
1736 audit: true,
1737 permissive: false,
1738 todo_bug: Some(NonZeroU32::new(1).unwrap())
1739 }
1740 );
1741 assert!(result.permit());
1742
1743 let result =
1745 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans);
1746 assert_eq!(
1747 result,
1748 PermissionCheckResult {
1749 granted: true,
1750 audit: false,
1751 permissive: false,
1752 todo_bug: None,
1753 }
1754 );
1755 assert!(result.permit());
1756
1757 let result =
1759 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint);
1760 assert_eq!(
1761 result,
1762 PermissionCheckResult {
1763 granted: false,
1764 audit: true,
1765 permissive: false,
1766 todo_bug: None
1767 }
1768 );
1769 assert!(!result.permit());
1770
1771 let result = permission_check.has_permission(
1773 other_sid,
1774 target_sid,
1775 CommonFsNodePermission::Read.for_class(FileClass::ChrFile),
1776 );
1777 assert_eq!(
1778 result,
1779 PermissionCheckResult {
1780 granted: true,
1781 audit: true,
1782 permissive: false,
1783 todo_bug: Some(NonZeroU32::new(2).unwrap())
1784 }
1785 );
1786 assert!(result.permit());
1787
1788 let result =
1790 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint);
1791 assert_eq!(
1792 result,
1793 PermissionCheckResult {
1794 granted: false,
1795 audit: true,
1796 permissive: false,
1797 todo_bug: None
1798 }
1799 );
1800 assert!(!result.permit());
1801
1802 let result =
1804 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint);
1805 assert_eq!(
1806 result,
1807 PermissionCheckResult {
1808 granted: false,
1809 audit: true,
1810 permissive: false,
1811 todo_bug: None
1812 }
1813 );
1814 assert!(!result.permit());
1815
1816 let result =
1818 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint);
1819 assert_eq!(
1820 result,
1821 PermissionCheckResult {
1822 granted: true,
1823 audit: true,
1824 permissive: true,
1825 todo_bug: Some(NonZeroU32::new(4).unwrap())
1826 }
1827 );
1828 assert!(result.permit());
1829
1830 let result = permission_check.has_permission(
1833 todo_permissive_sid,
1834 target_sid,
1835 FilePermission::Entrypoint,
1836 );
1837 assert_eq!(
1838 result,
1839 PermissionCheckResult {
1840 granted: true,
1841 audit: true,
1842 permissive: false,
1843 todo_bug: Some(NonZeroU32::new(5).unwrap())
1844 }
1845 );
1846 assert!(result.permit());
1847 let result = permission_check.has_permission(
1848 todo_permissive_sid,
1849 todo_permissive_sid,
1850 FilePermission::Entrypoint,
1851 );
1852 assert_eq!(
1853 result,
1854 PermissionCheckResult {
1855 granted: true,
1856 audit: true,
1857 permissive: false,
1858 todo_bug: Some(NonZeroU32::new(5).unwrap())
1859 }
1860 );
1861 assert!(result.permit());
1862 let result = permission_check.has_permission(
1863 todo_permissive_sid,
1864 target_sid,
1865 FilePermission::Entrypoint,
1866 );
1867 assert_eq!(
1868 result,
1869 PermissionCheckResult {
1870 granted: true,
1871 audit: true,
1872 permissive: false,
1873 todo_bug: Some(NonZeroU32::new(5).unwrap())
1874 }
1875 );
1876 assert!(result.permit());
1877 }
1878
1879 #[test]
1880 fn handle_unknown() {
1881 let security_server = security_server_with_tests_policy();
1882
1883 let sid = security_server
1884 .security_context_to_sid("user0:object_r:type0:s0".into())
1885 .expect("Resolve Context to SID");
1886
1887 const REJECT_POLICY: &[u8] =
1891 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-reject");
1892 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1893
1894 security_server.set_enforcing(true);
1895
1896 const DENY_POLICY: &[u8] =
1898 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny");
1899 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1900 let local_cache = Default::default();
1901 let permission_check = security_server.as_permission_check(&local_cache);
1902
1903 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1905 assert_eq!(
1906 result,
1907 PermissionCheckResult {
1908 granted: false,
1909 audit: true,
1910 permissive: false,
1911 todo_bug: None
1912 }
1913 );
1914 assert!(!result.permit());
1915 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
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
1927 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1929 assert_eq!(
1930 result,
1931 PermissionCheckResult {
1932 granted: true,
1933 audit: false,
1934 permissive: false,
1935 todo_bug: None
1936 }
1937 );
1938 assert!(result.permit());
1939 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1940 assert_eq!(
1941 result,
1942 PermissionCheckResult {
1943 granted: false,
1944 audit: true,
1945 permissive: false,
1946 todo_bug: None
1947 }
1948 );
1949 assert!(!result.permit());
1950
1951 const ALLOW_POLICY: &[u8] =
1953 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-allow");
1954 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1955 let local_cache2 = Default::default();
1956 let permission_check = security_server.as_permission_check(&local_cache2);
1957
1958 let result = permission_check.has_permission(sid, sid, ProcessPermission::GetSched);
1960 assert_eq!(
1961 result,
1962 PermissionCheckResult {
1963 granted: true,
1964 audit: false,
1965 permissive: false,
1966 todo_bug: None
1967 }
1968 );
1969 assert!(result.permit());
1970 let result = permission_check.has_permission(sid, sid, DirPermission::AddName);
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
1982 let result = permission_check.has_permission(sid, sid, DirPermission::Search);
1984 assert_eq!(
1985 result,
1986 PermissionCheckResult {
1987 granted: true,
1988 audit: false,
1989 permissive: false,
1990 todo_bug: None
1991 }
1992 );
1993 assert!(result.permit());
1994
1995 let result = permission_check.has_permission(sid, sid, DirPermission::Reparent);
1996 assert_eq!(
1997 result,
1998 PermissionCheckResult {
1999 granted: false,
2000 audit: true,
2001 permissive: false,
2002 todo_bug: None
2003 }
2004 );
2005 assert!(!result.permit());
2006 }
2007}