1#![allow(non_upper_case_globals)]
37
38use super::selinux_hooks::audit::Auditable;
39use super::{
40 BpfMapState, BpfProgState, FileObjectState, FileSystemState, KernelState, PerfEventState,
41 common_cap, selinux_hooks, yama,
42};
43use crate::mm::{Mapping, MappingOptions, ProtectionFlags};
44use crate::perf::PerfEventFile;
45use crate::security::selinux_hooks::current_task_state;
46use crate::task::loader::ResolvedProgram;
47use crate::task::{CurrentTask, Kernel, Task};
48use crate::vfs::fs_args::MountParams;
49use crate::vfs::socket::{
50 Socket, SocketAddress, SocketDomain, SocketFile, SocketPeer, SocketProtocol,
51 SocketShutdownFlags, SocketType,
52};
53use crate::vfs::{
54 DirEntryHandle, DowncastedFile, FileHandle, FileObject, FileSystem, FileSystemHandle,
55 FileSystemOps, FsNode, FsStr, FsString, Mount, NamespaceNode, ValueOrSize, XattrOp,
56};
57use ebpf::MapFlags;
58use linux_uapi::{
59 perf_type_id, perf_type_id_PERF_TYPE_BREAKPOINT, perf_type_id_PERF_TYPE_HARDWARE,
60 perf_type_id_PERF_TYPE_HW_CACHE, perf_type_id_PERF_TYPE_RAW, perf_type_id_PERF_TYPE_SOFTWARE,
61 perf_type_id_PERF_TYPE_TRACEPOINT,
62};
63use selinux::{FileSystemMountOptions, InitialSid, SecurityPermission, SecurityServer, TaskAttrs};
64use starnix_logging::{CATEGORY_STARNIX_SECURITY, log_debug};
65use starnix_uapi::arc_key::WeakKey;
66use starnix_uapi::auth::{Credentials, PtraceAccessMode};
67use starnix_uapi::device_id::DeviceId;
68use starnix_uapi::errors::Errno;
69use starnix_uapi::file_mode::{Access, FileMode};
70use starnix_uapi::inotify_mask::InotifyMask;
71use starnix_uapi::mount_flags::MountFlags;
72use starnix_uapi::open_flags::OpenFlags;
73use starnix_uapi::signals::Signal;
74use starnix_uapi::syslog::SyslogAction;
75use starnix_uapi::unmount_flags::UnmountFlags;
76use starnix_uapi::user_address::UserAddress;
77use starnix_uapi::{bpf_cmd, error, rlimit};
78use std::ops::Range;
79use std::sync::Arc;
80use syncio::zxio_node_attr_has_t;
81use zerocopy::FromBytes;
82
83macro_rules! track_hook_duration {
84 ($cname:literal) => {
85 fuchsia_trace::duration!(CATEGORY_STARNIX_SECURITY, $cname);
86 };
87}
88
89fn is_private_socket(socket: &Socket) -> bool {
91 socket.fs_node().is_some_and(|fs_node| fs_node.is_private())
92}
93
94bitflags::bitflags! {
95 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
98 pub struct PermissionFlags: u32 {
99 const EXEC = 1 as u32;
100 const WRITE = 2 as u32;
101 const READ = 4 as u32;
102 const APPEND = 8 as u32;
103
104 const ACCESS = 16 as u32;
107 }
108}
109
110impl PermissionFlags {
111 pub fn as_access(&self) -> Access {
112 let mut access = Access::empty();
113 if self.contains(PermissionFlags::READ) {
114 access |= Access::READ;
115 }
116 if self.contains(PermissionFlags::WRITE) {
117 access |= Access::WRITE;
120 }
121 if self.contains(PermissionFlags::EXEC) {
122 access |= Access::EXEC;
123 }
124 access
125 }
126}
127
128impl From<Access> for PermissionFlags {
129 fn from(access: Access) -> Self {
130 let mut permissions = PermissionFlags::empty();
132 if access.contains(Access::READ) {
133 permissions |= PermissionFlags::READ;
134 }
135 if access.contains(Access::WRITE) {
136 permissions |= PermissionFlags::WRITE;
137 }
138 if access.contains(Access::EXEC) {
139 permissions |= PermissionFlags::EXEC;
140 }
141 permissions
142 }
143}
144
145impl From<ProtectionFlags> for PermissionFlags {
146 fn from(protection_flags: ProtectionFlags) -> Self {
147 let mut flags = PermissionFlags::empty();
148 if protection_flags.contains(ProtectionFlags::READ) {
149 flags |= PermissionFlags::READ;
150 }
151 if protection_flags.contains(ProtectionFlags::WRITE) {
152 flags |= PermissionFlags::WRITE;
153 }
154 if protection_flags.contains(ProtectionFlags::EXEC) {
155 flags |= PermissionFlags::EXEC;
156 }
157 flags
158 }
159}
160
161impl From<OpenFlags> for PermissionFlags {
162 fn from(flags: OpenFlags) -> Self {
163 let mut permissions = PermissionFlags::empty();
164 if flags.can_read() {
165 permissions |= PermissionFlags::READ;
166 }
167 if flags.can_write() {
168 permissions |= PermissionFlags::WRITE;
169 if flags.contains(OpenFlags::APPEND) {
170 permissions |= PermissionFlags::APPEND;
171 }
172 }
173 permissions
174 }
175}
176
177impl From<MapFlags> for PermissionFlags {
178 fn from(bpf_flags: MapFlags) -> Self {
179 if bpf_flags.contains(MapFlags::SyscallReadOnly) {
180 PermissionFlags::READ
181 } else if bpf_flags.contains(MapFlags::SyscallWriteOnly) {
182 PermissionFlags::WRITE
183 } else {
184 PermissionFlags::READ | PermissionFlags::WRITE
185 }
186 }
187}
188
189#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
191pub enum PerfEventType {
192 Hardware,
193 Software,
194 Tracepoint,
195 Raw,
196 HwCache,
197 Breakpoint,
198}
199
200#[allow(non_upper_case_globals)]
202impl TryFrom<perf_type_id> for PerfEventType {
203 type Error = Errno;
204
205 fn try_from(type_id: perf_type_id) -> Result<Self, Errno> {
206 match type_id {
207 perf_type_id_PERF_TYPE_HARDWARE => Ok(Self::Hardware),
208 perf_type_id_PERF_TYPE_SOFTWARE => Ok(Self::Software),
209 perf_type_id_PERF_TYPE_TRACEPOINT => Ok(Self::Tracepoint),
210 perf_type_id_PERF_TYPE_RAW => Ok(Self::Raw),
211 perf_type_id_PERF_TYPE_HW_CACHE => Ok(Self::HwCache),
212 perf_type_id_PERF_TYPE_BREAKPOINT => Ok(Self::Breakpoint),
213 _ => {
214 return error!(ENOTSUP);
215 }
216 }
217 }
218}
219
220#[derive(PartialEq, Eq)]
222pub enum PerfEventTarget<'a> {
223 AllTasks,
225 CurrentTask,
227 Task(&'a Task),
229}
230
231#[derive(Clone, Copy, Debug, PartialEq, Eq)]
235pub enum PerfEventOpenType {
236 Open,
238 Cpu,
240 Kernel,
242 Tracepoint,
244}
245
246fn if_selinux_else<F, R, D>(task: &Task, hook: F, default: D) -> R
250where
251 F: FnOnce(&Arc<SecurityServer>) -> R,
252 D: Fn() -> R,
253{
254 if let Some(state) = task.kernel().security_state.state.as_ref() {
255 if state.has_policy() { hook(&state.server) } else { default() }
256 } else {
257 default()
258 }
259}
260
261fn if_selinux_else_default_ok<R, F>(task: &Task, hook: F) -> Result<R, Errno>
265where
266 F: FnOnce(&Arc<SecurityServer>) -> Result<R, Errno>,
267 R: Default,
268{
269 if_selinux_else(task, hook, || Ok(R::default()))
270}
271
272pub fn kernel_init_security(
275 enabled: bool,
276 options: String,
277 exceptions: Vec<String>,
278 inspect_node: &fuchsia_inspect::Node,
279) -> KernelState {
280 track_hook_duration!("security.hooks.kernel_init_security");
281 KernelState {
282 state: enabled
283 .then(|| selinux_hooks::kernel_init_security(options, exceptions, inspect_node)),
284 }
285}
286
287pub fn binder_set_context_mgr(
290 current_task: &CurrentTask,
291 context_mgr_creds: &Credentials,
292) -> Result<(), Errno> {
293 track_hook_duration!("security.hooks.binder_set_context_mgr");
294 if_selinux_else_default_ok(current_task, |security_server| {
295 selinux_hooks::binder::binder_set_context_mgr(
296 security_server,
297 current_task,
298 context_mgr_creds,
299 )
300 })
301}
302
303pub fn binder_transaction(
306 current_task: &CurrentTask,
307 source_creds: &Credentials,
308 target_creds: &Credentials,
309) -> Result<(), Errno> {
310 track_hook_duration!("security.hooks.binder_transaction");
311 if_selinux_else_default_ok(current_task, |security_server| {
312 selinux_hooks::binder::binder_transaction(
313 security_server,
314 current_task,
315 source_creds,
316 target_creds,
317 )
318 })
319}
320
321pub fn binder_transfer_binder(
324 current_task: &CurrentTask,
325 source_creds: &Credentials,
326 target_creds: &Credentials,
327) -> Result<(), Errno> {
328 track_hook_duration!("security.hooks.binder_transfer_binder");
329 if_selinux_else_default_ok(current_task, |security_server| {
330 selinux_hooks::binder::binder_transfer_binder(
331 security_server,
332 current_task,
333 source_creds,
334 target_creds,
335 )
336 })
337}
338
339pub fn binder_transfer_file(
342 current_task: &CurrentTask,
343 target_creds: &Credentials,
344 file: &FileObject,
345) -> Result<(), Errno> {
346 track_hook_duration!("security.hooks.binder_transfer_file");
347 if_selinux_else_default_ok(current_task, |security_server| {
348 selinux_hooks::binder::binder_transfer_file(
349 security_server,
350 current_task,
351 target_creds,
352 file,
353 )
354 })
355}
356
357pub fn binder_get_context(current_task: &CurrentTask, source_creds: &Credentials) -> FsString {
360 track_hook_duration!("security.hooks.binder_get_context");
361 if_selinux_else(
362 current_task,
363 |security_server| {
364 selinux_hooks::binder::binder_get_context(&security_server, source_creds).into()
365 },
366 || FsString::from(b"\0"),
367 )
368}
369
370pub fn sb_eat_lsm_opts(
374 kernel: &Kernel,
375 mount_params: &mut MountParams,
376) -> Result<FileSystemMountOptions, Errno> {
377 track_hook_duration!("security.hooks.sb_eat_lsm_opts");
378 if kernel.security_state.state.is_some() {
379 return selinux_hooks::superblock::sb_eat_lsm_opts(mount_params);
380 }
381 Ok(FileSystemMountOptions::default())
382}
383
384pub fn file_system_init_security(
387 mount_options: &FileSystemMountOptions,
388 ops: &dyn FileSystemOps,
389) -> Result<FileSystemState, Errno> {
390 track_hook_duration!("security.hooks.file_system_init_security");
391 Ok(FileSystemState {
392 state: selinux_hooks::superblock::file_system_init_security(mount_options, ops)?,
393 })
394}
395
396pub fn file_system_post_init_security(kernel: &Kernel, file_system: &FileSystemHandle) {
401 track_hook_duration!("security.hooks.file_system_post_init_security");
402 if let Some(state) = &kernel.security_state.state {
403 if !state.has_policy() {
404 log_debug!("Queuing {} FileSystem for labeling", file_system.name());
407 state.pending_file_systems.lock().insert(WeakKey::from(&file_system));
408 }
409 }
410}
411
412pub fn file_system_resolve_security(
417 current_task: &CurrentTask,
418 file_system: &FileSystemHandle,
419) -> Result<(), Errno> {
420 track_hook_duration!("security.hooks.file_system_resolve_security");
421 if_selinux_else_default_ok(current_task, |security_server| {
422 selinux_hooks::superblock::file_system_resolve_security(
423 security_server,
424 current_task,
425 file_system,
426 )
427 })
428}
429
430pub struct FsNodeSecurityXattr {
432 pub name: &'static FsStr,
433 pub value: FsString,
434}
435
436pub fn mmap_file(
440 current_task: &CurrentTask,
441 file: Option<&FileHandle>,
442 protection_flags: ProtectionFlags,
443 options: MappingOptions,
444) -> Result<(), Errno> {
445 track_hook_duration!("security.hooks.mmap_file");
446 if_selinux_else_default_ok(current_task, |security_server| {
447 selinux_hooks::file::mmap_file(
448 security_server,
449 current_task,
450 file,
451 protection_flags,
452 options,
453 )
454 })
455}
456
457pub fn file_mprotect(
461 current_task: &CurrentTask,
462 range: &Range<UserAddress>,
463 mapping: &Mapping,
464 prot: ProtectionFlags,
465) -> Result<(), Errno> {
466 track_hook_duration!("security.hooks.file_mprotect");
467 if_selinux_else_default_ok(current_task, |security_server| {
468 selinux_hooks::file::file_mprotect(security_server, current_task, range, mapping, prot)
469 })
470}
471
472pub fn file_permission(
475 current_task: &CurrentTask,
476 file: &FileObject,
477 permission_flags: PermissionFlags,
478) -> Result<(), Errno> {
479 track_hook_duration!("security.hooks.file_permission");
480 if_selinux_else_default_ok(current_task, |security_server| {
481 selinux_hooks::file::file_permission(security_server, current_task, file, permission_flags)
482 })
483}
484
485pub fn file_open(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
488 track_hook_duration!("security.hooks.file_open");
489 if file.node().is_private() {
490 return Ok(());
491 }
492 if_selinux_else_default_ok(current_task, |security_server| {
493 selinux_hooks::file::file_open(security_server, current_task, file)
494 })
495}
496
497pub fn fs_node_init_with_dentry(
503 current_task: &CurrentTask,
504 dir_entry: &DirEntryHandle,
505) -> Result<(), Errno> {
506 track_hook_duration!("security.hooks.fs_node_init_with_dentry");
507 if dir_entry.node.is_private() {
508 return Ok(());
509 }
510 if let Some(state) = ¤t_task.kernel().security_state.state {
515 selinux_hooks::fs_node::fs_node_init_with_dentry(
516 &state.server,
517 current_task,
518 dir_entry,
519 true,
521 )
522 } else {
523 Ok(())
524 }
525}
526
527pub fn fs_node_init_with_dentry_no_xattr(
528 current_task: &CurrentTask,
529 dir_entry: &DirEntryHandle,
530) -> Result<(), Errno> {
531 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
532 if dir_entry.node.is_private() {
533 return Ok(());
534 }
535 if let Some(state) = ¤t_task.kernel().security_state.state {
540 selinux_hooks::fs_node::fs_node_init_with_dentry(
541 &state.server,
542 current_task,
543 dir_entry,
544 false,
546 )
547 } else {
548 Ok(())
549 }
550}
551
552pub fn fs_node_init_with_dentry_deferred(kernel: &Kernel, dir_entry: &DirEntryHandle) {
556 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
557 if dir_entry.node.is_private() {
558 return;
559 }
560 if kernel.security_state.state.is_some() {
561 selinux_hooks::fs_node::fs_node_init_with_dentry_deferred(dir_entry);
562 }
563}
564
565pub fn fs_node_notify_security_context(
572 current_task: &CurrentTask,
573 fs_node: &FsNode,
574 context: &FsStr,
575) -> Result<(), Errno> {
576 track_hook_duration!("security.hooks.fs_node_notify_security_context");
577 if fs_node.is_private() {
578 return Ok(());
579 }
580 if_selinux_else(
581 current_task,
582 |security_server| {
583 selinux_hooks::fs_node::fs_node_notify_security_context(
584 security_server,
585 fs_node,
586 context,
587 )
588 },
589 || error!(ENOTSUP),
590 )
591}
592
593pub fn fs_node_init_on_create(
605 current_task: &CurrentTask,
606 new_node: &FsNode,
607 parent: &FsNode,
608 name: &FsStr,
609) -> Result<Option<FsNodeSecurityXattr>, Errno> {
610 track_hook_duration!("security.hooks.fs_node_init_on_create");
611 debug_assert!(!new_node.is_private());
612 debug_assert!(!parent.is_private());
613 if_selinux_else_default_ok(current_task, |security_server| {
614 selinux_hooks::fs_node::fs_node_init_on_create(
615 security_server,
616 current_task,
617 new_node,
618 Some(parent),
619 name,
620 )
621 })
622}
623
624pub fn dentry_create_files_as(
632 current_task: &CurrentTask,
633 parent: &FsNode,
634 new_node_mode: FileMode,
635 new_node_name: &FsStr,
636 new_creds: &mut Credentials,
637) -> Result<(), Errno> {
638 track_hook_duration!("security.hooks.dentry_create_files_as");
639 debug_assert!(!parent.is_private());
640 if_selinux_else_default_ok(current_task, |security_server| {
641 selinux_hooks::fs_node::dentry_create_files_as(
642 security_server,
643 current_task,
644 parent,
645 new_node_mode,
646 new_node_name,
647 new_creds,
648 )
649 })
650}
651
652pub fn fs_node_init_anon(
657 current_task: &CurrentTask,
658 new_node: &FsNode,
659 node_type: &str,
660) -> Result<(), Errno> {
661 track_hook_duration!("security.hooks.fs_node_init_anon");
662 if new_node.is_private() {
663 return Ok(());
664 }
665 if let Some(state) = current_task.kernel().security_state.state.as_ref() {
666 selinux_hooks::fs_node::fs_node_init_anon(&state.server, current_task, new_node, node_type)
667 } else {
668 Ok(())
669 }
670}
671
672pub fn check_fs_node_create_access(
676 current_task: &CurrentTask,
677 parent: &FsNode,
678 mode: FileMode,
679 name: &FsStr,
680) -> Result<(), Errno> {
681 track_hook_duration!("security.hooks.check_fs_node_create_access");
682 debug_assert!(!parent.is_private());
683 if_selinux_else_default_ok(current_task, |security_server| {
684 selinux_hooks::fs_node::check_fs_node_create_access(
685 security_server,
686 current_task,
687 parent,
688 mode,
689 name,
690 )
691 })
692}
693
694pub fn check_fs_node_symlink_access(
698 current_task: &CurrentTask,
699 parent: &FsNode,
700 name: &FsStr,
701 old_path: &FsStr,
702) -> Result<(), Errno> {
703 track_hook_duration!("security.hooks.check_fs_node_symlink_access");
704 debug_assert!(!parent.is_private());
705 if_selinux_else_default_ok(current_task, |security_server| {
706 selinux_hooks::fs_node::check_fs_node_symlink_access(
707 security_server,
708 current_task,
709 parent,
710 name,
711 old_path,
712 )
713 })
714}
715
716pub fn check_fs_node_mkdir_access(
720 current_task: &CurrentTask,
721 parent: &FsNode,
722 mode: FileMode,
723 name: &FsStr,
724) -> Result<(), Errno> {
725 track_hook_duration!("security.hooks.check_fs_node_mkdir_access");
726 debug_assert!(!parent.is_private());
727 if_selinux_else_default_ok(current_task, |security_server| {
728 selinux_hooks::fs_node::check_fs_node_mkdir_access(
729 security_server,
730 current_task,
731 parent,
732 mode,
733 name,
734 )
735 })
736}
737
738pub fn check_fs_node_mknod_access(
744 current_task: &CurrentTask,
745 parent: &FsNode,
746 mode: FileMode,
747 name: &FsStr,
748 device_id: DeviceId,
749) -> Result<(), Errno> {
750 track_hook_duration!("security.hooks.check_fs_node_mknod_access");
751 assert!(!mode.is_reg());
752 debug_assert!(!parent.is_private());
753
754 if_selinux_else_default_ok(current_task, |security_server| {
755 selinux_hooks::fs_node::check_fs_node_mknod_access(
756 security_server,
757 current_task,
758 parent,
759 mode,
760 name,
761 device_id,
762 )
763 })
764}
765
766pub fn check_fs_node_link_access(
769 current_task: &CurrentTask,
770 parent: &FsNode,
771 child: &FsNode,
772) -> Result<(), Errno> {
773 track_hook_duration!("security.hooks.check_fs_node_link_access");
774 debug_assert!(!parent.is_private());
775 debug_assert!(!child.is_private());
776 if_selinux_else_default_ok(current_task, |security_server| {
777 selinux_hooks::fs_node::check_fs_node_link_access(
778 security_server,
779 current_task,
780 parent,
781 child,
782 )
783 })
784}
785
786pub fn check_fs_node_unlink_access(
789 current_task: &CurrentTask,
790 parent: &FsNode,
791 child: &FsNode,
792 name: &FsStr,
793) -> Result<(), Errno> {
794 track_hook_duration!("security.hooks.check_fs_node_unlink_access");
795 debug_assert!(!parent.is_private());
796 debug_assert!(!child.is_private());
797 if_selinux_else_default_ok(current_task, |security_server| {
798 selinux_hooks::fs_node::check_fs_node_unlink_access(
799 security_server,
800 current_task,
801 parent,
802 child,
803 name,
804 )
805 })
806}
807
808pub fn check_fs_node_rmdir_access(
811 current_task: &CurrentTask,
812 parent: &FsNode,
813 child: &FsNode,
814 name: &FsStr,
815) -> Result<(), Errno> {
816 track_hook_duration!("security.hooks.check_fs_node_rmdir_access");
817 debug_assert!(!parent.is_private());
818 debug_assert!(!child.is_private());
819 if_selinux_else_default_ok(current_task, |security_server| {
820 selinux_hooks::fs_node::check_fs_node_rmdir_access(
821 security_server,
822 current_task,
823 parent,
824 child,
825 name,
826 )
827 })
828}
829
830pub fn check_fs_node_rename_access(
835 current_task: &CurrentTask,
836 old_parent: &FsNode,
837 moving_node: &FsNode,
838 new_parent: &FsNode,
839 replaced_node: Option<&FsNode>,
840 old_basename: &FsStr,
841 new_basename: &FsStr,
842) -> Result<(), Errno> {
843 track_hook_duration!("security.hooks.check_fs_node_rename_access");
844 debug_assert!(!old_parent.is_private());
845 debug_assert!(!moving_node.is_private());
846 debug_assert!(!new_parent.is_private());
847 debug_assert!(replaced_node.is_none_or(|node| !node.is_private()));
848 if_selinux_else_default_ok(current_task, |security_server| {
849 selinux_hooks::fs_node::check_fs_node_rename_access(
850 security_server,
851 current_task,
852 old_parent,
853 moving_node,
854 new_parent,
855 replaced_node,
856 old_basename,
857 new_basename,
858 )
859 })
860}
861
862pub fn check_fs_node_read_link_access(
865 current_task: &CurrentTask,
866 fs_node: &FsNode,
867) -> Result<(), Errno> {
868 track_hook_duration!("security.hooks.check_fs_node_read_link_access");
869 if fs_node.is_private() {
870 return Ok(());
871 }
872 if_selinux_else_default_ok(current_task, |security_server| {
873 selinux_hooks::fs_node::check_fs_node_read_link_access(
874 security_server,
875 current_task,
876 fs_node,
877 )
878 })
879}
880
881pub fn fs_node_permission(
884 current_task: &CurrentTask,
885 fs_node: &FsNode,
886 permission_flags: PermissionFlags,
887 audit_context: Auditable<'_>,
888) -> Result<(), Errno> {
889 track_hook_duration!("security.hooks.fs_node_permission");
890 if fs_node.is_private() {
891 return Ok(());
892 }
893 if_selinux_else_default_ok(current_task, |security_server| {
894 selinux_hooks::fs_node::fs_node_permission(
895 security_server,
896 current_task,
897 fs_node,
898 permission_flags,
899 audit_context,
900 )
901 })
902}
903
904pub fn file_receive(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
907 track_hook_duration!("security.hooks.file_receive");
908 if_selinux_else_default_ok(current_task, |security_server| {
909 let receiving_sid = current_task_state(current_task).current_sid;
910 selinux_hooks::file::file_receive(security_server, current_task, receiving_sid, file)
911 })
912}
913
914pub fn file_alloc_security(current_task: &CurrentTask) -> FileObjectState {
917 track_hook_duration!("security.hooks.file_alloc_security");
918 FileObjectState { state: selinux_hooks::file::file_alloc_security(current_task) }
919}
920
921pub fn bpf_map_alloc(current_task: &CurrentTask) -> BpfMapState {
925 track_hook_duration!("security.hooks.bpf_map_alloc");
926 BpfMapState { state: selinux_hooks::bpf::bpf_map_alloc(current_task) }
927}
928
929pub fn bpf_prog_alloc(current_task: &CurrentTask) -> BpfProgState {
933 track_hook_duration!("security.hooks.bpf_prog_alloc");
934 BpfProgState { state: selinux_hooks::bpf::bpf_prog_alloc(current_task) }
935}
936
937pub fn check_file_ioctl_access(
940 current_task: &CurrentTask,
941 file: &FileObject,
942 request: u32,
943) -> Result<(), Errno> {
944 track_hook_duration!("security.hooks.check_file_ioctl_access");
945 if_selinux_else_default_ok(current_task, |security_server| {
946 selinux_hooks::file::check_file_ioctl_access(security_server, current_task, file, request)
947 })
948}
949
950pub fn fs_node_copy_up(
960 current_task: &CurrentTask,
961 fs_node: &FsNode,
962 fs: &FileSystem,
963 new_creds: &mut Credentials,
964) {
965 if fs_node.is_private() {
966 return;
967 }
968 if_selinux_else(
969 current_task,
970 |_security_server| {
971 selinux_hooks::fs_node::fs_node_copy_up(current_task, fs_node, fs, new_creds)
972 },
973 || {},
974 )
975}
976
977pub fn check_file_lock_access(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
985 track_hook_duration!("security.hooks.check_file_lock_access");
986 if_selinux_else_default_ok(current_task, |security_server| {
987 selinux_hooks::file::check_file_lock_access(security_server, current_task, file)
988 })
989}
990
991pub fn check_file_fcntl_access(
994 current_task: &CurrentTask,
995 file: &FileObject,
996 fcntl_cmd: u32,
997 fcntl_arg: u64,
998) -> Result<(), Errno> {
999 track_hook_duration!("security.hooks.check_file_fcntl_access");
1000 if_selinux_else_default_ok(current_task, |security_server| {
1001 selinux_hooks::file::check_file_fcntl_access(
1002 security_server,
1003 current_task,
1004 file,
1005 fcntl_cmd,
1006 fcntl_arg,
1007 )
1008 })
1009}
1010
1011pub fn check_fs_node_setattr_access(
1014 current_task: &CurrentTask,
1015 node: &FsNode,
1016 attributes: &zxio_node_attr_has_t,
1017) -> Result<(), Errno> {
1018 track_hook_duration!("security.hooks.check_fs_node_setattr_access");
1019 if node.is_private() {
1020 return Ok(());
1021 }
1022 if_selinux_else_default_ok(current_task, |security_server| {
1023 selinux_hooks::fs_node::check_fs_node_setattr_access(
1024 security_server,
1025 current_task,
1026 node,
1027 attributes,
1028 )
1029 })
1030}
1031
1032pub fn task_alloc_for_kernel() -> TaskAttrs {
1035 track_hook_duration!("security.hooks.task_alloc_for_kernel");
1036 TaskAttrs::for_kernel()
1037}
1038
1039pub fn task_to_fs_node(current_task: &CurrentTask, task: &Task, fs_node: &FsNode) {
1045 track_hook_duration!("security.hooks.task_to_fs_node");
1046 if fs_node.is_private() {
1047 return;
1048 }
1049 if current_task.kernel().security_state.state.is_some() {
1052 selinux_hooks::task::fs_node_init_with_task(task, &fs_node);
1053 }
1054}
1055
1056pub fn task_for_context(task: &Task, context: &FsStr) -> Result<TaskAttrs, Errno> {
1062 track_hook_duration!("security.hooks.task_for_context");
1063 Ok(if let Some(kernel_state) = task.kernel().security_state.state.as_ref() {
1064 selinux_hooks::task::task_alloc_from_context(&kernel_state.server, context)
1065 } else {
1066 Ok(TaskAttrs::for_selinux_disabled())
1067 }?)
1068}
1069
1070pub fn has_dontaudit_access(current_task: &CurrentTask, fs_node: &FsNode) -> bool {
1074 track_hook_duration!("security.hooks.has_dontaudit_access");
1075 if fs_node.is_private() {
1076 return false;
1077 }
1078 if_selinux_else(
1079 current_task,
1080 |security_server| {
1081 selinux_hooks::fs_node::has_dontaudit_access(security_server, current_task, fs_node)
1082 },
1083 || false,
1084 )
1085}
1086
1087pub fn is_task_capable_noaudit(
1090 current_task: &CurrentTask,
1091 capability: starnix_uapi::auth::Capabilities,
1092) -> bool {
1093 check_task_capable_noaudit(current_task, capability).is_ok()
1094}
1095
1096pub fn check_creds_capable_noaudit(
1100 current_task: &CurrentTask,
1101 creds: &Credentials,
1102 capability: starnix_uapi::auth::Capabilities,
1103) -> Result<(), Errno> {
1104 track_hook_duration!("security.hooks.is_task_capable_noaudit");
1105 common_cap::creds_capable(creds, capability)?;
1106 let permitted = if_selinux_else(
1107 current_task,
1108 |security_server| {
1109 selinux_hooks::task::is_creds_capable_noaudit(
1110 &selinux_hooks::build_permission_check(current_task, security_server),
1111 ¤t_task,
1112 creds,
1113 capability,
1114 )
1115 },
1116 || true,
1117 );
1118 if permitted { Ok(()) } else { error!(EPERM) }
1119}
1120
1121pub fn check_task_capable_noaudit(
1124 current_task: &CurrentTask,
1125 capability: starnix_uapi::auth::Capabilities,
1126) -> Result<(), Errno> {
1127 check_creds_capable_noaudit(current_task, &**current_task.current_creds(), capability)
1128}
1129
1130pub fn check_creds_capable(
1133 current_task: &CurrentTask,
1134 creds: &Credentials,
1135 capability: starnix_uapi::auth::Capabilities,
1136) -> Result<(), Errno> {
1137 track_hook_duration!("security.hooks.check_creds_capable");
1138 common_cap::creds_capable(creds, capability)?;
1139 if_selinux_else_default_ok(current_task, |security_server| {
1140 selinux_hooks::task::check_creds_capable(
1141 &selinux_hooks::build_permission_check(current_task, security_server),
1142 ¤t_task,
1143 creds,
1144 capability,
1145 )
1146 })
1147}
1148
1149pub fn check_task_capable(
1152 current_task: &CurrentTask,
1153 capability: starnix_uapi::auth::Capabilities,
1154) -> Result<(), Errno> {
1155 check_creds_capable(current_task, &**current_task.current_creds(), capability)
1156}
1157
1158pub fn check_creds_ptrace_capable(
1161 current_task: &CurrentTask,
1162 creds: &Credentials,
1163 mode: PtraceAccessMode,
1164) -> Result<(), Errno> {
1165 if mode.contains(PtraceAccessMode::NOAUDIT) {
1166 check_creds_capable_noaudit(current_task, creds, starnix_uapi::auth::CAP_SYS_PTRACE)
1167 } else {
1168 check_creds_capable(current_task, creds, starnix_uapi::auth::CAP_SYS_PTRACE)
1169 }
1170}
1171
1172pub fn check_task_ptrace_capable(
1174 current_task: &CurrentTask,
1175 mode: PtraceAccessMode,
1176) -> Result<(), Errno> {
1177 check_creds_ptrace_capable(current_task, &**current_task.current_creds(), mode)
1178}
1179
1180pub fn check_task_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1183 track_hook_duration!("security.hooks.check_task_create_access");
1184 if_selinux_else_default_ok(current_task, |security_server| {
1185 selinux_hooks::task::check_task_create_access(
1186 &selinux_hooks::build_permission_check(current_task, security_server),
1187 current_task,
1188 )
1189 })
1190}
1191
1192pub fn check_socket_create_access(
1195 current_task: &CurrentTask,
1196 domain: SocketDomain,
1197 socket_type: SocketType,
1198 protocol: SocketProtocol,
1199 kernel_private: bool,
1200) -> Result<(), Errno> {
1201 track_hook_duration!("security.hooks.socket_create");
1202 if kernel_private {
1203 return Ok(());
1204 }
1205 if_selinux_else_default_ok(current_task, |security_server| {
1206 selinux_hooks::socket::check_socket_create_access(
1207 &security_server,
1208 current_task,
1209 domain,
1210 socket_type,
1211 protocol,
1212 )
1213 })
1214}
1215
1216pub fn socket_socketpair(
1219 current_task: &CurrentTask,
1220 left: DowncastedFile<'_, SocketFile>,
1221 right: DowncastedFile<'_, SocketFile>,
1222) -> Result<(), Errno> {
1223 track_hook_duration!("security.hooks.socket_socketpair");
1224 if left.file().node().is_private() {
1225 debug_assert!(right.file().node().is_private());
1226 return Ok(());
1227 }
1228 if_selinux_else_default_ok(current_task, |_| {
1229 selinux_hooks::socket::socket_socketpair(left, right)
1230 })
1231}
1232
1233pub fn socket_post_create(current_task: &CurrentTask, socket: &Socket) {
1236 track_hook_duration!("security.hooks.socket_post_create");
1237 if is_private_socket(socket) {
1238 return;
1239 }
1240 if let Some(state) = ¤t_task.kernel().security_state.state {
1241 selinux_hooks::socket::socket_post_create(&state.server, socket);
1242 }
1243}
1244
1245pub fn check_socket_bind_access(
1248 current_task: &CurrentTask,
1249 socket: &Socket,
1250 socket_address: &SocketAddress,
1251) -> Result<(), Errno> {
1252 track_hook_duration!("security.hooks.check_socket_bind_access");
1253 if is_private_socket(socket) {
1254 return Ok(());
1255 }
1256 if_selinux_else_default_ok(current_task, |security_server| {
1257 selinux_hooks::socket::check_socket_bind_access(
1258 &security_server,
1259 current_task,
1260 socket,
1261 socket_address,
1262 )
1263 })
1264}
1265
1266pub fn check_socket_connect_access(
1269 current_task: &CurrentTask,
1270 socket: DowncastedFile<'_, SocketFile>,
1271 socket_peer: &SocketPeer,
1272) -> Result<(), Errno> {
1273 track_hook_duration!("security.hooks.check_socket_connect_access");
1274 if socket.file().node().is_private() {
1275 return Ok(());
1276 }
1277 if_selinux_else_default_ok(current_task, |security_server| {
1278 selinux_hooks::socket::check_socket_connect_access(
1279 &security_server,
1280 current_task,
1281 socket,
1282 socket_peer,
1283 )
1284 })
1285}
1286
1287pub fn check_socket_listen_access(
1290 current_task: &CurrentTask,
1291 socket: &Socket,
1292 backlog: i32,
1293) -> Result<(), Errno> {
1294 track_hook_duration!("security.hooks.check_socket_listen_access");
1295 if is_private_socket(socket) {
1296 return Ok(());
1297 }
1298 if_selinux_else_default_ok(current_task, |security_server| {
1299 selinux_hooks::socket::check_socket_listen_access(
1300 &security_server,
1301 current_task,
1302 socket,
1303 backlog,
1304 )
1305 })
1306}
1307
1308pub fn socket_accept(
1312 current_task: &CurrentTask,
1313 listening_socket: DowncastedFile<'_, SocketFile>,
1314 accepted_socket: DowncastedFile<'_, SocketFile>,
1315) -> Result<(), Errno> {
1316 track_hook_duration!("security.hooks.check_socket_getname_access");
1317 if listening_socket.file().node().is_private() || accepted_socket.file().node().is_private() {
1318 return Ok(());
1319 }
1320 if_selinux_else_default_ok(current_task, |security_server| {
1321 selinux_hooks::socket::socket_accept(
1322 &security_server,
1323 current_task,
1324 listening_socket,
1325 accepted_socket,
1326 )
1327 })
1328}
1329
1330pub fn check_socket_getsockopt_access(
1333 current_task: &CurrentTask,
1334 socket: &Socket,
1335 level: u32,
1336 optname: u32,
1337) -> Result<(), Errno> {
1338 track_hook_duration!("security.hooks.check_socket_getsockopt_access");
1339 if is_private_socket(socket) {
1340 return Ok(());
1341 }
1342 if_selinux_else_default_ok(current_task, |security_server| {
1343 selinux_hooks::socket::check_socket_getsockopt_access(
1344 &security_server,
1345 current_task,
1346 socket,
1347 level,
1348 optname,
1349 )
1350 })
1351}
1352
1353pub fn check_socket_setsockopt_access(
1356 current_task: &CurrentTask,
1357 socket: &Socket,
1358 level: u32,
1359 optname: u32,
1360) -> Result<(), Errno> {
1361 track_hook_duration!("security.hooks.check_socket_setsockopt_access");
1362 if is_private_socket(socket) {
1363 return Ok(());
1364 }
1365 if_selinux_else_default_ok(current_task, |security_server| {
1366 selinux_hooks::socket::check_socket_setsockopt_access(
1367 &security_server,
1368 current_task,
1369 socket,
1370 level,
1371 optname,
1372 )
1373 })
1374}
1375
1376pub fn check_socket_sendmsg_access(
1379 current_task: &CurrentTask,
1380 socket: &Socket,
1381) -> Result<(), Errno> {
1382 track_hook_duration!("security.hooks.check_socket_sendmsg_access");
1383 if is_private_socket(socket) {
1384 return Ok(());
1385 }
1386 if_selinux_else_default_ok(current_task, |security_server| {
1387 selinux_hooks::socket::check_socket_sendmsg_access(&security_server, current_task, socket)
1388 })
1389}
1390
1391pub fn check_socket_recvmsg_access(
1394 current_task: &CurrentTask,
1395 socket: &Socket,
1396) -> Result<(), Errno> {
1397 track_hook_duration!("security.hooks.check_socket_recvmsg_access");
1398 if is_private_socket(socket) {
1399 return Ok(());
1400 }
1401 if_selinux_else_default_ok(current_task, |security_server| {
1402 selinux_hooks::socket::check_socket_recvmsg_access(&security_server, current_task, socket)
1403 })
1404}
1405
1406pub fn check_socket_getsockname_access(
1409 current_task: &CurrentTask,
1410 socket: &Socket,
1411) -> Result<(), Errno> {
1412 track_hook_duration!("security.hooks.check_socket_getname_access");
1413 if is_private_socket(socket) {
1414 return Ok(());
1415 }
1416 if_selinux_else_default_ok(current_task, |security_server| {
1417 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1418 })
1419}
1420
1421pub fn check_socket_getpeername_access(
1424 current_task: &CurrentTask,
1425 socket: &Socket,
1426) -> Result<(), Errno> {
1427 track_hook_duration!("security.hooks.check_socket_getname_access");
1428 if is_private_socket(socket) {
1429 return Ok(());
1430 }
1431 if_selinux_else_default_ok(current_task, |security_server| {
1432 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1433 })
1434}
1435
1436pub fn check_socket_shutdown_access(
1439 current_task: &CurrentTask,
1440 socket: &Socket,
1441 how: SocketShutdownFlags,
1442) -> Result<(), Errno> {
1443 track_hook_duration!("security.hooks.check_socket_shutdown_access");
1444 if is_private_socket(socket) {
1445 return Ok(());
1446 }
1447 if_selinux_else_default_ok(current_task, |security_server| {
1448 selinux_hooks::socket::check_socket_shutdown_access(
1449 &security_server,
1450 current_task,
1451 socket,
1452 how,
1453 )
1454 })
1455}
1456
1457pub fn socket_getpeersec_stream(
1460 current_task: &CurrentTask,
1461 socket: &Socket,
1462) -> Result<Vec<u8>, Errno> {
1463 track_hook_duration!("security.hooks.socket_getpeersec_stream");
1464 if is_private_socket(socket) {
1465 return Ok(Vec::default());
1466 }
1467 if_selinux_else_default_ok(current_task, |security_server| {
1468 selinux_hooks::socket::socket_getpeersec_stream(&security_server, current_task, socket)
1469 })
1470}
1471
1472pub fn socket_getpeersec_dgram(current_task: &CurrentTask, socket: &Socket) -> Vec<u8> {
1476 track_hook_duration!("security.hooks.socket_getpeersec_dgram");
1477 if is_private_socket(socket) {
1478 return Vec::default();
1479 }
1480 if_selinux_else(
1481 current_task,
1482 |security_server| {
1483 selinux_hooks::socket::socket_getpeersec_dgram(&security_server, current_task, socket)
1484 },
1485 Vec::default,
1486 )
1487}
1488
1489pub fn unix_may_send(
1493 current_task: &CurrentTask,
1494 sending_socket: &Socket,
1495 receiving_socket: &Socket,
1496) -> Result<(), Errno> {
1497 track_hook_duration!("security.hooks.unix_may_send");
1498 if is_private_socket(sending_socket) || is_private_socket(receiving_socket) {
1499 return Ok(());
1500 }
1501 if_selinux_else_default_ok(current_task, |security_server| {
1502 selinux_hooks::socket::unix_may_send(
1503 &security_server,
1504 current_task,
1505 sending_socket,
1506 receiving_socket,
1507 )
1508 })
1509}
1510
1511pub fn unix_stream_connect(
1515 current_task: &CurrentTask,
1516 client_socket: &Socket,
1517 listening_socket: &Socket,
1518 server_socket: &Socket,
1519) -> Result<(), Errno> {
1520 track_hook_duration!("security.hooks.unix_stream_connect");
1521 if is_private_socket(client_socket) || is_private_socket(listening_socket) {
1522 return Ok(());
1523 }
1524 if_selinux_else_default_ok(current_task, |security_server| {
1525 selinux_hooks::socket::unix_stream_connect(
1526 &security_server,
1527 current_task,
1528 client_socket,
1529 listening_socket,
1530 server_socket,
1531 )
1532 })
1533}
1534
1535pub fn check_netlink_send_access(
1539 current_task: &CurrentTask,
1540 socket: &Socket,
1541 message_type: u16,
1542) -> Result<(), Errno> {
1543 track_hook_duration!("security.hooks.check_netlink_send_access");
1544 if is_private_socket(socket) {
1545 return Ok(());
1546 }
1547 if_selinux_else_default_ok(current_task, |security_server| {
1548 selinux_hooks::netlink_socket::check_netlink_send_access(
1549 &security_server,
1550 current_task,
1551 socket,
1552 message_type,
1553 )
1554 })
1555}
1556
1557pub fn check_tun_dev_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1560 track_hook_duration!("security.hooks.check_tun_dev_create_access");
1561 if_selinux_else_default_ok(current_task, |security_server| {
1562 selinux_hooks::socket::check_tun_dev_create_access(&security_server, current_task)
1563 })
1564}
1565
1566pub fn bprm_creds_from_file(
1570 current_task: &CurrentTask,
1571 resolved_program: &mut ResolvedProgram,
1572) -> Result<(), Errno> {
1573 track_hook_duration!("security.hooks.bprm_creds_from_file");
1574 let mask_caps = {
1575 let state = current_task.read();
1576 state.no_new_privs() || state.is_ptraced_without_cap_sys_ptrace()
1577 };
1578
1579 let enable_suid = current_task.kernel().features.enable_suid && !mask_caps;
1580 if enable_suid {
1581 resolved_program.file.name().apply_suid_and_sgid(&mut resolved_program.creds);
1582 }
1583
1584 resolved_program.creds.fsuid = resolved_program.creds.euid;
1586 resolved_program.creds.fsgid = resolved_program.creds.egid;
1587
1588 resolved_program.creds.saved_uid = resolved_program.creds.euid;
1594 resolved_program.creds.saved_gid = resolved_program.creds.egid;
1595
1596 common_cap::bprm_creds_from_file(current_task, resolved_program, mask_caps)
1597}
1598
1599pub fn bprm_creds_for_exec(
1604 current_task: &CurrentTask,
1605 resolved_program: &mut ResolvedProgram,
1606) -> Result<(), Errno> {
1607 track_hook_duration!("security.hooks.bprm_creds_for_exec");
1608 if let Some(state) = ¤t_task.kernel().security_state.state {
1609 if state.has_policy() {
1610 return selinux_hooks::task::bprm_creds_for_exec(
1611 &state.server,
1612 current_task,
1613 resolved_program,
1614 );
1615 } else {
1616 let previous_sid = current_task.current_creds().security_state.current_sid;
1618 resolved_program.creds.security_state =
1619 TaskAttrs::for_transition(InitialSid::Init.into(), previous_sid);
1620 }
1621 }
1622 Ok(())
1623}
1624
1625pub fn bprm_committing_creds(
1630 current_task: &CurrentTask,
1631 resolved_program: &ResolvedProgram,
1632) -> Result<(), Errno> {
1633 track_hook_duration!("security.hooks.bprm_committing_creds");
1634 if_selinux_else_default_ok(current_task, |security_server| {
1635 selinux_hooks::task::bprm_committing_creds(security_server, current_task, resolved_program);
1636 Ok(())
1637 })
1638}
1639
1640pub fn bprm_committed_creds(current_task: &CurrentTask) -> Result<(), Errno> {
1644 track_hook_duration!("security.hooks.bprm_committed_creds");
1645 if_selinux_else_default_ok(current_task, |security_server| {
1646 selinux_hooks::task::bprm_committed_creds(security_server, current_task);
1647 Ok(())
1648 })
1649}
1650
1651pub fn check_task_getscheduler_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1654 track_hook_duration!("security.hooks.task_getscheduler");
1655 if_selinux_else_default_ok(source, |security_server| {
1656 selinux_hooks::task::check_getsched_access(
1657 &selinux_hooks::build_permission_check(source, security_server),
1658 &source,
1659 &target,
1660 )
1661 })
1662}
1663
1664pub fn check_task_setscheduler_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1667 track_hook_duration!("security.hooks.task_setscheduler");
1668 if_selinux_else_default_ok(source, |security_server| {
1669 selinux_hooks::task::check_setsched_access(
1670 &selinux_hooks::build_permission_check(source, security_server),
1671 &source,
1672 &target,
1673 )
1674 })
1675}
1676
1677pub fn check_task_setnice_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1680 track_hook_duration!("security.hooks.check_task_setnice_access");
1681 if_selinux_else_default_ok(source, |security_server| {
1682 selinux_hooks::task::check_setsched_access(
1683 &selinux_hooks::build_permission_check(source, security_server),
1684 &source,
1685 &target,
1686 )
1687 })
1688}
1689
1690pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1693 track_hook_duration!("security.hooks.check_getpgid_access");
1694 if_selinux_else_default_ok(source, |security_server| {
1695 selinux_hooks::task::check_getpgid_access(
1696 &selinux_hooks::build_permission_check(source, security_server),
1697 &source,
1698 &target,
1699 )
1700 })
1701}
1702
1703pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1706 track_hook_duration!("security.hooks.check_setpgid_access");
1707 if_selinux_else_default_ok(source, |security_server| {
1708 selinux_hooks::task::check_setpgid_access(
1709 &selinux_hooks::build_permission_check(source, security_server),
1710 &source,
1711 &target,
1712 )
1713 })
1714}
1715
1716pub fn check_task_getsid(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1719 track_hook_duration!("security.hooks.check_task_getsid");
1720 if_selinux_else_default_ok(source, |security_server| {
1721 selinux_hooks::task::check_task_getsid(
1722 &selinux_hooks::build_permission_check(source, security_server),
1723 &source,
1724 &target,
1725 )
1726 })
1727}
1728
1729pub fn check_getcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1732 track_hook_duration!("security.hooks.check_getcap_access");
1733 if_selinux_else_default_ok(source, |security_server| {
1734 selinux_hooks::task::check_getcap_access(
1735 &selinux_hooks::build_permission_check(source, security_server),
1736 &source,
1737 &target,
1738 )
1739 })
1740}
1741
1742pub fn check_setcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1746 track_hook_duration!("security.hooks.check_setcap_access");
1747 if_selinux_else_default_ok(source, |security_server| {
1748 selinux_hooks::task::check_setcap_access(
1749 &selinux_hooks::build_permission_check(source, security_server),
1750 &source,
1751 &target,
1752 )
1753 })
1754}
1755
1756pub fn check_signal_access(
1759 source: &CurrentTask,
1760 target: &Task,
1761 signal: Signal,
1762) -> Result<(), Errno> {
1763 track_hook_duration!("security.hooks.check_signal_access");
1764 if_selinux_else_default_ok(source, |security_server| {
1765 selinux_hooks::task::check_signal_access(
1766 &selinux_hooks::build_permission_check(source, security_server),
1767 &source,
1768 &target,
1769 signal,
1770 )
1771 })
1772}
1773
1774pub fn check_syslog_access(source: &CurrentTask, action: SyslogAction) -> Result<(), Errno> {
1777 track_hook_duration!("security.hooks.check_syslog_access");
1778 if_selinux_else_default_ok(source, |security_server| {
1779 selinux_hooks::task::check_syslog_access(
1780 &selinux_hooks::build_permission_check(source, security_server),
1781 &source,
1782 action,
1783 )
1784 })
1785}
1786
1787pub fn ptrace_traceme(current_task: &CurrentTask, parent_tracer_task: &Task) -> Result<(), Errno> {
1790 track_hook_duration!("security.hooks.ptrace_traceme");
1791 yama::ptrace_traceme(current_task, parent_tracer_task)?;
1792 common_cap::ptrace_traceme(current_task, parent_tracer_task)?;
1793 if_selinux_else_default_ok(current_task, |security_server| {
1794 selinux_hooks::task::ptrace_traceme(
1795 &selinux_hooks::build_permission_check(current_task, security_server),
1796 current_task,
1797 parent_tracer_task,
1798 )
1799 })
1800}
1801
1802pub fn ptrace_access_check(
1805 current_task: &CurrentTask,
1806 tracee_task: &Task,
1807 mode: PtraceAccessMode,
1808) -> Result<(), Errno> {
1809 track_hook_duration!("security.hooks.ptrace_access_check");
1810 yama::ptrace_access_check(current_task, tracee_task, mode)?;
1811 common_cap::ptrace_access_check(current_task, tracee_task, mode)?;
1812 if_selinux_else_default_ok(current_task, |security_server| {
1813 selinux_hooks::task::ptrace_access_check(
1814 &selinux_hooks::build_permission_check(current_task, security_server),
1815 current_task,
1816 tracee_task,
1817 mode,
1818 )
1819 })
1820}
1821
1822pub fn task_prlimit(
1825 source: &CurrentTask,
1826 target: &Task,
1827 check_get_rlimit: bool,
1828 check_set_rlimit: bool,
1829) -> Result<(), Errno> {
1830 track_hook_duration!("security.hooks.task_prlimit");
1831 if_selinux_else_default_ok(source, |security_server| {
1832 selinux_hooks::task::task_prlimit(
1833 &selinux_hooks::build_permission_check(source, security_server),
1834 &source,
1835 &target,
1836 check_get_rlimit,
1837 check_set_rlimit,
1838 )
1839 })
1840}
1841
1842pub fn task_setrlimit(
1845 source: &CurrentTask,
1846 target: &Task,
1847 old_limit: rlimit,
1848 new_limit: rlimit,
1849) -> Result<(), Errno> {
1850 track_hook_duration!("security.hooks.task_setrlimit");
1851 if_selinux_else_default_ok(source, |security_server| {
1852 selinux_hooks::task::task_setrlimit(
1853 &selinux_hooks::build_permission_check(source, security_server),
1854 &source,
1855 &target,
1856 old_limit,
1857 new_limit,
1858 )
1859 })
1860}
1861
1862pub fn sb_kern_mount(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1865 track_hook_duration!("security.hooks.sb_kern_mount");
1866 if_selinux_else_default_ok(current_task, |security_server| {
1867 selinux_hooks::superblock::sb_kern_mount(
1868 &selinux_hooks::build_permission_check(current_task, security_server),
1869 current_task,
1870 fs,
1871 )
1872 })
1873}
1874
1875pub fn sb_mount(
1879 current_task: &CurrentTask,
1880 path: &NamespaceNode,
1881 flags: MountFlags,
1882) -> Result<(), Errno> {
1883 track_hook_duration!("security.hooks.sb_mount");
1884 if path.entry.node.is_private() {
1885 return Ok(());
1888 }
1889 if_selinux_else_default_ok(current_task, |security_server| {
1890 selinux_hooks::superblock::sb_mount(
1891 &selinux_hooks::build_permission_check(current_task, security_server),
1892 current_task,
1893 path,
1894 flags,
1895 )
1896 })
1897}
1898
1899pub fn sb_remount(
1902 current_task: &CurrentTask,
1903 mount: &Mount,
1904 new_mount_options: FileSystemMountOptions,
1905) -> Result<(), Errno> {
1906 track_hook_duration!("security.hooks.sb_remount");
1907 if_selinux_else_default_ok(current_task, |security_server| {
1908 selinux_hooks::superblock::sb_remount(security_server, mount, new_mount_options)
1909 })
1910}
1911
1912pub fn sb_show_options<'a>(
1915 _kernel: &Kernel,
1916 fs: &'a FileSystem,
1917) -> Result<impl std::fmt::Display + 'a, Errno> {
1918 track_hook_duration!("security.hooks.sb_show_options");
1919 selinux_hooks::superblock::sb_show_options(fs)
1920}
1921
1922pub fn sb_statfs(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1925 track_hook_duration!("security.hooks.sb_statfs");
1926 if_selinux_else_default_ok(current_task, |security_server| {
1927 selinux_hooks::superblock::sb_statfs(
1928 &selinux_hooks::build_permission_check(current_task, security_server),
1929 current_task,
1930 fs,
1931 )
1932 })
1933}
1934
1935pub fn sb_umount(
1939 current_task: &CurrentTask,
1940 node: &NamespaceNode,
1941 flags: UnmountFlags,
1942) -> Result<(), Errno> {
1943 track_hook_duration!("security.hooks.sb_umount");
1944 if node.entry.node.is_private() {
1945 return Ok(());
1948 }
1949 if_selinux_else_default_ok(current_task, |security_server| {
1950 selinux_hooks::superblock::sb_umount(
1951 &selinux_hooks::build_permission_check(current_task, security_server),
1952 current_task,
1953 node,
1954 flags,
1955 )
1956 })
1957}
1958
1959pub fn check_fs_node_getattr_access(
1962 current_task: &CurrentTask,
1963 fs_node: &FsNode,
1964) -> Result<(), Errno> {
1965 track_hook_duration!("security.hooks.check_fs_node_getattr_access");
1966 if fs_node.is_private() {
1967 return Ok(());
1968 }
1969 if_selinux_else_default_ok(current_task, |security_server| {
1970 selinux_hooks::fs_node::check_fs_node_getattr_access(security_server, current_task, fs_node)
1971 })
1972}
1973
1974pub fn path_notify(
1978 current_task: &CurrentTask,
1979 fs_node: &FsNode,
1980 mask: InotifyMask,
1981) -> Result<(), Errno> {
1982 track_hook_duration!("security.hooks.path_notify");
1983 if fs_node.is_private() {
1984 return Ok(());
1985 }
1986 if_selinux_else_default_ok(current_task, |security_server| {
1987 selinux_hooks::fs_node::path_notify(security_server, current_task, fs_node, mask)
1988 })
1989}
1990
1991pub fn fs_node_xattr_skipcap(name: &FsStr) -> bool {
1994 common_cap::fs_node_xattr_skipcap(name) || selinux_hooks::fs_node::fs_node_xattr_skipcap(name)
1995}
1996
1997pub fn check_fs_node_setxattr_access(
2003 current_task: &CurrentTask,
2004 fs_node: &FsNode,
2005 name: &FsStr,
2006 value: &FsStr,
2007 op: XattrOp,
2008) -> Result<(), Errno> {
2009 track_hook_duration!("security.hooks.check_fs_node_setxattr_access");
2010 if fs_node.is_private() {
2011 return Ok(());
2012 }
2013 common_cap::fs_node_setxattr(current_task, fs_node, name, value, op)?;
2014 if_selinux_else_default_ok(current_task, |security_server| {
2015 selinux_hooks::fs_node::check_fs_node_setxattr_access(
2016 security_server,
2017 current_task,
2018 fs_node,
2019 name,
2020 value,
2021 op,
2022 )
2023 })
2024}
2025
2026pub fn check_fs_node_getxattr_access(
2028 current_task: &CurrentTask,
2029 fs_node: &FsNode,
2030 name: &FsStr,
2031) -> Result<(), Errno> {
2032 track_hook_duration!("security.hooks.check_fs_node_getxattr_access");
2033 if fs_node.is_private() {
2034 return Ok(());
2035 }
2036 if_selinux_else_default_ok(current_task, |security_server| {
2037 selinux_hooks::fs_node::check_fs_node_getxattr_access(
2038 security_server,
2039 current_task,
2040 fs_node,
2041 name,
2042 )
2043 })
2044}
2045
2046pub fn check_fs_node_listxattr_access(
2048 current_task: &CurrentTask,
2049 fs_node: &FsNode,
2050) -> Result<(), Errno> {
2051 track_hook_duration!("security.hooks.check_fs_node_listxattr_access");
2052 if fs_node.is_private() {
2053 return Ok(());
2054 }
2055 if_selinux_else_default_ok(current_task, |security_server| {
2056 selinux_hooks::fs_node::check_fs_node_listxattr_access(
2057 security_server,
2058 current_task,
2059 fs_node,
2060 )
2061 })
2062}
2063
2064pub fn check_fs_node_removexattr_access(
2066 current_task: &CurrentTask,
2067 fs_node: &FsNode,
2068 name: &FsStr,
2069) -> Result<(), Errno> {
2070 track_hook_duration!("security.hooks.check_fs_node_removexattr_access");
2071 if fs_node.is_private() {
2072 return Ok(());
2073 }
2074 common_cap::fs_node_removexattr(current_task, fs_node, name)?;
2075 if_selinux_else_default_ok(current_task, |security_server| {
2076 selinux_hooks::fs_node::check_fs_node_removexattr_access(
2077 security_server,
2078 current_task,
2079 fs_node,
2080 name,
2081 )
2082 })
2083}
2084
2085pub fn fs_node_needs_killpriv(current_task: &CurrentTask, fs_node: &FsNode) -> Result<bool, Errno> {
2090 track_hook_duration!("security.hooks.fs_node_needs_killpriv");
2091 if fs_node.is_private() {
2092 return Ok(false);
2093 }
2094 common_cap::fs_node_needs_killpriv(current_task, fs_node)
2095}
2096
2097pub fn fs_node_killpriv(current_task: &CurrentTask, fs_node: &FsNode) -> Result<(), Errno> {
2102 track_hook_duration!("security.hooks.fs_node_killpriv");
2103 if fs_node.is_private() {
2104 return Ok(());
2105 }
2106 common_cap::fs_node_killpriv(current_task, fs_node)
2107}
2108
2109pub fn fs_node_listsecurity(current_task: &CurrentTask, fs_node: &FsNode) -> Option<FsString> {
2116 track_hook_duration!("security.hooks.fs_node_listsecurity");
2117 if fs_node.is_private() {
2118 return None;
2119 }
2120 if_selinux_else(
2121 current_task,
2122 |_| selinux_hooks::fs_node::fs_node_listsecurity(fs_node),
2123 || None,
2124 )
2125}
2126
2127pub fn fs_node_getsecurity(
2135 current_task: &CurrentTask,
2136 fs_node: &FsNode,
2137 name: &FsStr,
2138 max_size: usize,
2139) -> Result<ValueOrSize<FsString>, Errno> {
2140 track_hook_duration!("security.hooks.fs_node_getsecurity");
2141 if fs_node.is_private() {
2142 return fs_node.ops().get_xattr(fs_node, current_task, name, max_size);
2143 }
2144 let result = if_selinux_else(
2145 current_task,
2146 |security_server| {
2147 selinux_hooks::fs_node::fs_node_getsecurity(
2148 security_server,
2149 current_task,
2150 fs_node,
2151 name,
2152 max_size,
2153 )
2154 .transpose()
2155 },
2156 || None,
2157 );
2158 let result = result.or_else(|| {
2159 common_cap::fs_node_getsecurity(current_task, fs_node, name, max_size).transpose()
2160 });
2161 result.unwrap_or_else(|| fs_node.ops().get_xattr(fs_node, current_task, name, max_size))
2162}
2163
2164pub fn fs_node_setsecurity(
2170 current_task: &CurrentTask,
2171 fs_node: &FsNode,
2172 name: &FsStr,
2173 value: &FsStr,
2174 op: XattrOp,
2175) -> Result<(), Errno> {
2176 track_hook_duration!("security.hooks.fs_node_setsecurity");
2177 if fs_node.is_private() {
2178 return fs_node.ops().set_xattr(fs_node, current_task, name, value, op);
2179 }
2180 let result = if_selinux_else(
2181 current_task,
2182 |security_server| {
2183 selinux_hooks::fs_node::fs_node_setsecurity(
2184 security_server,
2185 current_task,
2186 fs_node,
2187 name,
2188 value,
2189 op,
2190 )
2191 .transpose()
2192 },
2193 || None,
2194 );
2195 let result = result.or_else(|| {
2196 common_cap::fs_node_setsecurity(current_task, fs_node, name, value, op).transpose()
2197 });
2198 result.unwrap_or_else(|| fs_node.ops().set_xattr(fs_node, current_task, name, value, op))
2199}
2200
2201pub fn check_bpf_access<Attr: FromBytes>(
2205 current_task: &CurrentTask,
2206 cmd: bpf_cmd,
2207 attr: &Attr,
2208 attr_size: u32,
2209) -> Result<(), Errno> {
2210 track_hook_duration!("security.hooks.check_bpf_access");
2211 if_selinux_else_default_ok(current_task, |security_server| {
2212 selinux_hooks::bpf::check_bpf_access(security_server, current_task, cmd, attr, attr_size)
2213 })
2214}
2215
2216pub fn check_bpf_map_access(
2220 current_task: &CurrentTask,
2221 bpf_map_state: &BpfMapState,
2222 flags: PermissionFlags,
2223) -> Result<(), Errno> {
2224 track_hook_duration!("security.hooks.check_bpf_map_access");
2225 if_selinux_else_default_ok(current_task, |security_server| {
2226 let subject_sid = current_task_state(current_task).current_sid;
2227 selinux_hooks::bpf::check_bpf_map_access(
2228 security_server,
2229 current_task,
2230 subject_sid,
2231 bpf_map_state,
2232 flags,
2233 )
2234 })
2235}
2236
2237pub fn check_bpf_prog_access(
2242 current_task: &CurrentTask,
2243 bpf_program_state: &BpfProgState,
2244) -> Result<(), Errno> {
2245 track_hook_duration!("security.hooks.check_bpf_prog_access");
2246 if_selinux_else_default_ok(current_task, |security_server| {
2247 let subject_sid = current_task_state(current_task).current_sid;
2248 selinux_hooks::bpf::check_bpf_prog_access(
2249 security_server,
2250 current_task,
2251 subject_sid,
2252 bpf_program_state,
2253 )
2254 })
2255}
2256
2257pub fn check_perf_event_open_access(
2262 current_task: &CurrentTask,
2263 perf_event_open_type: PerfEventOpenType,
2264) -> Result<(), Errno> {
2265 track_hook_duration!("security.hooks.check_perf_event_open_access");
2266 if_selinux_else_default_ok(current_task, |security_server| {
2267 selinux_hooks::perf_event::check_perf_event_open_access(
2268 security_server,
2269 current_task,
2270 perf_event_open_type,
2271 )
2272 })
2273}
2274
2275pub fn perf_event_alloc(current_task: &CurrentTask) -> PerfEventState {
2279 track_hook_duration!("security.hooks.perf_event_alloc");
2280 PerfEventState { state: selinux_hooks::perf_event::perf_event_alloc(current_task) }
2281}
2282
2283pub fn check_perf_event_read_access(
2286 current_task: &CurrentTask,
2287 perf_event_file: &PerfEventFile,
2288) -> Result<(), Errno> {
2289 track_hook_duration!("security.hooks.check_perf_event_read_access");
2290 if_selinux_else_default_ok(current_task, |security_server| {
2291 selinux_hooks::perf_event::check_perf_event_read_access(
2292 security_server,
2293 current_task,
2294 perf_event_file,
2295 )
2296 })
2297}
2298
2299pub fn check_perf_event_write_access(
2302 current_task: &CurrentTask,
2303 perf_event_file: &PerfEventFile,
2304) -> Result<(), Errno> {
2305 track_hook_duration!("security.hooks.check_perf_event_write_access");
2306 if_selinux_else_default_ok(current_task, |security_server| {
2307 selinux_hooks::perf_event::check_perf_event_write_access(
2308 security_server,
2309 current_task,
2310 perf_event_file,
2311 )
2312 })
2313}
2314
2315#[derive(Debug, Clone, Copy, PartialEq)]
2317pub enum ProcAttr {
2318 Current,
2319 Exec,
2320 FsCreate,
2321 KeyCreate,
2322 Previous,
2323 SockCreate,
2324}
2325
2326pub fn get_procattr(
2329 current_task: &CurrentTask,
2330 target: &Task,
2331 attr: ProcAttr,
2332) -> Result<Vec<u8>, Errno> {
2333 track_hook_duration!("security.hooks.get_procattr");
2334 if_selinux_else(
2335 current_task,
2336 |security_server| {
2337 selinux_hooks::task::get_procattr(security_server, current_task, target, attr)
2338 },
2339 || error!(EINVAL),
2341 )
2342}
2343
2344pub fn set_procattr(
2347 current_task: &CurrentTask,
2348 attr: ProcAttr,
2349 context: &[u8],
2350) -> Result<(), Errno> {
2351 track_hook_duration!("security.hooks.set_procattr");
2352 if_selinux_else(
2353 current_task,
2354 |security_server| {
2355 selinux_hooks::task::set_procattr(security_server, current_task, attr, context)
2356 },
2357 || error!(EINVAL),
2359 )
2360}
2361
2362pub fn fs_is_xattr_labeled(fs: FileSystemHandle) -> bool {
2364 fs.security_state.state.supports_xattr()
2365}
2366
2367pub fn selinuxfs_init_null(current_task: &CurrentTask, null_fs_node: &FileHandle) {
2370 selinux_hooks::selinuxfs::selinuxfs_init_null(current_task, null_fs_node)
2373}
2374
2375pub fn selinuxfs_policy_loaded(current_task: &CurrentTask) {
2381 track_hook_duration!("security.hooks.selinuxfs_policy_loaded");
2382 selinux_hooks::selinuxfs::selinuxfs_policy_loaded(current_task)
2383}
2384
2385pub fn selinuxfs_get_admin_api(current_task: &CurrentTask) -> Option<Arc<SecurityServer>> {
2389 current_task.kernel().security_state.state.as_ref().map(|state| state.server.clone())
2390}
2391
2392pub fn selinuxfs_check_access(
2395 current_task: &CurrentTask,
2396 permission: SecurityPermission,
2397) -> Result<(), Errno> {
2398 track_hook_duration!("security.hooks.selinuxfs_check_access");
2399 if_selinux_else_default_ok(current_task, |security_server| {
2400 selinux_hooks::selinuxfs::selinuxfs_check_access(security_server, current_task, permission)
2401 })
2402}
2403
2404pub fn creds_start_internal_operation(current_task: &CurrentTask) -> Arc<Credentials> {
2407 track_hook_duration!("security.hooks.creds_start_internal_operation");
2408 let mut creds = Credentials::clone(¤t_task.current_creds());
2409 creds.security_state.internal_operation = true;
2410 creds.into()
2411}
2412
2413pub mod testing {
2414 use super::{Arc, KernelState, SecurityServer, selinux_hooks};
2415 use starnix_sync::LockDepMutex;
2416 use std::sync::OnceLock;
2417 use std::sync::atomic::AtomicU64;
2418
2419 pub fn kernel_state(security_server: Option<Arc<SecurityServer>>) -> KernelState {
2422 let state = security_server.map(|server| selinux_hooks::KernelState {
2423 server,
2424 pending_file_systems: LockDepMutex::default(),
2425 selinuxfs_null: OnceLock::default(),
2426 access_denial_count: AtomicU64::new(0u64),
2427 has_policy: false.into(),
2428 _inspect_node: fuchsia_inspect::Node::default(),
2429 });
2430 KernelState { state }
2431 }
2432}
2433
2434#[cfg(test)]
2435mod tests {
2436 use super::*;
2437 use crate::device::mem::new_null_file;
2438 use crate::mm::DumpPolicy;
2439 use crate::security;
2440 use crate::security::selinux_hooks::get_cached_sid;
2441 use crate::security::selinux_hooks::testing::{
2442 self, spawn_kernel_with_selinux_hooks_test_policy_and_run,
2443 };
2444 use crate::testing::{
2445 create_task, create_task_with_security_context, spawn_kernel_and_run,
2446 spawn_kernel_with_selinux_and_run,
2447 };
2448 use linux_uapi::XATTR_NAME_SELINUX;
2449 use selinux::InitialSid;
2450 use starnix_uapi::auth::{
2451 CAP_SYS_PTRACE, PTRACE_MODE_ATTACH, PTRACE_MODE_ATTACH_REALCREDS, PTRACE_MODE_NOAUDIT,
2452 PTRACE_MODE_READ_FSCREDS,
2453 };
2454 use starnix_uapi::signals::SIGTERM;
2455 use std::ffi::CString;
2456 use std::sync::atomic::Ordering;
2457
2458 const VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_valid_t:s0";
2459 const VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] = b"u:object_r:test_valid_t:s0\0";
2460
2461 const DIFFERENT_VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_different_valid_t:s0";
2462 const DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] =
2463 b"u:object_r:test_different_valid_t:s0\0";
2464
2465 const INVALID_SECURITY_CONTEXT_INTERNAL_NUL: &[u8] = b"u:object_r:test_valid_\0t:s0";
2466
2467 const INVALID_SECURITY_CONTEXT: &[u8] = b"not_a_u:object_r:test_valid_t:s0";
2468
2469 #[derive(Default, Debug, PartialEq)]
2470 enum TestHookResult {
2471 WasRun,
2472 WasNotRun,
2473 #[default]
2474 WasNotRunDefault,
2475 }
2476
2477 #[fuchsia::test]
2478 async fn if_selinux_else_disabled() {
2479 spawn_kernel_and_run(async |current_task| {
2480 assert!(current_task.kernel().security_state.state.is_none());
2481
2482 let check_result =
2483 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2484 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2485
2486 let run_else_result = if_selinux_else(
2487 current_task,
2488 |_| TestHookResult::WasRun,
2489 || TestHookResult::WasNotRun,
2490 );
2491 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2492 })
2493 .await;
2494 }
2495
2496 #[fuchsia::test]
2497 async fn if_selinux_else_without_policy() {
2498 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2499 let check_result =
2500 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2501 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2502
2503 let run_else_result = if_selinux_else(
2504 current_task,
2505 |_| TestHookResult::WasRun,
2506 || TestHookResult::WasNotRun,
2507 );
2508 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2509 })
2510 .await;
2511 }
2512
2513 #[fuchsia::test]
2514 async fn if_selinux_else_with_policy() {
2515 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2516 let check_result =
2517 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2518 assert_eq!(check_result, Ok(TestHookResult::WasRun));
2519
2520 let run_else_result = if_selinux_else(
2521 current_task,
2522 |_| TestHookResult::WasRun,
2523 || TestHookResult::WasNotRun,
2524 );
2525 assert_eq!(run_else_result, TestHookResult::WasRun);
2526 })
2527 .await;
2528 }
2529
2530 #[fuchsia::test]
2531 async fn task_create_access_allowed_for_selinux_disabled() {
2532 spawn_kernel_and_run(async |current_task| {
2533 assert!(current_task.kernel().security_state.state.is_none());
2534 assert_eq!(check_task_create_access(current_task), Ok(()));
2535 })
2536 .await;
2537 }
2538
2539 #[fuchsia::test]
2540 async fn task_create_access_allowed_for_permissive_mode() {
2541 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2542 security_server.set_enforcing(false);
2543 assert_eq!(check_task_create_access(current_task), Ok(()));
2544 })
2545 .await;
2546 }
2547
2548 #[fuchsia::test]
2549 async fn exec_access_allowed_for_selinux_disabled() {
2550 spawn_kernel_and_run(async |current_task| {
2551 assert!(current_task.kernel().security_state.state.is_none());
2552 let executable = testing::create_test_file(current_task);
2553 let file = testing::open_test_file(current_task, &executable);
2554 let mut resolved_program = testing::make_resolved_program(current_task, file);
2555 assert_eq!(bprm_creds_for_exec(current_task, &mut resolved_program), Ok(()));
2556 })
2557 .await;
2558 }
2559
2560 #[fuchsia::test]
2561 async fn exec_access_allowed_for_permissive_mode() {
2562 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2563 security_server.set_enforcing(false);
2564 let executable = testing::create_test_file(current_task);
2565 let file = testing::open_test_file(current_task, &executable);
2566 let mut resolved_program = testing::make_resolved_program(current_task, file);
2567 let result = bprm_creds_for_exec(current_task, &mut resolved_program);
2569 assert!(result.is_ok());
2570 })
2571 .await;
2572 }
2573
2574 #[fuchsia::test]
2575 async fn exec_no_state_update_for_selinux_disabled() {
2576 spawn_kernel_and_run(async |current_task| {
2577 let target_sid = InitialSid::Unlabeled.into();
2578
2579 assert!(selinux_hooks::current_task_state(current_task).current_sid != target_sid);
2580
2581 testing::mutate_attrs_for_test(current_task, |attrs| {
2583 attrs.exec_sid = Some(target_sid);
2584 });
2585
2586 let executable = testing::create_test_file(current_task);
2587 let file = testing::open_test_file(current_task, &executable);
2588 let mut resolved_program = testing::make_resolved_program(current_task, file);
2589
2590 let before_hook_sid = selinux_hooks::current_task_state(current_task).current_sid;
2591
2592 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2593 assert_eq!(resolved_program.creds.security_state.current_sid, before_hook_sid);
2594 })
2595 .await;
2596 }
2597
2598 #[fuchsia::test]
2599 async fn exec_initial_context_for_selinux_without_policy() {
2600 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2601 let elf_sid = InitialSid::Unlabeled.into();
2602 assert_ne!(selinux_hooks::current_task_state(current_task).current_sid, elf_sid);
2603 assert_ne!(
2604 selinux_hooks::current_task_state(current_task).current_sid,
2605 InitialSid::Init.into()
2606 );
2607
2608 testing::mutate_attrs_for_test(current_task, |attrs| {
2610 attrs.exec_sid = Some(elf_sid);
2611 });
2612
2613 let executable = testing::create_test_file(current_task);
2614 let file = testing::open_test_file(current_task, &executable);
2615 let mut resolved_program = testing::make_resolved_program(current_task, file);
2616
2617 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2618
2619 assert_eq!(resolved_program.creds.security_state.current_sid, InitialSid::Init.into());
2620 })
2621 .await;
2622 }
2623
2624 #[fuchsia::test]
2625 async fn exec_state_update_for_permissive_mode() {
2626 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2627 security_server.set_enforcing(false);
2628 let elf_sid = security_server
2629 .security_context_to_sid(b"u:object_r:fork_no_t:s0".into())
2630 .expect("invalid security context");
2631
2632 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).current_sid);
2633
2634 testing::mutate_attrs_for_test(current_task, |attrs| {
2636 attrs.exec_sid = Some(elf_sid);
2637 });
2638
2639 let executable = testing::create_test_file(current_task);
2640 let file = testing::open_test_file(current_task, &executable);
2641 let mut resolved_program = testing::make_resolved_program(current_task, file);
2642
2643 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2644 assert_eq!(resolved_program.creds.security_state.current_sid, elf_sid);
2645 })
2646 .await;
2647 }
2648
2649 #[fuchsia::test]
2650 async fn getsched_access_allowed_for_selinux_disabled() {
2651 spawn_kernel_and_run(async |current_task| {
2652 let another_task = create_task(¤t_task.kernel(), "another-task");
2653 assert_eq!(check_task_getscheduler_access(current_task, &another_task), Ok(()));
2654 })
2655 .await;
2656 }
2657
2658 #[fuchsia::test]
2659 async fn getsched_access_allowed_for_permissive_mode() {
2660 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2661 let another_task = create_task(¤t_task.kernel(), "another-task");
2662 assert_eq!(check_task_getscheduler_access(current_task, &another_task), Ok(()));
2663 })
2664 .await;
2665 }
2666
2667 #[fuchsia::test]
2668 async fn setsched_access_allowed_for_selinux_disabled() {
2669 spawn_kernel_and_run(async |current_task| {
2670 let another_task = create_task(¤t_task.kernel(), "another-task");
2671 assert_eq!(check_task_setscheduler_access(current_task, &another_task), Ok(()));
2672 })
2673 .await;
2674 }
2675
2676 #[fuchsia::test]
2677 async fn setsched_access_allowed_for_permissive_mode() {
2678 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2679 let another_task = create_task(¤t_task.kernel(), "another-task");
2680 assert_eq!(check_task_setscheduler_access(current_task, &another_task), Ok(()));
2681 })
2682 .await;
2683 }
2684
2685 #[fuchsia::test]
2686 async fn getpgid_access_allowed_for_selinux_disabled() {
2687 spawn_kernel_and_run(async |current_task| {
2688 let another_task = create_task(¤t_task.kernel(), "another-task");
2689 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2690 })
2691 .await;
2692 }
2693
2694 #[fuchsia::test]
2695 async fn getpgid_access_allowed_for_permissive_mode() {
2696 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2697 let another_task = create_task(¤t_task.kernel(), "another-task");
2698 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2699 })
2700 .await;
2701 }
2702
2703 #[fuchsia::test]
2704 async fn setpgid_access_allowed_for_selinux_disabled() {
2705 spawn_kernel_and_run(async |current_task| {
2706 let another_task = create_task(¤t_task.kernel(), "another-task");
2707 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2708 })
2709 .await;
2710 }
2711
2712 #[fuchsia::test]
2713 async fn setpgid_access_allowed_for_permissive_mode() {
2714 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2715 let another_task = create_task(¤t_task.kernel(), "another-task");
2716 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2717 })
2718 .await;
2719 }
2720
2721 #[fuchsia::test]
2722 async fn task_getsid_allowed_for_selinux_disabled() {
2723 spawn_kernel_and_run(async |current_task| {
2724 let another_task = create_task(¤t_task.kernel(), "another-task");
2725 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2726 })
2727 .await;
2728 }
2729
2730 #[fuchsia::test]
2731 async fn task_getsid_allowed_for_permissive_mode() {
2732 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2733 let another_task = create_task(¤t_task.kernel(), "another-task");
2734 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2735 })
2736 .await;
2737 }
2738
2739 #[fuchsia::test]
2740 async fn signal_access_allowed_for_selinux_disabled() {
2741 spawn_kernel_and_run(async |current_task| {
2742 let another_task = create_task(¤t_task.kernel(), "another-task");
2743 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2744 })
2745 .await;
2746 }
2747
2748 #[fuchsia::test]
2749 async fn signal_access_allowed_for_permissive_mode() {
2750 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2751 let another_task = create_task(¤t_task.kernel(), "another-task");
2752 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2753 })
2754 .await;
2755 }
2756
2757 #[fuchsia::test]
2758 async fn ptrace_traceme_access_allowed_for_selinux_disabled() {
2759 spawn_kernel_and_run(async |current_task| {
2760 let another_task = create_task(¤t_task.kernel(), "another-task");
2761 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2762 })
2763 .await;
2764 }
2765
2766 #[fuchsia::test]
2767 async fn ptrace_traceme_access_allowed_for_permissive_mode() {
2768 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2769 let another_task = create_task(¤t_task.kernel(), "another-task");
2770 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2771 })
2772 .await;
2773 }
2774
2775 #[fuchsia::test]
2776 async fn ptrace_attach_access_allowed_for_selinux_disabled() {
2777 spawn_kernel_and_run(async |current_task| {
2778 let another_task = create_task(¤t_task.kernel(), "another-task");
2779 assert_eq!(
2780 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2781 Ok(())
2782 );
2783 })
2784 .await;
2785 }
2786
2787 #[fuchsia::test]
2788 async fn ptrace_attach_access_allowed_for_permissive_mode() {
2789 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2790 let another_task = create_task(¤t_task.kernel(), "another-task");
2791 assert_eq!(
2792 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2793 Ok(())
2794 );
2795 })
2796 .await;
2797 }
2798
2799 #[fuchsia::test]
2800 async fn task_prlimit_access_allowed_for_selinux_disabled() {
2801 spawn_kernel_and_run(async |current_task| {
2802 let another_task = create_task(¤t_task.kernel(), "another-task");
2803 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2804 })
2805 .await;
2806 }
2807
2808 #[fuchsia::test]
2809 async fn task_prlimit_access_allowed_for_permissive_mode() {
2810 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2811 let another_task = create_task(¤t_task.kernel(), "another-task");
2812 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2813 })
2814 .await;
2815 }
2816
2817 #[fuchsia::test]
2818 async fn fs_node_task_to_fs_node_noop_selinux_disabled() {
2819 spawn_kernel_and_run(async |current_task| {
2820 let node = &testing::create_test_file(current_task).entry.node;
2821 task_to_fs_node(current_task, ¤t_task.task, &node);
2822 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2823 })
2824 .await;
2825 }
2826
2827 #[fuchsia::test]
2828 async fn fs_node_setsecurity_selinux_disabled_only_sets_xattr() {
2829 spawn_kernel_and_run(async |current_task| {
2830 let node = &testing::create_test_file(current_task).entry.node;
2831
2832 fs_node_setsecurity(
2833 ¤t_task,
2834 &node,
2835 XATTR_NAME_SELINUX.to_bytes().into(),
2836 VALID_SECURITY_CONTEXT.into(),
2837 XattrOp::Set,
2838 )
2839 .expect("set_xattr(security.selinux) failed");
2840
2841 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2842 })
2843 .await;
2844 }
2845
2846 #[fuchsia::test]
2847 async fn fs_node_setsecurity_selinux_without_policy_only_sets_xattr() {
2848 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2849 let node = &testing::create_test_file(current_task).entry.node;
2850 fs_node_setsecurity(
2851 ¤t_task,
2852 &node,
2853 XATTR_NAME_SELINUX.to_bytes().into(),
2854 VALID_SECURITY_CONTEXT.into(),
2855 XattrOp::Set,
2856 )
2857 .expect("set_xattr(security.selinux) failed");
2858
2859 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2860 })
2861 .await;
2862 }
2863
2864 #[fuchsia::test]
2865 async fn fs_node_setsecurity_selinux_permissive_sets_xattr_and_label() {
2866 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2867 security_server.set_enforcing(false);
2868 let expected_sid = security_server
2869 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2870 .expect("no SID for VALID_SECURITY_CONTEXT");
2871 let node = &testing::create_test_file(¤t_task).entry.node;
2872
2873 assert_ne!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2875
2876 fs_node_setsecurity(
2877 ¤t_task,
2878 &node,
2879 XATTR_NAME_SELINUX.to_bytes().into(),
2880 VALID_SECURITY_CONTEXT.into(),
2881 XattrOp::Set,
2882 )
2883 .expect("set_xattr(security.selinux) failed");
2884
2885 assert_eq!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2888 })
2889 .await;
2890 }
2891
2892 #[fuchsia::test]
2893 async fn fs_node_setsecurity_not_selinux_only_sets_xattr() {
2894 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2895 let valid_security_context_sid = security_server
2896 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2897 .expect("no SID for VALID_SECURITY_CONTEXT");
2898 let node = &testing::create_test_file(current_task).entry.node;
2899 let whatever_sid = selinux_hooks::get_cached_sid(node);
2903 assert_ne!(Some(valid_security_context_sid), whatever_sid);
2904
2905 fs_node_setsecurity(
2906 ¤t_task,
2907 &node,
2908 "security.selinu!".into(), VALID_SECURITY_CONTEXT.into(),
2910 XattrOp::Set,
2911 )
2912 .expect("set_xattr(security.selinux) failed");
2913
2914 assert_eq!(whatever_sid, selinux_hooks::get_cached_sid(node));
2916 })
2917 .await;
2918 }
2919
2920 #[fuchsia::test]
2921 async fn fs_node_setsecurity_selinux_enforcing_invalid_context_fails() {
2922 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2923 let node = &testing::create_test_file(current_task).entry.node;
2924
2925 let before_sid = selinux_hooks::get_cached_sid(node);
2926 assert_ne!(Some(InitialSid::Unlabeled.into()), before_sid);
2927
2928 assert!(
2929 check_fs_node_setxattr_access(
2930 ¤t_task,
2931 &node,
2932 XATTR_NAME_SELINUX.to_bytes().into(),
2933 "!".into(), XattrOp::Set,
2935 )
2936 .is_err()
2937 );
2938
2939 assert_eq!(before_sid, selinux_hooks::get_cached_sid(node));
2940 })
2941 .await;
2942 }
2943
2944 #[fuchsia::test]
2945 async fn fs_node_setsecurity_selinux_permissive_invalid_context_sets_xattr_and_label() {
2946 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2947 security_server.set_enforcing(false);
2948 let node = &testing::create_test_file(current_task).entry.node;
2949
2950 assert_ne!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2951
2952 fs_node_setsecurity(
2953 ¤t_task,
2954 &node,
2955 XATTR_NAME_SELINUX.to_bytes().into(),
2956 "!".into(), XattrOp::Set,
2958 )
2959 .expect("set_xattr(security.selinux) failed");
2960
2961 assert_eq!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2962 })
2963 .await;
2964 }
2965
2966 #[fuchsia::test]
2967 async fn fs_node_setsecurity_different_sid_for_different_context() {
2968 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2969 let node = &testing::create_test_file(current_task).entry.node;
2970
2971 fs_node_setsecurity(
2972 ¤t_task,
2973 &node,
2974 XATTR_NAME_SELINUX.to_bytes().into(),
2975 VALID_SECURITY_CONTEXT.into(),
2976 XattrOp::Set,
2977 )
2978 .expect("set_xattr(security.selinux) failed");
2979
2980 assert!(selinux_hooks::get_cached_sid(node).is_some());
2981
2982 let first_sid = selinux_hooks::get_cached_sid(node).unwrap();
2983 fs_node_setsecurity(
2984 ¤t_task,
2985 &node,
2986 XATTR_NAME_SELINUX.to_bytes().into(),
2987 DIFFERENT_VALID_SECURITY_CONTEXT.into(),
2988 XattrOp::Set,
2989 )
2990 .expect("set_xattr(security.selinux) failed");
2991
2992 assert!(selinux_hooks::get_cached_sid(node).is_some());
2993
2994 let second_sid = selinux_hooks::get_cached_sid(node).unwrap();
2995
2996 assert_ne!(first_sid, second_sid);
2997 })
2998 .await;
2999 }
3000
3001 #[fuchsia::test]
3002 async fn fs_node_getsecurity_returns_cached_context() {
3003 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3004 let node = &testing::create_test_file(current_task).entry.node;
3005
3006 const TEST_VALUE: &str = "Something Random";
3008 node.ops()
3009 .set_xattr(
3010 node,
3011 current_task,
3012 XATTR_NAME_SELINUX.to_bytes().into(),
3013 TEST_VALUE.into(),
3014 XattrOp::Set,
3015 )
3016 .expect("set_xattr(security.selinux) failed");
3017
3018 let sid = security_server
3020 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
3021 .expect("security context to SID");
3022 selinux_hooks::set_cached_sid(&node, sid);
3023
3024 let result =
3026 fs_node_getsecurity(current_task, node, XATTR_NAME_SELINUX.to_bytes().into(), 4096);
3027 assert_eq!(
3028 result,
3029 Ok(ValueOrSize::Value(FsString::new(VALID_SECURITY_CONTEXT_WITH_NUL.into())))
3030 );
3031 })
3032 .await;
3033 }
3034
3035 #[fuchsia::test]
3036 async fn fs_node_getsecurity_delegates_to_get_xattr() {
3037 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3038 let node = &testing::create_test_file(current_task).entry.node;
3039
3040 security_server.set_enforcing(false);
3043 const TEST_VALUE: &str = "Something Random";
3044 fs_node_setsecurity(
3045 ¤t_task,
3046 node,
3047 XATTR_NAME_SELINUX.to_bytes().into(),
3048 TEST_VALUE.into(),
3049 XattrOp::Set,
3050 )
3051 .expect("set_xattr(security.selinux) failed");
3052 security_server.set_enforcing(true);
3053
3054 let result =
3056 fs_node_getsecurity(current_task, node, XATTR_NAME_SELINUX.to_bytes().into(), 4096);
3057 assert_eq!(result, Ok(ValueOrSize::Value(FsString::new(TEST_VALUE.into()))));
3058 })
3059 .await;
3060 }
3061
3062 #[fuchsia::test]
3063 async fn set_get_procattr() {
3064 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3065 assert_eq!(get_procattr(current_task, current_task, ProcAttr::Exec), Ok(Vec::new()));
3066
3067 assert_eq!(
3068 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3070 Ok(())
3071 );
3072
3073 assert_eq!(
3074 set_procattr(
3076 current_task,
3077 ProcAttr::SockCreate,
3078 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3079 ),
3080 error!(EACCES)
3081 );
3082
3083 assert_eq!(
3084 set_procattr(
3086 current_task,
3087 ProcAttr::Previous,
3088 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3089 ),
3090 error!(EINVAL)
3091 );
3092
3093 assert_eq!(
3094 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3096 error!(EINVAL)
3097 );
3098
3099 assert_eq!(
3100 get_procattr(current_task, current_task, ProcAttr::Exec),
3101 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3102 );
3103
3104 assert!(get_procattr(current_task, current_task, ProcAttr::Current).is_ok());
3105 })
3106 .await;
3107 }
3108
3109 #[fuchsia::test]
3110 async fn set_get_procattr_with_nulls() {
3111 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3112 assert_eq!(get_procattr(current_task, current_task, ProcAttr::Exec), Ok(Vec::new()));
3113
3114 assert_eq!(
3115 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT_WITH_NUL.into()),
3117 Ok(())
3118 );
3119
3120 assert_eq!(
3121 set_procattr(
3123 current_task,
3124 ProcAttr::FsCreate,
3125 INVALID_SECURITY_CONTEXT_INTERNAL_NUL.into()
3126 ),
3127 error!(EINVAL)
3128 );
3129
3130 assert_eq!(
3131 get_procattr(current_task, current_task, ProcAttr::Exec),
3132 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3133 );
3134
3135 assert_eq!(
3136 get_procattr(current_task, current_task, ProcAttr::FsCreate),
3137 Ok(Vec::new())
3138 );
3139 })
3140 .await;
3141 }
3142
3143 #[fuchsia::test]
3144 async fn set_get_procattr_clear_context() {
3145 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3146 assert_eq!(
3148 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3149 Ok(())
3150 );
3151 assert_eq!(
3152 set_procattr(
3153 current_task,
3154 ProcAttr::FsCreate,
3155 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3156 ),
3157 Ok(())
3158 );
3159
3160 assert_eq!(set_procattr(current_task, ProcAttr::Exec, b"\0"), Ok(()));
3162 assert_eq!(current_task.current_creds().security_state.exec_sid, None);
3163
3164 assert_eq!(set_procattr(current_task, ProcAttr::FsCreate, b"\x0a"), Ok(()));
3166 assert_eq!(current_task.current_creds().security_state.fscreate_sid, None);
3167 })
3168 .await;
3169 }
3170
3171 #[fuchsia::test]
3172 async fn set_get_procattr_setcurrent() {
3173 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3174 let initial_previous =
3176 get_procattr(current_task, current_task, ProcAttr::Previous).unwrap();
3177
3178 assert_eq!(
3179 set_procattr(current_task, ProcAttr::Current, VALID_SECURITY_CONTEXT.into()),
3181 Ok(())
3182 );
3183
3184 assert_eq!(
3185 get_procattr(current_task, current_task, ProcAttr::Current),
3187 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3188 );
3189
3190 assert_eq!(
3191 get_procattr(current_task, current_task, ProcAttr::Previous),
3193 Ok(initial_previous.clone())
3194 );
3195
3196 assert_eq!(
3197 set_procattr(
3199 current_task,
3200 ProcAttr::Current,
3201 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3202 ),
3203 Ok(())
3204 );
3205
3206 assert_eq!(
3207 get_procattr(current_task, current_task, ProcAttr::Current),
3209 Ok(DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL.into())
3210 );
3211
3212 assert_eq!(
3213 get_procattr(current_task, current_task, ProcAttr::Previous),
3215 Ok(initial_previous.clone())
3216 );
3217 })
3218 .await;
3219 }
3220
3221 #[fuchsia::test]
3222 async fn set_get_procattr_selinux_permissive() {
3223 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3224 security_server.set_enforcing(false);
3225 assert_eq!(
3226 get_procattr(current_task, ¤t_task.task, ProcAttr::Exec),
3227 Ok(Vec::new())
3228 );
3229
3230 assert_eq!(
3231 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3233 Ok(())
3234 );
3235
3236 assert_eq!(
3237 set_procattr(
3240 current_task,
3241 ProcAttr::FsCreate,
3242 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3243 ),
3244 Ok(())
3245 );
3246
3247 assert_eq!(
3248 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3250 error!(EINVAL)
3251 );
3252
3253 assert_eq!(
3254 get_procattr(current_task, ¤t_task.task, ProcAttr::Exec),
3255 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3256 );
3257
3258 assert!(get_procattr(current_task, ¤t_task.task, ProcAttr::Current).is_ok());
3259 })
3260 .await;
3261 }
3262
3263 #[fuchsia::test]
3264 async fn set_get_procattr_selinux_disabled() {
3265 spawn_kernel_and_run(async |current_task| {
3266 assert_eq!(
3267 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3268 error!(EINVAL)
3269 );
3270
3271 assert_eq!(
3272 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3274 error!(EINVAL)
3275 );
3276
3277 assert_eq!(
3278 set_procattr(¤t_task, ProcAttr::FsCreate, VALID_SECURITY_CONTEXT.into()),
3280 error!(EINVAL)
3281 );
3282
3283 assert_eq!(
3284 set_procattr(¤t_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3286 error!(EINVAL)
3287 );
3288
3289 assert_eq!(
3290 get_procattr(¤t_task, ¤t_task.task, ProcAttr::Current),
3291 error!(EINVAL)
3292 );
3293 })
3294 .await;
3295 }
3296
3297 #[fuchsia::test]
3298 async fn create_file_with_fscreate_sid() {
3299 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3300 let sid =
3301 security_server.security_context_to_sid(VALID_SECURITY_CONTEXT.into()).unwrap();
3302 let source_node = &testing::create_test_file(current_task).entry.node;
3303
3304 fs_node_setsecurity(
3305 ¤t_task,
3306 &source_node,
3307 XATTR_NAME_SELINUX.to_bytes().into(),
3308 VALID_SECURITY_CONTEXT.into(),
3309 XattrOp::Set,
3310 )
3311 .expect("set_xattr(security.selinux) failed");
3312
3313 let mut creds = Credentials::clone(¤t_task.current_creds());
3314 security::fs_node_copy_up(current_task, source_node, &source_node.fs(), &mut creds);
3315 let dir_entry = current_task
3316 .override_creds(creds.into(), || {
3317 current_task
3318 .fs()
3319 .root()
3320 .create_node(
3321 ¤t_task,
3322 "test_file2".into(),
3323 FileMode::IFREG,
3324 DeviceId::NONE,
3325 )
3326 .unwrap()
3327 })
3328 .entry;
3329
3330 assert_eq!(get_cached_sid(&dir_entry.node), Some(sid));
3331 })
3332 .await;
3333 }
3334
3335 #[fuchsia::test]
3336 async fn test_check_ptrace_access_mode_noaudit() {
3337 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3338 let tracer_task = create_task_with_security_context(
3339 ¤t_task.kernel(),
3340 "tracer_task",
3341 &CString::new(b"u:object_r:test_ptrace_tracer_no_t:s0").unwrap(),
3342 );
3343 let tracee_task = create_task_with_security_context(
3344 ¤t_task.kernel(),
3345 "target_task",
3346 &CString::new(b"u:object_r:test_ptrace_traced_t:s0").unwrap(),
3347 );
3348
3349 let initial_denials = current_task.kernel().security_state.access_denial_count();
3351 assert_eq!(
3352 tracer_task.check_ptrace_access_mode(
3353 PTRACE_MODE_ATTACH_REALCREDS | PTRACE_MODE_NOAUDIT,
3354 &tracee_task
3355 ),
3356 error!(EACCES)
3357 );
3358 assert_eq!(current_task.kernel().security_state.access_denial_count(), initial_denials);
3359
3360 assert_eq!(
3361 tracer_task.check_ptrace_access_mode(PTRACE_MODE_ATTACH_REALCREDS, &tracee_task),
3362 error!(EACCES)
3363 );
3364 assert_eq!(
3365 current_task.kernel().security_state.access_denial_count(),
3366 initial_denials + 1
3367 );
3368
3369 let orig_tracee_creds = Credentials::clone(&tracee_task.current_creds());
3372 let mut diff_uid_creds = orig_tracee_creds.clone();
3373 diff_uid_creds.uid = 1000;
3374 tracee_task.set_creds(diff_uid_creds);
3375
3376 let denials_before_uid = current_task.kernel().security_state.access_denial_count();
3377 assert_eq!(
3378 tracer_task.check_ptrace_access_mode(
3379 PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT,
3380 &tracee_task
3381 ),
3382 error!(EPERM)
3383 );
3384 assert_eq!(
3385 current_task.kernel().security_state.access_denial_count(),
3386 denials_before_uid
3387 );
3388
3389 assert_eq!(
3390 tracer_task.check_ptrace_access_mode(PTRACE_MODE_READ_FSCREDS, &tracee_task),
3391 error!(EPERM)
3392 );
3393 assert_eq!(
3394 current_task.kernel().security_state.access_denial_count(),
3395 denials_before_uid + 1
3396 );
3397 tracee_task.set_creds(orig_tracee_creds);
3398
3399 tracee_task.mm().unwrap().dumpable.store(DumpPolicy::Disable);
3402 let denials_before_dumpable =
3403 current_task.kernel().security_state.access_denial_count();
3404 assert_eq!(
3405 tracer_task.check_ptrace_access_mode(
3406 PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT,
3407 &tracee_task
3408 ),
3409 error!(EPERM)
3410 );
3411 assert_eq!(
3412 current_task.kernel().security_state.access_denial_count(),
3413 denials_before_dumpable
3414 );
3415
3416 assert_eq!(
3417 tracer_task.check_ptrace_access_mode(PTRACE_MODE_READ_FSCREDS, &tracee_task),
3418 error!(EPERM)
3419 );
3420 assert_eq!(
3421 current_task.kernel().security_state.access_denial_count(),
3422 denials_before_dumpable + 1
3423 );
3424 tracee_task.mm().unwrap().dumpable.store(DumpPolicy::User);
3425
3426 let orig_caller_creds = Credentials::clone(&tracer_task.current_creds());
3429 let mut reduced_cap_creds = orig_caller_creds.clone();
3430 reduced_cap_creds.cap_effective = CAP_SYS_PTRACE;
3431 tracer_task.set_creds(reduced_cap_creds);
3432
3433 let denials_before_common_cap =
3434 current_task.kernel().security_state.access_denial_count();
3435 assert_eq!(
3436 tracer_task.check_ptrace_access_mode(
3437 PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT,
3438 &tracee_task
3439 ),
3440 error!(EPERM)
3441 );
3442 assert_eq!(
3443 current_task.kernel().security_state.access_denial_count(),
3444 denials_before_common_cap
3445 );
3446
3447 assert_eq!(
3448 tracer_task.check_ptrace_access_mode(PTRACE_MODE_READ_FSCREDS, &tracee_task),
3449 error!(EPERM)
3450 );
3451 assert_eq!(
3452 current_task.kernel().security_state.access_denial_count(),
3453 denials_before_common_cap + 1
3454 );
3455 tracer_task.set_creds(orig_caller_creds);
3456
3457 for scope in [yama::SCOPE_RESTRICTED, yama::SCOPE_ADMIN_ONLY] {
3460 current_task.kernel().ptrace_scope.store(scope, Ordering::Relaxed);
3461 let denials_before_yama =
3462 current_task.kernel().security_state.access_denial_count();
3463 assert_eq!(
3464 tracer_task.check_ptrace_access_mode(
3465 PTRACE_MODE_ATTACH_REALCREDS | PTRACE_MODE_NOAUDIT,
3466 &tracee_task
3467 ),
3468 error!(EPERM)
3469 );
3470 assert_eq!(
3471 current_task.kernel().security_state.access_denial_count(),
3472 denials_before_yama
3473 );
3474
3475 assert_eq!(
3476 tracer_task
3477 .check_ptrace_access_mode(PTRACE_MODE_ATTACH_REALCREDS, &tracee_task),
3478 error!(EPERM)
3479 );
3480 assert_eq!(
3481 current_task.kernel().security_state.access_denial_count(),
3482 denials_before_yama + 1
3483 );
3484 }
3485 current_task.kernel().ptrace_scope.store(yama::SCOPE_CLASSIC, Ordering::Relaxed);
3486 })
3487 .await;
3488 }
3489
3490 #[fuchsia::test]
3491 async fn private_fs_node_bypasses_fs_node_hooks() {
3492 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
3493 let private_file = new_null_file(current_task, OpenFlags::RDWR);
3494
3495 let node = private_file.node();
3496 assert!(node.is_private());
3497 assert_eq!(get_cached_sid(node), None);
3498 assert_eq!(fs_node_listsecurity(current_task, node), None);
3499 assert_eq!(check_fs_node_getattr_access(current_task, node), Ok(()));
3500 assert_eq!(
3501 fs_node_permission(
3502 current_task,
3503 node,
3504 PermissionFlags::READ | PermissionFlags::WRITE,
3505 (&*current_task).into(),
3506 ),
3507 Ok(())
3508 );
3509 assert_eq!(sb_mount(current_task, &private_file.name, MountFlags::empty()), Ok(()));
3510 assert_eq!(file_open(current_task, &private_file), Ok(()));
3511 })
3512 .await;
3513 }
3514
3515 #[fuchsia::test]
3516 async fn private_fs_node_file_enforces_fd_use() {
3517 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3518 let private_file = new_null_file(current_task, OpenFlags::RDWR | OpenFlags::APPEND);
3519
3520 assert_eq!(
3521 file_permission(
3522 current_task,
3523 &private_file,
3524 PermissionFlags::READ | PermissionFlags::WRITE,
3525 ),
3526 Ok(())
3527 );
3528 assert_eq!(
3529 check_file_fcntl_access(
3530 current_task,
3531 &private_file,
3532 starnix_uapi::F_SETFL,
3533 OpenFlags::RDWR.bits() as u64,
3534 ),
3535 Ok(())
3536 );
3537
3538 let other_sid = security_server
3541 .security_context_to_sid(DIFFERENT_VALID_SECURITY_CONTEXT.into())
3542 .expect("invalid security context");
3543 testing::mutate_attrs_for_test(current_task, |attrs| attrs.current_sid = other_sid);
3544 assert_eq!(
3545 file_permission(
3546 current_task,
3547 &private_file,
3548 PermissionFlags::READ | PermissionFlags::WRITE,
3549 ),
3550 error!(EACCES)
3551 );
3552 assert_eq!(
3553 check_file_fcntl_access(
3554 current_task,
3555 &private_file,
3556 starnix_uapi::F_SETFL,
3557 OpenFlags::RDWR.bits() as u64,
3558 ),
3559 error!(EACCES)
3560 );
3561 })
3562 .await;
3563 }
3564
3565 fn create_private_test_socket(
3566 current_task: &CurrentTask,
3567 security_server: &SecurityServer,
3568 ) -> FileHandle {
3569 let task_sid = security_server
3570 .security_context_to_sid(b"u:object_r:test_socket_create_no_t:s0".into())
3571 .expect("invalid security context");
3572 testing::mutate_attrs_for_test(current_task, |attrs| attrs.current_sid = task_sid);
3573
3574 SocketFile::new_socket(
3575 current_task,
3576 SocketDomain::Unix,
3577 SocketType::Stream,
3578 OpenFlags::RDWR,
3579 SocketProtocol::IP,
3580 true,
3581 )
3582 .expect("kernel_private socket creation should bypass access check")
3583 }
3584
3585 #[fuchsia::test]
3586 async fn private_socket_bypasses_creation_and_labeling() {
3587 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3588 let private_socket_file = create_private_test_socket(current_task, security_server);
3589
3590 let node = private_socket_file.node();
3591 assert!(node.is_private());
3592 assert_eq!(get_cached_sid(node), None);
3593
3594 let socket =
3595 Socket::get_from_file(&private_socket_file).expect("FileHandle should be a socket");
3596 assert!(is_private_socket(socket));
3597 })
3598 .await;
3599 }
3600
3601 #[fuchsia::test]
3602 async fn private_socket_bypasses_socket_ops_hooks() {
3603 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3604 let private_socket_file = create_private_test_socket(current_task, security_server);
3605 let socket =
3606 Socket::get_from_file(&private_socket_file).expect("FileHandle should be a socket");
3607
3608 assert_eq!(check_socket_getsockname_access(current_task, socket), Ok(()));
3609 assert_eq!(check_socket_getpeername_access(current_task, socket), Ok(()));
3610 assert_eq!(
3611 check_socket_shutdown_access(current_task, socket, SocketShutdownFlags::READ),
3612 Ok(())
3613 );
3614 assert_eq!(socket_getpeersec_stream(current_task, socket), Ok(Vec::<u8>::new()));
3615 assert_eq!(socket_getpeersec_dgram(current_task, socket), Vec::<u8>::new());
3616 })
3617 .await;
3618 }
3619
3620 #[fuchsia::test]
3621 async fn private_socket_bypasses_connection_hooks() {
3622 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3623 let private_socket_file = create_private_test_socket(current_task, security_server);
3624 let socket =
3625 Socket::get_from_file(&private_socket_file).expect("FileHandle should be a socket");
3626 let socket_downcasted = private_socket_file
3627 .downcast_file::<SocketFile>()
3628 .expect("downcast to SocketFile should succeed");
3629
3630 assert_eq!(
3631 socket_socketpair(current_task, socket_downcasted, socket_downcasted),
3632 Ok(())
3633 );
3634 assert_eq!(
3635 check_socket_connect_access(
3636 current_task,
3637 socket_downcasted,
3638 &SocketPeer::Handle(socket.clone()),
3639 ),
3640 Ok(())
3641 );
3642 assert_eq!(socket_accept(current_task, socket_downcasted, socket_downcasted), Ok(()));
3643 })
3644 .await;
3645 }
3646}