1#![allow(non_upper_case_globals)]
37
38use super::selinux_hooks::audit::Auditable;
39use super::{
40 BpfMapState, BpfProgState, FileObjectState, FileSystemState, KernelState, NonPrivateDirEntry,
41 NonPrivateFsNode, NonPrivateSocket, NonPrivateSocketFile, PerfEventState, common_cap,
42 selinux_hooks, yama,
43};
44use crate::mm::{Mapping, MappingOptions, ProtectionFlags};
45use crate::perf::PerfEventFile;
46use crate::security::selinux_hooks::current_task_state;
47use crate::task::loader::ResolvedProgram;
48use crate::task::{CurrentTask, Kernel, Task};
49use crate::vfs::fs_args::MountParams;
50use crate::vfs::socket::{
51 Socket, SocketAddress, SocketDomain, SocketFile, SocketPeer, SocketProtocol,
52 SocketShutdownFlags, SocketType,
53};
54use crate::vfs::{
55 DirEntryHandle, DowncastedFile, FileHandle, FileObject, FileSystem, FileSystemHandle,
56 FileSystemOps, FsNode, FsStr, FsString, Mount, NamespaceNode, ValueOrSize, XattrOp,
57};
58use ebpf::MapFlags;
59use linux_uapi::{
60 perf_type_id, perf_type_id_PERF_TYPE_BREAKPOINT, perf_type_id_PERF_TYPE_HARDWARE,
61 perf_type_id_PERF_TYPE_HW_CACHE, perf_type_id_PERF_TYPE_RAW, perf_type_id_PERF_TYPE_SOFTWARE,
62 perf_type_id_PERF_TYPE_TRACEPOINT,
63};
64use selinux::{FileSystemMountOptions, InitialSid, SecurityPermission, SecurityServer, TaskAttrs};
65use starnix_logging::{CATEGORY_STARNIX_SECURITY, log_debug};
66use starnix_uapi::arc_key::WeakKey;
67use starnix_uapi::auth::{CAP_SETUID, Credentials, PtraceAccessMode};
68use starnix_uapi::device_id::DeviceId;
69use starnix_uapi::errors::Errno;
70use starnix_uapi::file_mode::{Access, FileMode};
71use starnix_uapi::inotify_mask::InotifyMask;
72use starnix_uapi::mount_flags::MountFlags;
73use starnix_uapi::open_flags::OpenFlags;
74use starnix_uapi::signals::Signal;
75use starnix_uapi::syslog::SyslogAction;
76use starnix_uapi::unmount_flags::UnmountFlags;
77use starnix_uapi::user_address::UserAddress;
78use starnix_uapi::{bpf_cmd, error, rlimit};
79use std::ops::Range;
80use std::sync::Arc;
81use syncio::zxio_node_attr_has_t;
82use zerocopy::FromBytes;
83
84macro_rules! track_hook_duration {
85 ($cname:literal) => {
86 fuchsia_trace::duration!(CATEGORY_STARNIX_SECURITY, $cname);
87 };
88}
89
90bitflags::bitflags! {
91 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
94 pub struct PermissionFlags: u32 {
95 const EXEC = 1 as u32;
96 const WRITE = 2 as u32;
97 const READ = 4 as u32;
98 const APPEND = 8 as u32;
99
100 const ACCESS = 16 as u32;
103 }
104}
105
106impl PermissionFlags {
107 pub fn as_access(&self) -> Access {
108 let mut access = Access::empty();
109 if self.contains(PermissionFlags::READ) {
110 access |= Access::READ;
111 }
112 if self.contains(PermissionFlags::WRITE) {
113 access |= Access::WRITE;
116 }
117 if self.contains(PermissionFlags::EXEC) {
118 access |= Access::EXEC;
119 }
120 access
121 }
122}
123
124impl From<Access> for PermissionFlags {
125 fn from(access: Access) -> Self {
126 let mut permissions = PermissionFlags::empty();
128 if access.contains(Access::READ) {
129 permissions |= PermissionFlags::READ;
130 }
131 if access.contains(Access::WRITE) {
132 permissions |= PermissionFlags::WRITE;
133 }
134 if access.contains(Access::EXEC) {
135 permissions |= PermissionFlags::EXEC;
136 }
137 permissions
138 }
139}
140
141impl From<ProtectionFlags> for PermissionFlags {
142 fn from(protection_flags: ProtectionFlags) -> Self {
143 let mut flags = PermissionFlags::empty();
144 if protection_flags.contains(ProtectionFlags::READ) {
145 flags |= PermissionFlags::READ;
146 }
147 if protection_flags.contains(ProtectionFlags::WRITE) {
148 flags |= PermissionFlags::WRITE;
149 }
150 if protection_flags.contains(ProtectionFlags::EXEC) {
151 flags |= PermissionFlags::EXEC;
152 }
153 flags
154 }
155}
156
157impl From<OpenFlags> for PermissionFlags {
158 fn from(flags: OpenFlags) -> Self {
159 let mut permissions = PermissionFlags::empty();
160 if flags.can_read() {
161 permissions |= PermissionFlags::READ;
162 }
163 if flags.can_write() {
164 permissions |= PermissionFlags::WRITE;
165 if flags.contains(OpenFlags::APPEND) {
166 permissions |= PermissionFlags::APPEND;
167 }
168 }
169 permissions
170 }
171}
172
173impl From<MapFlags> for PermissionFlags {
174 fn from(bpf_flags: MapFlags) -> Self {
175 if bpf_flags.contains(MapFlags::SyscallReadOnly) {
176 PermissionFlags::READ
177 } else if bpf_flags.contains(MapFlags::SyscallWriteOnly) {
178 PermissionFlags::WRITE
179 } else {
180 PermissionFlags::READ | PermissionFlags::WRITE
181 }
182 }
183}
184
185#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
187pub enum PerfEventType {
188 Hardware,
189 Software,
190 Tracepoint,
191 Raw,
192 HwCache,
193 Breakpoint,
194}
195
196#[allow(non_upper_case_globals)]
198impl TryFrom<perf_type_id> for PerfEventType {
199 type Error = Errno;
200
201 fn try_from(type_id: perf_type_id) -> Result<Self, Errno> {
202 match type_id {
203 perf_type_id_PERF_TYPE_HARDWARE => Ok(Self::Hardware),
204 perf_type_id_PERF_TYPE_SOFTWARE => Ok(Self::Software),
205 perf_type_id_PERF_TYPE_TRACEPOINT => Ok(Self::Tracepoint),
206 perf_type_id_PERF_TYPE_RAW => Ok(Self::Raw),
207 perf_type_id_PERF_TYPE_HW_CACHE => Ok(Self::HwCache),
208 perf_type_id_PERF_TYPE_BREAKPOINT => Ok(Self::Breakpoint),
209 _ => {
210 return error!(ENOTSUP);
211 }
212 }
213 }
214}
215
216#[derive(PartialEq, Eq)]
218pub enum PerfEventTarget<'a> {
219 AllTasks,
221 CurrentTask,
223 Task(&'a Task),
225}
226
227#[derive(Clone, Copy, Debug, PartialEq, Eq)]
231pub enum PerfEventOpenType {
232 Open,
234 Cpu,
236 Kernel,
238 Tracepoint,
240}
241
242fn if_selinux_else<F, R, D>(task: &Task, hook: F, default: D) -> R
246where
247 F: FnOnce(&Arc<SecurityServer>) -> R,
248 D: Fn() -> R,
249{
250 if let Some(state) = task.kernel().security_state.state.as_ref() {
251 if state.has_policy() { hook(&state.server) } else { default() }
252 } else {
253 default()
254 }
255}
256
257fn if_selinux_else_default_ok<R, F>(task: &Task, hook: F) -> Result<R, Errno>
261where
262 F: FnOnce(&Arc<SecurityServer>) -> Result<R, Errno>,
263 R: Default,
264{
265 if_selinux_else(task, hook, || Ok(R::default()))
266}
267
268pub fn kernel_init_security(
271 enabled: bool,
272 options: String,
273 exceptions: Vec<String>,
274 inspect_node: &fuchsia_inspect::Node,
275) -> KernelState {
276 track_hook_duration!("security.hooks.kernel_init_security");
277 KernelState {
278 state: enabled
279 .then(|| selinux_hooks::kernel_init_security(options, exceptions, inspect_node)),
280 }
281}
282
283pub fn binder_set_context_mgr(
286 current_task: &CurrentTask,
287 context_mgr_creds: &Credentials,
288) -> Result<(), Errno> {
289 track_hook_duration!("security.hooks.binder_set_context_mgr");
290 if_selinux_else_default_ok(current_task, |security_server| {
291 selinux_hooks::binder::binder_set_context_mgr(
292 security_server,
293 current_task,
294 context_mgr_creds,
295 )
296 })
297}
298
299pub fn binder_transaction(
302 current_task: &CurrentTask,
303 source_creds: &Credentials,
304 target_creds: &Credentials,
305) -> Result<(), Errno> {
306 track_hook_duration!("security.hooks.binder_transaction");
307 if_selinux_else_default_ok(current_task, |security_server| {
308 selinux_hooks::binder::binder_transaction(
309 security_server,
310 current_task,
311 source_creds,
312 target_creds,
313 )
314 })
315}
316
317pub fn binder_transfer_binder(
320 current_task: &CurrentTask,
321 source_creds: &Credentials,
322 target_creds: &Credentials,
323) -> Result<(), Errno> {
324 track_hook_duration!("security.hooks.binder_transfer_binder");
325 if_selinux_else_default_ok(current_task, |security_server| {
326 selinux_hooks::binder::binder_transfer_binder(
327 security_server,
328 current_task,
329 source_creds,
330 target_creds,
331 )
332 })
333}
334
335pub fn binder_transfer_file(
338 current_task: &CurrentTask,
339 target_creds: &Credentials,
340 file: &FileObject,
341) -> Result<(), Errno> {
342 track_hook_duration!("security.hooks.binder_transfer_file");
343 if_selinux_else_default_ok(current_task, |security_server| {
344 selinux_hooks::binder::binder_transfer_file(
345 security_server,
346 current_task,
347 target_creds,
348 file,
349 )
350 })
351}
352
353pub fn binder_get_context(current_task: &CurrentTask, source_creds: &Credentials) -> FsString {
356 track_hook_duration!("security.hooks.binder_get_context");
357 if_selinux_else(
358 current_task,
359 |security_server| {
360 selinux_hooks::binder::binder_get_context(&security_server, source_creds).into()
361 },
362 || FsString::from(b"\0"),
363 )
364}
365
366pub fn sb_eat_lsm_opts(
370 kernel: &Kernel,
371 mount_params: &mut MountParams,
372) -> Result<FileSystemMountOptions, Errno> {
373 track_hook_duration!("security.hooks.sb_eat_lsm_opts");
374 if kernel.security_state.state.is_some() {
375 return selinux_hooks::superblock::sb_eat_lsm_opts(mount_params);
376 }
377 Ok(FileSystemMountOptions::default())
378}
379
380pub fn file_system_init_security(
383 mount_options: &FileSystemMountOptions,
384 ops: &dyn FileSystemOps,
385) -> Result<FileSystemState, Errno> {
386 track_hook_duration!("security.hooks.file_system_init_security");
387 Ok(FileSystemState {
388 state: selinux_hooks::superblock::file_system_init_security(mount_options, ops)?,
389 })
390}
391
392pub fn file_system_post_init_security(kernel: &Kernel, file_system: &FileSystemHandle) {
395 track_hook_duration!("security.hooks.file_system_post_init_security");
396 if let Some(state) = &kernel.security_state.state {
397 if !state.has_policy() {
398 log_debug!("Queuing {} FileSystem for labeling", file_system.name());
401 state.pending_file_systems.lock().insert(WeakKey::from(&file_system));
402 }
403 }
404}
405
406pub fn file_system_resolve_security(
411 current_task: &CurrentTask,
412 file_system: &FileSystemHandle,
413) -> Result<(), Errno> {
414 track_hook_duration!("security.hooks.file_system_resolve_security");
415 if_selinux_else_default_ok(current_task, |security_server| {
416 selinux_hooks::superblock::file_system_resolve_security(
417 security_server,
418 current_task,
419 file_system,
420 )
421 })
422}
423
424pub struct FsNodeSecurityXattr {
426 pub name: &'static FsStr,
427 pub value: Box<[u8]>,
428}
429
430pub fn mmap_file(
434 current_task: &CurrentTask,
435 file: Option<&FileHandle>,
436 protection_flags: ProtectionFlags,
437 options: MappingOptions,
438) -> Result<(), Errno> {
439 track_hook_duration!("security.hooks.mmap_file");
440 if_selinux_else_default_ok(current_task, |security_server| {
441 selinux_hooks::file::mmap_file(
442 security_server,
443 current_task,
444 file,
445 protection_flags,
446 options,
447 )
448 })
449}
450
451pub fn file_mprotect(
455 current_task: &CurrentTask,
456 range: &Range<UserAddress>,
457 mapping: &Mapping,
458 prot: ProtectionFlags,
459) -> Result<(), Errno> {
460 track_hook_duration!("security.hooks.file_mprotect");
461 if_selinux_else_default_ok(current_task, |security_server| {
462 selinux_hooks::file::file_mprotect(security_server, current_task, range, mapping, prot)
463 })
464}
465
466pub fn file_permission(
469 current_task: &CurrentTask,
470 file: &FileObject,
471 permission_flags: PermissionFlags,
472) -> Result<(), Errno> {
473 track_hook_duration!("security.hooks.file_permission");
474 if_selinux_else_default_ok(current_task, |security_server| {
475 selinux_hooks::file::file_permission(security_server, current_task, file, permission_flags)
476 })
477}
478
479pub fn file_open(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
482 track_hook_duration!("security.hooks.file_open");
483 let Some(fs_node) = NonPrivateFsNode::new(file.node()) else {
484 return Ok(());
485 };
486 if_selinux_else_default_ok(current_task, |security_server| {
487 selinux_hooks::file::file_open(security_server, current_task, file, fs_node)
488 })
489}
490
491pub fn fs_node_init_with_dentry(
497 current_task: &CurrentTask,
498 dir_entry: &DirEntryHandle,
499) -> Result<(), Errno> {
500 track_hook_duration!("security.hooks.fs_node_init_with_dentry");
501 let Some(dir_entry) = NonPrivateDirEntry::new(dir_entry) else {
502 return Ok(());
503 };
504 if let Some(state) = ¤t_task.kernel().security_state.state {
509 selinux_hooks::fs_node::fs_node_init_with_dentry(
510 &state.server,
511 current_task,
512 dir_entry,
513 true,
515 )
516 } else {
517 Ok(())
518 }
519}
520
521pub fn fs_node_init_with_dentry_no_xattr(
522 current_task: &CurrentTask,
523 dir_entry: &DirEntryHandle,
524) -> Result<(), Errno> {
525 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
526 let Some(dir_entry) = NonPrivateDirEntry::new(dir_entry) else {
527 return Ok(());
528 };
529 if let Some(state) = ¤t_task.kernel().security_state.state {
534 selinux_hooks::fs_node::fs_node_init_with_dentry(
535 &state.server,
536 current_task,
537 dir_entry,
538 false,
540 )
541 } else {
542 Ok(())
543 }
544}
545
546pub fn fs_node_notify_security_context(
553 current_task: &CurrentTask,
554 fs_node: &FsNode,
555 context: &FsStr,
556) {
557 track_hook_duration!("security.hooks.fs_node_notify_security_context");
558 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
559 return;
560 };
561 if_selinux_else(
562 current_task,
563 |security_server| {
564 selinux_hooks::fs_node::fs_node_notify_security_context(
565 security_server,
566 fs_node,
567 context,
568 )
569 },
570 || (),
571 )
572}
573
574pub fn fs_node_init_on_create(
586 current_task: &CurrentTask,
587 new_node: &FsNode,
588 parent: &FsNode,
589 name: &FsStr,
590) -> Result<Option<FsNodeSecurityXattr>, Errno> {
591 track_hook_duration!("security.hooks.fs_node_init_on_create");
592 let (Some(new_node), Some(parent)) =
593 (NonPrivateFsNode::assert_from(new_node), NonPrivateFsNode::assert_from(parent))
594 else {
595 return Ok(None);
596 };
597 if_selinux_else_default_ok(current_task, |security_server| {
598 selinux_hooks::fs_node::fs_node_init_on_create(
599 security_server,
600 current_task,
601 new_node,
602 Some(parent),
603 name,
604 )
605 })
606}
607
608pub fn dentry_init_security(
621 current_task: &CurrentTask,
622 parent: &FsNode,
623 mode: FileMode,
624 name: &FsStr,
625) -> Result<Option<FsNodeSecurityXattr>, Errno> {
626 track_hook_duration!("security.hooks.dentry_init_security");
627 let Some(parent) = NonPrivateFsNode::assert_from(parent) else {
628 return Ok(None);
629 };
630 if_selinux_else_default_ok(current_task, |security_server| {
631 selinux_hooks::fs_node::dentry_init_security(
632 security_server,
633 current_task,
634 parent,
635 mode,
636 name,
637 )
638 })
639}
640
641pub fn dentry_create_files_as(
649 current_task: &CurrentTask,
650 parent: &FsNode,
651 new_node_mode: FileMode,
652 new_node_name: &FsStr,
653 new_creds: &mut Credentials,
654) -> Result<(), Errno> {
655 track_hook_duration!("security.hooks.dentry_create_files_as");
656 let Some(parent) = NonPrivateFsNode::assert_from(parent) else {
657 return Ok(());
658 };
659 if_selinux_else_default_ok(current_task, |security_server| {
660 selinux_hooks::fs_node::dentry_create_files_as(
661 security_server,
662 current_task,
663 parent,
664 new_node_mode,
665 new_node_name,
666 new_creds,
667 )
668 })
669}
670
671pub fn fs_node_init_anon(
676 current_task: &CurrentTask,
677 new_node: &FsNode,
678 node_type: &str,
679) -> Result<(), Errno> {
680 track_hook_duration!("security.hooks.fs_node_init_anon");
681 let Some(new_node) = NonPrivateFsNode::new(new_node) else {
682 return Ok(());
683 };
684 if let Some(state) = current_task.kernel().security_state.state.as_ref() {
685 selinux_hooks::fs_node::fs_node_init_anon(&state.server, current_task, new_node, node_type)
686 } else {
687 Ok(())
688 }
689}
690
691pub fn check_fs_node_create_access(
695 current_task: &CurrentTask,
696 parent: &FsNode,
697 mode: FileMode,
698 name: &FsStr,
699) -> Result<(), Errno> {
700 track_hook_duration!("security.hooks.check_fs_node_create_access");
701 let Some(parent) = NonPrivateFsNode::assert_from(parent) else {
702 return Ok(());
703 };
704 if_selinux_else_default_ok(current_task, |security_server| {
705 selinux_hooks::fs_node::check_fs_node_create_access(
706 security_server,
707 current_task,
708 parent,
709 mode,
710 name,
711 )
712 })
713}
714
715pub fn check_fs_node_symlink_access(
719 current_task: &CurrentTask,
720 parent: &FsNode,
721 name: &FsStr,
722 old_path: &FsStr,
723) -> Result<(), Errno> {
724 track_hook_duration!("security.hooks.check_fs_node_symlink_access");
725 let Some(parent) = NonPrivateFsNode::assert_from(parent) else {
726 return Ok(());
727 };
728 if_selinux_else_default_ok(current_task, |security_server| {
729 selinux_hooks::fs_node::check_fs_node_symlink_access(
730 security_server,
731 current_task,
732 parent,
733 name,
734 old_path,
735 )
736 })
737}
738
739pub fn check_fs_node_mkdir_access(
743 current_task: &CurrentTask,
744 parent: &FsNode,
745 mode: FileMode,
746 name: &FsStr,
747) -> Result<(), Errno> {
748 track_hook_duration!("security.hooks.check_fs_node_mkdir_access");
749 let Some(parent) = NonPrivateFsNode::assert_from(parent) else {
750 return Ok(());
751 };
752 if_selinux_else_default_ok(current_task, |security_server| {
753 selinux_hooks::fs_node::check_fs_node_mkdir_access(
754 security_server,
755 current_task,
756 parent,
757 mode,
758 name,
759 )
760 })
761}
762
763pub fn check_fs_node_mknod_access(
769 current_task: &CurrentTask,
770 parent: &FsNode,
771 mode: FileMode,
772 name: &FsStr,
773 device_id: DeviceId,
774) -> Result<(), Errno> {
775 track_hook_duration!("security.hooks.check_fs_node_mknod_access");
776 assert!(!mode.is_reg());
777 let Some(parent) = NonPrivateFsNode::assert_from(parent) else {
778 return Ok(());
779 };
780
781 if_selinux_else_default_ok(current_task, |security_server| {
782 selinux_hooks::fs_node::check_fs_node_mknod_access(
783 security_server,
784 current_task,
785 parent,
786 mode,
787 name,
788 device_id,
789 )
790 })
791}
792
793pub fn check_fs_node_link_access(
796 current_task: &CurrentTask,
797 parent: &FsNode,
798 child: &FsNode,
799) -> Result<(), Errno> {
800 track_hook_duration!("security.hooks.check_fs_node_link_access");
801 let (Some(parent), Some(child)) =
802 (NonPrivateFsNode::assert_from(parent), NonPrivateFsNode::assert_from(child))
803 else {
804 return Ok(());
805 };
806 if_selinux_else_default_ok(current_task, |security_server| {
807 selinux_hooks::fs_node::check_fs_node_link_access(
808 security_server,
809 current_task,
810 parent,
811 child,
812 )
813 })
814}
815
816pub fn check_fs_node_unlink_access(
819 current_task: &CurrentTask,
820 parent: &FsNode,
821 child: &FsNode,
822 name: &FsStr,
823) -> Result<(), Errno> {
824 track_hook_duration!("security.hooks.check_fs_node_unlink_access");
825 let (Some(parent), Some(child)) =
826 (NonPrivateFsNode::assert_from(parent), NonPrivateFsNode::assert_from(child))
827 else {
828 return Ok(());
829 };
830 if_selinux_else_default_ok(current_task, |security_server| {
831 selinux_hooks::fs_node::check_fs_node_unlink_access(
832 security_server,
833 current_task,
834 parent,
835 child,
836 name,
837 )
838 })
839}
840
841pub fn check_fs_node_rmdir_access(
844 current_task: &CurrentTask,
845 parent: &FsNode,
846 child: &FsNode,
847 name: &FsStr,
848) -> Result<(), Errno> {
849 track_hook_duration!("security.hooks.check_fs_node_rmdir_access");
850 let (Some(parent), Some(child)) =
851 (NonPrivateFsNode::assert_from(parent), NonPrivateFsNode::assert_from(child))
852 else {
853 return Ok(());
854 };
855 if_selinux_else_default_ok(current_task, |security_server| {
856 selinux_hooks::fs_node::check_fs_node_rmdir_access(
857 security_server,
858 current_task,
859 parent,
860 child,
861 name,
862 )
863 })
864}
865
866pub fn check_fs_node_rename_access(
871 current_task: &CurrentTask,
872 old_parent: &FsNode,
873 moving_node: &FsNode,
874 new_parent: &FsNode,
875 replaced_node: Option<&FsNode>,
876 old_basename: &FsStr,
877 new_basename: &FsStr,
878) -> Result<(), Errno> {
879 track_hook_duration!("security.hooks.check_fs_node_rename_access");
880 let (Some(old_parent), Some(moving_node), Some(new_parent)) = (
881 NonPrivateFsNode::assert_from(old_parent),
882 NonPrivateFsNode::assert_from(moving_node),
883 NonPrivateFsNode::assert_from(new_parent),
884 ) else {
885 return Ok(());
886 };
887 let replaced_node = match replaced_node {
888 Some(node) => {
889 let Some(node) = NonPrivateFsNode::assert_from(node) else {
890 return Ok(());
891 };
892 Some(node)
893 }
894 None => None,
895 };
896 if_selinux_else_default_ok(current_task, |security_server| {
897 selinux_hooks::fs_node::check_fs_node_rename_access(
898 security_server,
899 current_task,
900 old_parent,
901 moving_node,
902 new_parent,
903 replaced_node,
904 old_basename,
905 new_basename,
906 )
907 })
908}
909
910pub fn check_fs_node_read_link_access(
913 current_task: &CurrentTask,
914 fs_node: &FsNode,
915) -> Result<(), Errno> {
916 track_hook_duration!("security.hooks.check_fs_node_read_link_access");
917 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
918 return Ok(());
919 };
920 if_selinux_else_default_ok(current_task, |security_server| {
921 selinux_hooks::fs_node::check_fs_node_read_link_access(
922 security_server,
923 current_task,
924 fs_node,
925 )
926 })
927}
928
929pub fn fs_node_permission(
932 current_task: &CurrentTask,
933 fs_node: &FsNode,
934 permission_flags: PermissionFlags,
935 audit_context: Auditable<'_>,
936) -> Result<(), Errno> {
937 track_hook_duration!("security.hooks.fs_node_permission");
938 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
939 return Ok(());
940 };
941 if_selinux_else_default_ok(current_task, |security_server| {
942 selinux_hooks::fs_node::fs_node_permission(
943 security_server,
944 current_task,
945 fs_node,
946 permission_flags,
947 audit_context,
948 )
949 })
950}
951
952pub fn file_receive(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
955 track_hook_duration!("security.hooks.file_receive");
956 if_selinux_else_default_ok(current_task, |security_server| {
957 let receiving_sid = current_task_state(current_task).current_sid;
958 selinux_hooks::file::file_receive(security_server, current_task, receiving_sid, file)
959 })
960}
961
962pub fn file_alloc_security(current_task: &CurrentTask) -> FileObjectState {
965 track_hook_duration!("security.hooks.file_alloc_security");
966 FileObjectState { state: selinux_hooks::file::file_alloc_security(current_task) }
967}
968
969pub fn bpf_map_alloc(current_task: &CurrentTask) -> BpfMapState {
973 track_hook_duration!("security.hooks.bpf_map_alloc");
974 BpfMapState { state: selinux_hooks::bpf::bpf_map_alloc(current_task) }
975}
976
977pub fn bpf_prog_alloc(current_task: &CurrentTask) -> BpfProgState {
981 track_hook_duration!("security.hooks.bpf_prog_alloc");
982 BpfProgState { state: selinux_hooks::bpf::bpf_prog_alloc(current_task) }
983}
984
985pub fn check_file_ioctl_access(
988 current_task: &CurrentTask,
989 file: &FileObject,
990 request: u32,
991) -> Result<(), Errno> {
992 track_hook_duration!("security.hooks.check_file_ioctl_access");
993 if_selinux_else_default_ok(current_task, |security_server| {
994 selinux_hooks::file::check_file_ioctl_access(security_server, current_task, file, request)
995 })
996}
997
998pub fn fs_node_copy_up(
1006 current_task: &CurrentTask,
1007 fs_node: &FsNode,
1008 fs: &FileSystem,
1009 new_creds: &mut Credentials,
1010) {
1011 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
1012 return;
1013 };
1014 if_selinux_else(
1015 current_task,
1016 |_security_server| {
1017 selinux_hooks::fs_node::fs_node_copy_up(current_task, fs_node, fs, new_creds)
1018 },
1019 || {},
1020 )
1021}
1022
1023pub fn check_file_lock_access(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
1031 track_hook_duration!("security.hooks.check_file_lock_access");
1032 if_selinux_else_default_ok(current_task, |security_server| {
1033 selinux_hooks::file::check_file_lock_access(security_server, current_task, file)
1034 })
1035}
1036
1037pub fn check_file_fcntl_access(
1040 current_task: &CurrentTask,
1041 file: &FileObject,
1042 fcntl_cmd: u32,
1043 fcntl_arg: u64,
1044) -> Result<(), Errno> {
1045 track_hook_duration!("security.hooks.check_file_fcntl_access");
1046 if_selinux_else_default_ok(current_task, |security_server| {
1047 selinux_hooks::file::check_file_fcntl_access(
1048 security_server,
1049 current_task,
1050 file,
1051 fcntl_cmd,
1052 fcntl_arg,
1053 )
1054 })
1055}
1056
1057pub fn check_fs_node_setattr_access(
1060 current_task: &CurrentTask,
1061 node: &FsNode,
1062 attributes: &zxio_node_attr_has_t,
1063) -> Result<(), Errno> {
1064 track_hook_duration!("security.hooks.check_fs_node_setattr_access");
1065 let Some(node) = NonPrivateFsNode::new(node) else {
1066 return Ok(());
1067 };
1068 if_selinux_else_default_ok(current_task, |security_server| {
1069 selinux_hooks::fs_node::check_fs_node_setattr_access(
1070 security_server,
1071 current_task,
1072 node,
1073 attributes,
1074 )
1075 })
1076}
1077
1078pub fn task_alloc_for_kernel() -> TaskAttrs {
1081 track_hook_duration!("security.hooks.task_alloc_for_kernel");
1082 TaskAttrs::for_kernel()
1083}
1084
1085pub fn task_to_fs_node(current_task: &CurrentTask, task: &Task, fs_node: &FsNode) {
1091 track_hook_duration!("security.hooks.task_to_fs_node");
1092 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
1093 return;
1094 };
1095 if current_task.kernel().security_state.state.is_some() {
1098 selinux_hooks::task::fs_node_init_with_task(task, fs_node);
1099 }
1100}
1101
1102pub fn task_for_context(task: &Task, context: &FsStr) -> Result<TaskAttrs, Errno> {
1108 track_hook_duration!("security.hooks.task_for_context");
1109 Ok(if let Some(kernel_state) = task.kernel().security_state.state.as_ref() {
1110 selinux_hooks::task::task_alloc_from_context(&kernel_state.server, context)
1111 } else {
1112 Ok(TaskAttrs::for_selinux_disabled())
1113 }?)
1114}
1115
1116pub fn has_dontaudit_access(current_task: &CurrentTask, fs_node: &FsNode) -> bool {
1120 track_hook_duration!("security.hooks.has_dontaudit_access");
1121 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
1122 return false;
1123 };
1124 if_selinux_else(
1125 current_task,
1126 |security_server| {
1127 selinux_hooks::fs_node::has_dontaudit_access(security_server, current_task, fs_node)
1128 },
1129 || false,
1130 )
1131}
1132
1133pub fn is_task_capable_noaudit(
1136 current_task: &CurrentTask,
1137 capability: starnix_uapi::auth::Capabilities,
1138) -> bool {
1139 check_task_capable_noaudit(current_task, capability).is_ok()
1140}
1141
1142pub fn check_creds_capable_noaudit(
1146 current_task: &CurrentTask,
1147 creds: &Credentials,
1148 capability: starnix_uapi::auth::Capabilities,
1149) -> Result<(), Errno> {
1150 track_hook_duration!("security.hooks.is_task_capable_noaudit");
1151 common_cap::creds_capable(creds, capability)?;
1152 let permitted = if_selinux_else(
1153 current_task,
1154 |security_server| {
1155 selinux_hooks::task::is_creds_capable_noaudit(
1156 &selinux_hooks::build_permission_check(current_task, security_server),
1157 ¤t_task,
1158 creds,
1159 capability,
1160 )
1161 },
1162 || true,
1163 );
1164 if permitted { Ok(()) } else { error!(EPERM) }
1165}
1166
1167pub fn check_task_capable_noaudit(
1170 current_task: &CurrentTask,
1171 capability: starnix_uapi::auth::Capabilities,
1172) -> Result<(), Errno> {
1173 check_creds_capable_noaudit(current_task, &**current_task.current_creds(), capability)
1174}
1175
1176pub fn check_creds_capable(
1179 current_task: &CurrentTask,
1180 creds: &Credentials,
1181 capability: starnix_uapi::auth::Capabilities,
1182) -> Result<(), Errno> {
1183 track_hook_duration!("security.hooks.check_creds_capable");
1184 common_cap::creds_capable(creds, capability)?;
1185 if_selinux_else_default_ok(current_task, |security_server| {
1186 selinux_hooks::task::check_creds_capable(
1187 &selinux_hooks::build_permission_check(current_task, security_server),
1188 ¤t_task,
1189 creds,
1190 capability,
1191 )
1192 })
1193}
1194
1195pub fn check_task_capable(
1198 current_task: &CurrentTask,
1199 capability: starnix_uapi::auth::Capabilities,
1200) -> Result<(), Errno> {
1201 check_creds_capable(current_task, &**current_task.current_creds(), capability)
1202}
1203
1204pub fn check_creds_ptrace_capable(
1207 current_task: &CurrentTask,
1208 creds: &Credentials,
1209 mode: PtraceAccessMode,
1210) -> Result<(), Errno> {
1211 if mode.contains(PtraceAccessMode::NOAUDIT) {
1212 check_creds_capable_noaudit(current_task, creds, starnix_uapi::auth::CAP_SYS_PTRACE)
1213 } else {
1214 check_creds_capable(current_task, creds, starnix_uapi::auth::CAP_SYS_PTRACE)
1215 }
1216}
1217
1218pub fn check_task_ptrace_capable(
1220 current_task: &CurrentTask,
1221 mode: PtraceAccessMode,
1222) -> Result<(), Errno> {
1223 check_creds_ptrace_capable(current_task, &**current_task.current_creds(), mode)
1224}
1225
1226pub fn check_task_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1229 track_hook_duration!("security.hooks.check_task_create_access");
1230 if_selinux_else_default_ok(current_task, |security_server| {
1231 selinux_hooks::task::check_task_create_access(
1232 &selinux_hooks::build_permission_check(current_task, security_server),
1233 current_task,
1234 )
1235 })
1236}
1237
1238pub fn check_socket_create_access(
1241 current_task: &CurrentTask,
1242 domain: SocketDomain,
1243 socket_type: SocketType,
1244 protocol: SocketProtocol,
1245 kernel_private: bool,
1246) -> Result<(), Errno> {
1247 track_hook_duration!("security.hooks.socket_create");
1248 if kernel_private {
1249 return Ok(());
1250 }
1251 if_selinux_else_default_ok(current_task, |security_server| {
1252 selinux_hooks::socket::check_socket_create_access(
1253 &security_server,
1254 current_task,
1255 domain,
1256 socket_type,
1257 protocol,
1258 )
1259 })
1260}
1261
1262pub fn socket_socketpair(
1265 current_task: &CurrentTask,
1266 left: DowncastedFile<'_, SocketFile>,
1267 right: DowncastedFile<'_, SocketFile>,
1268) -> Result<(), Errno> {
1269 track_hook_duration!("security.hooks.socket_socketpair");
1270 let Some(left) = NonPrivateSocketFile::new(left) else {
1271 debug_assert!(NonPrivateSocketFile::new(right).is_none());
1272 return Ok(());
1273 };
1274 let Some(right) = NonPrivateSocketFile::assert_from(right) else {
1275 return Ok(());
1276 };
1277 if_selinux_else_default_ok(current_task, |_| {
1278 selinux_hooks::socket::socket_socketpair(left, right)
1279 })
1280}
1281
1282pub fn socket_post_create(current_task: &CurrentTask, socket: &Socket) {
1285 track_hook_duration!("security.hooks.socket_post_create");
1286 let Some(socket) = NonPrivateSocket::new(socket) else {
1287 return;
1288 };
1289 if let Some(state) = ¤t_task.kernel().security_state.state {
1290 selinux_hooks::socket::socket_post_create(&state.server, socket);
1291 }
1292}
1293
1294pub fn check_socket_bind_access(
1297 current_task: &CurrentTask,
1298 socket: &Socket,
1299 socket_address: &SocketAddress,
1300) -> Result<(), Errno> {
1301 track_hook_duration!("security.hooks.check_socket_bind_access");
1302 let Some(socket) = NonPrivateSocket::new(socket) else {
1303 return Ok(());
1304 };
1305 if_selinux_else_default_ok(current_task, |security_server| {
1306 selinux_hooks::socket::check_socket_bind_access(
1307 &security_server,
1308 current_task,
1309 socket,
1310 socket_address,
1311 )
1312 })
1313}
1314
1315pub fn check_socket_connect_access(
1318 current_task: &CurrentTask,
1319 socket: DowncastedFile<'_, SocketFile>,
1320 socket_peer: &SocketPeer,
1321) -> Result<(), Errno> {
1322 track_hook_duration!("security.hooks.check_socket_connect_access");
1323 let Some(socket) = NonPrivateSocketFile::new(socket) else {
1324 return Ok(());
1325 };
1326 if_selinux_else_default_ok(current_task, |security_server| {
1327 selinux_hooks::socket::check_socket_connect_access(
1328 &security_server,
1329 current_task,
1330 socket,
1331 socket_peer,
1332 )
1333 })
1334}
1335
1336pub fn check_socket_listen_access(
1339 current_task: &CurrentTask,
1340 socket: &Socket,
1341 backlog: i32,
1342) -> Result<(), Errno> {
1343 track_hook_duration!("security.hooks.check_socket_listen_access");
1344 let Some(socket) = NonPrivateSocket::new(socket) else {
1345 return Ok(());
1346 };
1347 if_selinux_else_default_ok(current_task, |security_server| {
1348 selinux_hooks::socket::check_socket_listen_access(
1349 &security_server,
1350 current_task,
1351 socket,
1352 backlog,
1353 )
1354 })
1355}
1356
1357pub fn socket_accept(
1361 current_task: &CurrentTask,
1362 listening_socket: DowncastedFile<'_, SocketFile>,
1363 accepted_socket: DowncastedFile<'_, SocketFile>,
1364) -> Result<(), Errno> {
1365 track_hook_duration!("security.hooks.check_socket_getname_access");
1366 let (Some(listening_socket), Some(accepted_socket)) =
1367 (NonPrivateSocketFile::new(listening_socket), NonPrivateSocketFile::new(accepted_socket))
1368 else {
1369 return Ok(());
1370 };
1371 if_selinux_else_default_ok(current_task, |security_server| {
1372 selinux_hooks::socket::socket_accept(
1373 &security_server,
1374 current_task,
1375 listening_socket,
1376 accepted_socket,
1377 )
1378 })
1379}
1380
1381pub fn check_socket_getsockopt_access(
1384 current_task: &CurrentTask,
1385 socket: &Socket,
1386 level: u32,
1387 optname: u32,
1388) -> Result<(), Errno> {
1389 track_hook_duration!("security.hooks.check_socket_getsockopt_access");
1390 let Some(socket) = NonPrivateSocket::new(socket) else {
1391 return Ok(());
1392 };
1393 if_selinux_else_default_ok(current_task, |security_server| {
1394 selinux_hooks::socket::check_socket_getsockopt_access(
1395 &security_server,
1396 current_task,
1397 socket,
1398 level,
1399 optname,
1400 )
1401 })
1402}
1403
1404pub fn check_socket_setsockopt_access(
1407 current_task: &CurrentTask,
1408 socket: &Socket,
1409 level: u32,
1410 optname: u32,
1411) -> Result<(), Errno> {
1412 track_hook_duration!("security.hooks.check_socket_setsockopt_access");
1413 let Some(socket) = NonPrivateSocket::new(socket) else {
1414 return Ok(());
1415 };
1416 if_selinux_else_default_ok(current_task, |security_server| {
1417 selinux_hooks::socket::check_socket_setsockopt_access(
1418 &security_server,
1419 current_task,
1420 socket,
1421 level,
1422 optname,
1423 )
1424 })
1425}
1426
1427pub fn check_socket_sendmsg_access(
1430 current_task: &CurrentTask,
1431 socket: &Socket,
1432) -> Result<(), Errno> {
1433 track_hook_duration!("security.hooks.check_socket_sendmsg_access");
1434 let Some(socket) = NonPrivateSocket::new(socket) else {
1435 return Ok(());
1436 };
1437 if_selinux_else_default_ok(current_task, |security_server| {
1438 selinux_hooks::socket::check_socket_sendmsg_access(&security_server, current_task, socket)
1439 })
1440}
1441
1442pub fn check_socket_recvmsg_access(
1445 current_task: &CurrentTask,
1446 socket: &Socket,
1447) -> Result<(), Errno> {
1448 track_hook_duration!("security.hooks.check_socket_recvmsg_access");
1449 let Some(socket) = NonPrivateSocket::new(socket) else {
1450 return Ok(());
1451 };
1452 if_selinux_else_default_ok(current_task, |security_server| {
1453 selinux_hooks::socket::check_socket_recvmsg_access(&security_server, current_task, socket)
1454 })
1455}
1456
1457pub fn check_socket_getsockname_access(
1460 current_task: &CurrentTask,
1461 socket: &Socket,
1462) -> Result<(), Errno> {
1463 track_hook_duration!("security.hooks.check_socket_getname_access");
1464 let Some(socket) = NonPrivateSocket::new(socket) else {
1465 return Ok(());
1466 };
1467 if_selinux_else_default_ok(current_task, |security_server| {
1468 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1469 })
1470}
1471
1472pub fn check_socket_getpeername_access(
1475 current_task: &CurrentTask,
1476 socket: &Socket,
1477) -> Result<(), Errno> {
1478 track_hook_duration!("security.hooks.check_socket_getname_access");
1479 let Some(socket) = NonPrivateSocket::new(socket) else {
1480 return Ok(());
1481 };
1482 if_selinux_else_default_ok(current_task, |security_server| {
1483 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1484 })
1485}
1486
1487pub fn check_socket_shutdown_access(
1490 current_task: &CurrentTask,
1491 socket: &Socket,
1492 how: SocketShutdownFlags,
1493) -> Result<(), Errno> {
1494 track_hook_duration!("security.hooks.check_socket_shutdown_access");
1495 let Some(socket) = NonPrivateSocket::new(socket) else {
1496 return Ok(());
1497 };
1498 if_selinux_else_default_ok(current_task, |security_server| {
1499 selinux_hooks::socket::check_socket_shutdown_access(
1500 &security_server,
1501 current_task,
1502 socket,
1503 how,
1504 )
1505 })
1506}
1507
1508pub fn socket_getpeersec_stream(
1511 current_task: &CurrentTask,
1512 socket: &Socket,
1513) -> Result<Vec<u8>, Errno> {
1514 track_hook_duration!("security.hooks.socket_getpeersec_stream");
1515 let Some(socket) = NonPrivateSocket::new(socket) else {
1516 return Ok(Vec::default());
1517 };
1518 if_selinux_else_default_ok(current_task, |security_server| {
1519 selinux_hooks::socket::socket_getpeersec_stream(&security_server, current_task, socket)
1520 })
1521}
1522
1523pub fn socket_getpeersec_dgram(current_task: &CurrentTask, socket: &Socket) -> Vec<u8> {
1527 track_hook_duration!("security.hooks.socket_getpeersec_dgram");
1528 let Some(socket) = NonPrivateSocket::new(socket) else {
1529 return Vec::default();
1530 };
1531 if_selinux_else(
1532 current_task,
1533 |security_server| {
1534 selinux_hooks::socket::socket_getpeersec_dgram(&security_server, current_task, socket)
1535 },
1536 Vec::default,
1537 )
1538}
1539
1540pub fn unix_may_send(
1544 current_task: &CurrentTask,
1545 sending_socket: &Socket,
1546 receiving_socket: &Socket,
1547) -> Result<(), Errno> {
1548 track_hook_duration!("security.hooks.unix_may_send");
1549 let (Some(sending_socket), Some(receiving_socket)) =
1550 (NonPrivateSocket::new(sending_socket), NonPrivateSocket::new(receiving_socket))
1551 else {
1552 return Ok(());
1553 };
1554 if_selinux_else_default_ok(current_task, |security_server| {
1555 selinux_hooks::socket::unix_may_send(
1556 &security_server,
1557 current_task,
1558 sending_socket,
1559 receiving_socket,
1560 )
1561 })
1562}
1563
1564pub fn unix_stream_connect(
1568 current_task: &CurrentTask,
1569 client_socket: &Socket,
1570 listening_socket: &Socket,
1571 server_socket: &Socket,
1572) -> Result<(), Errno> {
1573 track_hook_duration!("security.hooks.unix_stream_connect");
1574 let (Some(client_socket), Some(listening_socket)) =
1575 (NonPrivateSocket::new(client_socket), NonPrivateSocket::new(listening_socket))
1576 else {
1577 return Ok(());
1578 };
1579 if_selinux_else_default_ok(current_task, |security_server| {
1580 selinux_hooks::socket::unix_stream_connect(
1581 &security_server,
1582 current_task,
1583 client_socket,
1584 listening_socket,
1585 server_socket,
1586 )
1587 })
1588}
1589
1590pub fn check_netlink_send_access(
1594 current_task: &CurrentTask,
1595 socket: &Socket,
1596 message_type: u16,
1597) -> Result<(), Errno> {
1598 track_hook_duration!("security.hooks.check_netlink_send_access");
1599 let Some(socket) = NonPrivateSocket::new(socket) else {
1600 return Ok(());
1601 };
1602 if_selinux_else_default_ok(current_task, |security_server| {
1603 selinux_hooks::netlink_socket::check_netlink_send_access(
1604 &security_server,
1605 current_task,
1606 socket,
1607 message_type,
1608 )
1609 })
1610}
1611
1612pub fn check_tun_dev_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1615 track_hook_duration!("security.hooks.check_tun_dev_create_access");
1616 if_selinux_else_default_ok(current_task, |security_server| {
1617 selinux_hooks::socket::check_tun_dev_create_access(&security_server, current_task)
1618 })
1619}
1620
1621pub fn bprm_creds_from_file(
1625 current_task: &CurrentTask,
1626 resolved_program: &mut ResolvedProgram,
1627) -> Result<(), Errno> {
1628 track_hook_duration!("security.hooks.bprm_creds_from_file");
1629 let (no_new_privs, is_ptraced_without_cap_sys_ptrace) = {
1630 let state = current_task.read();
1631 (state.no_new_privs(), state.is_ptraced_without_cap_sys_ptrace())
1632 };
1633 let is_unsafe_share_or_ptrace =
1634 is_ptraced_without_cap_sys_ptrace || current_task.has_shared_fs();
1635 let mask_caps = no_new_privs || is_unsafe_share_or_ptrace;
1636
1637 let enable_suid = current_task.kernel().features.enable_suid
1641 && !no_new_privs
1642 && (!is_unsafe_share_or_ptrace || is_task_capable_noaudit(current_task, CAP_SETUID));
1643 if enable_suid {
1644 resolved_program.file.name().apply_suid_and_sgid(&mut resolved_program.creds);
1645 }
1646
1647 resolved_program.creds.fsuid = resolved_program.creds.euid;
1649 resolved_program.creds.fsgid = resolved_program.creds.egid;
1650
1651 resolved_program.creds.saved_uid = resolved_program.creds.euid;
1657 resolved_program.creds.saved_gid = resolved_program.creds.egid;
1658
1659 common_cap::bprm_creds_from_file(current_task, resolved_program, mask_caps)
1660}
1661
1662pub fn bprm_creds_for_exec(
1667 current_task: &CurrentTask,
1668 resolved_program: &mut ResolvedProgram,
1669) -> Result<(), Errno> {
1670 track_hook_duration!("security.hooks.bprm_creds_for_exec");
1671 if let Some(state) = ¤t_task.kernel().security_state.state {
1672 if state.has_policy() {
1673 return selinux_hooks::task::bprm_creds_for_exec(
1674 &state.server,
1675 current_task,
1676 resolved_program,
1677 );
1678 } else {
1679 let previous_sid = current_task.current_creds().security_state.current_sid;
1681 resolved_program.creds.security_state =
1682 TaskAttrs::for_transition(InitialSid::Init.into(), previous_sid);
1683 }
1684 }
1685 Ok(())
1686}
1687
1688pub fn bprm_committing_creds(
1693 current_task: &CurrentTask,
1694 resolved_program: &ResolvedProgram,
1695) -> Result<(), Errno> {
1696 track_hook_duration!("security.hooks.bprm_committing_creds");
1697 if_selinux_else_default_ok(current_task, |security_server| {
1698 selinux_hooks::task::bprm_committing_creds(security_server, current_task, resolved_program);
1699 Ok(())
1700 })
1701}
1702
1703pub fn bprm_committed_creds(current_task: &CurrentTask) -> Result<(), Errno> {
1707 track_hook_duration!("security.hooks.bprm_committed_creds");
1708 if_selinux_else_default_ok(current_task, |security_server| {
1709 selinux_hooks::task::bprm_committed_creds(security_server, current_task);
1710 Ok(())
1711 })
1712}
1713
1714pub fn check_task_getscheduler_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1717 track_hook_duration!("security.hooks.task_getscheduler");
1718 if_selinux_else_default_ok(source, |security_server| {
1719 selinux_hooks::task::check_getsched_access(
1720 &selinux_hooks::build_permission_check(source, security_server),
1721 &source,
1722 &target,
1723 )
1724 })
1725}
1726
1727pub fn check_task_setscheduler_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1730 track_hook_duration!("security.hooks.task_setscheduler");
1731 if_selinux_else_default_ok(source, |security_server| {
1732 selinux_hooks::task::check_setsched_access(
1733 &selinux_hooks::build_permission_check(source, security_server),
1734 &source,
1735 &target,
1736 )
1737 })
1738}
1739
1740pub fn check_task_setnice_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1743 track_hook_duration!("security.hooks.check_task_setnice_access");
1744 if_selinux_else_default_ok(source, |security_server| {
1745 selinux_hooks::task::check_setsched_access(
1746 &selinux_hooks::build_permission_check(source, security_server),
1747 &source,
1748 &target,
1749 )
1750 })
1751}
1752
1753pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1756 track_hook_duration!("security.hooks.check_getpgid_access");
1757 if_selinux_else_default_ok(source, |security_server| {
1758 selinux_hooks::task::check_getpgid_access(
1759 &selinux_hooks::build_permission_check(source, security_server),
1760 &source,
1761 &target,
1762 )
1763 })
1764}
1765
1766pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1769 track_hook_duration!("security.hooks.check_setpgid_access");
1770 if_selinux_else_default_ok(source, |security_server| {
1771 selinux_hooks::task::check_setpgid_access(
1772 &selinux_hooks::build_permission_check(source, security_server),
1773 &source,
1774 &target,
1775 )
1776 })
1777}
1778
1779pub fn check_task_getsid(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1782 track_hook_duration!("security.hooks.check_task_getsid");
1783 if_selinux_else_default_ok(source, |security_server| {
1784 selinux_hooks::task::check_task_getsid(
1785 &selinux_hooks::build_permission_check(source, security_server),
1786 &source,
1787 &target,
1788 )
1789 })
1790}
1791
1792pub fn check_getcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1795 track_hook_duration!("security.hooks.check_getcap_access");
1796 if_selinux_else_default_ok(source, |security_server| {
1797 selinux_hooks::task::check_getcap_access(
1798 &selinux_hooks::build_permission_check(source, security_server),
1799 &source,
1800 &target,
1801 )
1802 })
1803}
1804
1805pub fn check_setcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1809 track_hook_duration!("security.hooks.check_setcap_access");
1810 if_selinux_else_default_ok(source, |security_server| {
1811 selinux_hooks::task::check_setcap_access(
1812 &selinux_hooks::build_permission_check(source, security_server),
1813 &source,
1814 &target,
1815 )
1816 })
1817}
1818
1819pub fn check_signal_access(
1822 source: &CurrentTask,
1823 target: &Task,
1824 signal: Signal,
1825) -> Result<(), Errno> {
1826 track_hook_duration!("security.hooks.check_signal_access");
1827 if_selinux_else_default_ok(source, |security_server| {
1828 selinux_hooks::task::check_signal_access(
1829 &selinux_hooks::build_permission_check(source, security_server),
1830 &source,
1831 &target,
1832 signal,
1833 )
1834 })
1835}
1836
1837pub fn check_syslog_access(source: &CurrentTask, action: SyslogAction) -> Result<(), Errno> {
1840 track_hook_duration!("security.hooks.check_syslog_access");
1841 if_selinux_else_default_ok(source, |security_server| {
1842 selinux_hooks::task::check_syslog_access(
1843 &selinux_hooks::build_permission_check(source, security_server),
1844 &source,
1845 action,
1846 )
1847 })
1848}
1849
1850pub fn ptrace_traceme(current_task: &CurrentTask, parent_tracer_task: &Task) -> Result<(), Errno> {
1853 track_hook_duration!("security.hooks.ptrace_traceme");
1854 yama::ptrace_traceme(current_task, parent_tracer_task)?;
1855 common_cap::ptrace_traceme(current_task, parent_tracer_task)?;
1856 if_selinux_else_default_ok(current_task, |security_server| {
1857 selinux_hooks::task::ptrace_traceme(
1858 &selinux_hooks::build_permission_check(current_task, security_server),
1859 current_task,
1860 parent_tracer_task,
1861 )
1862 })
1863}
1864
1865pub fn ptrace_access_check(
1868 current_task: &CurrentTask,
1869 tracee_task: &Task,
1870 mode: PtraceAccessMode,
1871) -> Result<(), Errno> {
1872 track_hook_duration!("security.hooks.ptrace_access_check");
1873 yama::ptrace_access_check(current_task, tracee_task, mode)?;
1874 common_cap::ptrace_access_check(current_task, tracee_task, mode)?;
1875 if_selinux_else_default_ok(current_task, |security_server| {
1876 selinux_hooks::task::ptrace_access_check(
1877 &selinux_hooks::build_permission_check(current_task, security_server),
1878 current_task,
1879 tracee_task,
1880 mode,
1881 )
1882 })
1883}
1884
1885pub fn task_prlimit(
1888 source: &CurrentTask,
1889 target: &Task,
1890 check_get_rlimit: bool,
1891 check_set_rlimit: bool,
1892) -> Result<(), Errno> {
1893 track_hook_duration!("security.hooks.task_prlimit");
1894 if_selinux_else_default_ok(source, |security_server| {
1895 selinux_hooks::task::task_prlimit(
1896 &selinux_hooks::build_permission_check(source, security_server),
1897 &source,
1898 &target,
1899 check_get_rlimit,
1900 check_set_rlimit,
1901 )
1902 })
1903}
1904
1905pub fn task_setrlimit(
1908 source: &CurrentTask,
1909 target: &Task,
1910 old_limit: rlimit,
1911 new_limit: rlimit,
1912) -> Result<(), Errno> {
1913 track_hook_duration!("security.hooks.task_setrlimit");
1914 if_selinux_else_default_ok(source, |security_server| {
1915 selinux_hooks::task::task_setrlimit(
1916 &selinux_hooks::build_permission_check(source, security_server),
1917 &source,
1918 &target,
1919 old_limit,
1920 new_limit,
1921 )
1922 })
1923}
1924
1925pub fn sb_kern_mount(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1928 track_hook_duration!("security.hooks.sb_kern_mount");
1929 if_selinux_else_default_ok(current_task, |security_server| {
1930 selinux_hooks::superblock::sb_kern_mount(
1931 &selinux_hooks::build_permission_check(current_task, security_server),
1932 current_task,
1933 fs,
1934 )
1935 })
1936}
1937
1938pub fn sb_mount(
1942 current_task: &CurrentTask,
1943 path: &NamespaceNode,
1944 flags: MountFlags,
1945) -> Result<(), Errno> {
1946 track_hook_duration!("security.hooks.sb_mount");
1947 let Some(fs_node) = NonPrivateFsNode::new(&path.entry.node) else {
1948 return Ok(());
1951 };
1952 if_selinux_else_default_ok(current_task, |security_server| {
1953 selinux_hooks::superblock::sb_mount(
1954 &selinux_hooks::build_permission_check(current_task, security_server),
1955 current_task,
1956 path,
1957 fs_node,
1958 flags,
1959 )
1960 })
1961}
1962
1963pub fn sb_remount(
1966 current_task: &CurrentTask,
1967 mount: &Mount,
1968 new_mount_options: FileSystemMountOptions,
1969) -> Result<(), Errno> {
1970 track_hook_duration!("security.hooks.sb_remount");
1971 if_selinux_else_default_ok(current_task, |security_server| {
1972 selinux_hooks::superblock::sb_remount(security_server, mount, new_mount_options)
1973 })
1974}
1975
1976pub fn sb_show_options<'a>(
1979 _kernel: &Kernel,
1980 fs: &'a FileSystem,
1981) -> Result<impl std::fmt::Display + 'a, Errno> {
1982 track_hook_duration!("security.hooks.sb_show_options");
1983 selinux_hooks::superblock::sb_show_options(fs)
1984}
1985
1986pub fn sb_statfs(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1989 track_hook_duration!("security.hooks.sb_statfs");
1990 if_selinux_else_default_ok(current_task, |security_server| {
1991 selinux_hooks::superblock::sb_statfs(
1992 &selinux_hooks::build_permission_check(current_task, security_server),
1993 current_task,
1994 fs,
1995 )
1996 })
1997}
1998
1999pub fn sb_umount(
2003 current_task: &CurrentTask,
2004 node: &NamespaceNode,
2005 flags: UnmountFlags,
2006) -> Result<(), Errno> {
2007 track_hook_duration!("security.hooks.sb_umount");
2008 if NonPrivateFsNode::new(&node.entry.node).is_none() {
2009 return Ok(());
2012 }
2013 if_selinux_else_default_ok(current_task, |security_server| {
2014 selinux_hooks::superblock::sb_umount(
2015 &selinux_hooks::build_permission_check(current_task, security_server),
2016 current_task,
2017 node,
2018 flags,
2019 )
2020 })
2021}
2022
2023pub fn check_fs_node_getattr_access(
2026 current_task: &CurrentTask,
2027 fs_node: &FsNode,
2028) -> Result<(), Errno> {
2029 track_hook_duration!("security.hooks.check_fs_node_getattr_access");
2030 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2031 return Ok(());
2032 };
2033 if_selinux_else_default_ok(current_task, |security_server| {
2034 selinux_hooks::fs_node::check_fs_node_getattr_access(security_server, current_task, fs_node)
2035 })
2036}
2037
2038pub fn path_notify(
2042 current_task: &CurrentTask,
2043 fs_node: &FsNode,
2044 mask: InotifyMask,
2045) -> Result<(), Errno> {
2046 track_hook_duration!("security.hooks.path_notify");
2047 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2048 return Ok(());
2049 };
2050 if_selinux_else_default_ok(current_task, |security_server| {
2051 selinux_hooks::fs_node::path_notify(security_server, current_task, fs_node, mask)
2052 })
2053}
2054
2055pub fn fs_node_xattr_skipcap(current_task: &CurrentTask, name: &FsStr) -> bool {
2058 common_cap::fs_node_xattr_skipcap(name)
2059 || (current_task.kernel().security_state.state.is_some()
2060 && selinux_hooks::fs_node::fs_node_xattr_skipcap(name))
2061}
2062
2063pub fn check_fs_node_setxattr_access(
2069 current_task: &CurrentTask,
2070 fs_node: &FsNode,
2071 name: &FsStr,
2072 value: &[u8],
2073 op: XattrOp,
2074) -> Result<(), Errno> {
2075 track_hook_duration!("security.hooks.check_fs_node_setxattr_access");
2076 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2077 return Ok(());
2078 };
2079 common_cap::fs_node_setxattr(current_task, fs_node, name, value, op)?;
2080 if_selinux_else_default_ok(current_task, |security_server| {
2081 selinux_hooks::fs_node::check_fs_node_setxattr_access(
2082 security_server,
2083 current_task,
2084 fs_node,
2085 name,
2086 value,
2087 op,
2088 )
2089 })
2090}
2091
2092pub fn check_fs_node_getxattr_access(
2094 current_task: &CurrentTask,
2095 fs_node: &FsNode,
2096 name: &FsStr,
2097) -> Result<(), Errno> {
2098 track_hook_duration!("security.hooks.check_fs_node_getxattr_access");
2099 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2100 return Ok(());
2101 };
2102 if_selinux_else_default_ok(current_task, |security_server| {
2103 selinux_hooks::fs_node::check_fs_node_getxattr_access(
2104 security_server,
2105 current_task,
2106 fs_node,
2107 name,
2108 )
2109 })
2110}
2111
2112pub fn check_fs_node_listxattr_access(
2114 current_task: &CurrentTask,
2115 fs_node: &FsNode,
2116) -> Result<(), Errno> {
2117 track_hook_duration!("security.hooks.check_fs_node_listxattr_access");
2118 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2119 return Ok(());
2120 };
2121 if_selinux_else_default_ok(current_task, |security_server| {
2122 selinux_hooks::fs_node::check_fs_node_listxattr_access(
2123 security_server,
2124 current_task,
2125 fs_node,
2126 )
2127 })
2128}
2129
2130pub fn check_fs_node_removexattr_access(
2132 current_task: &CurrentTask,
2133 fs_node: &FsNode,
2134 name: &FsStr,
2135) -> Result<(), Errno> {
2136 track_hook_duration!("security.hooks.check_fs_node_removexattr_access");
2137 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2138 return Ok(());
2139 };
2140 common_cap::fs_node_removexattr(current_task, fs_node, name)?;
2141 if_selinux_else_default_ok(current_task, |security_server| {
2142 selinux_hooks::fs_node::check_fs_node_removexattr_access(
2143 security_server,
2144 current_task,
2145 fs_node,
2146 name,
2147 )
2148 })
2149}
2150
2151pub fn fs_node_needs_killpriv(current_task: &CurrentTask, fs_node: &FsNode) -> Result<bool, Errno> {
2156 track_hook_duration!("security.hooks.fs_node_needs_killpriv");
2157 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2158 return Ok(false);
2159 };
2160 common_cap::fs_node_needs_killpriv(current_task, fs_node)
2161}
2162
2163pub fn fs_node_killpriv(current_task: &CurrentTask, fs_node: &FsNode) -> Result<(), Errno> {
2168 track_hook_duration!("security.hooks.fs_node_killpriv");
2169 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2170 return Ok(());
2171 };
2172 common_cap::fs_node_killpriv(current_task, fs_node)
2173}
2174
2175pub fn fs_node_listsecurity(current_task: &CurrentTask, fs_node: &FsNode) -> Option<FsString> {
2182 track_hook_duration!("security.hooks.fs_node_listsecurity");
2183 let Some(fs_node) = NonPrivateFsNode::new(fs_node) else {
2184 return None;
2185 };
2186 if_selinux_else(
2187 current_task,
2188 |_| selinux_hooks::fs_node::fs_node_listsecurity(fs_node),
2189 || None,
2190 )
2191}
2192
2193pub fn fs_node_getsecurity(
2201 current_task: &CurrentTask,
2202 fs_node: &FsNode,
2203 name: &FsStr,
2204 max_size: usize,
2205) -> Result<ValueOrSize<Box<[u8]>>, Errno> {
2206 track_hook_duration!("security.hooks.fs_node_getsecurity");
2207 let Some(non_private_node) = NonPrivateFsNode::new(fs_node) else {
2208 return fs_node.ops().get_xattr(fs_node, current_task, name, max_size);
2209 };
2210 let result = if_selinux_else(
2211 current_task,
2212 |security_server| {
2213 selinux_hooks::fs_node::fs_node_getsecurity(
2214 security_server,
2215 current_task,
2216 non_private_node,
2217 name,
2218 max_size,
2219 )
2220 .transpose()
2221 },
2222 || None,
2223 );
2224 let result = result.or_else(|| {
2225 common_cap::fs_node_getsecurity(current_task, non_private_node, name, max_size).transpose()
2226 });
2227 result.unwrap_or_else(|| fs_node.ops().get_xattr(fs_node, current_task, name, max_size))
2228}
2229
2230pub fn fs_node_setsecurity(
2236 current_task: &CurrentTask,
2237 fs_node: &FsNode,
2238 name: &FsStr,
2239 value: &[u8],
2240 op: XattrOp,
2241) -> Result<(), Errno> {
2242 track_hook_duration!("security.hooks.fs_node_setsecurity");
2243 let Some(non_private_node) = NonPrivateFsNode::new(fs_node) else {
2244 return fs_node.ops().set_xattr(fs_node, current_task, name, value, op);
2245 };
2246 let result = if_selinux_else(
2247 current_task,
2248 |security_server| {
2249 selinux_hooks::fs_node::fs_node_setsecurity(
2250 security_server,
2251 current_task,
2252 non_private_node,
2253 name,
2254 value,
2255 op,
2256 )
2257 .transpose()
2258 },
2259 || None,
2260 );
2261 let result = result.or_else(|| {
2262 common_cap::fs_node_setsecurity(current_task, non_private_node, name, value, op).transpose()
2263 });
2264 result.unwrap_or_else(|| fs_node.ops().set_xattr(fs_node, current_task, name, value, op))
2265}
2266
2267pub fn check_bpf_access<Attr: FromBytes>(
2271 current_task: &CurrentTask,
2272 cmd: bpf_cmd,
2273 attr: &Attr,
2274 attr_size: u32,
2275) -> Result<(), Errno> {
2276 track_hook_duration!("security.hooks.check_bpf_access");
2277 if_selinux_else_default_ok(current_task, |security_server| {
2278 selinux_hooks::bpf::check_bpf_access(security_server, current_task, cmd, attr, attr_size)
2279 })
2280}
2281
2282pub fn check_bpf_map_access(
2286 current_task: &CurrentTask,
2287 bpf_map_state: &BpfMapState,
2288 flags: PermissionFlags,
2289) -> Result<(), Errno> {
2290 track_hook_duration!("security.hooks.check_bpf_map_access");
2291 if_selinux_else_default_ok(current_task, |security_server| {
2292 let subject_sid = current_task_state(current_task).current_sid;
2293 selinux_hooks::bpf::check_bpf_map_access(
2294 security_server,
2295 current_task,
2296 subject_sid,
2297 bpf_map_state,
2298 flags,
2299 )
2300 })
2301}
2302
2303pub fn check_bpf_prog_access(
2308 current_task: &CurrentTask,
2309 bpf_program_state: &BpfProgState,
2310) -> Result<(), Errno> {
2311 track_hook_duration!("security.hooks.check_bpf_prog_access");
2312 if_selinux_else_default_ok(current_task, |security_server| {
2313 let subject_sid = current_task_state(current_task).current_sid;
2314 selinux_hooks::bpf::check_bpf_prog_access(
2315 security_server,
2316 current_task,
2317 subject_sid,
2318 bpf_program_state,
2319 )
2320 })
2321}
2322
2323pub fn check_perf_event_open_access(
2328 current_task: &CurrentTask,
2329 perf_event_open_type: PerfEventOpenType,
2330) -> Result<(), Errno> {
2331 track_hook_duration!("security.hooks.check_perf_event_open_access");
2332 if_selinux_else_default_ok(current_task, |security_server| {
2333 selinux_hooks::perf_event::check_perf_event_open_access(
2334 security_server,
2335 current_task,
2336 perf_event_open_type,
2337 )
2338 })
2339}
2340
2341pub fn perf_event_alloc(current_task: &CurrentTask) -> PerfEventState {
2345 track_hook_duration!("security.hooks.perf_event_alloc");
2346 PerfEventState { state: selinux_hooks::perf_event::perf_event_alloc(current_task) }
2347}
2348
2349pub fn check_perf_event_read_access(
2352 current_task: &CurrentTask,
2353 perf_event_file: &PerfEventFile,
2354) -> Result<(), Errno> {
2355 track_hook_duration!("security.hooks.check_perf_event_read_access");
2356 if_selinux_else_default_ok(current_task, |security_server| {
2357 selinux_hooks::perf_event::check_perf_event_read_access(
2358 security_server,
2359 current_task,
2360 perf_event_file,
2361 )
2362 })
2363}
2364
2365pub fn check_perf_event_write_access(
2368 current_task: &CurrentTask,
2369 perf_event_file: &PerfEventFile,
2370) -> Result<(), Errno> {
2371 track_hook_duration!("security.hooks.check_perf_event_write_access");
2372 if_selinux_else_default_ok(current_task, |security_server| {
2373 selinux_hooks::perf_event::check_perf_event_write_access(
2374 security_server,
2375 current_task,
2376 perf_event_file,
2377 )
2378 })
2379}
2380
2381#[derive(Debug, Clone, Copy, PartialEq)]
2383pub enum ProcAttr {
2384 Current,
2385 Exec,
2386 FsCreate,
2387 KeyCreate,
2388 Previous,
2389 SockCreate,
2390}
2391
2392pub fn get_procattr(
2395 current_task: &CurrentTask,
2396 target: &Task,
2397 attr: ProcAttr,
2398) -> Result<Vec<u8>, Errno> {
2399 track_hook_duration!("security.hooks.get_procattr");
2400 if_selinux_else(
2401 current_task,
2402 |security_server| {
2403 selinux_hooks::task::get_procattr(security_server, current_task, target, attr)
2404 },
2405 || error!(EINVAL),
2407 )
2408}
2409
2410pub fn set_procattr(
2413 current_task: &CurrentTask,
2414 attr: ProcAttr,
2415 context: &[u8],
2416) -> Result<(), Errno> {
2417 track_hook_duration!("security.hooks.set_procattr");
2418 if_selinux_else(
2419 current_task,
2420 |security_server| {
2421 selinux_hooks::task::set_procattr(security_server, current_task, attr, context)
2422 },
2423 || error!(EINVAL),
2425 )
2426}
2427
2428pub fn fs_is_xattr_labeled(fs: FileSystemHandle) -> bool {
2430 fs.security_state.state.supports_xattr()
2431}
2432
2433pub fn selinuxfs_init_null(current_task: &CurrentTask, null_fs_node: &FileHandle) {
2436 selinux_hooks::selinuxfs::selinuxfs_init_null(current_task, null_fs_node)
2439}
2440
2441pub fn selinuxfs_policy_loaded(current_task: &CurrentTask) {
2447 track_hook_duration!("security.hooks.selinuxfs_policy_loaded");
2448 selinux_hooks::selinuxfs::selinuxfs_policy_loaded(current_task)
2449}
2450
2451pub fn selinuxfs_get_admin_api(current_task: &CurrentTask) -> Option<Arc<SecurityServer>> {
2455 current_task.kernel().security_state.state.as_ref().map(|state| state.server.clone())
2456}
2457
2458pub fn selinuxfs_check_access(
2461 current_task: &CurrentTask,
2462 permission: SecurityPermission,
2463) -> Result<(), Errno> {
2464 track_hook_duration!("security.hooks.selinuxfs_check_access");
2465 if_selinux_else_default_ok(current_task, |security_server| {
2466 selinux_hooks::selinuxfs::selinuxfs_check_access(security_server, current_task, permission)
2467 })
2468}
2469
2470pub fn creds_start_internal_operation(current_task: &CurrentTask) -> Arc<Credentials> {
2473 track_hook_duration!("security.hooks.creds_start_internal_operation");
2474 let mut creds = Credentials::clone(¤t_task.current_creds());
2475 creds.security_state.internal_operation = true;
2476 creds.into()
2477}
2478
2479pub mod testing {
2480 use super::{Arc, KernelState, SecurityServer, selinux_hooks};
2481 use starnix_sync::LockDepMutex;
2482 use std::sync::OnceLock;
2483 use std::sync::atomic::AtomicU64;
2484
2485 pub fn kernel_state(security_server: Option<Arc<SecurityServer>>) -> KernelState {
2488 let state = security_server.map(|server| selinux_hooks::KernelState {
2489 server,
2490 pending_file_systems: LockDepMutex::default(),
2491 selinuxfs_null: OnceLock::default(),
2492 access_denial_count: AtomicU64::new(0u64),
2493 has_policy: false.into(),
2494 _inspect_node: fuchsia_inspect::Node::default(),
2495 });
2496 KernelState { state }
2497 }
2498}
2499
2500#[cfg(test)]
2501mod tests {
2502 use super::*;
2503 use crate::device::mem::new_null_file;
2504 use crate::mm::DumpPolicy;
2505 use crate::security;
2506 use crate::security::selinux_hooks::get_cached_sid;
2507 use crate::security::selinux_hooks::testing::{
2508 self, spawn_kernel_with_selinux_hooks_test_policy_and_run,
2509 };
2510 use crate::testing::{
2511 create_task, create_task_with_security_context, spawn_kernel_and_run,
2512 spawn_kernel_with_selinux_and_run,
2513 };
2514 use linux_uapi::{XATTR_NAME_CAPS, XATTR_NAME_SELINUX};
2515 use selinux::InitialSid;
2516 use starnix_uapi::auth::{
2517 CAP_SYS_ADMIN, CAP_SYS_PTRACE, PTRACE_MODE_ATTACH, PTRACE_MODE_ATTACH_REALCREDS,
2518 PTRACE_MODE_NOAUDIT, PTRACE_MODE_READ_FSCREDS,
2519 };
2520 use starnix_uapi::signals::SIGTERM;
2521 use std::ffi::CString;
2522 use std::sync::atomic::Ordering;
2523
2524 const VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_valid_t:s0";
2525 const VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] = b"u:object_r:test_valid_t:s0\0";
2526
2527 const DIFFERENT_VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_different_valid_t:s0";
2528 const DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] =
2529 b"u:object_r:test_different_valid_t:s0\0";
2530
2531 const INVALID_SECURITY_CONTEXT_INTERNAL_NUL: &[u8] = b"u:object_r:test_valid_\0t:s0";
2532
2533 const INVALID_SECURITY_CONTEXT: &[u8] = b"not_a_u:object_r:test_valid_t:s0";
2534
2535 #[derive(Default, Debug, PartialEq)]
2536 enum TestHookResult {
2537 WasRun,
2538 WasNotRun,
2539 #[default]
2540 WasNotRunDefault,
2541 }
2542
2543 #[fuchsia::test]
2544 async fn if_selinux_else_disabled() {
2545 spawn_kernel_and_run(async |current_task| {
2546 assert!(current_task.kernel().security_state.state.is_none());
2547
2548 let check_result =
2549 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2550 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2551
2552 let run_else_result = if_selinux_else(
2553 current_task,
2554 |_| TestHookResult::WasRun,
2555 || TestHookResult::WasNotRun,
2556 );
2557 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2558 })
2559 .await;
2560 }
2561
2562 #[fuchsia::test]
2563 async fn if_selinux_else_without_policy() {
2564 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2565 let check_result =
2566 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2567 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2568
2569 let run_else_result = if_selinux_else(
2570 current_task,
2571 |_| TestHookResult::WasRun,
2572 || TestHookResult::WasNotRun,
2573 );
2574 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2575 })
2576 .await;
2577 }
2578
2579 #[fuchsia::test]
2580 async fn if_selinux_else_with_policy() {
2581 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2582 let check_result =
2583 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2584 assert_eq!(check_result, Ok(TestHookResult::WasRun));
2585
2586 let run_else_result = if_selinux_else(
2587 current_task,
2588 |_| TestHookResult::WasRun,
2589 || TestHookResult::WasNotRun,
2590 );
2591 assert_eq!(run_else_result, TestHookResult::WasRun);
2592 })
2593 .await;
2594 }
2595
2596 #[fuchsia::test]
2597 async fn task_create_access_allowed_for_selinux_disabled() {
2598 spawn_kernel_and_run(async |current_task| {
2599 assert!(current_task.kernel().security_state.state.is_none());
2600 assert_eq!(check_task_create_access(current_task), Ok(()));
2601 })
2602 .await;
2603 }
2604
2605 #[fuchsia::test]
2606 async fn task_create_access_allowed_for_permissive_mode() {
2607 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2608 assert_eq!(check_task_create_access(current_task), error!(EACCES));
2609 security_server.set_enforcing(false);
2610 assert_eq!(check_task_create_access(current_task), Ok(()));
2611 })
2612 .await;
2613 }
2614
2615 #[fuchsia::test]
2616 async fn exec_access_allowed_for_selinux_disabled() {
2617 spawn_kernel_and_run(async |current_task| {
2618 assert!(current_task.kernel().security_state.state.is_none());
2619 let executable = testing::create_test_file(current_task);
2620 let file = testing::open_test_file(current_task, &executable);
2621 let mut resolved_program = testing::make_resolved_program(current_task, file);
2622 assert_eq!(bprm_creds_for_exec(current_task, &mut resolved_program), Ok(()));
2623 })
2624 .await;
2625 }
2626
2627 #[fuchsia::test]
2628 async fn exec_access_allowed_for_permissive_mode() {
2629 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2630 security_server.set_enforcing(false);
2631 let executable = testing::create_test_file(current_task);
2632 let file = testing::open_test_file(current_task, &executable);
2633 let mut resolved_program = testing::make_resolved_program(current_task, file);
2634 let result = bprm_creds_for_exec(current_task, &mut resolved_program);
2636 assert!(result.is_ok());
2637 })
2638 .await;
2639 }
2640
2641 #[fuchsia::test]
2642 async fn exec_no_state_update_for_selinux_disabled() {
2643 spawn_kernel_and_run(async |current_task| {
2644 let target_sid = InitialSid::Unlabeled.into();
2645
2646 assert!(selinux_hooks::current_task_state(current_task).current_sid != target_sid);
2647
2648 testing::mutate_attrs_for_test(current_task, |attrs| {
2650 attrs.exec_sid = Some(target_sid);
2651 });
2652
2653 let executable = testing::create_test_file(current_task);
2654 let file = testing::open_test_file(current_task, &executable);
2655 let mut resolved_program = testing::make_resolved_program(current_task, file);
2656
2657 let before_hook_sid = selinux_hooks::current_task_state(current_task).current_sid;
2658
2659 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2660 assert_eq!(resolved_program.creds.security_state.current_sid, before_hook_sid);
2661 })
2662 .await;
2663 }
2664
2665 #[fuchsia::test]
2666 async fn exec_initial_context_for_selinux_without_policy() {
2667 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2668 let elf_sid = InitialSid::Unlabeled.into();
2669 assert_ne!(selinux_hooks::current_task_state(current_task).current_sid, elf_sid);
2670 assert_ne!(
2671 selinux_hooks::current_task_state(current_task).current_sid,
2672 InitialSid::Init.into()
2673 );
2674
2675 testing::mutate_attrs_for_test(current_task, |attrs| {
2677 attrs.exec_sid = Some(elf_sid);
2678 });
2679
2680 let executable = testing::create_test_file(current_task);
2681 let file = testing::open_test_file(current_task, &executable);
2682 let mut resolved_program = testing::make_resolved_program(current_task, file);
2683
2684 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2685
2686 assert_eq!(resolved_program.creds.security_state.current_sid, InitialSid::Init.into());
2687 })
2688 .await;
2689 }
2690
2691 #[fuchsia::test]
2692 async fn exec_state_update_for_permissive_mode() {
2693 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2694 security_server.set_enforcing(false);
2695 let elf_sid = security_server
2696 .security_context_to_sid(b"u:object_r:fork_no_t:s0".into())
2697 .expect("invalid security context");
2698
2699 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).current_sid);
2700
2701 testing::mutate_attrs_for_test(current_task, |attrs| {
2703 attrs.exec_sid = Some(elf_sid);
2704 });
2705
2706 let executable = testing::create_test_file(current_task);
2707 let file = testing::open_test_file(current_task, &executable);
2708 let mut resolved_program = testing::make_resolved_program(current_task, file);
2709
2710 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2711 assert_eq!(resolved_program.creds.security_state.current_sid, elf_sid);
2712 })
2713 .await;
2714 }
2715
2716 #[fuchsia::test]
2717 async fn getsched_access_allowed_for_selinux_disabled() {
2718 spawn_kernel_and_run(async |current_task| {
2719 let another_task = create_task(¤t_task.kernel(), "another-task");
2720 assert_eq!(check_task_getscheduler_access(current_task, &another_task), Ok(()));
2721 })
2722 .await;
2723 }
2724
2725 #[fuchsia::test]
2726 async fn getsched_access_allowed_for_permissive_mode() {
2727 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2728 let another_task = create_task(¤t_task.kernel(), "another-task");
2729 assert_eq!(check_task_getscheduler_access(current_task, &another_task), error!(EACCES));
2730 security_server.set_enforcing(false);
2731 assert_eq!(check_task_getscheduler_access(current_task, &another_task), Ok(()));
2732 })
2733 .await;
2734 }
2735
2736 #[fuchsia::test]
2737 async fn setsched_access_allowed_for_selinux_disabled() {
2738 spawn_kernel_and_run(async |current_task| {
2739 let another_task = create_task(¤t_task.kernel(), "another-task");
2740 assert_eq!(check_task_setscheduler_access(current_task, &another_task), Ok(()));
2741 })
2742 .await;
2743 }
2744
2745 #[fuchsia::test]
2746 async fn setsched_access_allowed_for_permissive_mode() {
2747 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2748 let another_task = create_task(¤t_task.kernel(), "another-task");
2749 assert_eq!(check_task_setscheduler_access(current_task, &another_task), error!(EACCES));
2750 security_server.set_enforcing(false);
2751 assert_eq!(check_task_setscheduler_access(current_task, &another_task), Ok(()));
2752 })
2753 .await;
2754 }
2755
2756 #[fuchsia::test]
2757 async fn getpgid_access_allowed_for_selinux_disabled() {
2758 spawn_kernel_and_run(async |current_task| {
2759 let another_task = create_task(¤t_task.kernel(), "another-task");
2760 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2761 })
2762 .await;
2763 }
2764
2765 #[fuchsia::test]
2766 async fn getpgid_access_allowed_for_permissive_mode() {
2767 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2768 let another_task = create_task(¤t_task.kernel(), "another-task");
2769 assert_eq!(check_getpgid_access(current_task, &another_task), error!(EACCES));
2770 security_server.set_enforcing(false);
2771 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2772 })
2773 .await;
2774 }
2775
2776 #[fuchsia::test]
2777 async fn setpgid_access_allowed_for_selinux_disabled() {
2778 spawn_kernel_and_run(async |current_task| {
2779 let another_task = create_task(¤t_task.kernel(), "another-task");
2780 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2781 })
2782 .await;
2783 }
2784
2785 #[fuchsia::test]
2786 async fn setpgid_access_allowed_for_permissive_mode() {
2787 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2788 let another_task = create_task(¤t_task.kernel(), "another-task");
2789 assert_eq!(check_setpgid_access(current_task, &another_task), error!(EACCES));
2790 security_server.set_enforcing(false);
2791 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2792 })
2793 .await;
2794 }
2795
2796 #[fuchsia::test]
2797 async fn task_getsid_allowed_for_selinux_disabled() {
2798 spawn_kernel_and_run(async |current_task| {
2799 let another_task = create_task(¤t_task.kernel(), "another-task");
2800 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2801 })
2802 .await;
2803 }
2804
2805 #[fuchsia::test]
2806 async fn task_getsid_allowed_for_permissive_mode() {
2807 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2808 let another_task = create_task(¤t_task.kernel(), "another-task");
2809 assert_eq!(check_task_getsid(current_task, &another_task), error!(EACCES));
2810 security_server.set_enforcing(false);
2811 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2812 })
2813 .await;
2814 }
2815
2816 #[fuchsia::test]
2817 async fn signal_access_allowed_for_selinux_disabled() {
2818 spawn_kernel_and_run(async |current_task| {
2819 let another_task = create_task(¤t_task.kernel(), "another-task");
2820 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2821 })
2822 .await;
2823 }
2824
2825 #[fuchsia::test]
2826 async fn signal_access_allowed_for_permissive_mode() {
2827 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2828 let another_task = create_task(¤t_task.kernel(), "another-task");
2829 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), error!(EACCES));
2830 security_server.set_enforcing(false);
2831 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2832 })
2833 .await;
2834 }
2835
2836 #[fuchsia::test]
2837 async fn ptrace_traceme_access_allowed_for_selinux_disabled() {
2838 spawn_kernel_and_run(async |current_task| {
2839 let another_task = create_task(¤t_task.kernel(), "another-task");
2840 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2841 })
2842 .await;
2843 }
2844
2845 #[fuchsia::test]
2846 async fn ptrace_traceme_access_allowed_for_permissive_mode() {
2847 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2848 let another_task = create_task(¤t_task.kernel(), "another-task");
2849 assert_eq!(ptrace_traceme(current_task, &another_task), error!(EACCES));
2850 security_server.set_enforcing(false);
2851 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2852 })
2853 .await;
2854 }
2855
2856 #[fuchsia::test]
2857 async fn ptrace_attach_access_allowed_for_selinux_disabled() {
2858 spawn_kernel_and_run(async |current_task| {
2859 let another_task = create_task(¤t_task.kernel(), "another-task");
2860 assert_eq!(
2861 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2862 Ok(())
2863 );
2864 })
2865 .await;
2866 }
2867
2868 #[fuchsia::test]
2869 async fn ptrace_attach_access_allowed_for_permissive_mode() {
2870 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2871 let another_task = create_task(¤t_task.kernel(), "another-task");
2872 assert_eq!(
2873 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2874 error!(EACCES)
2875 );
2876 security_server.set_enforcing(false);
2877 assert_eq!(
2878 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2879 Ok(())
2880 );
2881 })
2882 .await;
2883 }
2884
2885 #[fuchsia::test]
2886 async fn task_prlimit_access_allowed_for_selinux_disabled() {
2887 spawn_kernel_and_run(async |current_task| {
2888 let another_task = create_task(¤t_task.kernel(), "another-task");
2889 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2890 })
2891 .await;
2892 }
2893
2894 #[fuchsia::test]
2895 async fn task_prlimit_access_allowed_for_permissive_mode() {
2896 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2897 let another_task = create_task(¤t_task.kernel(), "another-task");
2898 assert_eq!(task_prlimit(current_task, &another_task, true, true), error!(EACCES));
2899 security_server.set_enforcing(false);
2900 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2901 })
2902 .await;
2903 }
2904
2905 #[fuchsia::test]
2906 async fn fs_node_task_to_fs_node_noop_selinux_disabled() {
2907 spawn_kernel_and_run(async |current_task| {
2908 let node = &testing::create_test_file(current_task).entry.node;
2909 task_to_fs_node(current_task, ¤t_task.task, &node);
2910 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2911 })
2912 .await;
2913 }
2914
2915 #[fuchsia::test]
2916 async fn fs_node_setsecurity_selinux_disabled_only_sets_xattr() {
2917 spawn_kernel_and_run(async |current_task| {
2918 let node = &testing::create_test_file(current_task).entry.node;
2919
2920 fs_node_setsecurity(
2921 ¤t_task,
2922 &node,
2923 XATTR_NAME_SELINUX.to_bytes().into(),
2924 VALID_SECURITY_CONTEXT.into(),
2925 XattrOp::Set,
2926 )
2927 .expect("set_xattr(security.selinux) failed");
2928
2929 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2930 })
2931 .await;
2932 }
2933
2934 #[fuchsia::test]
2935 async fn fs_node_setsecurity_selinux_without_policy_only_sets_xattr() {
2936 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2937 let node = &testing::create_test_file(current_task).entry.node;
2938 fs_node_setsecurity(
2939 ¤t_task,
2940 &node,
2941 XATTR_NAME_SELINUX.to_bytes().into(),
2942 VALID_SECURITY_CONTEXT.into(),
2943 XattrOp::Set,
2944 )
2945 .expect("set_xattr(security.selinux) failed");
2946
2947 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2948 })
2949 .await;
2950 }
2951
2952 #[fuchsia::test]
2953 async fn fs_node_xattr_skipcap_requires_active_lsm() {
2954 spawn_kernel_and_run(async |current_task| {
2955 let node = &testing::create_test_file(current_task).entry.node;
2956 let mount = ¤t_task.fs().root().mount;
2957
2958 assert!(!fs_node_xattr_skipcap(current_task, XATTR_NAME_SELINUX.to_bytes().into()));
2959 assert!(fs_node_xattr_skipcap(current_task, XATTR_NAME_CAPS.to_bytes().into()));
2960
2961 let mut creds = Credentials::clone(¤t_task.current_creds());
2962 creds.cap_effective &= !CAP_SYS_ADMIN;
2963 current_task.set_creds(creds);
2964
2965 assert_eq!(
2966 node.set_xattr(
2967 current_task,
2968 mount,
2969 XATTR_NAME_SELINUX.to_bytes().into(),
2970 VALID_SECURITY_CONTEXT.into(),
2971 XattrOp::Set,
2972 ),
2973 error!(EPERM)
2974 );
2975 assert_eq!(
2976 node.remove_xattr(current_task, mount, XATTR_NAME_SELINUX.to_bytes().into()),
2977 error!(EPERM)
2978 );
2979 })
2980 .await;
2981
2982 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2983 let node = &testing::create_test_file(current_task).entry.node;
2984 let mount = ¤t_task.fs().root().mount;
2985
2986 assert!(fs_node_xattr_skipcap(current_task, XATTR_NAME_SELINUX.to_bytes().into()));
2987 assert!(fs_node_xattr_skipcap(current_task, XATTR_NAME_CAPS.to_bytes().into()));
2988
2989 let mut creds = Credentials::clone(¤t_task.current_creds());
2990 creds.cap_effective &= !CAP_SYS_ADMIN;
2991 current_task.set_creds(creds);
2992
2993 assert_eq!(
2994 node.set_xattr(
2995 current_task,
2996 mount,
2997 XATTR_NAME_SELINUX.to_bytes().into(),
2998 VALID_SECURITY_CONTEXT.into(),
2999 XattrOp::Set,
3000 ),
3001 Ok(())
3002 );
3003 assert_eq!(
3004 node.remove_xattr(current_task, mount, XATTR_NAME_SELINUX.to_bytes().into()),
3005 Ok(())
3006 );
3007 })
3008 .await;
3009
3010 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3011 let node = &testing::create_test_file(current_task).entry.node;
3012 let mount = ¤t_task.fs().root().mount;
3013
3014 assert!(fs_node_xattr_skipcap(current_task, XATTR_NAME_SELINUX.to_bytes().into()));
3015 assert!(fs_node_xattr_skipcap(current_task, XATTR_NAME_CAPS.to_bytes().into()));
3016
3017 let mut creds = Credentials::clone(¤t_task.current_creds());
3018 creds.cap_effective &= !CAP_SYS_ADMIN;
3019 current_task.set_creds(creds);
3020
3021 assert_eq!(
3022 node.remove_xattr(current_task, mount, XATTR_NAME_SELINUX.to_bytes().into()),
3023 error!(EACCES)
3024 );
3025 })
3026 .await;
3027 }
3028
3029 #[fuchsia::test]
3030 async fn fs_node_setsecurity_selinux_permissive_sets_xattr_and_label() {
3031 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3032 security_server.set_enforcing(false);
3033 let expected_sid = security_server
3034 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
3035 .expect("no SID for VALID_SECURITY_CONTEXT");
3036 let node = &testing::create_test_file(¤t_task).entry.node;
3037
3038 assert_ne!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
3040
3041 fs_node_setsecurity(
3042 ¤t_task,
3043 &node,
3044 XATTR_NAME_SELINUX.to_bytes().into(),
3045 VALID_SECURITY_CONTEXT.into(),
3046 XattrOp::Set,
3047 )
3048 .expect("set_xattr(security.selinux) failed");
3049
3050 assert_eq!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
3053 })
3054 .await;
3055 }
3056
3057 #[fuchsia::test]
3058 async fn fs_node_setsecurity_not_selinux_only_sets_xattr() {
3059 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3060 let valid_security_context_sid = security_server
3061 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
3062 .expect("no SID for VALID_SECURITY_CONTEXT");
3063 let node = &testing::create_test_file(current_task).entry.node;
3064 let whatever_sid = selinux_hooks::get_cached_sid(node);
3068 assert_ne!(Some(valid_security_context_sid), whatever_sid);
3069
3070 fs_node_setsecurity(
3071 ¤t_task,
3072 &node,
3073 "security.selinu!".into(), VALID_SECURITY_CONTEXT.into(),
3075 XattrOp::Set,
3076 )
3077 .expect("set_xattr(security.selinux) failed");
3078
3079 assert_eq!(whatever_sid, selinux_hooks::get_cached_sid(node));
3081 })
3082 .await;
3083 }
3084
3085 #[fuchsia::test]
3086 async fn fs_node_setsecurity_selinux_enforcing_invalid_context_fails() {
3087 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3088 let node = &testing::create_test_file(current_task).entry.node;
3089
3090 let before_sid = selinux_hooks::get_cached_sid(node);
3091 assert_ne!(Some(InitialSid::Unlabeled.into()), before_sid);
3092
3093 assert!(
3094 check_fs_node_setxattr_access(
3095 ¤t_task,
3096 &node,
3097 XATTR_NAME_SELINUX.to_bytes().into(),
3098 b"!", XattrOp::Set,
3100 )
3101 .is_err()
3102 );
3103
3104 assert_eq!(before_sid, selinux_hooks::get_cached_sid(node));
3105 })
3106 .await;
3107 }
3108
3109 #[fuchsia::test]
3110 async fn fs_node_setsecurity_selinux_permissive_invalid_context_sets_xattr_and_label() {
3111 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3112 security_server.set_enforcing(false);
3113 let node = &testing::create_test_file(current_task).entry.node;
3114
3115 assert_ne!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
3116
3117 fs_node_setsecurity(
3118 ¤t_task,
3119 &node,
3120 XATTR_NAME_SELINUX.to_bytes().into(),
3121 b"!", XattrOp::Set,
3123 )
3124 .expect("set_xattr(security.selinux) failed");
3125
3126 assert_eq!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
3127 })
3128 .await;
3129 }
3130
3131 #[fuchsia::test]
3132 async fn fs_node_setsecurity_different_sid_for_different_context() {
3133 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3134 let node = &testing::create_test_file(current_task).entry.node;
3135
3136 fs_node_setsecurity(
3137 ¤t_task,
3138 &node,
3139 XATTR_NAME_SELINUX.to_bytes().into(),
3140 VALID_SECURITY_CONTEXT.into(),
3141 XattrOp::Set,
3142 )
3143 .expect("set_xattr(security.selinux) failed");
3144
3145 assert!(selinux_hooks::get_cached_sid(node).is_some());
3146
3147 let first_sid = selinux_hooks::get_cached_sid(node).unwrap();
3148 fs_node_setsecurity(
3149 ¤t_task,
3150 &node,
3151 XATTR_NAME_SELINUX.to_bytes().into(),
3152 DIFFERENT_VALID_SECURITY_CONTEXT.into(),
3153 XattrOp::Set,
3154 )
3155 .expect("set_xattr(security.selinux) failed");
3156
3157 assert!(selinux_hooks::get_cached_sid(node).is_some());
3158
3159 let second_sid = selinux_hooks::get_cached_sid(node).unwrap();
3160
3161 assert_ne!(first_sid, second_sid);
3162 })
3163 .await;
3164 }
3165
3166 #[fuchsia::test]
3167 async fn fs_node_getsecurity_returns_cached_context() {
3168 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3169 let node = &testing::create_test_file(current_task).entry.node;
3170
3171 const TEST_VALUE: &[u8] = b"Something Random";
3173 node.ops()
3174 .set_xattr(
3175 node,
3176 current_task,
3177 XATTR_NAME_SELINUX.to_bytes().into(),
3178 TEST_VALUE,
3179 XattrOp::Set,
3180 )
3181 .expect("set_xattr(security.selinux) failed");
3182
3183 let sid = security_server
3185 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
3186 .expect("security context to SID");
3187 selinux_hooks::set_cached_sid(NonPrivateFsNode::new(node).unwrap(), sid);
3188
3189 let result =
3191 fs_node_getsecurity(current_task, node, XATTR_NAME_SELINUX.to_bytes().into(), 4096);
3192 assert_eq!(result, Ok(ValueOrSize::Value(VALID_SECURITY_CONTEXT_WITH_NUL.into())));
3193 })
3194 .await;
3195 }
3196
3197 #[fuchsia::test]
3198 async fn fs_node_getsecurity_delegates_to_get_xattr() {
3199 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3200 let node = &testing::create_test_file(current_task).entry.node;
3201
3202 security_server.set_enforcing(false);
3205 const TEST_VALUE: &[u8] = b"Something Random";
3206 fs_node_setsecurity(
3207 ¤t_task,
3208 node,
3209 XATTR_NAME_SELINUX.to_bytes().into(),
3210 TEST_VALUE,
3211 XattrOp::Set,
3212 )
3213 .expect("set_xattr(security.selinux) failed");
3214 security_server.set_enforcing(true);
3215
3216 let result =
3218 fs_node_getsecurity(current_task, node, XATTR_NAME_SELINUX.to_bytes().into(), 4096);
3219 assert_eq!(result, Ok(ValueOrSize::Value(TEST_VALUE.into())));
3220 })
3221 .await;
3222 }
3223
3224 #[fuchsia::test]
3225 async fn set_get_procattr() {
3226 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3227 assert_eq!(get_procattr(current_task, current_task, ProcAttr::Exec), Ok(Vec::new()));
3228
3229 assert_eq!(
3230 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3232 Ok(())
3233 );
3234
3235 assert_eq!(
3236 set_procattr(
3238 current_task,
3239 ProcAttr::SockCreate,
3240 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3241 ),
3242 error!(EACCES)
3243 );
3244
3245 assert_eq!(
3246 set_procattr(
3248 current_task,
3249 ProcAttr::Previous,
3250 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3251 ),
3252 error!(EINVAL)
3253 );
3254
3255 assert_eq!(
3256 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3258 error!(EINVAL)
3259 );
3260
3261 assert_eq!(
3262 get_procattr(current_task, current_task, ProcAttr::Exec),
3263 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3264 );
3265
3266 assert!(get_procattr(current_task, current_task, ProcAttr::Current).is_ok());
3267 })
3268 .await;
3269 }
3270
3271 #[fuchsia::test]
3272 async fn set_get_procattr_with_nulls() {
3273 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3274 assert_eq!(get_procattr(current_task, current_task, ProcAttr::Exec), Ok(Vec::new()));
3275
3276 assert_eq!(
3277 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT_WITH_NUL.into()),
3279 Ok(())
3280 );
3281
3282 assert_eq!(
3283 set_procattr(
3285 current_task,
3286 ProcAttr::FsCreate,
3287 INVALID_SECURITY_CONTEXT_INTERNAL_NUL.into()
3288 ),
3289 error!(EINVAL)
3290 );
3291
3292 assert_eq!(
3293 get_procattr(current_task, current_task, ProcAttr::Exec),
3294 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3295 );
3296
3297 assert_eq!(
3298 get_procattr(current_task, current_task, ProcAttr::FsCreate),
3299 Ok(Vec::new())
3300 );
3301 })
3302 .await;
3303 }
3304
3305 #[fuchsia::test]
3306 async fn set_get_procattr_clear_context() {
3307 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3308 assert_eq!(
3310 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3311 Ok(())
3312 );
3313 assert_eq!(
3314 set_procattr(
3315 current_task,
3316 ProcAttr::FsCreate,
3317 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3318 ),
3319 Ok(())
3320 );
3321
3322 assert_eq!(set_procattr(current_task, ProcAttr::Exec, b"\0"), Ok(()));
3324 assert_eq!(current_task.current_creds().security_state.exec_sid, None);
3325
3326 assert_eq!(set_procattr(current_task, ProcAttr::FsCreate, b"\x0a"), Ok(()));
3328 assert_eq!(current_task.current_creds().security_state.fscreate_sid, None);
3329 })
3330 .await;
3331 }
3332
3333 #[fuchsia::test]
3334 async fn set_get_procattr_setcurrent() {
3335 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3336 let initial_previous =
3338 get_procattr(current_task, current_task, ProcAttr::Previous).unwrap();
3339
3340 assert_eq!(
3341 set_procattr(current_task, ProcAttr::Current, VALID_SECURITY_CONTEXT.into()),
3343 Ok(())
3344 );
3345
3346 assert_eq!(
3347 get_procattr(current_task, current_task, ProcAttr::Current),
3349 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3350 );
3351
3352 assert_eq!(
3353 get_procattr(current_task, current_task, ProcAttr::Previous),
3355 Ok(initial_previous.clone())
3356 );
3357
3358 assert_eq!(
3359 set_procattr(
3361 current_task,
3362 ProcAttr::Current,
3363 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3364 ),
3365 Ok(())
3366 );
3367
3368 assert_eq!(
3369 get_procattr(current_task, current_task, ProcAttr::Current),
3371 Ok(DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL.into())
3372 );
3373
3374 assert_eq!(
3375 get_procattr(current_task, current_task, ProcAttr::Previous),
3377 Ok(initial_previous.clone())
3378 );
3379 })
3380 .await;
3381 }
3382
3383 #[fuchsia::test]
3384 async fn set_get_procattr_selinux_permissive() {
3385 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3386 security_server.set_enforcing(false);
3387 assert_eq!(
3388 get_procattr(current_task, ¤t_task.task, ProcAttr::Exec),
3389 Ok(Vec::new())
3390 );
3391
3392 assert_eq!(
3393 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3395 Ok(())
3396 );
3397
3398 assert_eq!(
3399 set_procattr(
3402 current_task,
3403 ProcAttr::FsCreate,
3404 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3405 ),
3406 Ok(())
3407 );
3408
3409 assert_eq!(
3410 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3412 error!(EINVAL)
3413 );
3414
3415 assert_eq!(
3416 get_procattr(current_task, ¤t_task.task, ProcAttr::Exec),
3417 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3418 );
3419
3420 assert!(get_procattr(current_task, ¤t_task.task, ProcAttr::Current).is_ok());
3421 })
3422 .await;
3423 }
3424
3425 #[fuchsia::test]
3426 async fn set_get_procattr_selinux_disabled() {
3427 spawn_kernel_and_run(async |current_task| {
3428 assert_eq!(
3429 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3430 error!(EINVAL)
3431 );
3432
3433 assert_eq!(
3434 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3436 error!(EINVAL)
3437 );
3438
3439 assert_eq!(
3440 set_procattr(¤t_task, ProcAttr::FsCreate, VALID_SECURITY_CONTEXT.into()),
3442 error!(EINVAL)
3443 );
3444
3445 assert_eq!(
3446 set_procattr(¤t_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3448 error!(EINVAL)
3449 );
3450
3451 assert_eq!(
3452 get_procattr(¤t_task, ¤t_task.task, ProcAttr::Current),
3453 error!(EINVAL)
3454 );
3455 })
3456 .await;
3457 }
3458
3459 #[fuchsia::test]
3460 async fn create_file_with_fscreate_sid() {
3461 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3462 let sid =
3463 security_server.security_context_to_sid(VALID_SECURITY_CONTEXT.into()).unwrap();
3464 let source_node = &testing::create_test_file(current_task).entry.node;
3465
3466 fs_node_setsecurity(
3467 ¤t_task,
3468 &source_node,
3469 XATTR_NAME_SELINUX.to_bytes().into(),
3470 VALID_SECURITY_CONTEXT.into(),
3471 XattrOp::Set,
3472 )
3473 .expect("set_xattr(security.selinux) failed");
3474
3475 let mut creds = Credentials::clone(¤t_task.current_creds());
3476 security::fs_node_copy_up(current_task, source_node, &source_node.fs(), &mut creds);
3477 let dir_entry = current_task
3478 .override_creds(creds.into(), || {
3479 current_task
3480 .fs()
3481 .root()
3482 .create_node(
3483 ¤t_task,
3484 "test_file2".into(),
3485 FileMode::IFREG,
3486 DeviceId::NONE,
3487 )
3488 .unwrap()
3489 })
3490 .entry;
3491
3492 assert_eq!(get_cached_sid(&dir_entry.node), Some(sid));
3493 })
3494 .await;
3495 }
3496
3497 #[fuchsia::test]
3498 async fn test_check_ptrace_access_mode_noaudit() {
3499 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3500 let tracer_task = create_task_with_security_context(
3501 ¤t_task.kernel(),
3502 "tracer_task",
3503 &CString::new(b"u:object_r:test_ptrace_tracer_no_t:s0").unwrap(),
3504 );
3505 let tracee_task = create_task_with_security_context(
3506 ¤t_task.kernel(),
3507 "target_task",
3508 &CString::new(b"u:object_r:test_ptrace_traced_t:s0").unwrap(),
3509 );
3510
3511 let initial_denials = current_task.kernel().security_state.access_denial_count();
3513 assert_eq!(
3514 tracer_task.check_ptrace_access_mode(
3515 PTRACE_MODE_ATTACH_REALCREDS | PTRACE_MODE_NOAUDIT,
3516 &tracee_task
3517 ),
3518 error!(EACCES)
3519 );
3520 assert_eq!(current_task.kernel().security_state.access_denial_count(), initial_denials);
3521
3522 assert_eq!(
3523 tracer_task.check_ptrace_access_mode(PTRACE_MODE_ATTACH_REALCREDS, &tracee_task),
3524 error!(EACCES)
3525 );
3526 assert_eq!(
3527 current_task.kernel().security_state.access_denial_count(),
3528 initial_denials + 1
3529 );
3530
3531 let orig_tracee_creds = Credentials::clone(&tracee_task.current_creds());
3534 let mut diff_uid_creds = orig_tracee_creds.clone();
3535 diff_uid_creds.uid = 1000;
3536 tracee_task.set_creds(diff_uid_creds);
3537
3538 let denials_before_uid = current_task.kernel().security_state.access_denial_count();
3539 assert_eq!(
3540 tracer_task.check_ptrace_access_mode(
3541 PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT,
3542 &tracee_task
3543 ),
3544 error!(EPERM)
3545 );
3546 assert_eq!(
3547 current_task.kernel().security_state.access_denial_count(),
3548 denials_before_uid
3549 );
3550
3551 assert_eq!(
3552 tracer_task.check_ptrace_access_mode(PTRACE_MODE_READ_FSCREDS, &tracee_task),
3553 error!(EPERM)
3554 );
3555 assert_eq!(
3556 current_task.kernel().security_state.access_denial_count(),
3557 denials_before_uid + 1
3558 );
3559 tracee_task.set_creds(orig_tracee_creds);
3560
3561 tracee_task.mm().unwrap().dumpable.store(DumpPolicy::Disable);
3564 let denials_before_dumpable =
3565 current_task.kernel().security_state.access_denial_count();
3566 assert_eq!(
3567 tracer_task.check_ptrace_access_mode(
3568 PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT,
3569 &tracee_task
3570 ),
3571 error!(EPERM)
3572 );
3573 assert_eq!(
3574 current_task.kernel().security_state.access_denial_count(),
3575 denials_before_dumpable
3576 );
3577
3578 assert_eq!(
3579 tracer_task.check_ptrace_access_mode(PTRACE_MODE_READ_FSCREDS, &tracee_task),
3580 error!(EPERM)
3581 );
3582 assert_eq!(
3583 current_task.kernel().security_state.access_denial_count(),
3584 denials_before_dumpable + 1
3585 );
3586 tracee_task.mm().unwrap().dumpable.store(DumpPolicy::User);
3587
3588 let orig_caller_creds = Credentials::clone(&tracer_task.current_creds());
3591 let mut reduced_cap_creds = orig_caller_creds.clone();
3592 reduced_cap_creds.cap_effective = CAP_SYS_PTRACE;
3593 tracer_task.set_creds(reduced_cap_creds);
3594
3595 let denials_before_common_cap =
3596 current_task.kernel().security_state.access_denial_count();
3597 assert_eq!(
3598 tracer_task.check_ptrace_access_mode(
3599 PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT,
3600 &tracee_task
3601 ),
3602 error!(EPERM)
3603 );
3604 assert_eq!(
3605 current_task.kernel().security_state.access_denial_count(),
3606 denials_before_common_cap
3607 );
3608
3609 assert_eq!(
3610 tracer_task.check_ptrace_access_mode(PTRACE_MODE_READ_FSCREDS, &tracee_task),
3611 error!(EPERM)
3612 );
3613 assert_eq!(
3614 current_task.kernel().security_state.access_denial_count(),
3615 denials_before_common_cap + 1
3616 );
3617 tracer_task.set_creds(orig_caller_creds);
3618
3619 for scope in [yama::SCOPE_RESTRICTED, yama::SCOPE_ADMIN_ONLY] {
3622 current_task.kernel().ptrace_scope.store(scope, Ordering::Relaxed);
3623 let denials_before_yama =
3624 current_task.kernel().security_state.access_denial_count();
3625 assert_eq!(
3626 tracer_task.check_ptrace_access_mode(
3627 PTRACE_MODE_ATTACH_REALCREDS | PTRACE_MODE_NOAUDIT,
3628 &tracee_task
3629 ),
3630 error!(EPERM)
3631 );
3632 assert_eq!(
3633 current_task.kernel().security_state.access_denial_count(),
3634 denials_before_yama
3635 );
3636
3637 assert_eq!(
3638 tracer_task
3639 .check_ptrace_access_mode(PTRACE_MODE_ATTACH_REALCREDS, &tracee_task),
3640 error!(EPERM)
3641 );
3642 assert_eq!(
3643 current_task.kernel().security_state.access_denial_count(),
3644 denials_before_yama + 1
3645 );
3646 }
3647 current_task.kernel().ptrace_scope.store(yama::SCOPE_CLASSIC, Ordering::Relaxed);
3648 })
3649 .await;
3650 }
3651
3652 #[fuchsia::test]
3653 async fn private_fs_node_bypasses_fs_node_hooks() {
3654 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3655 let private_file = new_null_file(current_task, OpenFlags::RDWR);
3656
3657 let node = private_file.node();
3658 assert!(node.is_private());
3659 assert_eq!(get_cached_sid(node), None);
3660 assert_eq!(fs_node_listsecurity(current_task, node), None);
3661 assert_eq!(check_fs_node_getattr_access(current_task, node), Ok(()));
3662 assert_eq!(
3663 fs_node_permission(
3664 current_task,
3665 node,
3666 PermissionFlags::READ | PermissionFlags::WRITE,
3667 (&*current_task).into(),
3668 ),
3669 Ok(())
3670 );
3671 assert_eq!(sb_mount(current_task, &private_file.name, MountFlags::empty()), Ok(()));
3672 assert_eq!(file_open(current_task, &private_file), Ok(()));
3673 })
3674 .await;
3675 }
3676
3677 #[fuchsia::test]
3678 async fn private_fs_node_file_enforces_fd_use() {
3679 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3680 let private_file = new_null_file(current_task, OpenFlags::RDWR | OpenFlags::APPEND);
3681
3682 assert_eq!(
3683 file_permission(
3684 current_task,
3685 &private_file,
3686 PermissionFlags::READ | PermissionFlags::WRITE,
3687 ),
3688 Ok(())
3689 );
3690 assert_eq!(
3691 check_file_fcntl_access(
3692 current_task,
3693 &private_file,
3694 starnix_uapi::F_SETFL,
3695 OpenFlags::RDWR.bits() as u64,
3696 ),
3697 Ok(())
3698 );
3699
3700 let other_sid = security_server
3703 .security_context_to_sid(DIFFERENT_VALID_SECURITY_CONTEXT.into())
3704 .expect("invalid security context");
3705 testing::mutate_attrs_for_test(current_task, |attrs| attrs.current_sid = other_sid);
3706 assert_eq!(
3707 file_permission(
3708 current_task,
3709 &private_file,
3710 PermissionFlags::READ | PermissionFlags::WRITE,
3711 ),
3712 error!(EACCES)
3713 );
3714 assert_eq!(
3715 check_file_fcntl_access(
3716 current_task,
3717 &private_file,
3718 starnix_uapi::F_SETFL,
3719 OpenFlags::RDWR.bits() as u64,
3720 ),
3721 error!(EACCES)
3722 );
3723 })
3724 .await;
3725 }
3726
3727 fn create_private_test_socket(
3728 current_task: &CurrentTask,
3729 security_server: &SecurityServer,
3730 ) -> FileHandle {
3731 let task_sid = security_server
3732 .security_context_to_sid(b"u:object_r:test_socket_create_no_t:s0".into())
3733 .expect("invalid security context");
3734 testing::mutate_attrs_for_test(current_task, |attrs| attrs.current_sid = task_sid);
3735
3736 SocketFile::new_socket(
3737 current_task,
3738 SocketDomain::Unix,
3739 SocketType::Stream,
3740 OpenFlags::RDWR,
3741 SocketProtocol::IP,
3742 true,
3743 )
3744 .expect("kernel_private socket creation should bypass access check")
3745 }
3746
3747 #[fuchsia::test]
3748 async fn private_socket_bypasses_creation_and_labeling() {
3749 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3750 let private_socket_file = create_private_test_socket(current_task, security_server);
3751
3752 let node = private_socket_file.node();
3753 assert!(node.is_private());
3754 assert_eq!(get_cached_sid(node), None);
3755
3756 let socket =
3757 Socket::get_from_file(&private_socket_file).expect("FileHandle should be a socket");
3758 assert!(NonPrivateSocket::new(socket).is_none());
3759 })
3760 .await;
3761 }
3762
3763 #[fuchsia::test]
3764 async fn private_socket_bypasses_socket_ops_hooks() {
3765 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3766 let private_socket_file = create_private_test_socket(current_task, security_server);
3767 let socket =
3768 Socket::get_from_file(&private_socket_file).expect("FileHandle should be a socket");
3769
3770 assert_eq!(check_socket_getsockname_access(current_task, socket), Ok(()));
3771 assert_eq!(check_socket_getpeername_access(current_task, socket), Ok(()));
3772 assert_eq!(
3773 check_socket_shutdown_access(current_task, socket, SocketShutdownFlags::READ),
3774 Ok(())
3775 );
3776 assert_eq!(socket_getpeersec_stream(current_task, socket), Ok(Vec::<u8>::new()));
3777 assert_eq!(socket_getpeersec_dgram(current_task, socket), Vec::<u8>::new());
3778 })
3779 .await;
3780 }
3781
3782 #[fuchsia::test]
3783 async fn private_socket_bypasses_connection_hooks() {
3784 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3785 let private_socket_file = create_private_test_socket(current_task, security_server);
3786 let socket =
3787 Socket::get_from_file(&private_socket_file).expect("FileHandle should be a socket");
3788 let socket_downcasted = private_socket_file
3789 .downcast_file::<SocketFile>()
3790 .expect("downcast to SocketFile should succeed");
3791
3792 assert_eq!(
3793 socket_socketpair(current_task, socket_downcasted, socket_downcasted),
3794 Ok(())
3795 );
3796 assert_eq!(
3797 check_socket_connect_access(
3798 current_task,
3799 socket_downcasted,
3800 &SocketPeer::Handle(socket.clone()),
3801 ),
3802 Ok(())
3803 );
3804 assert_eq!(socket_accept(current_task, socket_downcasted, socket_downcasted), Ok(()));
3805 })
3806 .await;
3807 }
3808}