1use crate::access_vector_cache::{AccessVectorCache, CacheStats, Query};
6use crate::exceptions_config::ExceptionsConfig;
7use crate::permission_check::PermissionCheck;
8use crate::policy::SecurityContext;
9use crate::policy::metadata::HandleUnknown;
10use crate::policy::parser::PolicyData;
11
12use crate::policy::{
13 AccessDecision, AccessVector, AccessVectorComputer, ClassId, ClassPermissionId,
14 FsUseLabelAndType, FsUseType, Policy, XpermsAccessDecision, XpermsKind, parse_policy_by_value,
15};
16use crate::sid_table::SidTable;
17use crate::sync::RwLock;
18use crate::{
19 ClassPermission, FileSystemLabel, FileSystemLabelingScheme, FileSystemMountOptions,
20 FileSystemMountSids, FsNodeClass, InitialSid, KernelPermission, NullessByteStr, ObjectClass,
21 PolicyCap, SeLinuxStatus, SeLinuxStatusPublisher, SecurityId,
22};
23
24use anyhow::Context as _;
25use std::collections::HashMap;
26use std::ops::DerefMut;
27use std::sync::Arc;
28
29const ROOT_PATH: &'static str = "/";
30
31struct ActivePolicy {
32 parsed: Arc<Policy>,
34
35 binary: PolicyData,
37
38 sid_table: SidTable,
40
41 exceptions: ExceptionsConfig,
43}
44
45#[derive(Default)]
46struct SeLinuxBooleans {
47 active: HashMap<String, bool>,
50 pending: HashMap<String, bool>,
52}
53
54impl SeLinuxBooleans {
55 fn reset(&mut self, booleans: Vec<(String, bool)>) {
56 self.active = HashMap::from_iter(booleans);
57 self.pending.clear();
58 }
59 fn names(&self) -> Vec<String> {
60 self.active.keys().cloned().collect()
61 }
62 fn set_pending(&mut self, name: &str, value: bool) -> Result<(), ()> {
63 if !self.active.contains_key(name) {
64 return Err(());
65 }
66 self.pending.insert(name.into(), value);
67 Ok(())
68 }
69 fn get(&self, name: &str) -> Result<(bool, bool), ()> {
70 let active = self.active.get(name).ok_or(())?;
71 let pending = self.pending.get(name).unwrap_or(active);
72 Ok((*active, *pending))
73 }
74 fn commit_pending(&mut self) {
75 self.active.extend(self.pending.drain());
76 }
77}
78
79struct SecurityServerState {
80 active_policy: Option<ActivePolicy>,
82
83 booleans: SeLinuxBooleans,
85
86 status_publisher: Option<Box<dyn SeLinuxStatusPublisher>>,
88
89 enforcing: bool,
91
92 policy_change_count: u32,
96}
97
98impl SecurityServerState {
99 fn deny_unknown(&self) -> bool {
100 self.active_policy
101 .as_ref()
102 .map_or(true, |p| p.parsed.handle_unknown() != HandleUnknown::Allow)
103 }
104 fn reject_unknown(&self) -> bool {
105 self.active_policy
106 .as_ref()
107 .map_or(false, |p| p.parsed.handle_unknown() == HandleUnknown::Reject)
108 }
109
110 fn expect_active_policy(&self) -> &ActivePolicy {
111 &self.active_policy.as_ref().expect("policy should be loaded")
112 }
113
114 fn expect_active_policy_mut(&mut self) -> &mut ActivePolicy {
115 self.active_policy.as_mut().expect("policy should be loaded")
116 }
117}
118
119pub(crate) struct SecurityServerBackend {
120 state: RwLock<SecurityServerState>,
122}
123
124pub struct SecurityServer {
125 access_vector_cache: AccessVectorCache,
128
129 backend: Arc<SecurityServerBackend>,
131
132 exceptions: Vec<String>,
134}
135
136impl SecurityServer {
137 pub fn new_default() -> Arc<Self> {
139 Self::new(String::new(), Vec::new())
140 }
141
142 pub fn new(options: String, exceptions: Vec<String>) -> Arc<Self> {
144 assert_eq!(options, String::new());
146
147 let backend = Arc::new(SecurityServerBackend {
148 state: RwLock::new(SecurityServerState {
149 active_policy: None,
150 booleans: SeLinuxBooleans::default(),
151 status_publisher: None,
152 enforcing: false,
153 policy_change_count: 0,
154 }),
155 });
156
157 let access_vector_cache = AccessVectorCache::new(backend.clone());
158
159 Arc::new(Self { access_vector_cache, backend, exceptions })
160 }
161
162 pub fn as_permission_check<'a>(self: &'a Self) -> PermissionCheck<'a> {
165 PermissionCheck::new(self, &self.access_vector_cache)
166 }
167
168 pub fn security_context_to_sid(
172 &self,
173 security_context: NullessByteStr<'_>,
174 ) -> Result<SecurityId, anyhow::Error> {
175 let mut locked_state = self.backend.state.write();
176 let active_policy = locked_state
177 .active_policy
178 .as_mut()
179 .ok_or_else(|| anyhow::anyhow!("no policy loaded"))?;
180 let context = active_policy
181 .parsed
182 .parse_security_context(security_context)
183 .map_err(anyhow::Error::from)?;
184 active_policy.sid_table.security_context_to_sid(&context).map_err(anyhow::Error::from)
185 }
186
187 pub fn sid_to_security_context(&self, sid: SecurityId) -> Option<Vec<u8>> {
192 let locked_state = self.backend.state.read();
193 let active_policy = locked_state.active_policy.as_ref()?;
194 let context = active_policy.sid_table.try_sid_to_security_context(sid)?;
195 Some(active_policy.parsed.serialize_security_context(context))
196 }
197
198 pub fn sid_to_security_context_with_nul(&self, sid: SecurityId) -> Option<Vec<u8>> {
200 self.sid_to_security_context(sid).map(|mut context| {
201 context.push(0u8);
202 context
203 })
204 }
205
206 pub fn load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
208 let unvalidated_policy = parse_policy_by_value(binary_policy)?;
211 let parsed = Arc::new(unvalidated_policy.validate()?);
212 let binary = parsed.binary().clone();
213
214 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
215 let exceptions = ExceptionsConfig::new(&parsed, &exceptions)?;
216
217 self.with_state_and_update_status(|state| {
219 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
220 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
221 } else {
222 SidTable::new(parsed.clone())
223 };
224
225 state.booleans.reset(
228 parsed
229 .conditional_booleans()
230 .iter()
231 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
233 .collect(),
234 );
235
236 state.active_policy = Some(ActivePolicy { parsed, binary, sid_table, exceptions });
237 state.policy_change_count += 1;
238 });
239
240 self.access_vector_cache.reset();
243
244 Ok(())
245 }
246
247 pub fn get_binary_policy(&self) -> Option<PolicyData> {
249 self.backend.state.read().active_policy.as_ref().map(|p| p.binary.clone())
250 }
251
252 pub fn policy_version(&self) -> Option<u32> {
253 self.backend.state.read().active_policy.as_ref().map(|p|p.parsed.policy_version())
254 }
255
256 pub fn set_enforcing(&self, enforcing: bool) {
258 self.with_state_and_update_status(|state| state.enforcing = enforcing);
259 }
260
261 pub fn is_enforcing(&self) -> bool {
262 self.backend.state.read().enforcing
263 }
264
265 pub fn deny_unknown(&self) -> bool {
268 self.backend.state.read().deny_unknown()
269 }
270
271 pub fn reject_unknown(&self) -> bool {
274 self.backend.state.read().reject_unknown()
275 }
276
277 pub fn conditional_booleans(&self) -> Vec<String> {
280 self.backend.state.read().booleans.names()
281 }
282
283 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
285 self.backend.state.read().booleans.get(name)
286 }
287
288 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
290 self.backend.state.write().booleans.set_pending(name, value)
291 }
292
293 pub fn commit_pending_booleans(&self) {
295 self.with_state_and_update_status(|state| {
297 state.booleans.commit_pending();
298 state.policy_change_count += 1;
299 });
300 }
301
302 pub fn is_policycap_enabled(&self, policy_cap: PolicyCap) -> bool {
304 let locked_state = self.backend.state.read();
305 let Some(policy) = &locked_state.active_policy else {
306 return false;
307 };
308 policy.parsed.has_policycap(policy_cap)
309 }
310
311 pub fn avc_cache_stats(&self) -> CacheStats {
313 self.access_vector_cache.cache_stats()
314 }
315
316 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
318 let locked_state = self.backend.state.read();
319 let names = locked_state
320 .expect_active_policy()
321 .parsed
322 .classes()
323 .iter()
324 .map(|class| class.class_name.to_vec())
325 .collect();
326 Ok(names)
327 }
328
329 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
331 let locked_state = self.backend.state.read();
332 Ok(locked_state
333 .expect_active_policy()
334 .parsed
335 .classes()
336 .iter()
337 .find(|class| class.class_name == name.as_bytes())
338 .ok_or(())?
339 .class_id)
340 }
341
342 pub fn class_permissions_by_name(
346 &self,
347 name: &str,
348 ) -> Result<Vec<(ClassPermissionId, Vec<u8>)>, ()> {
349 let locked_state = self.backend.state.read();
350 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
351 }
352
353 pub fn resolve_fs_label(
357 &self,
358 fs_type: NullessByteStr<'_>,
359 mount_options: &FileSystemMountOptions,
360 ) -> FileSystemLabel {
361 let mut locked_state = self.backend.state.write();
362 let active_policy = locked_state.expect_active_policy_mut();
363
364 let mount_sids = FileSystemMountSids {
365 context: sid_from_mount_option(active_policy, &mount_options.context),
366 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context),
367 def_context: sid_from_mount_option(active_policy, &mount_options.def_context),
368 root_context: sid_from_mount_option(active_policy, &mount_options.root_context),
369 };
370 if let Some(mountpoint_sid) = mount_sids.context {
371 FileSystemLabel {
375 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
376 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
377 mount_sids,
378 }
379 } else if let Some(FsUseLabelAndType { context, use_type }) =
380 active_policy.parsed.fs_use_label_and_type(fs_type)
381 {
382 let fs_sid_from_policy =
384 active_policy.sid_table.security_context_to_sid(&context).unwrap();
385 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
386 FileSystemLabel {
387 sid: fs_sid,
388 scheme: FileSystemLabelingScheme::FsUse {
389 fs_use_type: use_type,
390 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
391 },
392 mount_sids,
393 }
394 } else if let Some(context) =
395 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
396 {
397 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
399 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
400 FileSystemLabel { sid: fs_sid, scheme: FileSystemLabelingScheme::GenFsCon, mount_sids }
401 } else {
402 FileSystemLabel {
404 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
405 scheme: FileSystemLabelingScheme::FsUse {
406 fs_use_type: FsUseType::Xattr,
407 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
408 },
409 mount_sids,
410 }
411 }
412 }
413
414 pub fn genfscon_label_for_fs_and_path(
418 &self,
419 fs_type: NullessByteStr<'_>,
420 node_path: NullessByteStr<'_>,
421 class_id: Option<ClassId>,
422 ) -> Option<SecurityId> {
423 let mut locked_state = self.backend.state.write();
424 let active_policy = locked_state.expect_active_policy_mut();
425 let security_context = active_policy.parsed.genfscon_label_for_fs_and_path(
426 fs_type,
427 node_path.into(),
428 class_id,
429 )?;
430 Some(active_policy.sid_table.security_context_to_sid(&security_context).unwrap())
431 }
432
433 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
438 let locked_state = self.backend.state.read();
439 let active_policy = locked_state.expect_active_policy();
440 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
441 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
442 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
443 }
444
445 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
452 self.with_state_and_update_status(|state| {
453 assert!(state.status_publisher.is_none());
454 state.status_publisher = Some(status_holder);
455 });
456 }
457
458 fn with_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
461 let mut locked_state = self.backend.state.write();
462 f(locked_state.deref_mut());
463 let new_value = SeLinuxStatus {
464 is_enforcing: locked_state.enforcing,
465 change_count: locked_state.policy_change_count,
466 deny_unknown: locked_state.deny_unknown(),
467 };
468 if let Some(status_publisher) = &mut locked_state.status_publisher {
469 status_publisher.set_status(new_value);
470 }
471 }
472
473 pub fn compute_create_sid(
478 &self,
479 source_sid: SecurityId,
480 target_sid: SecurityId,
481 target_class: impl Into<ObjectClass>,
482 ) -> Result<SecurityId, anyhow::Error> {
483 self.backend.compute_create_sid(source_sid, target_sid, target_class)
484 }
485
486 pub fn transform_memfd_sid(&self, original_sid: SecurityId) -> Option<SecurityId> {
489 self.backend.transform_memfd_sid(original_sid)
490 }
491}
492
493impl SecurityServerBackend {
494 fn compute_create_sid(
495 &self,
496 source_sid: SecurityId,
497 target_sid: SecurityId,
498 target_class: impl Into<ObjectClass>,
499 ) -> Result<SecurityId, anyhow::Error> {
500 let mut locked_state = self.state.write();
501 let active_policy = locked_state.expect_active_policy_mut();
502
503 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
504 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
505
506 let security_context = active_policy.parsed.compute_create_context(
507 source_context,
508 target_context,
509 target_class.into(),
510 );
511
512 active_policy
513 .sid_table
514 .security_context_to_sid(&security_context)
515 .map_err(anyhow::Error::from)
516 .context("computing new security context from policy")
517 }
518
519 fn transform_memfd_sid(&self, original_sid: SecurityId) -> Option<SecurityId> {
521 let mut locked_state = self.state.write();
522 let active_policy = locked_state.active_policy.as_mut()?;
523 let new_type_id = active_policy.exceptions.memfd_type_override?;
524 let original_security_context =
525 active_policy.sid_table.sid_to_security_context(original_sid);
526 let new_security_context = SecurityContext::new(
527 original_security_context.user(),
528 original_security_context.role(),
529 new_type_id,
530 original_security_context.low_level().clone(),
531 original_security_context.high_level().cloned(),
532 );
533 active_policy.sid_table.security_context_to_sid(&new_security_context).ok()
534 }
535}
536
537impl Query for SecurityServerBackend {
538 fn compute_access_decision(
539 &self,
540 source_sid: SecurityId,
541 target_sid: SecurityId,
542 target_class: ObjectClass,
543 ) -> AccessDecision {
544 let locked_state = self.state.read();
545
546 let active_policy = match &locked_state.active_policy {
547 Some(active_policy) => active_policy,
548 None => return AccessDecision::allow(AccessVector::ALL),
550 };
551
552 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
553 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
554
555 let mut decision = active_policy.parsed.compute_access_decision(
556 &source_context,
557 &target_context,
558 target_class,
559 );
560
561 decision.todo_bug = active_policy.exceptions.lookup(
562 source_context.type_(),
563 target_context.type_(),
564 target_class,
565 );
566
567 decision
568 }
569
570 fn compute_new_fs_node_sid(
571 &self,
572 source_sid: SecurityId,
573 target_sid: SecurityId,
574 fs_node_class: FsNodeClass,
575 ) -> Result<SecurityId, anyhow::Error> {
576 self.compute_create_sid(source_sid, target_sid, fs_node_class)
577 }
578
579 fn compute_new_fs_node_sid_with_name(
580 &self,
581 source_sid: SecurityId,
582 target_sid: SecurityId,
583 fs_node_class: FsNodeClass,
584 fs_node_name: NullessByteStr<'_>,
585 ) -> Option<SecurityId> {
586 let mut locked_state = self.state.write();
587
588 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
590
591 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
592 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
593
594 let new_file_context = active_policy.parsed.compute_create_context_with_name(
595 source_context,
596 target_context,
597 fs_node_class,
598 fs_node_name,
599 )?;
600
601 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
602 }
603
604 fn compute_xperms_access_decision(
605 &self,
606 xperms_kind: XpermsKind,
607 source_sid: SecurityId,
608 target_sid: SecurityId,
609 target_class: ObjectClass,
610 xperms_prefix: u8,
611 ) -> XpermsAccessDecision {
612 let locked_state = self.state.read();
613
614 let active_policy = match &locked_state.active_policy {
615 Some(active_policy) => active_policy,
616 None => return XpermsAccessDecision::ALLOW_ALL,
618 };
619
620 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
621 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
622
623 active_policy.parsed.compute_xperms_access_decision(
624 xperms_kind,
625 &source_context,
626 &target_context,
627 target_class,
628 xperms_prefix,
629 )
630 }
631}
632
633impl AccessVectorComputer for SecurityServer {
634 fn access_vector_from_permissions<
635 P: ClassPermission + Into<KernelPermission> + Clone + 'static,
636 >(
637 &self,
638 permissions: &[P],
639 ) -> Option<AccessVector> {
640 match &self.backend.state.read().active_policy {
641 Some(policy) => policy.parsed.access_vector_from_permissions(permissions),
642 None => Some(AccessVector::NONE),
643 }
644 }
645}
646
647fn sid_from_mount_option(
650 active_policy: &mut ActivePolicy,
651 mount_option: &Option<Vec<u8>>,
652) -> Option<SecurityId> {
653 if let Some(label) = mount_option.as_ref() {
654 Some(
655 if let Some(context) = active_policy.parsed.parse_security_context(label.into()).ok() {
656 active_policy.sid_table.security_context_to_sid(&context).unwrap()
657 } else {
658 InitialSid::Unlabeled.into()
660 },
661 )
662 } else {
663 None
664 }
665}
666
667#[cfg(test)]
668mod tests {
669 use super::*;
670 use crate::permission_check::PermissionCheckResult;
671 use crate::{
672 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
673 ProcessPermission,
674 };
675 use std::num::NonZeroU64;
676
677 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
678 const TESTS_BINARY_POLICY: &[u8] =
679 include_bytes!("../testdata/micro_policies/security_server_tests_policy.pp");
680 const MINIMAL_BINARY_POLICY: &[u8] =
681 include_bytes!("../testdata/composite_policies/compiled/minimal_policy.pp");
682
683 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
684 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
685 let security_server = SecurityServer::new_default();
686 assert_eq!(
687 Ok(()),
688 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
689 );
690 security_server
691 }
692
693 #[test]
694 fn compute_access_vector_allows_all() {
695 let security_server = SecurityServer::new_default();
696 let sid1 = InitialSid::Kernel.into();
697 let sid2 = InitialSid::Unlabeled.into();
698 assert_eq!(
699 security_server
700 .backend
701 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
702 .allow,
703 AccessVector::ALL
704 );
705 }
706
707 #[test]
708 fn loaded_policy_can_be_retrieved() {
709 let security_server = security_server_with_tests_policy();
710 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_slice());
711 }
712
713 #[test]
714 fn loaded_policy_is_validated() {
715 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
716 let security_server = SecurityServer::new_default();
717 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
718 }
719
720 #[test]
721 fn enforcing_mode_is_reported() {
722 let security_server = SecurityServer::new_default();
723 assert!(!security_server.is_enforcing());
724
725 security_server.set_enforcing(true);
726 assert!(security_server.is_enforcing());
727 }
728
729 #[test]
730 fn without_policy_conditional_booleans_are_empty() {
731 let security_server = SecurityServer::new_default();
732 assert!(security_server.conditional_booleans().is_empty());
733 }
734
735 #[test]
736 fn conditional_booleans_can_be_queried() {
737 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
738 let security_server = SecurityServer::new_default();
739 assert_eq!(
740 Ok(()),
741 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
742 );
743
744 let booleans = security_server.conditional_booleans();
745 assert!(!booleans.is_empty());
746 let boolean = booleans[0].as_str();
747
748 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
749 assert!(security_server.get_boolean(boolean).is_ok());
750 }
751
752 #[test]
753 fn conditional_booleans_can_be_changed() {
754 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
755 let security_server = SecurityServer::new_default();
756 assert_eq!(
757 Ok(()),
758 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
759 );
760
761 let booleans = security_server.conditional_booleans();
762 assert!(!booleans.is_empty());
763 let boolean = booleans[0].as_str();
764
765 let (active, pending) = security_server.get_boolean(boolean).unwrap();
766 assert_eq!(active, pending, "Initially active and pending values should match");
767
768 security_server.set_pending_boolean(boolean, !active).unwrap();
769 let (active, pending) = security_server.get_boolean(boolean).unwrap();
770 assert!(active != pending, "Before commit pending should differ from active");
771
772 security_server.commit_pending_booleans();
773 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
774 assert_eq!(final_active, pending, "Pending value should be active after commit");
775 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
776 }
777
778 #[test]
779 fn parse_security_context_no_policy() {
780 let security_server = SecurityServer::new_default();
781 let error = security_server
782 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
783 .expect_err("expected error");
784 let error_string = format!("{:?}", error);
785 assert!(error_string.contains("no policy"));
786 }
787
788 #[test]
789 fn compute_new_fs_node_sid_no_defaults() {
790 let security_server = SecurityServer::new_default();
791 let policy_bytes =
792 include_bytes!("../testdata/micro_policies/file_no_defaults_policy.pp").to_vec();
793 security_server.load_policy(policy_bytes).expect("binary policy loads");
794
795 let source_sid = security_server
796 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
797 .expect("creating SID from security context should succeed");
798 let target_sid = security_server
799 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
800 .expect("creating SID from security context should succeed");
801
802 let computed_sid = security_server
803 .as_permission_check()
804 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
805 .expect("new sid computed");
806 let computed_context = security_server
807 .sid_to_security_context(computed_sid)
808 .expect("computed sid associated with context");
809
810 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
813 }
814
815 #[test]
816 fn compute_new_fs_node_sid_source_defaults() {
817 let security_server = SecurityServer::new_default();
818 let policy_bytes =
819 include_bytes!("../testdata/micro_policies/file_source_defaults_policy.pp").to_vec();
820 security_server.load_policy(policy_bytes).expect("binary policy loads");
821
822 let source_sid = security_server
823 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
824 .expect("creating SID from security context should succeed");
825 let target_sid = security_server
826 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
827 .expect("creating SID from security context should succeed");
828
829 let computed_sid = security_server
830 .as_permission_check()
831 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
832 .expect("new sid computed");
833 let computed_context = security_server
834 .sid_to_security_context(computed_sid)
835 .expect("computed sid associated with context");
836
837 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
840 }
841
842 #[test]
843 fn compute_new_fs_node_sid_target_defaults() {
844 let security_server = SecurityServer::new_default();
845 let policy_bytes =
846 include_bytes!("../testdata/micro_policies/file_target_defaults_policy.pp").to_vec();
847 security_server.load_policy(policy_bytes).expect("binary policy loads");
848
849 let source_sid = security_server
850 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
851 .expect("creating SID from security context should succeed");
852 let target_sid = security_server
853 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
854 .expect("creating SID from security context should succeed");
855
856 let computed_sid = security_server
857 .as_permission_check()
858 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
859 .expect("new sid computed");
860 let computed_context = security_server
861 .sid_to_security_context(computed_sid)
862 .expect("computed sid associated with context");
863
864 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
866 }
867
868 #[test]
869 fn compute_new_fs_node_sid_range_source_low_default() {
870 let security_server = SecurityServer::new_default();
871 let policy_bytes =
872 include_bytes!("../testdata/micro_policies/file_range_source_low_policy.pp").to_vec();
873 security_server.load_policy(policy_bytes).expect("binary policy loads");
874
875 let source_sid = security_server
876 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
877 .expect("creating SID from security context should succeed");
878 let target_sid = security_server
879 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
880 .expect("creating SID from security context should succeed");
881
882 let computed_sid = security_server
883 .as_permission_check()
884 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
885 .expect("new sid computed");
886 let computed_context = security_server
887 .sid_to_security_context(computed_sid)
888 .expect("computed sid associated with context");
889
890 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
892 }
893
894 #[test]
895 fn compute_new_fs_node_sid_range_source_low_high_default() {
896 let security_server = SecurityServer::new_default();
897 let policy_bytes =
898 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy.pp")
899 .to_vec();
900 security_server.load_policy(policy_bytes).expect("binary policy loads");
901
902 let source_sid = security_server
903 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
904 .expect("creating SID from security context should succeed");
905 let target_sid = security_server
906 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
907 .expect("creating SID from security context should succeed");
908
909 let computed_sid = security_server
910 .as_permission_check()
911 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
912 .expect("new sid computed");
913 let computed_context = security_server
914 .sid_to_security_context(computed_sid)
915 .expect("computed sid associated with context");
916
917 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
919 }
920
921 #[test]
922 fn compute_new_fs_node_sid_range_source_high_default() {
923 let security_server = SecurityServer::new_default();
924 let policy_bytes =
925 include_bytes!("../testdata/micro_policies/file_range_source_high_policy.pp").to_vec();
926 security_server.load_policy(policy_bytes).expect("binary policy loads");
927
928 let source_sid = security_server
929 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
930 .expect("creating SID from security context should succeed");
931 let target_sid = security_server
932 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
933 .expect("creating SID from security context should succeed");
934
935 let computed_sid = security_server
936 .as_permission_check()
937 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
938 .expect("new sid computed");
939 let computed_context = security_server
940 .sid_to_security_context(computed_sid)
941 .expect("computed sid associated with context");
942
943 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
945 }
946
947 #[test]
948 fn compute_new_fs_node_sid_range_target_low_default() {
949 let security_server = SecurityServer::new_default();
950 let policy_bytes =
951 include_bytes!("../testdata/micro_policies/file_range_target_low_policy.pp").to_vec();
952 security_server.load_policy(policy_bytes).expect("binary policy loads");
953
954 let source_sid = security_server
955 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
956 .expect("creating SID from security context should succeed");
957 let target_sid = security_server
958 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
959 .expect("creating SID from security context should succeed");
960
961 let computed_sid = security_server
962 .as_permission_check()
963 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
964 .expect("new sid computed");
965 let computed_context = security_server
966 .sid_to_security_context(computed_sid)
967 .expect("computed sid associated with context");
968
969 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
971 }
972
973 #[test]
974 fn compute_new_fs_node_sid_range_target_low_high_default() {
975 let security_server = SecurityServer::new_default();
976 let policy_bytes =
977 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy.pp")
978 .to_vec();
979 security_server.load_policy(policy_bytes).expect("binary policy loads");
980
981 let source_sid = security_server
982 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
983 .expect("creating SID from security context should succeed");
984 let target_sid = security_server
985 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
986 .expect("creating SID from security context should succeed");
987
988 let computed_sid = security_server
989 .as_permission_check()
990 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
991 .expect("new sid computed");
992 let computed_context = security_server
993 .sid_to_security_context(computed_sid)
994 .expect("computed sid associated with context");
995
996 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
998 }
999
1000 #[test]
1001 fn compute_new_fs_node_sid_range_target_high_default() {
1002 let security_server = SecurityServer::new_default();
1003 let policy_bytes =
1004 include_bytes!("../testdata/micro_policies/file_range_target_high_policy.pp").to_vec();
1005 security_server.load_policy(policy_bytes).expect("binary policy loads");
1006
1007 let source_sid = security_server
1008 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
1009 .expect("creating SID from security context should succeed");
1010 let target_sid = security_server
1011 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
1012 .expect("creating SID from security context should succeed");
1013
1014 let computed_sid = security_server
1015 .as_permission_check()
1016 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1017 .expect("new sid computed");
1018 let computed_context = security_server
1019 .sid_to_security_context(computed_sid)
1020 .expect("computed sid associated with context");
1021
1022 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1024 }
1025
1026 #[test]
1027 fn compute_new_fs_node_sid_with_name() {
1028 let security_server = SecurityServer::new_default();
1029 let policy_bytes =
1030 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy.pp")
1031 .to_vec();
1032 security_server.load_policy(policy_bytes).expect("binary policy loads");
1033
1034 let source_sid = security_server
1035 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1036 .expect("creating SID from security context should succeed");
1037 let target_sid = security_server
1038 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1039 .expect("creating SID from security context should succeed");
1040
1041 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1042 let computed_sid = security_server
1043 .as_permission_check()
1044 .compute_new_fs_node_sid(
1045 source_sid,
1046 target_sid,
1047 FileClass::File.into(),
1048 SPECIAL_FILE_NAME.into(),
1049 )
1050 .expect("new sid computed");
1051 let computed_context = security_server
1052 .sid_to_security_context(computed_sid)
1053 .expect("computed sid associated with context");
1054
1055 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1057
1058 let computed_sid = security_server
1059 .as_permission_check()
1060 .compute_new_fs_node_sid(
1061 source_sid,
1062 target_sid,
1063 FileClass::Character.into(),
1064 SPECIAL_FILE_NAME.into(),
1065 )
1066 .expect("new sid computed");
1067 let computed_context = security_server
1068 .sid_to_security_context(computed_sid)
1069 .expect("computed sid associated with context");
1070
1071 assert_eq!(computed_context, b"source_u:object_r:target_t:s0");
1074
1075 const OTHER_FILE_NAME: &[u8] = b"other_file";
1076 let computed_sid = security_server
1077 .as_permission_check()
1078 .compute_new_fs_node_sid(
1079 source_sid,
1080 target_sid,
1081 FileClass::File.into(),
1082 OTHER_FILE_NAME.into(),
1083 )
1084 .expect("new sid computed");
1085 let computed_context = security_server
1086 .sid_to_security_context(computed_sid)
1087 .expect("computed sid associated with context");
1088
1089 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1092 }
1093
1094 #[test]
1095 fn permissions_are_fresh_after_different_policy_load() {
1096 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1097 let allow_fork_bytes =
1098 include_bytes!("../testdata/composite_policies/compiled/allow_fork.pp").to_vec();
1099 let context = b"source_u:object_r:source_t:s0:c0";
1100
1101 let security_server = SecurityServer::new_default();
1102 security_server.set_enforcing(true);
1103
1104 let permission_check = security_server.as_permission_check();
1105
1106 assert_eq!(
1108 Ok(()),
1109 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1110 );
1111 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1112
1113 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1115
1116 assert_eq!(
1118 Ok(()),
1119 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1120 );
1121
1122 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1124 }
1125
1126 #[test]
1127 fn unknown_sids_are_effectively_unlabeled() {
1128 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1129 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy.pp"
1130 )
1131 .to_vec();
1132 let with_additional_domain_policy_bytes = include_bytes!(
1133 "../testdata/composite_policies/compiled/with_additional_domain_policy.pp"
1134 )
1135 .to_vec();
1136 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1137 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1138
1139 let security_server = SecurityServer::new_default();
1140 security_server.set_enforcing(true);
1141
1142 assert_eq!(
1145 Ok(()),
1146 security_server
1147 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1148 .map_err(|e| format!("{:?}", e))
1149 );
1150 let allowed_type_sid =
1151 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1152 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1153
1154 assert_eq!(
1157 Ok(()),
1158 security_server
1159 .load_policy(with_additional_domain_policy_bytes.clone())
1160 .map_err(|e| format!("{:?}", e))
1161 );
1162 let additional_type_sid =
1163 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1164 assert_eq!(
1165 allowed_type_sid,
1166 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1167 );
1168
1169 let permission_check = security_server.as_permission_check();
1170
1171 assert!(
1175 !permission_check
1176 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1177 .permit
1178 );
1179 assert!(
1180 !permission_check
1181 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1182 .permit
1183 );
1184 assert!(
1185 !permission_check
1186 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1187 .permit
1188 );
1189 assert!(
1190 !permission_check
1191 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1192 .permit
1193 );
1194
1195 assert_eq!(
1197 Ok(()),
1198 security_server
1199 .load_policy(with_unlabeled_access_domain_policy_bytes)
1200 .map_err(|e| format!("{:?}", e))
1201 );
1202
1203 assert!(
1207 permission_check
1208 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1209 .permit
1210 );
1211 assert!(
1212 !permission_check
1213 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1214 .permit
1215 );
1216
1217 assert!(
1222 !permission_check
1223 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1224 .permit
1225 );
1226 assert!(
1227 permission_check
1228 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1229 .permit
1230 );
1231
1232 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1234
1235 assert_eq!(
1238 Ok(()),
1239 security_server
1240 .load_policy(with_additional_domain_policy_bytes)
1241 .map_err(|e| format!("{:?}", e))
1242 );
1243 assert_eq!(
1244 additional_type_context.to_vec(),
1245 security_server.sid_to_security_context(additional_type_sid).unwrap()
1246 );
1247 }
1248
1249 #[test]
1250 fn permission_check_permissive() {
1251 let security_server = security_server_with_tests_policy();
1252 security_server.set_enforcing(false);
1253 assert!(!security_server.is_enforcing());
1254
1255 let sid =
1256 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1257 let permission_check = security_server.as_permission_check();
1258
1259 assert_eq!(
1262 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1263 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1264 );
1265
1266 assert_eq!(
1270 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1271 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1272 );
1273
1274 assert_eq!(
1278 permission_check.has_permission(
1279 sid,
1280 sid,
1281 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1282 ),
1283 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1284 );
1285 }
1286
1287 #[test]
1288 fn permission_check_enforcing() {
1289 let security_server = security_server_with_tests_policy();
1290 security_server.set_enforcing(true);
1291 assert!(security_server.is_enforcing());
1292
1293 let sid =
1294 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1295 let permission_check = security_server.as_permission_check();
1296
1297 assert_eq!(
1299 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1300 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1301 );
1302
1303 assert_eq!(
1306 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1307 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1308 );
1309
1310 assert_eq!(
1313 permission_check.has_permission(
1314 sid,
1315 sid,
1316 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1317 ),
1318 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1319 );
1320 }
1321
1322 #[test]
1323 fn permissive_domain() {
1324 let security_server = security_server_with_tests_policy();
1325 security_server.set_enforcing(true);
1326 assert!(security_server.is_enforcing());
1327
1328 let permissive_sid = security_server
1329 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1330 .unwrap();
1331 let non_permissive_sid = security_server
1332 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1333 .unwrap();
1334
1335 let permission_check = security_server.as_permission_check();
1336
1337 assert_eq!(
1339 permission_check.has_permission(
1340 permissive_sid,
1341 permissive_sid,
1342 ProcessPermission::GetSched
1343 ),
1344 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1345 );
1346 assert_eq!(
1347 permission_check.has_permission(
1348 non_permissive_sid,
1349 non_permissive_sid,
1350 ProcessPermission::GetSched
1351 ),
1352 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1353 );
1354
1355 assert_eq!(
1358 permission_check.has_permission(
1359 permissive_sid,
1360 non_permissive_sid,
1361 ProcessPermission::GetSched
1362 ),
1363 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1364 );
1365 assert_eq!(
1366 permission_check.has_permission(
1367 non_permissive_sid,
1368 permissive_sid,
1369 ProcessPermission::GetSched
1370 ),
1371 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1372 );
1373
1374 assert_eq!(
1379 permission_check.has_permission(
1380 permissive_sid,
1381 non_permissive_sid,
1382 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1383 ),
1384 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1385 );
1386 assert_eq!(
1387 permission_check.has_permission(
1388 non_permissive_sid,
1389 non_permissive_sid,
1390 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1391 ),
1392 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1393 );
1394 }
1395
1396 #[test]
1397 fn auditallow_and_dontaudit() {
1398 let security_server = security_server_with_tests_policy();
1399 security_server.set_enforcing(true);
1400 assert!(security_server.is_enforcing());
1401
1402 let audit_sid = security_server
1403 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1404 .unwrap();
1405
1406 let permission_check = security_server.as_permission_check();
1407
1408 assert_eq!(
1410 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork),
1411 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1412 );
1413
1414 assert_eq!(
1416 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched),
1417 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1418 );
1419
1420 assert_eq!(
1422 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched),
1423 PermissionCheckResult { permit: false, audit: false, todo_bug: None }
1424 );
1425
1426 assert_eq!(
1428 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid),
1429 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1430 );
1431 }
1432
1433 #[test]
1434 fn access_checks_with_exceptions_config() {
1435 const EXCEPTIONS_CONFIG: &[&str] = &[
1436 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1438 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1439 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1440 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1441 "todo_permissive b/005 test_exception_todo_permissive_t",
1442 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1444 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1445 "todo_permissive b/103 test_undefined_source_t",
1446 ];
1447 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1448 let security_server = SecurityServer::new(String::new(), exceptions_config);
1449 security_server.set_enforcing(true);
1450
1451 const EXCEPTIONS_POLICY: &[u8] =
1452 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1453 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1454
1455 let source_sid = security_server
1456 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1457 .unwrap();
1458 let target_sid = security_server
1459 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1460 .unwrap();
1461 let other_sid = security_server
1462 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1463 .unwrap();
1464 let permissive_sid = security_server
1465 .security_context_to_sid(
1466 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1467 )
1468 .unwrap();
1469 let unmatched_sid = security_server
1470 .security_context_to_sid(
1471 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1472 )
1473 .unwrap();
1474 let todo_permissive_sid = security_server
1475 .security_context_to_sid(
1476 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1477 )
1478 .unwrap();
1479
1480 let permission_check = security_server.as_permission_check();
1481
1482 assert_eq!(
1484 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid),
1485 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1486 );
1487
1488 assert_eq!(
1490 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint),
1491 PermissionCheckResult {
1492 permit: true,
1493 audit: true,
1494 todo_bug: Some(NonZeroU64::new(1).unwrap())
1495 }
1496 );
1497
1498 assert_eq!(
1500 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans),
1501 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1502 );
1503
1504 assert_eq!(
1506 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint),
1507 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1508 );
1509
1510 assert_eq!(
1512 permission_check.has_permission(
1513 other_sid,
1514 target_sid,
1515 CommonFsNodePermission::Read.for_class(FileClass::Character)
1516 ),
1517 PermissionCheckResult {
1518 permit: true,
1519 audit: true,
1520 todo_bug: Some(NonZeroU64::new(2).unwrap())
1521 }
1522 );
1523
1524 assert_eq!(
1526 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint),
1527 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1528 );
1529
1530 assert_eq!(
1532 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint),
1533 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1534 );
1535
1536 assert_eq!(
1538 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint),
1539 PermissionCheckResult {
1540 permit: true,
1541 audit: true,
1542 todo_bug: Some(NonZeroU64::new(4).unwrap())
1543 }
1544 );
1545
1546 assert_eq!(
1549 permission_check.has_permission(
1550 todo_permissive_sid,
1551 target_sid,
1552 FilePermission::Entrypoint
1553 ),
1554 PermissionCheckResult {
1555 permit: true,
1556 audit: true,
1557 todo_bug: Some(NonZeroU64::new(5).unwrap())
1558 }
1559 );
1560 assert_eq!(
1561 permission_check.has_permission(
1562 todo_permissive_sid,
1563 todo_permissive_sid,
1564 FilePermission::Entrypoint
1565 ),
1566 PermissionCheckResult {
1567 permit: true,
1568 audit: true,
1569 todo_bug: Some(NonZeroU64::new(5).unwrap())
1570 }
1571 );
1572 assert_eq!(
1573 permission_check.has_permission(
1574 todo_permissive_sid,
1575 target_sid,
1576 FilePermission::Entrypoint
1577 ),
1578 PermissionCheckResult {
1579 permit: true,
1580 audit: true,
1581 todo_bug: Some(NonZeroU64::new(5).unwrap())
1582 }
1583 );
1584 }
1585
1586 #[test]
1587 fn memfd_not_relabeled_no_exception() {
1588 const EXCEPTIONS_CONFIG: &[&str] = &[];
1589 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1590 let security_server = SecurityServer::new(String::new(), exceptions_config);
1591 security_server.set_enforcing(true);
1592
1593 const EXCEPTIONS_POLICY: &[u8] =
1594 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1595 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1596
1597 let original_sid = security_server
1598 .security_context_to_sid(b"test_exception_u:object_r:test_exception_target_t:s0".into())
1599 .expect("creating SID from security context should succeed");
1600 assert_eq!(security_server.transform_memfd_sid(original_sid), None);
1601 }
1602
1603 #[test]
1604 fn memfd_not_relabeled_undefined() {
1605 const EXCEPTIONS_CONFIG: &[&str] = &["memfd_type_override test_undefined_t"];
1606 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1607 let security_server = SecurityServer::new(String::new(), exceptions_config);
1608 security_server.set_enforcing(true);
1609
1610 const EXCEPTIONS_POLICY: &[u8] =
1611 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1612 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1613
1614 let original_sid = security_server
1615 .security_context_to_sid(b"test_exception_u:object_r:test_exception_target_t:s0".into())
1616 .expect("creating SID from security context should succeed");
1617 assert_eq!(security_server.transform_memfd_sid(original_sid), None);
1618 }
1619
1620 #[test]
1621 fn memfd_relabeled() {
1622 const EXCEPTIONS_CONFIG: &[&str] = &["memfd_type_override test_exception_other_t"];
1623 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1624 let security_server = SecurityServer::new(String::new(), exceptions_config);
1625 security_server.set_enforcing(true);
1626
1627 const EXCEPTIONS_POLICY: &[u8] =
1628 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1629 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1630
1631 let original_sid = security_server
1632 .security_context_to_sid(b"test_exception_u:object_r:test_exception_target_t:s0".into())
1633 .expect("creating SID from security context should succeed");
1634 let expected_sid = security_server
1635 .security_context_to_sid(b"test_exception_u:object_r:test_exception_other_t:s0".into())
1636 .expect("creating SID from security context should succeed");
1637 assert_eq!(security_server.transform_memfd_sid(original_sid), Some(expected_sid));
1638 }
1639
1640 #[test]
1641 fn handle_unknown() {
1642 let security_server = security_server_with_tests_policy();
1643
1644 let sid = security_server
1645 .security_context_to_sid("user0:object_r:type0:s0".into())
1646 .expect("Resolve Context to SID");
1647
1648 const REJECT_POLICY: &[u8] = include_bytes!(
1652 "../testdata/composite_policies/compiled/handle_unknown_policy-reject.pp"
1653 );
1654 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1655
1656 security_server.set_enforcing(true);
1657
1658 const DENY_POLICY: &[u8] =
1660 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny.pp");
1661 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1662 let permission_check = security_server.as_permission_check();
1663
1664 assert_eq!(
1666 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1667 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1668 );
1669 assert_eq!(
1670 permission_check.has_permission(sid, sid, DirPermission::AddName),
1671 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1672 );
1673
1674 assert_eq!(
1676 permission_check.has_permission(sid, sid, DirPermission::Search),
1677 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1678 );
1679 assert_eq!(
1680 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1681 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1682 );
1683
1684 const ALLOW_POLICY: &[u8] = include_bytes!(
1686 "../testdata/composite_policies/compiled/handle_unknown_policy-allow.pp"
1687 );
1688 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1689 let permission_check = security_server.as_permission_check();
1690
1691 assert_eq!(
1693 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1694 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1695 );
1696 assert_eq!(
1697 permission_check.has_permission(sid, sid, DirPermission::AddName),
1698 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1699 );
1700
1701 assert_eq!(
1703 permission_check.has_permission(sid, sid, DirPermission::Search),
1704 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1705 );
1706 assert_eq!(
1707 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1708 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1709 );
1710 }
1711}