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 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 load_policy(&self, binary_policy: Vec<u8>) -> Result<(), anyhow::Error> {
200 let unvalidated_policy = parse_policy_by_value(binary_policy)?;
203 let parsed = Arc::new(unvalidated_policy.validate()?);
204 let binary = parsed.binary().clone();
205
206 let exceptions = self.exceptions.iter().map(String::as_str).collect::<Vec<&str>>();
207 let exceptions = ExceptionsConfig::new(&parsed, &exceptions)?;
208
209 self.with_state_and_update_status(|state| {
211 let sid_table = if let Some(previous_active_policy) = &state.active_policy {
212 SidTable::new_from_previous(parsed.clone(), &previous_active_policy.sid_table)
213 } else {
214 SidTable::new(parsed.clone())
215 };
216
217 state.booleans.reset(
220 parsed
221 .conditional_booleans()
222 .iter()
223 .map(|(name, value)| (String::from_utf8((*name).to_vec()).unwrap(), *value))
225 .collect(),
226 );
227
228 state.active_policy = Some(ActivePolicy { parsed, binary, sid_table, exceptions });
229 state.policy_change_count += 1;
230 });
231
232 self.access_vector_cache.reset();
235
236 Ok(())
237 }
238
239 pub fn get_binary_policy(&self) -> Option<PolicyData> {
241 self.backend.state.read().active_policy.as_ref().map(|p| p.binary.clone())
242 }
243
244 pub fn has_policy(&self) -> bool {
246 self.backend.state.read().active_policy.is_some()
247 }
248
249 pub fn set_enforcing(&self, enforcing: bool) {
251 self.with_state_and_update_status(|state| state.enforcing = enforcing);
252 }
253
254 pub fn is_enforcing(&self) -> bool {
255 self.backend.state.read().enforcing
256 }
257
258 pub fn deny_unknown(&self) -> bool {
261 self.backend.state.read().deny_unknown()
262 }
263
264 pub fn reject_unknown(&self) -> bool {
267 self.backend.state.read().reject_unknown()
268 }
269
270 pub fn conditional_booleans(&self) -> Vec<String> {
273 self.backend.state.read().booleans.names()
274 }
275
276 pub fn get_boolean(&self, name: &str) -> Result<(bool, bool), ()> {
278 self.backend.state.read().booleans.get(name)
279 }
280
281 pub fn set_pending_boolean(&self, name: &str, value: bool) -> Result<(), ()> {
283 self.backend.state.write().booleans.set_pending(name, value)
284 }
285
286 pub fn commit_pending_booleans(&self) {
288 self.with_state_and_update_status(|state| {
290 state.booleans.commit_pending();
291 state.policy_change_count += 1;
292 });
293 }
294
295 pub fn avc_cache_stats(&self) -> CacheStats {
297 self.access_vector_cache.cache_stats()
298 }
299
300 pub fn class_names(&self) -> Result<Vec<Vec<u8>>, ()> {
302 let locked_state = self.backend.state.read();
303 let names = locked_state
304 .expect_active_policy()
305 .parsed
306 .classes()
307 .iter()
308 .map(|class| class.class_name.to_vec())
309 .collect();
310 Ok(names)
311 }
312
313 pub fn class_id_by_name(&self, name: &str) -> Result<ClassId, ()> {
315 let locked_state = self.backend.state.read();
316 Ok(locked_state
317 .expect_active_policy()
318 .parsed
319 .classes()
320 .iter()
321 .find(|class| class.class_name == name.as_bytes())
322 .ok_or(())?
323 .class_id)
324 }
325
326 pub fn class_permissions_by_name(
330 &self,
331 name: &str,
332 ) -> Result<Vec<(ClassPermissionId, Vec<u8>)>, ()> {
333 let locked_state = self.backend.state.read();
334 locked_state.expect_active_policy().parsed.find_class_permissions_by_name(name)
335 }
336
337 pub fn resolve_fs_label(
341 &self,
342 fs_type: NullessByteStr<'_>,
343 mount_options: &FileSystemMountOptions,
344 ) -> FileSystemLabel {
345 let mut locked_state = self.backend.state.write();
346 let active_policy = locked_state.expect_active_policy_mut();
347
348 let mount_sids = FileSystemMountSids {
349 context: sid_from_mount_option(active_policy, &mount_options.context),
350 fs_context: sid_from_mount_option(active_policy, &mount_options.fs_context),
351 def_context: sid_from_mount_option(active_policy, &mount_options.def_context),
352 root_context: sid_from_mount_option(active_policy, &mount_options.root_context),
353 };
354 if let Some(mountpoint_sid) = mount_sids.context {
355 FileSystemLabel {
359 sid: mount_sids.fs_context.unwrap_or(mountpoint_sid),
360 scheme: FileSystemLabelingScheme::Mountpoint { sid: mountpoint_sid },
361 mount_sids,
362 }
363 } else if let Some(FsUseLabelAndType { context, use_type }) =
364 active_policy.parsed.fs_use_label_and_type(fs_type)
365 {
366 let fs_sid_from_policy =
368 active_policy.sid_table.security_context_to_sid(&context).unwrap();
369 let fs_sid = mount_sids.fs_context.unwrap_or(fs_sid_from_policy);
370 FileSystemLabel {
371 sid: fs_sid,
372 scheme: FileSystemLabelingScheme::FsUse {
373 fs_use_type: use_type,
374 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
375 },
376 mount_sids,
377 }
378 } else if let Some(context) =
379 active_policy.parsed.genfscon_label_for_fs_and_path(fs_type, ROOT_PATH.into(), None)
380 {
381 let genfscon_sid = active_policy.sid_table.security_context_to_sid(&context).unwrap();
383 let fs_sid = mount_sids.fs_context.unwrap_or(genfscon_sid);
384 FileSystemLabel { sid: fs_sid, scheme: FileSystemLabelingScheme::GenFsCon, mount_sids }
385 } else {
386 FileSystemLabel {
388 sid: mount_sids.fs_context.unwrap_or_else(|| InitialSid::Unlabeled.into()),
389 scheme: FileSystemLabelingScheme::FsUse {
390 fs_use_type: FsUseType::Xattr,
391 default_sid: mount_sids.def_context.unwrap_or_else(|| InitialSid::File.into()),
392 },
393 mount_sids,
394 }
395 }
396 }
397
398 pub fn genfscon_label_for_fs_and_path(
402 &self,
403 fs_type: NullessByteStr<'_>,
404 node_path: NullessByteStr<'_>,
405 class_id: Option<ClassId>,
406 ) -> Option<SecurityId> {
407 let mut locked_state = self.backend.state.write();
408 let active_policy = locked_state.expect_active_policy_mut();
409 let security_context = active_policy.parsed.genfscon_label_for_fs_and_path(
410 fs_type,
411 node_path.into(),
412 class_id,
413 )?;
414 Some(active_policy.sid_table.security_context_to_sid(&security_context).unwrap())
415 }
416
417 pub fn is_bounded_by(&self, bounded_sid: SecurityId, parent_sid: SecurityId) -> bool {
422 let locked_state = self.backend.state.read();
423 let active_policy = locked_state.expect_active_policy();
424 let bounded_type = active_policy.sid_table.sid_to_security_context(bounded_sid).type_();
425 let parent_type = active_policy.sid_table.sid_to_security_context(parent_sid).type_();
426 active_policy.parsed.is_bounded_by(bounded_type, parent_type)
427 }
428
429 pub fn set_status_publisher(&self, status_holder: Box<dyn SeLinuxStatusPublisher>) {
436 self.with_state_and_update_status(|state| {
437 assert!(state.status_publisher.is_none());
438 state.status_publisher = Some(status_holder);
439 });
440 }
441
442 fn with_state_and_update_status(&self, f: impl FnOnce(&mut SecurityServerState)) {
445 let mut locked_state = self.backend.state.write();
446 f(locked_state.deref_mut());
447 let new_value = SeLinuxStatus {
448 is_enforcing: locked_state.enforcing,
449 change_count: locked_state.policy_change_count,
450 deny_unknown: locked_state.deny_unknown(),
451 };
452 if let Some(status_publisher) = &mut locked_state.status_publisher {
453 status_publisher.set_status(new_value);
454 }
455 }
456
457 pub fn compute_create_sid(
462 &self,
463 source_sid: SecurityId,
464 target_sid: SecurityId,
465 target_class: impl Into<ObjectClass>,
466 ) -> Result<SecurityId, anyhow::Error> {
467 self.backend.compute_create_sid(source_sid, target_sid, target_class)
468 }
469
470 pub fn transform_memfd_sid(&self, original_sid: SecurityId) -> Option<SecurityId> {
473 self.backend.transform_memfd_sid(original_sid)
474 }
475}
476
477impl SecurityServerBackend {
478 fn compute_create_sid(
479 &self,
480 source_sid: SecurityId,
481 target_sid: SecurityId,
482 target_class: impl Into<ObjectClass>,
483 ) -> Result<SecurityId, anyhow::Error> {
484 let mut locked_state = self.state.write();
485 let active_policy = locked_state.expect_active_policy_mut();
486
487 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
488 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
489
490 let security_context = active_policy.parsed.compute_create_context(
491 source_context,
492 target_context,
493 target_class.into(),
494 );
495
496 active_policy
497 .sid_table
498 .security_context_to_sid(&security_context)
499 .map_err(anyhow::Error::from)
500 .context("computing new security context from policy")
501 }
502
503 fn transform_memfd_sid(&self, original_sid: SecurityId) -> Option<SecurityId> {
505 let mut locked_state = self.state.write();
506 let active_policy = locked_state.active_policy.as_mut()?;
507 let new_type_id = active_policy.exceptions.memfd_type_override?;
508 let original_security_context =
509 active_policy.sid_table.sid_to_security_context(original_sid);
510 let new_security_context = SecurityContext::new(
511 original_security_context.user(),
512 original_security_context.role(),
513 new_type_id,
514 original_security_context.low_level().clone(),
515 original_security_context.high_level().cloned(),
516 );
517 active_policy.sid_table.security_context_to_sid(&new_security_context).ok()
518 }
519}
520
521impl Query for SecurityServerBackend {
522 fn compute_access_decision(
523 &self,
524 source_sid: SecurityId,
525 target_sid: SecurityId,
526 target_class: ObjectClass,
527 ) -> AccessDecision {
528 let locked_state = self.state.read();
529
530 let active_policy = match &locked_state.active_policy {
531 Some(active_policy) => active_policy,
532 None => return AccessDecision::allow(AccessVector::ALL),
534 };
535
536 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
537 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
538
539 let mut decision = active_policy.parsed.compute_access_decision(
540 &source_context,
541 &target_context,
542 target_class,
543 );
544
545 decision.todo_bug = active_policy.exceptions.lookup(
546 source_context.type_(),
547 target_context.type_(),
548 target_class,
549 );
550
551 decision
552 }
553
554 fn compute_new_fs_node_sid(
555 &self,
556 source_sid: SecurityId,
557 target_sid: SecurityId,
558 fs_node_class: FsNodeClass,
559 ) -> Result<SecurityId, anyhow::Error> {
560 self.compute_create_sid(source_sid, target_sid, fs_node_class)
561 }
562
563 fn compute_new_fs_node_sid_with_name(
564 &self,
565 source_sid: SecurityId,
566 target_sid: SecurityId,
567 fs_node_class: FsNodeClass,
568 fs_node_name: NullessByteStr<'_>,
569 ) -> Option<SecurityId> {
570 let mut locked_state = self.state.write();
571
572 let active_policy = locked_state.active_policy.as_mut().expect("Policy loaded");
574
575 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
576 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
577
578 let new_file_context = active_policy.parsed.compute_create_context_with_name(
579 source_context,
580 target_context,
581 fs_node_class,
582 fs_node_name,
583 )?;
584
585 active_policy.sid_table.security_context_to_sid(&new_file_context).ok()
586 }
587
588 fn compute_xperms_access_decision(
589 &self,
590 xperms_kind: XpermsKind,
591 source_sid: SecurityId,
592 target_sid: SecurityId,
593 target_class: ObjectClass,
594 xperms_prefix: u8,
595 ) -> XpermsAccessDecision {
596 let locked_state = self.state.read();
597
598 let active_policy = match &locked_state.active_policy {
599 Some(active_policy) => active_policy,
600 None => return XpermsAccessDecision::ALLOW_ALL,
602 };
603
604 let source_context = active_policy.sid_table.sid_to_security_context(source_sid);
605 let target_context = active_policy.sid_table.sid_to_security_context(target_sid);
606
607 active_policy.parsed.compute_xperms_access_decision(
608 xperms_kind,
609 &source_context,
610 &target_context,
611 target_class,
612 xperms_prefix,
613 )
614 }
615}
616
617impl AccessVectorComputer for SecurityServer {
618 fn access_vector_from_permissions<
619 P: ClassPermission + Into<KernelPermission> + Clone + 'static,
620 >(
621 &self,
622 permissions: &[P],
623 ) -> Option<AccessVector> {
624 match &self.backend.state.read().active_policy {
625 Some(policy) => policy.parsed.access_vector_from_permissions(permissions),
626 None => Some(AccessVector::NONE),
627 }
628 }
629}
630
631fn sid_from_mount_option(
634 active_policy: &mut ActivePolicy,
635 mount_option: &Option<Vec<u8>>,
636) -> Option<SecurityId> {
637 if let Some(label) = mount_option.as_ref() {
638 Some(
639 if let Some(context) = active_policy.parsed.parse_security_context(label.into()).ok() {
640 active_policy.sid_table.security_context_to_sid(&context).unwrap()
641 } else {
642 InitialSid::Unlabeled.into()
644 },
645 )
646 } else {
647 None
648 }
649}
650
651#[cfg(test)]
652mod tests {
653 use super::*;
654 use crate::permission_check::PermissionCheckResult;
655 use crate::{
656 CommonFsNodePermission, DirPermission, FileClass, FilePermission, ForClass, KernelClass,
657 ProcessPermission,
658 };
659 use std::num::NonZeroU64;
660
661 const TESTSUITE_BINARY_POLICY: &[u8] = include_bytes!("../testdata/policies/selinux_testsuite");
662 const TESTS_BINARY_POLICY: &[u8] =
663 include_bytes!("../testdata/micro_policies/security_server_tests_policy.pp");
664 const MINIMAL_BINARY_POLICY: &[u8] =
665 include_bytes!("../testdata/composite_policies/compiled/minimal_policy.pp");
666
667 fn security_server_with_tests_policy() -> Arc<SecurityServer> {
668 let policy_bytes = TESTS_BINARY_POLICY.to_vec();
669 let security_server = SecurityServer::new_default();
670 assert_eq!(
671 Ok(()),
672 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
673 );
674 security_server
675 }
676
677 #[test]
678 fn compute_access_vector_allows_all() {
679 let security_server = SecurityServer::new_default();
680 let sid1 = InitialSid::Kernel.into();
681 let sid2 = InitialSid::Unlabeled.into();
682 assert_eq!(
683 security_server
684 .backend
685 .compute_access_decision(sid1, sid2, KernelClass::Process.into())
686 .allow,
687 AccessVector::ALL
688 );
689 }
690
691 #[test]
692 fn loaded_policy_can_be_retrieved() {
693 let security_server = security_server_with_tests_policy();
694 assert_eq!(TESTS_BINARY_POLICY, security_server.get_binary_policy().unwrap().as_slice());
695 }
696
697 #[test]
698 fn loaded_policy_is_validated() {
699 let not_really_a_policy = "not a real policy".as_bytes().to_vec();
700 let security_server = SecurityServer::new_default();
701 assert!(security_server.load_policy(not_really_a_policy.clone()).is_err());
702 }
703
704 #[test]
705 fn enforcing_mode_is_reported() {
706 let security_server = SecurityServer::new_default();
707 assert!(!security_server.is_enforcing());
708
709 security_server.set_enforcing(true);
710 assert!(security_server.is_enforcing());
711 }
712
713 #[test]
714 fn without_policy_conditional_booleans_are_empty() {
715 let security_server = SecurityServer::new_default();
716 assert!(security_server.conditional_booleans().is_empty());
717 }
718
719 #[test]
720 fn conditional_booleans_can_be_queried() {
721 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
722 let security_server = SecurityServer::new_default();
723 assert_eq!(
724 Ok(()),
725 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
726 );
727
728 let booleans = security_server.conditional_booleans();
729 assert!(!booleans.is_empty());
730 let boolean = booleans[0].as_str();
731
732 assert!(security_server.get_boolean("this_is_not_a_valid_boolean_name").is_err());
733 assert!(security_server.get_boolean(boolean).is_ok());
734 }
735
736 #[test]
737 fn conditional_booleans_can_be_changed() {
738 let policy_bytes = TESTSUITE_BINARY_POLICY.to_vec();
739 let security_server = SecurityServer::new_default();
740 assert_eq!(
741 Ok(()),
742 security_server.load_policy(policy_bytes).map_err(|e| format!("{:?}", e))
743 );
744
745 let booleans = security_server.conditional_booleans();
746 assert!(!booleans.is_empty());
747 let boolean = booleans[0].as_str();
748
749 let (active, pending) = security_server.get_boolean(boolean).unwrap();
750 assert_eq!(active, pending, "Initially active and pending values should match");
751
752 security_server.set_pending_boolean(boolean, !active).unwrap();
753 let (active, pending) = security_server.get_boolean(boolean).unwrap();
754 assert!(active != pending, "Before commit pending should differ from active");
755
756 security_server.commit_pending_booleans();
757 let (final_active, final_pending) = security_server.get_boolean(boolean).unwrap();
758 assert_eq!(final_active, pending, "Pending value should be active after commit");
759 assert_eq!(final_active, final_pending, "Active and pending are the same after commit");
760 }
761
762 #[test]
763 fn parse_security_context_no_policy() {
764 let security_server = SecurityServer::new_default();
765 let error = security_server
766 .security_context_to_sid(b"unconfined_u:unconfined_r:unconfined_t:s0".into())
767 .expect_err("expected error");
768 let error_string = format!("{:?}", error);
769 assert!(error_string.contains("no policy"));
770 }
771
772 #[test]
773 fn compute_new_fs_node_sid_no_defaults() {
774 let security_server = SecurityServer::new_default();
775 let policy_bytes =
776 include_bytes!("../testdata/micro_policies/file_no_defaults_policy.pp").to_vec();
777 security_server.load_policy(policy_bytes).expect("binary policy loads");
778
779 let source_sid = security_server
780 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1".into())
781 .expect("creating SID from security context should succeed");
782 let target_sid = security_server
783 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
784 .expect("creating SID from security context should succeed");
785
786 let computed_sid = security_server
787 .as_permission_check()
788 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
789 .expect("new sid computed");
790 let computed_context = security_server
791 .sid_to_security_context(computed_sid)
792 .expect("computed sid associated with context");
793
794 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
797 }
798
799 #[test]
800 fn compute_new_fs_node_sid_source_defaults() {
801 let security_server = SecurityServer::new_default();
802 let policy_bytes =
803 include_bytes!("../testdata/micro_policies/file_source_defaults_policy.pp").to_vec();
804 security_server.load_policy(policy_bytes).expect("binary policy loads");
805
806 let source_sid = security_server
807 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
808 .expect("creating SID from security context should succeed");
809 let target_sid = security_server
810 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
811 .expect("creating SID from security context should succeed");
812
813 let computed_sid = security_server
814 .as_permission_check()
815 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
816 .expect("new sid computed");
817 let computed_context = security_server
818 .sid_to_security_context(computed_sid)
819 .expect("computed sid associated with context");
820
821 assert_eq!(computed_context, b"user_u:unconfined_r:unconfined_t:s0");
824 }
825
826 #[test]
827 fn compute_new_fs_node_sid_target_defaults() {
828 let security_server = SecurityServer::new_default();
829 let policy_bytes =
830 include_bytes!("../testdata/micro_policies/file_target_defaults_policy.pp").to_vec();
831 security_server.load_policy(policy_bytes).expect("binary policy loads");
832
833 let source_sid = security_server
834 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s2:c0".into())
835 .expect("creating SID from security context should succeed");
836 let target_sid = security_server
837 .security_context_to_sid(b"file_u:object_r:file_t:s1-s3:c0".into())
838 .expect("creating SID from security context should succeed");
839
840 let computed_sid = security_server
841 .as_permission_check()
842 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
843 .expect("new sid computed");
844 let computed_context = security_server
845 .sid_to_security_context(computed_sid)
846 .expect("computed sid associated with context");
847
848 assert_eq!(computed_context, b"file_u:object_r:file_t:s0");
850 }
851
852 #[test]
853 fn compute_new_fs_node_sid_range_source_low_default() {
854 let security_server = SecurityServer::new_default();
855 let policy_bytes =
856 include_bytes!("../testdata/micro_policies/file_range_source_low_policy.pp").to_vec();
857 security_server.load_policy(policy_bytes).expect("binary policy loads");
858
859 let source_sid = security_server
860 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
861 .expect("creating SID from security context should succeed");
862 let target_sid = security_server
863 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
864 .expect("creating SID from security context should succeed");
865
866 let computed_sid = security_server
867 .as_permission_check()
868 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
869 .expect("new sid computed");
870 let computed_context = security_server
871 .sid_to_security_context(computed_sid)
872 .expect("computed sid associated with context");
873
874 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
876 }
877
878 #[test]
879 fn compute_new_fs_node_sid_range_source_low_high_default() {
880 let security_server = SecurityServer::new_default();
881 let policy_bytes =
882 include_bytes!("../testdata/micro_policies/file_range_source_low_high_policy.pp")
883 .to_vec();
884 security_server.load_policy(policy_bytes).expect("binary policy loads");
885
886 let source_sid = security_server
887 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
888 .expect("creating SID from security context should succeed");
889 let target_sid = security_server
890 .security_context_to_sid(b"file_u:object_r:file_t:s1".into())
891 .expect("creating SID from security context should succeed");
892
893 let computed_sid = security_server
894 .as_permission_check()
895 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
896 .expect("new sid computed");
897 let computed_context = security_server
898 .sid_to_security_context(computed_sid)
899 .expect("computed sid associated with context");
900
901 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
903 }
904
905 #[test]
906 fn compute_new_fs_node_sid_range_source_high_default() {
907 let security_server = SecurityServer::new_default();
908 let policy_bytes =
909 include_bytes!("../testdata/micro_policies/file_range_source_high_policy.pp").to_vec();
910 security_server.load_policy(policy_bytes).expect("binary policy loads");
911
912 let source_sid = security_server
913 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0-s1:c0".into())
914 .expect("creating SID from security context should succeed");
915 let target_sid = security_server
916 .security_context_to_sid(b"file_u:object_r:file_t:s0".into())
917 .expect("creating SID from security context should succeed");
918
919 let computed_sid = security_server
920 .as_permission_check()
921 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
922 .expect("new sid computed");
923 let computed_context = security_server
924 .sid_to_security_context(computed_sid)
925 .expect("computed sid associated with context");
926
927 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
929 }
930
931 #[test]
932 fn compute_new_fs_node_sid_range_target_low_default() {
933 let security_server = SecurityServer::new_default();
934 let policy_bytes =
935 include_bytes!("../testdata/micro_policies/file_range_target_low_policy.pp").to_vec();
936 security_server.load_policy(policy_bytes).expect("binary policy loads");
937
938 let source_sid = security_server
939 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
940 .expect("creating SID from security context should succeed");
941 let target_sid = security_server
942 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
943 .expect("creating SID from security context should succeed");
944
945 let computed_sid = security_server
946 .as_permission_check()
947 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
948 .expect("new sid computed");
949 let computed_context = security_server
950 .sid_to_security_context(computed_sid)
951 .expect("computed sid associated with context");
952
953 assert_eq!(computed_context, b"user_u:object_r:file_t:s0");
955 }
956
957 #[test]
958 fn compute_new_fs_node_sid_range_target_low_high_default() {
959 let security_server = SecurityServer::new_default();
960 let policy_bytes =
961 include_bytes!("../testdata/micro_policies/file_range_target_low_high_policy.pp")
962 .to_vec();
963 security_server.load_policy(policy_bytes).expect("binary policy loads");
964
965 let source_sid = security_server
966 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s1".into())
967 .expect("creating SID from security context should succeed");
968 let target_sid = security_server
969 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
970 .expect("creating SID from security context should succeed");
971
972 let computed_sid = security_server
973 .as_permission_check()
974 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
975 .expect("new sid computed");
976 let computed_context = security_server
977 .sid_to_security_context(computed_sid)
978 .expect("computed sid associated with context");
979
980 assert_eq!(computed_context, b"user_u:object_r:file_t:s0-s1:c0");
982 }
983
984 #[test]
985 fn compute_new_fs_node_sid_range_target_high_default() {
986 let security_server = SecurityServer::new_default();
987 let policy_bytes =
988 include_bytes!("../testdata/micro_policies/file_range_target_high_policy.pp").to_vec();
989 security_server.load_policy(policy_bytes).expect("binary policy loads");
990
991 let source_sid = security_server
992 .security_context_to_sid(b"user_u:unconfined_r:unconfined_t:s0".into())
993 .expect("creating SID from security context should succeed");
994 let target_sid = security_server
995 .security_context_to_sid(b"file_u:object_r:file_t:s0-s1:c0".into())
996 .expect("creating SID from security context should succeed");
997
998 let computed_sid = security_server
999 .as_permission_check()
1000 .compute_new_fs_node_sid(source_sid, target_sid, FileClass::File.into(), "".into())
1001 .expect("new sid computed");
1002 let computed_context = security_server
1003 .sid_to_security_context(computed_sid)
1004 .expect("computed sid associated with context");
1005
1006 assert_eq!(computed_context, b"user_u:object_r:file_t:s1:c0");
1008 }
1009
1010 #[test]
1011 fn compute_new_fs_node_sid_with_name() {
1012 let security_server = SecurityServer::new_default();
1013 let policy_bytes =
1014 include_bytes!("../testdata/composite_policies/compiled/type_transition_policy.pp")
1015 .to_vec();
1016 security_server.load_policy(policy_bytes).expect("binary policy loads");
1017
1018 let source_sid = security_server
1019 .security_context_to_sid(b"source_u:source_r:source_t:s0".into())
1020 .expect("creating SID from security context should succeed");
1021 let target_sid = security_server
1022 .security_context_to_sid(b"target_u:object_r:target_t:s0".into())
1023 .expect("creating SID from security context should succeed");
1024
1025 const SPECIAL_FILE_NAME: &[u8] = b"special_file";
1026 let computed_sid = security_server
1027 .as_permission_check()
1028 .compute_new_fs_node_sid(
1029 source_sid,
1030 target_sid,
1031 FileClass::File.into(),
1032 SPECIAL_FILE_NAME.into(),
1033 )
1034 .expect("new sid computed");
1035 let computed_context = security_server
1036 .sid_to_security_context(computed_sid)
1037 .expect("computed sid associated with context");
1038
1039 assert_eq!(computed_context, b"source_u:object_r:special_transition_t:s0");
1041
1042 let computed_sid = security_server
1043 .as_permission_check()
1044 .compute_new_fs_node_sid(
1045 source_sid,
1046 target_sid,
1047 FileClass::Character.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:target_t:s0");
1058
1059 const OTHER_FILE_NAME: &[u8] = b"other_file";
1060 let computed_sid = security_server
1061 .as_permission_check()
1062 .compute_new_fs_node_sid(
1063 source_sid,
1064 target_sid,
1065 FileClass::File.into(),
1066 OTHER_FILE_NAME.into(),
1067 )
1068 .expect("new sid computed");
1069 let computed_context = security_server
1070 .sid_to_security_context(computed_sid)
1071 .expect("computed sid associated with context");
1072
1073 assert_eq!(computed_context, b"source_u:object_r:transition_t:s0");
1076 }
1077
1078 #[test]
1079 fn permissions_are_fresh_after_different_policy_load() {
1080 let minimal_bytes = MINIMAL_BINARY_POLICY.to_vec();
1081 let allow_fork_bytes =
1082 include_bytes!("../testdata/composite_policies/compiled/allow_fork.pp").to_vec();
1083 let context = b"source_u:object_r:source_t:s0:c0";
1084
1085 let security_server = SecurityServer::new_default();
1086 security_server.set_enforcing(true);
1087
1088 let permission_check = security_server.as_permission_check();
1089
1090 assert_eq!(
1092 Ok(()),
1093 security_server.load_policy(minimal_bytes).map_err(|e| format!("{:?}", e))
1094 );
1095 let sid = security_server.security_context_to_sid(context.into()).unwrap();
1096
1097 assert!(!permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1099
1100 assert_eq!(
1102 Ok(()),
1103 security_server.load_policy(allow_fork_bytes).map_err(|e| format!("{:?}", e))
1104 );
1105
1106 assert!(permission_check.has_permission(sid, sid, ProcessPermission::Fork).permit);
1108 }
1109
1110 #[test]
1111 fn unknown_sids_are_effectively_unlabeled() {
1112 let with_unlabeled_access_domain_policy_bytes = include_bytes!(
1113 "../testdata/composite_policies/compiled/with_unlabeled_access_domain_policy.pp"
1114 )
1115 .to_vec();
1116 let with_additional_domain_policy_bytes = include_bytes!(
1117 "../testdata/composite_policies/compiled/with_additional_domain_policy.pp"
1118 )
1119 .to_vec();
1120 let allowed_type_context = b"source_u:object_r:allowed_t:s0:c0";
1121 let additional_type_context = b"source_u:object_r:additional_t:s0:c0";
1122
1123 let security_server = SecurityServer::new_default();
1124 security_server.set_enforcing(true);
1125
1126 assert_eq!(
1129 Ok(()),
1130 security_server
1131 .load_policy(with_unlabeled_access_domain_policy_bytes.clone())
1132 .map_err(|e| format!("{:?}", e))
1133 );
1134 let allowed_type_sid =
1135 security_server.security_context_to_sid(allowed_type_context.into()).unwrap();
1136 assert!(security_server.security_context_to_sid(additional_type_context.into()).is_err());
1137
1138 assert_eq!(
1141 Ok(()),
1142 security_server
1143 .load_policy(with_additional_domain_policy_bytes.clone())
1144 .map_err(|e| format!("{:?}", e))
1145 );
1146 let additional_type_sid =
1147 security_server.security_context_to_sid(additional_type_context.into()).unwrap();
1148 assert_eq!(
1149 allowed_type_sid,
1150 security_server.security_context_to_sid(allowed_type_context.into()).unwrap()
1151 );
1152
1153 let permission_check = security_server.as_permission_check();
1154
1155 assert!(
1159 !permission_check
1160 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1161 .permit
1162 );
1163 assert!(
1164 !permission_check
1165 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1166 .permit
1167 );
1168 assert!(
1169 !permission_check
1170 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1171 .permit
1172 );
1173 assert!(
1174 !permission_check
1175 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1176 .permit
1177 );
1178
1179 assert_eq!(
1181 Ok(()),
1182 security_server
1183 .load_policy(with_unlabeled_access_domain_policy_bytes)
1184 .map_err(|e| format!("{:?}", e))
1185 );
1186
1187 assert!(
1191 permission_check
1192 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::GetSched)
1193 .permit
1194 );
1195 assert!(
1196 !permission_check
1197 .has_permission(allowed_type_sid, additional_type_sid, ProcessPermission::SetSched)
1198 .permit
1199 );
1200
1201 assert!(
1206 !permission_check
1207 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::GetSched)
1208 .permit
1209 );
1210 assert!(
1211 permission_check
1212 .has_permission(additional_type_sid, allowed_type_sid, ProcessPermission::SetSched)
1213 .permit
1214 );
1215
1216 assert!(security_server.sid_to_security_context(additional_type_sid).is_none());
1218
1219 assert_eq!(
1222 Ok(()),
1223 security_server
1224 .load_policy(with_additional_domain_policy_bytes)
1225 .map_err(|e| format!("{:?}", e))
1226 );
1227 assert_eq!(
1228 additional_type_context.to_vec(),
1229 security_server.sid_to_security_context(additional_type_sid).unwrap()
1230 );
1231 }
1232
1233 #[test]
1234 fn permission_check_permissive() {
1235 let security_server = security_server_with_tests_policy();
1236 security_server.set_enforcing(false);
1237 assert!(!security_server.is_enforcing());
1238
1239 let sid =
1240 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1241 let permission_check = security_server.as_permission_check();
1242
1243 assert_eq!(
1246 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1247 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1248 );
1249
1250 assert_eq!(
1254 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1255 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1256 );
1257
1258 assert_eq!(
1262 permission_check.has_permission(
1263 sid,
1264 sid,
1265 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1266 ),
1267 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1268 );
1269 }
1270
1271 #[test]
1272 fn permission_check_enforcing() {
1273 let security_server = security_server_with_tests_policy();
1274 security_server.set_enforcing(true);
1275 assert!(security_server.is_enforcing());
1276
1277 let sid =
1278 security_server.security_context_to_sid("user0:object_r:type0:s0".into()).unwrap();
1279 let permission_check = security_server.as_permission_check();
1280
1281 assert_eq!(
1283 permission_check.has_permission(sid, sid, ProcessPermission::Fork),
1284 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1285 );
1286
1287 assert_eq!(
1290 permission_check.has_permission(sid, sid, ProcessPermission::GetRlimit),
1291 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1292 );
1293
1294 assert_eq!(
1297 permission_check.has_permission(
1298 sid,
1299 sid,
1300 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1301 ),
1302 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1303 );
1304 }
1305
1306 #[test]
1307 fn permissive_domain() {
1308 let security_server = security_server_with_tests_policy();
1309 security_server.set_enforcing(true);
1310 assert!(security_server.is_enforcing());
1311
1312 let permissive_sid = security_server
1313 .security_context_to_sid("user0:object_r:permissive_t:s0".into())
1314 .unwrap();
1315 let non_permissive_sid = security_server
1316 .security_context_to_sid("user0:object_r:non_permissive_t:s0".into())
1317 .unwrap();
1318
1319 let permission_check = security_server.as_permission_check();
1320
1321 assert_eq!(
1323 permission_check.has_permission(
1324 permissive_sid,
1325 permissive_sid,
1326 ProcessPermission::GetSched
1327 ),
1328 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1329 );
1330 assert_eq!(
1331 permission_check.has_permission(
1332 non_permissive_sid,
1333 non_permissive_sid,
1334 ProcessPermission::GetSched
1335 ),
1336 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1337 );
1338
1339 assert_eq!(
1342 permission_check.has_permission(
1343 permissive_sid,
1344 non_permissive_sid,
1345 ProcessPermission::GetSched
1346 ),
1347 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1348 );
1349 assert_eq!(
1350 permission_check.has_permission(
1351 non_permissive_sid,
1352 permissive_sid,
1353 ProcessPermission::GetSched
1354 ),
1355 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1356 );
1357
1358 assert_eq!(
1363 permission_check.has_permission(
1364 permissive_sid,
1365 non_permissive_sid,
1366 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1367 ),
1368 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1369 );
1370 assert_eq!(
1371 permission_check.has_permission(
1372 non_permissive_sid,
1373 non_permissive_sid,
1374 CommonFsNodePermission::GetAttr.for_class(FileClass::Block)
1375 ),
1376 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1377 );
1378 }
1379
1380 #[test]
1381 fn auditallow_and_dontaudit() {
1382 let security_server = security_server_with_tests_policy();
1383 security_server.set_enforcing(true);
1384 assert!(security_server.is_enforcing());
1385
1386 let audit_sid = security_server
1387 .security_context_to_sid("user0:object_r:test_audit_t:s0".into())
1388 .unwrap();
1389
1390 let permission_check = security_server.as_permission_check();
1391
1392 assert_eq!(
1394 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::Fork),
1395 PermissionCheckResult { permit: true, audit: true, todo_bug: None }
1396 );
1397
1398 assert_eq!(
1400 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::SetSched),
1401 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1402 );
1403
1404 assert_eq!(
1406 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetSched),
1407 PermissionCheckResult { permit: false, audit: false, todo_bug: None }
1408 );
1409
1410 assert_eq!(
1412 permission_check.has_permission(audit_sid, audit_sid, ProcessPermission::GetPgid),
1413 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1414 );
1415 }
1416
1417 #[test]
1418 fn access_checks_with_exceptions_config() {
1419 const EXCEPTIONS_CONFIG: &[&str] = &[
1420 "todo_deny b/001 test_exception_source_t test_exception_target_t file",
1422 "todo_deny b/002 test_exception_other_t test_exception_target_t chr_file",
1423 "todo_deny b/003 test_exception_source_t test_exception_other_t anon_inode",
1424 "todo_deny b/004 test_exception_permissive_t test_exception_target_t file",
1425 "todo_permissive b/005 test_exception_todo_permissive_t",
1426 "todo_deny b/101 test_undefined_source_t test_exception_target_t file",
1428 "todo_deny b/102 test_exception_source_t test_undefined_target_t file",
1429 "todo_permissive b/103 test_undefined_source_t",
1430 ];
1431 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1432 let security_server = SecurityServer::new(String::new(), exceptions_config);
1433 security_server.set_enforcing(true);
1434
1435 const EXCEPTIONS_POLICY: &[u8] =
1436 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1437 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1438
1439 let source_sid = security_server
1440 .security_context_to_sid("test_exception_u:object_r:test_exception_source_t:s0".into())
1441 .unwrap();
1442 let target_sid = security_server
1443 .security_context_to_sid("test_exception_u:object_r:test_exception_target_t:s0".into())
1444 .unwrap();
1445 let other_sid = security_server
1446 .security_context_to_sid("test_exception_u:object_r:test_exception_other_t:s0".into())
1447 .unwrap();
1448 let permissive_sid = security_server
1449 .security_context_to_sid(
1450 "test_exception_u:object_r:test_exception_permissive_t:s0".into(),
1451 )
1452 .unwrap();
1453 let unmatched_sid = security_server
1454 .security_context_to_sid(
1455 "test_exception_u:object_r:test_exception_unmatched_t:s0".into(),
1456 )
1457 .unwrap();
1458 let todo_permissive_sid = security_server
1459 .security_context_to_sid(
1460 "test_exception_u:object_r:test_exception_todo_permissive_t:s0".into(),
1461 )
1462 .unwrap();
1463
1464 let permission_check = security_server.as_permission_check();
1465
1466 assert_eq!(
1468 permission_check.has_permission(source_sid, target_sid, ProcessPermission::GetPgid),
1469 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1470 );
1471
1472 assert_eq!(
1474 permission_check.has_permission(source_sid, target_sid, FilePermission::Entrypoint),
1475 PermissionCheckResult {
1476 permit: true,
1477 audit: true,
1478 todo_bug: Some(NonZeroU64::new(1).unwrap())
1479 }
1480 );
1481
1482 assert_eq!(
1484 permission_check.has_permission(source_sid, target_sid, FilePermission::ExecuteNoTrans),
1485 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1486 );
1487
1488 assert_eq!(
1490 permission_check.has_permission(other_sid, target_sid, FilePermission::Entrypoint),
1491 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1492 );
1493
1494 assert_eq!(
1496 permission_check.has_permission(
1497 other_sid,
1498 target_sid,
1499 CommonFsNodePermission::Read.for_class(FileClass::Character)
1500 ),
1501 PermissionCheckResult {
1502 permit: true,
1503 audit: true,
1504 todo_bug: Some(NonZeroU64::new(2).unwrap())
1505 }
1506 );
1507
1508 assert_eq!(
1510 permission_check.has_permission(source_sid, unmatched_sid, FilePermission::Entrypoint),
1511 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1512 );
1513
1514 assert_eq!(
1516 permission_check.has_permission(unmatched_sid, target_sid, FilePermission::Entrypoint),
1517 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1518 );
1519
1520 assert_eq!(
1522 permission_check.has_permission(permissive_sid, target_sid, FilePermission::Entrypoint),
1523 PermissionCheckResult {
1524 permit: true,
1525 audit: true,
1526 todo_bug: Some(NonZeroU64::new(4).unwrap())
1527 }
1528 );
1529
1530 assert_eq!(
1533 permission_check.has_permission(
1534 todo_permissive_sid,
1535 target_sid,
1536 FilePermission::Entrypoint
1537 ),
1538 PermissionCheckResult {
1539 permit: true,
1540 audit: true,
1541 todo_bug: Some(NonZeroU64::new(5).unwrap())
1542 }
1543 );
1544 assert_eq!(
1545 permission_check.has_permission(
1546 todo_permissive_sid,
1547 todo_permissive_sid,
1548 FilePermission::Entrypoint
1549 ),
1550 PermissionCheckResult {
1551 permit: true,
1552 audit: true,
1553 todo_bug: Some(NonZeroU64::new(5).unwrap())
1554 }
1555 );
1556 assert_eq!(
1557 permission_check.has_permission(
1558 todo_permissive_sid,
1559 target_sid,
1560 FilePermission::Entrypoint
1561 ),
1562 PermissionCheckResult {
1563 permit: true,
1564 audit: true,
1565 todo_bug: Some(NonZeroU64::new(5).unwrap())
1566 }
1567 );
1568 }
1569
1570 #[test]
1571 fn memfd_not_relabeled_no_exception() {
1572 const EXCEPTIONS_CONFIG: &[&str] = &[];
1573 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1574 let security_server = SecurityServer::new(String::new(), exceptions_config);
1575 security_server.set_enforcing(true);
1576
1577 const EXCEPTIONS_POLICY: &[u8] =
1578 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1579 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1580
1581 let original_sid = security_server
1582 .security_context_to_sid(b"test_exception_u:object_r:test_exception_target_t:s0".into())
1583 .expect("creating SID from security context should succeed");
1584 assert_eq!(security_server.transform_memfd_sid(original_sid), None);
1585 }
1586
1587 #[test]
1588 fn memfd_not_relabeled_undefined() {
1589 const EXCEPTIONS_CONFIG: &[&str] = &["memfd_type_override test_undefined_t"];
1590 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1591 let security_server = SecurityServer::new(String::new(), exceptions_config);
1592 security_server.set_enforcing(true);
1593
1594 const EXCEPTIONS_POLICY: &[u8] =
1595 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1596 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1597
1598 let original_sid = security_server
1599 .security_context_to_sid(b"test_exception_u:object_r:test_exception_target_t:s0".into())
1600 .expect("creating SID from security context should succeed");
1601 assert_eq!(security_server.transform_memfd_sid(original_sid), None);
1602 }
1603
1604 #[test]
1605 fn memfd_relabeled() {
1606 const EXCEPTIONS_CONFIG: &[&str] = &["memfd_type_override test_exception_other_t"];
1607 let exceptions_config = EXCEPTIONS_CONFIG.iter().map(|x| String::from(*x)).collect();
1608 let security_server = SecurityServer::new(String::new(), exceptions_config);
1609 security_server.set_enforcing(true);
1610
1611 const EXCEPTIONS_POLICY: &[u8] =
1612 include_bytes!("../testdata/composite_policies/compiled/exceptions_config_policy.pp");
1613 assert!(security_server.load_policy(EXCEPTIONS_POLICY.into()).is_ok());
1614
1615 let original_sid = security_server
1616 .security_context_to_sid(b"test_exception_u:object_r:test_exception_target_t:s0".into())
1617 .expect("creating SID from security context should succeed");
1618 let expected_sid = security_server
1619 .security_context_to_sid(b"test_exception_u:object_r:test_exception_other_t:s0".into())
1620 .expect("creating SID from security context should succeed");
1621 assert_eq!(security_server.transform_memfd_sid(original_sid), Some(expected_sid));
1622 }
1623
1624 #[test]
1625 fn handle_unknown() {
1626 let security_server = security_server_with_tests_policy();
1627
1628 let sid = security_server
1629 .security_context_to_sid("user0:object_r:type0:s0".into())
1630 .expect("Resolve Context to SID");
1631
1632 const REJECT_POLICY: &[u8] = include_bytes!(
1636 "../testdata/composite_policies/compiled/handle_unknown_policy-reject.pp"
1637 );
1638 assert!(security_server.load_policy(REJECT_POLICY.to_vec()).is_err());
1639
1640 security_server.set_enforcing(true);
1641
1642 const DENY_POLICY: &[u8] =
1644 include_bytes!("../testdata/composite_policies/compiled/handle_unknown_policy-deny.pp");
1645 assert!(security_server.load_policy(DENY_POLICY.to_vec()).is_ok());
1646 let permission_check = security_server.as_permission_check();
1647
1648 assert_eq!(
1650 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1651 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1652 );
1653 assert_eq!(
1654 permission_check.has_permission(sid, sid, DirPermission::AddName),
1655 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1656 );
1657
1658 assert_eq!(
1660 permission_check.has_permission(sid, sid, DirPermission::Search),
1661 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1662 );
1663 assert_eq!(
1664 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1665 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1666 );
1667
1668 const ALLOW_POLICY: &[u8] = include_bytes!(
1670 "../testdata/composite_policies/compiled/handle_unknown_policy-allow.pp"
1671 );
1672 assert!(security_server.load_policy(ALLOW_POLICY.to_vec()).is_ok());
1673 let permission_check = security_server.as_permission_check();
1674
1675 assert_eq!(
1677 permission_check.has_permission(sid, sid, ProcessPermission::GetSched),
1678 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1679 );
1680 assert_eq!(
1681 permission_check.has_permission(sid, sid, DirPermission::AddName),
1682 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1683 );
1684
1685 assert_eq!(
1687 permission_check.has_permission(sid, sid, DirPermission::Search),
1688 PermissionCheckResult { permit: true, audit: false, todo_bug: None }
1689 );
1690 assert_eq!(
1691 permission_check.has_permission(sid, sid, DirPermission::Reparent),
1692 PermissionCheckResult { permit: false, audit: true, todo_bug: None }
1693 );
1694 }
1695}