1#![allow(non_upper_case_globals)]
7
8use super::selinux_hooks::audit::Auditable;
9use super::{
10 BinderConnectionState, BpfMapState, BpfProgState, FileObjectState, FileSystemState,
11 KernelState, PerfEventState, common_cap, selinux_hooks, yama,
12};
13use crate::bpf::map::BpfMap;
14use crate::bpf::program::Program;
15use crate::mm::{Mapping, MappingOptions, ProtectionFlags};
16use crate::perf::PerfEventFile;
17use crate::security::selinux_hooks::current_task_state;
18use crate::task::loader::ResolvedElf;
19use crate::task::{CurrentTask, Kernel, Task};
20use crate::vfs::fs_args::MountParams;
21use crate::vfs::socket::{
22 Socket, SocketAddress, SocketDomain, SocketFile, SocketPeer, SocketProtocol,
23 SocketShutdownFlags, SocketType,
24};
25use crate::vfs::{
26 DirEntryHandle, DowncastedFile, FileHandle, FileObject, FileSystem, FileSystemHandle,
27 FileSystemOps, FsNode, FsStr, FsString, Mount, NamespaceNode, ValueOrSize, XattrOp,
28};
29use ebpf::MapFlags;
30use linux_uapi::{
31 perf_event_attr, perf_type_id, perf_type_id_PERF_TYPE_BREAKPOINT,
32 perf_type_id_PERF_TYPE_HARDWARE, perf_type_id_PERF_TYPE_HW_CACHE, perf_type_id_PERF_TYPE_RAW,
33 perf_type_id_PERF_TYPE_SOFTWARE, perf_type_id_PERF_TYPE_TRACEPOINT,
34};
35use selinux::{FileSystemMountOptions, SecurityPermission, SecurityServer, TaskAttrs};
36use starnix_logging::{CATEGORY_STARNIX_SECURITY, log_debug, trace_duration};
37use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked, Unlocked};
38use starnix_types::ownership::TempRef;
39use starnix_uapi::arc_key::WeakKey;
40use starnix_uapi::auth::{Credentials, PtraceAccessMode};
41use starnix_uapi::device_id::DeviceId;
42use starnix_uapi::errors::Errno;
43use starnix_uapi::file_mode::{Access, FileMode};
44use starnix_uapi::mount_flags::MountFlags;
45use starnix_uapi::open_flags::OpenFlags;
46use starnix_uapi::signals::Signal;
47use starnix_uapi::syslog::SyslogAction;
48use starnix_uapi::unmount_flags::UnmountFlags;
49use starnix_uapi::user_address::UserAddress;
50use starnix_uapi::{bpf_cmd, error, rlimit};
51use std::ops::Range;
52use std::sync::Arc;
53use syncio::zxio_node_attr_has_t;
54use zerocopy::FromBytes;
55
56macro_rules! track_hook_duration {
57 ($cname:literal) => {
58 trace_duration!(CATEGORY_STARNIX_SECURITY, $cname);
59 };
60}
61
62bitflags::bitflags! {
63 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
66 pub struct PermissionFlags: u32 {
67 const EXEC = 1 as u32;
68 const WRITE = 2 as u32;
69 const READ = 4 as u32;
70 const APPEND = 8 as u32;
71
72 const ACCESS = 16 as u32;
75
76 const FOR_OPEN = 32 as u32;
79 }
80}
81
82impl PermissionFlags {
83 pub fn as_access(&self) -> Access {
84 let mut access = Access::empty();
85 if self.contains(PermissionFlags::READ) {
86 access |= Access::READ;
87 }
88 if self.contains(PermissionFlags::WRITE) {
89 access |= Access::WRITE;
92 }
93 if self.contains(PermissionFlags::EXEC) {
94 access |= Access::EXEC;
95 }
96 access
97 }
98}
99
100impl From<Access> for PermissionFlags {
101 fn from(access: Access) -> Self {
102 let mut permissions = PermissionFlags::empty();
104 if access.contains(Access::READ) {
105 permissions |= PermissionFlags::READ;
106 }
107 if access.contains(Access::WRITE) {
108 permissions |= PermissionFlags::WRITE;
109 }
110 if access.contains(Access::EXEC) {
111 permissions |= PermissionFlags::EXEC;
112 }
113 permissions
114 }
115}
116
117impl From<ProtectionFlags> for PermissionFlags {
118 fn from(protection_flags: ProtectionFlags) -> Self {
119 let mut flags = PermissionFlags::empty();
120 if protection_flags.contains(ProtectionFlags::READ) {
121 flags |= PermissionFlags::READ;
122 }
123 if protection_flags.contains(ProtectionFlags::WRITE) {
124 flags |= PermissionFlags::WRITE;
125 }
126 if protection_flags.contains(ProtectionFlags::EXEC) {
127 flags |= PermissionFlags::EXEC;
128 }
129 flags
130 }
131}
132
133impl From<OpenFlags> for PermissionFlags {
134 fn from(flags: OpenFlags) -> Self {
135 let mut permissions = PermissionFlags::empty();
136 if flags.can_read() {
137 permissions |= PermissionFlags::READ;
138 }
139 if flags.can_write() {
140 permissions |= PermissionFlags::WRITE;
141 if flags.contains(OpenFlags::APPEND) {
142 permissions |= PermissionFlags::APPEND;
143 }
144 }
145 permissions
146 }
147}
148
149impl From<MapFlags> for PermissionFlags {
150 fn from(bpf_flags: MapFlags) -> Self {
151 if bpf_flags.contains(MapFlags::SyscallReadOnly) {
152 PermissionFlags::READ
153 } else if bpf_flags.contains(MapFlags::SyscallWriteOnly) {
154 PermissionFlags::WRITE
155 } else {
156 PermissionFlags::READ | PermissionFlags::WRITE
157 }
158 }
159}
160
161#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
163pub enum PerfEventType {
164 Hardware,
165 Software,
166 Tracepoint,
167 Raw,
168 HwCache,
169 Breakpoint,
170}
171
172#[allow(non_upper_case_globals)]
174impl TryFrom<perf_type_id> for PerfEventType {
175 type Error = Errno;
176
177 fn try_from(type_id: perf_type_id) -> Result<Self, Errno> {
178 match type_id {
179 perf_type_id_PERF_TYPE_HARDWARE => Ok(Self::Hardware),
180 perf_type_id_PERF_TYPE_SOFTWARE => Ok(Self::Software),
181 perf_type_id_PERF_TYPE_TRACEPOINT => Ok(Self::Tracepoint),
182 perf_type_id_PERF_TYPE_RAW => Ok(Self::Raw),
183 perf_type_id_PERF_TYPE_HW_CACHE => Ok(Self::HwCache),
184 perf_type_id_PERF_TYPE_BREAKPOINT => Ok(Self::Breakpoint),
185 _ => {
186 return error!(ENOTSUP);
187 }
188 }
189 }
190}
191
192#[derive(PartialEq, Eq)]
194pub enum TargetTaskType<'a> {
195 AllTasks,
197 CurrentTask,
199 Task(&'a Task),
201}
202
203fn if_selinux_else_with_context<F, R, D, C>(context: C, task: &Task, hook: F, default: D) -> R
207where
208 F: FnOnce(C, &Arc<SecurityServer>) -> R,
209 D: Fn(C) -> R,
210{
211 if let Some(state) = task.kernel().security_state.state.as_ref() {
212 if state.has_policy() { hook(context, &state.server) } else { default(context) }
213 } else {
214 default(context)
215 }
216}
217
218fn if_selinux_else<F, R, D>(task: &Task, hook: F, default: D) -> R
222where
223 F: FnOnce(&Arc<SecurityServer>) -> R,
224 D: Fn() -> R,
225{
226 if_selinux_else_with_context(
227 (),
228 task,
229 |_, security_server| hook(security_server),
230 |_| default(),
231 )
232}
233
234fn if_selinux_else_default_ok_with_context<R, F, C>(
238 context: C,
239 task: &Task,
240 hook: F,
241) -> Result<R, Errno>
242where
243 F: FnOnce(C, &Arc<SecurityServer>) -> Result<R, Errno>,
244 R: Default,
245{
246 if_selinux_else_with_context(context, task, hook, |_| Ok(R::default()))
247}
248
249fn if_selinux_else_default_ok<R, F>(task: &Task, hook: F) -> Result<R, Errno>
253where
254 F: FnOnce(&Arc<SecurityServer>) -> Result<R, Errno>,
255 R: Default,
256{
257 if_selinux_else(task, hook, || Ok(R::default()))
258}
259
260pub fn kernel_init_security(
263 enabled: bool,
264 options: String,
265 exceptions: Vec<String>,
266 inspect_node: &fuchsia_inspect::Node,
267) -> KernelState {
268 track_hook_duration!("security.hooks.kernel_init_security");
269 KernelState {
270 state: enabled
271 .then(|| selinux_hooks::kernel_init_security(options, exceptions, inspect_node)),
272 }
273}
274
275pub fn binder_set_context_mgr(current_task: &CurrentTask) -> Result<(), Errno> {
278 track_hook_duration!("security.hooks.binder_set_context_mgr");
279 if_selinux_else_default_ok(current_task, |security_server| {
280 selinux_hooks::binder::binder_set_context_mgr(security_server, current_task)
281 })
282}
283
284pub fn binder_transaction(
287 current_task: &CurrentTask,
288 target_task: &Task,
289 connection_state: &BinderConnectionState,
290) -> Result<(), Errno> {
291 track_hook_duration!("security.hooks.binder_transaction");
292 if_selinux_else_default_ok(current_task, |security_server| {
293 selinux_hooks::binder::binder_transaction(
294 security_server,
295 &connection_state.state,
296 current_task,
297 target_task,
298 )
299 })
300}
301
302pub fn binder_transfer_binder(current_task: &CurrentTask, target_task: &Task) -> Result<(), Errno> {
305 track_hook_duration!("security.hooks.binder_transfer_binder");
306 if_selinux_else_default_ok(current_task, |security_server| {
307 selinux_hooks::binder::binder_transfer_binder(security_server, current_task, target_task)
308 })
309}
310
311pub fn binder_transfer_file(
314 current_task: &CurrentTask,
315 receiving_task: &Task,
316 file: &FileObject,
317) -> Result<(), Errno> {
318 track_hook_duration!("security.hooks.binder_transfer_file");
319 if_selinux_else_default_ok(current_task, |security_server| {
320 selinux_hooks::binder::binder_transfer_file(
321 security_server,
322 current_task,
323 receiving_task,
324 file,
325 )
326 })
327}
328
329pub fn binder_get_context(
332 current_task: &CurrentTask,
333 connection_state: &BinderConnectionState,
334) -> Option<Vec<u8>> {
335 track_hook_duration!("security.hooks.binder_get_context");
336 if_selinux_else(
337 current_task,
338 |security_server| {
339 selinux_hooks::binder::binder_get_context(&security_server, &connection_state.state)
340 },
341 || None,
342 )
343}
344
345pub fn sb_eat_lsm_opts(
349 kernel: &Kernel,
350 mount_params: &mut MountParams,
351) -> Result<FileSystemMountOptions, Errno> {
352 track_hook_duration!("security.hooks.sb_eat_lsm_opts");
353 if kernel.security_state.state.is_some() {
354 return selinux_hooks::superblock::sb_eat_lsm_opts(mount_params);
355 }
356 Ok(FileSystemMountOptions::default())
357}
358
359pub fn file_system_init_security(
362 mount_options: &FileSystemMountOptions,
363 ops: &dyn FileSystemOps,
364) -> Result<FileSystemState, Errno> {
365 track_hook_duration!("security.hooks.file_system_init_security");
366 Ok(FileSystemState {
367 state: selinux_hooks::superblock::file_system_init_security(mount_options, ops)?,
368 })
369}
370
371pub fn file_system_post_init_security(kernel: &Kernel, file_system: &FileSystemHandle) {
376 track_hook_duration!("security.hooks.file_system_post_init_security");
377 if let Some(state) = &kernel.security_state.state {
378 if !state.has_policy() {
379 log_debug!("Queuing {} FileSystem for labeling", file_system.name());
382 state.pending_file_systems.lock().insert(WeakKey::from(&file_system));
383 }
384 }
385}
386
387pub fn file_system_resolve_security<L>(
392 locked: &mut Locked<L>,
393 current_task: &CurrentTask,
394 file_system: &FileSystemHandle,
395) -> Result<(), Errno>
396where
397 L: LockEqualOrBefore<FileOpsCore>,
398{
399 track_hook_duration!("security.hooks.file_system_resolve_security");
400 if_selinux_else_default_ok_with_context(locked, current_task, |locked, security_server| {
401 selinux_hooks::superblock::file_system_resolve_security(
402 locked,
403 security_server,
404 current_task,
405 file_system,
406 )
407 })
408}
409
410pub struct FsNodeSecurityXattr {
412 pub name: &'static FsStr,
413 pub value: FsString,
414}
415
416pub fn mmap_file(
420 current_task: &CurrentTask,
421 file: Option<&FileHandle>,
422 protection_flags: ProtectionFlags,
423 options: MappingOptions,
424) -> Result<(), Errno> {
425 track_hook_duration!("security.hooks.mmap_file");
426 if_selinux_else_default_ok(current_task, |security_server| {
427 selinux_hooks::file::mmap_file(
428 security_server,
429 current_task,
430 file,
431 protection_flags,
432 options,
433 )
434 })
435}
436
437pub fn file_mprotect(
441 current_task: &CurrentTask,
442 range: &Range<UserAddress>,
443 mapping: &Mapping,
444 prot: ProtectionFlags,
445) -> Result<(), Errno> {
446 track_hook_duration!("security.hooks.file_mprotect");
447 if_selinux_else_default_ok(current_task, |security_server| {
448 selinux_hooks::file::file_mprotect(security_server, current_task, range, mapping, prot)
449 })
450}
451
452pub fn file_permission(
455 current_task: &CurrentTask,
456 file: &FileObject,
457 permission_flags: PermissionFlags,
458) -> Result<(), Errno> {
459 track_hook_duration!("security.hooks.file_permission");
460 if_selinux_else_default_ok(current_task, |security_server| {
461 selinux_hooks::file::file_permission(security_server, current_task, file, permission_flags)
462 })
463}
464
465pub fn fs_node_init_with_dentry<L>(
471 locked: &mut Locked<L>,
472 current_task: &CurrentTask,
473 dir_entry: &DirEntryHandle,
474) -> Result<(), Errno>
475where
476 L: LockEqualOrBefore<FileOpsCore>,
477{
478 track_hook_duration!("security.hooks.fs_node_init_with_dentry");
479 if let Some(state) = ¤t_task.kernel().security_state.state {
484 selinux_hooks::fs_node::fs_node_init_with_dentry(
485 Some(locked.cast_locked()),
486 &state.server,
487 current_task,
488 dir_entry,
489 )
490 } else {
491 Ok(())
492 }
493}
494
495pub fn fs_node_init_with_dentry_no_xattr(
496 current_task: &CurrentTask,
497 dir_entry: &DirEntryHandle,
498) -> Result<(), Errno> {
499 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
500 if let Some(state) = ¤t_task.kernel().security_state.state {
505 if dir_entry.node.is_private() {
508 return selinux_hooks::fs_node::fs_node_init_anon(
509 &state.server,
510 current_task,
511 &dir_entry.node,
512 "",
513 );
514 }
515
516 selinux_hooks::fs_node::fs_node_init_with_dentry(
517 None,
518 &state.server,
519 current_task,
520 dir_entry,
521 )
522 } else {
523 Ok(())
524 }
525}
526
527pub fn fs_node_init_with_dentry_deferred(kernel: &Kernel, dir_entry: &DirEntryHandle) {
531 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
532 if kernel.security_state.state.is_some() {
533 selinux_hooks::fs_node::fs_node_init_with_dentry_deferred(dir_entry);
534 }
535}
536
537pub fn fs_node_notify_security_context(
544 current_task: &CurrentTask,
545 fs_node: &FsNode,
546 context: &FsStr,
547) -> Result<(), Errno> {
548 track_hook_duration!("security.hooks.fs_node_notify_security_context");
549 if_selinux_else(
550 current_task,
551 |security_server| {
552 selinux_hooks::fs_node::fs_node_notify_security_context(
553 security_server,
554 fs_node,
555 context,
556 )
557 },
558 || error!(ENOTSUP),
559 )
560}
561
562pub fn fs_node_init_on_create(
574 current_task: &CurrentTask,
575 new_node: &FsNode,
576 parent: &FsNode,
577 name: &FsStr,
578) -> Result<Option<FsNodeSecurityXattr>, Errno> {
579 track_hook_duration!("security.hooks.fs_node_init_on_create");
580 if_selinux_else_default_ok(current_task, |security_server| {
581 selinux_hooks::fs_node::fs_node_init_on_create(
582 security_server,
583 current_task,
584 new_node,
585 Some(parent),
586 name,
587 )
588 })
589}
590
591pub fn dentry_create_files_as(
599 current_task: &CurrentTask,
600 parent: &FsNode,
601 new_node_mode: FileMode,
602 new_node_name: &FsStr,
603 new_creds: &mut Credentials,
604) -> Result<(), Errno> {
605 track_hook_duration!("security.hooks.dentry_create_files_as");
606 if_selinux_else_default_ok(current_task, |security_server| {
607 selinux_hooks::fs_node::dentry_create_files_as(
608 security_server,
609 current_task,
610 parent,
611 new_node_mode,
612 new_node_name,
613 new_creds,
614 )
615 })
616}
617
618pub fn fs_node_init_anon(
623 current_task: &CurrentTask,
624 new_node: &FsNode,
625 node_type: &str,
626) -> Result<(), Errno> {
627 track_hook_duration!("security.hooks.fs_node_init_anon");
628 if let Some(state) = current_task.kernel().security_state.state.as_ref() {
629 selinux_hooks::fs_node::fs_node_init_anon(&state.server, current_task, new_node, node_type)
630 } else {
631 Ok(())
632 }
633}
634
635pub fn check_fs_node_create_access(
639 current_task: &CurrentTask,
640 parent: &FsNode,
641 mode: FileMode,
642 name: &FsStr,
643) -> Result<(), Errno> {
644 track_hook_duration!("security.hooks.check_fs_node_create_access");
645 if_selinux_else_default_ok(current_task, |security_server| {
646 selinux_hooks::fs_node::check_fs_node_create_access(
647 security_server,
648 current_task,
649 parent,
650 mode,
651 name,
652 )
653 })
654}
655
656pub fn check_fs_node_symlink_access(
660 current_task: &CurrentTask,
661 parent: &FsNode,
662 name: &FsStr,
663 old_path: &FsStr,
664) -> Result<(), Errno> {
665 track_hook_duration!("security.hooks.check_fs_node_symlink_access");
666 if_selinux_else_default_ok(current_task, |security_server| {
667 selinux_hooks::fs_node::check_fs_node_symlink_access(
668 security_server,
669 current_task,
670 parent,
671 name,
672 old_path,
673 )
674 })
675}
676
677pub fn check_fs_node_mkdir_access(
681 current_task: &CurrentTask,
682 parent: &FsNode,
683 mode: FileMode,
684 name: &FsStr,
685) -> Result<(), Errno> {
686 track_hook_duration!("security.hooks.check_fs_node_mkdir_access");
687 if_selinux_else_default_ok(current_task, |security_server| {
688 selinux_hooks::fs_node::check_fs_node_mkdir_access(
689 security_server,
690 current_task,
691 parent,
692 mode,
693 name,
694 )
695 })
696}
697
698pub fn check_fs_node_mknod_access(
704 current_task: &CurrentTask,
705 parent: &FsNode,
706 mode: FileMode,
707 name: &FsStr,
708 device_id: DeviceId,
709) -> Result<(), Errno> {
710 track_hook_duration!("security.hooks.check_fs_node_mknod_access");
711 assert!(!mode.is_reg());
712
713 if_selinux_else_default_ok(current_task, |security_server| {
714 selinux_hooks::fs_node::check_fs_node_mknod_access(
715 security_server,
716 current_task,
717 parent,
718 mode,
719 name,
720 device_id,
721 )
722 })
723}
724
725pub fn check_fs_node_link_access(
728 current_task: &CurrentTask,
729 parent: &FsNode,
730 child: &FsNode,
731) -> Result<(), Errno> {
732 track_hook_duration!("security.hooks.check_fs_node_link_access");
733 if_selinux_else_default_ok(current_task, |security_server| {
734 selinux_hooks::fs_node::check_fs_node_link_access(
735 security_server,
736 current_task,
737 parent,
738 child,
739 )
740 })
741}
742
743pub fn check_fs_node_unlink_access(
746 current_task: &CurrentTask,
747 parent: &FsNode,
748 child: &FsNode,
749 name: &FsStr,
750) -> Result<(), Errno> {
751 track_hook_duration!("security.hooks.check_fs_node_unlink_access");
752 if_selinux_else_default_ok(current_task, |security_server| {
753 selinux_hooks::fs_node::check_fs_node_unlink_access(
754 security_server,
755 current_task,
756 parent,
757 child,
758 name,
759 )
760 })
761}
762
763pub fn check_fs_node_rmdir_access(
766 current_task: &CurrentTask,
767 parent: &FsNode,
768 child: &FsNode,
769 name: &FsStr,
770) -> Result<(), Errno> {
771 track_hook_duration!("security.hooks.check_fs_node_rmdir_access");
772 if_selinux_else_default_ok(current_task, |security_server| {
773 selinux_hooks::fs_node::check_fs_node_rmdir_access(
774 security_server,
775 current_task,
776 parent,
777 child,
778 name,
779 )
780 })
781}
782
783pub fn check_fs_node_rename_access(
788 current_task: &CurrentTask,
789 old_parent: &FsNode,
790 moving_node: &FsNode,
791 new_parent: &FsNode,
792 replaced_node: Option<&FsNode>,
793 old_basename: &FsStr,
794 new_basename: &FsStr,
795) -> Result<(), Errno> {
796 track_hook_duration!("security.hooks.check_fs_node_rename_access");
797 if_selinux_else_default_ok(current_task, |security_server| {
798 selinux_hooks::fs_node::check_fs_node_rename_access(
799 security_server,
800 current_task,
801 old_parent,
802 moving_node,
803 new_parent,
804 replaced_node,
805 old_basename,
806 new_basename,
807 )
808 })
809}
810
811pub fn check_fs_node_read_link_access(
814 current_task: &CurrentTask,
815 fs_node: &FsNode,
816) -> Result<(), Errno> {
817 track_hook_duration!("security.hooks.check_fs_node_read_link_access");
818 if_selinux_else_default_ok(current_task, |security_server| {
819 selinux_hooks::fs_node::check_fs_node_read_link_access(
820 security_server,
821 current_task,
822 fs_node,
823 )
824 })
825}
826
827pub fn fs_node_permission(
830 current_task: &CurrentTask,
831 fs_node: &FsNode,
832 permission_flags: PermissionFlags,
833 audit_context: Auditable<'_>,
834) -> Result<(), Errno> {
835 track_hook_duration!("security.hooks.fs_node_permission");
836 if_selinux_else_default_ok(current_task, |security_server| {
837 selinux_hooks::fs_node::fs_node_permission(
838 security_server,
839 current_task,
840 fs_node,
841 permission_flags,
842 audit_context,
843 )
844 })
845}
846
847pub fn file_receive(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
850 track_hook_duration!("security.hooks.file_receive");
851 if_selinux_else_default_ok(current_task, |security_server| {
852 let receiving_sid = current_task_state(current_task).current_sid;
853 selinux_hooks::file::file_receive(security_server, current_task, receiving_sid, file)
854 })
855}
856
857pub fn file_alloc_security(current_task: &CurrentTask) -> FileObjectState {
860 track_hook_duration!("security.hooks.file_alloc_security");
861 FileObjectState { state: selinux_hooks::file::file_alloc_security(current_task) }
862}
863
864pub fn binder_connection_alloc(current_task: &CurrentTask) -> BinderConnectionState {
867 track_hook_duration!("security.hooks.binder_connection_alloc");
868 BinderConnectionState { state: selinux_hooks::binder::binder_connection_alloc(current_task) }
869}
870
871pub fn bpf_map_alloc(current_task: &CurrentTask) -> BpfMapState {
875 track_hook_duration!("security.hooks.bpf_map_alloc");
876 BpfMapState { state: selinux_hooks::bpf::bpf_map_alloc(current_task) }
877}
878
879pub fn bpf_prog_alloc(current_task: &CurrentTask) -> BpfProgState {
883 track_hook_duration!("security.hooks.bpf_prog_alloc");
884 BpfProgState { state: selinux_hooks::bpf::bpf_prog_alloc(current_task) }
885}
886
887pub fn check_file_ioctl_access(
890 current_task: &CurrentTask,
891 file: &FileObject,
892 request: u32,
893) -> Result<(), Errno> {
894 track_hook_duration!("security.hooks.check_file_ioctl_access");
895 if_selinux_else_default_ok(current_task, |security_server| {
896 selinux_hooks::file::check_file_ioctl_access(security_server, current_task, file, request)
897 })
898}
899
900pub fn fs_node_copy_up(
910 current_task: &CurrentTask,
911 fs_node: &FsNode,
912 fs: &FileSystem,
913 new_creds: &mut Credentials,
914) {
915 if_selinux_else(
916 current_task,
917 |_security_server| {
918 selinux_hooks::fs_node::fs_node_copy_up(current_task, fs_node, fs, new_creds)
919 },
920 || {},
921 )
922}
923
924pub fn check_file_lock_access(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
932 track_hook_duration!("security.hooks.check_file_lock_access");
933 if_selinux_else_default_ok(current_task, |security_server| {
934 selinux_hooks::file::check_file_lock_access(security_server, current_task, file)
935 })
936}
937
938pub fn check_file_fcntl_access(
941 current_task: &CurrentTask,
942 file: &FileObject,
943 fcntl_cmd: u32,
944 fcntl_arg: u64,
945) -> Result<(), Errno> {
946 track_hook_duration!("security.hooks.check_file_fcntl_access");
947 if_selinux_else_default_ok(current_task, |security_server| {
948 selinux_hooks::file::check_file_fcntl_access(
949 security_server,
950 current_task,
951 file,
952 fcntl_cmd,
953 fcntl_arg,
954 )
955 })
956}
957
958pub fn check_fs_node_setattr_access(
961 current_task: &CurrentTask,
962 node: &FsNode,
963 attributes: &zxio_node_attr_has_t,
964) -> Result<(), Errno> {
965 track_hook_duration!("security.hooks.check_fs_node_setattr_access");
966 if_selinux_else_default_ok(current_task, |security_server| {
967 selinux_hooks::fs_node::check_fs_node_setattr_access(
968 security_server,
969 current_task,
970 node,
971 attributes,
972 )
973 })
974}
975
976pub fn task_alloc_for_kernel() -> TaskAttrs {
979 track_hook_duration!("security.hooks.task_alloc_for_kernel");
980 TaskAttrs::for_kernel()
981}
982
983pub fn task_to_fs_node(current_task: &CurrentTask, task: &TempRef<'_, Task>, fs_node: &FsNode) {
989 track_hook_duration!("security.hooks.task_to_fs_node");
990 if current_task.kernel().security_state.state.is_some() {
993 selinux_hooks::task::fs_node_init_with_task(task, &fs_node);
994 }
995}
996
997pub fn task_for_context(task: &Task, context: &FsStr) -> Result<TaskAttrs, Errno> {
1003 track_hook_duration!("security.hooks.task_for_context");
1004 Ok(if let Some(kernel_state) = task.kernel().security_state.state.as_ref() {
1005 selinux_hooks::task::task_alloc_from_context(&kernel_state.server, context)
1006 } else {
1007 Ok(TaskAttrs::for_selinux_disabled())
1008 }?)
1009}
1010
1011pub fn has_dontaudit_access(current_task: &CurrentTask, fs_node: &FsNode) -> bool {
1015 track_hook_duration!("security.hooks.has_dontaudit_access");
1016 if_selinux_else(
1017 current_task,
1018 |security_server| {
1019 selinux_hooks::fs_node::has_dontaudit_access(security_server, current_task, fs_node)
1020 },
1021 || false,
1022 )
1023}
1024
1025pub fn is_task_capable_noaudit(
1028 current_task: &CurrentTask,
1029 capability: starnix_uapi::auth::Capabilities,
1030) -> bool {
1031 track_hook_duration!("security.hooks.is_task_capable_noaudit");
1032 return common_cap::capable(current_task, capability).is_ok()
1033 && if_selinux_else(
1034 current_task,
1035 |security_server| {
1036 selinux_hooks::task::is_task_capable_noaudit(
1037 &selinux_hooks::build_permission_check(current_task, security_server),
1038 ¤t_task,
1039 capability,
1040 )
1041 },
1042 || true,
1043 );
1044}
1045
1046pub fn check_task_capable(
1049 current_task: &CurrentTask,
1050 capability: starnix_uapi::auth::Capabilities,
1051) -> Result<(), Errno> {
1052 track_hook_duration!("security.hooks.check_task_capable");
1053 common_cap::capable(current_task, capability)?;
1054 if_selinux_else_default_ok(current_task, |security_server| {
1055 selinux_hooks::task::check_task_capable(
1056 &selinux_hooks::build_permission_check(current_task, security_server),
1057 ¤t_task,
1058 capability,
1059 )
1060 })
1061}
1062
1063pub fn check_task_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1069 track_hook_duration!("security.hooks.check_task_create_access");
1070 if_selinux_else_default_ok(current_task, |security_server| {
1071 selinux_hooks::task::check_task_create_access(
1072 &selinux_hooks::build_permission_check(current_task, security_server),
1073 current_task,
1074 )
1075 })
1076}
1077
1078pub fn check_socket_create_access<L>(
1081 locked: &mut Locked<L>,
1082 current_task: &CurrentTask,
1083 domain: SocketDomain,
1084 socket_type: SocketType,
1085 protocol: SocketProtocol,
1086 kernel_private: bool,
1087) -> Result<(), Errno>
1088where
1089 L: LockEqualOrBefore<FileOpsCore>,
1090{
1091 track_hook_duration!("security.hooks.socket_create");
1092 if_selinux_else_default_ok(current_task, |security_server| {
1093 selinux_hooks::socket::check_socket_create_access(
1094 locked,
1095 &security_server,
1096 current_task,
1097 domain,
1098 socket_type,
1099 protocol,
1100 kernel_private,
1101 )
1102 })
1103}
1104
1105pub fn socket_socketpair(
1108 current_task: &CurrentTask,
1109 left: DowncastedFile<'_, SocketFile>,
1110 right: DowncastedFile<'_, SocketFile>,
1111) -> Result<(), Errno> {
1112 track_hook_duration!("security.hooks.socket_socketpair");
1113 if_selinux_else_default_ok(current_task, |_| {
1114 selinux_hooks::socket::socket_socketpair(left, right)
1115 })
1116}
1117
1118pub fn socket_post_create(current_task: &CurrentTask, socket: &Socket) {
1121 track_hook_duration!("security.hooks.socket_post_create");
1122 if let Some(state) = ¤t_task.kernel().security_state.state {
1123 selinux_hooks::socket::socket_post_create(&state.server, socket);
1124 }
1125}
1126
1127pub fn check_socket_bind_access(
1130 current_task: &CurrentTask,
1131 socket: &Socket,
1132 socket_address: &SocketAddress,
1133) -> Result<(), Errno> {
1134 track_hook_duration!("security.hooks.check_socket_bind_access");
1135 if_selinux_else_default_ok(current_task, |security_server| {
1136 selinux_hooks::socket::check_socket_bind_access(
1137 &security_server,
1138 current_task,
1139 socket,
1140 socket_address,
1141 )
1142 })
1143}
1144
1145pub fn check_socket_connect_access(
1148 current_task: &CurrentTask,
1149 socket: DowncastedFile<'_, SocketFile>,
1150 socket_peer: &SocketPeer,
1151) -> Result<(), Errno> {
1152 track_hook_duration!("security.hooks.check_socket_connect_access");
1153 if_selinux_else_default_ok(current_task, |security_server| {
1154 selinux_hooks::socket::check_socket_connect_access(
1155 &security_server,
1156 current_task,
1157 socket,
1158 socket_peer,
1159 )
1160 })
1161}
1162
1163pub fn check_socket_listen_access(
1166 current_task: &CurrentTask,
1167 socket: &Socket,
1168 backlog: i32,
1169) -> Result<(), Errno> {
1170 track_hook_duration!("security.hooks.check_socket_listen_access");
1171 if_selinux_else_default_ok(current_task, |security_server| {
1172 selinux_hooks::socket::check_socket_listen_access(
1173 &security_server,
1174 current_task,
1175 socket,
1176 backlog,
1177 )
1178 })
1179}
1180
1181pub fn socket_accept(
1185 current_task: &CurrentTask,
1186 listening_socket: DowncastedFile<'_, SocketFile>,
1187 accepted_socket: DowncastedFile<'_, SocketFile>,
1188) -> Result<(), Errno> {
1189 track_hook_duration!("security.hooks.check_socket_getname_access");
1190 if_selinux_else_default_ok(current_task, |security_server| {
1191 selinux_hooks::socket::socket_accept(
1192 &security_server,
1193 current_task,
1194 listening_socket,
1195 accepted_socket,
1196 )
1197 })
1198}
1199
1200pub fn check_socket_getsockopt_access(
1203 current_task: &CurrentTask,
1204 socket: &Socket,
1205 level: u32,
1206 optname: u32,
1207) -> Result<(), Errno> {
1208 track_hook_duration!("security.hooks.check_socket_getsockopt_access");
1209 if_selinux_else_default_ok(current_task, |security_server| {
1210 selinux_hooks::socket::check_socket_getsockopt_access(
1211 &security_server,
1212 current_task,
1213 socket,
1214 level,
1215 optname,
1216 )
1217 })
1218}
1219
1220pub fn check_socket_setsockopt_access(
1223 current_task: &CurrentTask,
1224 socket: &Socket,
1225 level: u32,
1226 optname: u32,
1227) -> Result<(), Errno> {
1228 track_hook_duration!("security.hooks.check_socket_setsockopt_access");
1229 if_selinux_else_default_ok(current_task, |security_server| {
1230 selinux_hooks::socket::check_socket_setsockopt_access(
1231 &security_server,
1232 current_task,
1233 socket,
1234 level,
1235 optname,
1236 )
1237 })
1238}
1239
1240pub fn check_socket_sendmsg_access(
1243 current_task: &CurrentTask,
1244 socket: &Socket,
1245) -> Result<(), Errno> {
1246 track_hook_duration!("security.hooks.check_socket_sendmsg_access");
1247 if_selinux_else_default_ok(current_task, |security_server| {
1248 selinux_hooks::socket::check_socket_sendmsg_access(&security_server, current_task, socket)
1249 })
1250}
1251
1252pub fn check_socket_recvmsg_access(
1255 current_task: &CurrentTask,
1256 socket: &Socket,
1257) -> Result<(), Errno> {
1258 track_hook_duration!("security.hooks.check_socket_recvmsg_access");
1259 if_selinux_else_default_ok(current_task, |security_server| {
1260 selinux_hooks::socket::check_socket_recvmsg_access(&security_server, current_task, socket)
1261 })
1262}
1263
1264pub fn check_socket_getsockname_access(
1267 current_task: &CurrentTask,
1268 socket: &Socket,
1269) -> Result<(), Errno> {
1270 track_hook_duration!("security.hooks.check_socket_getname_access");
1271 if_selinux_else_default_ok(current_task, |security_server| {
1272 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1273 })
1274}
1275
1276pub fn check_socket_getpeername_access(
1279 current_task: &CurrentTask,
1280 socket: &Socket,
1281) -> Result<(), Errno> {
1282 track_hook_duration!("security.hooks.check_socket_getname_access");
1283 if_selinux_else_default_ok(current_task, |security_server| {
1284 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1285 })
1286}
1287
1288pub fn check_socket_shutdown_access(
1291 current_task: &CurrentTask,
1292 socket: &Socket,
1293 how: SocketShutdownFlags,
1294) -> Result<(), Errno> {
1295 track_hook_duration!("security.hooks.check_socket_shutdown_access");
1296 if_selinux_else_default_ok(current_task, |security_server| {
1297 selinux_hooks::socket::check_socket_shutdown_access(
1298 &security_server,
1299 current_task,
1300 socket,
1301 how,
1302 )
1303 })
1304}
1305
1306pub fn socket_getpeersec_stream(
1309 current_task: &CurrentTask,
1310 socket: &Socket,
1311) -> Result<Vec<u8>, Errno> {
1312 track_hook_duration!("security.hooks.socket_getpeersec_stream");
1313 if_selinux_else_default_ok(current_task, |security_server| {
1314 selinux_hooks::socket::socket_getpeersec_stream(&security_server, current_task, socket)
1315 })
1316}
1317
1318pub fn socket_getpeersec_dgram(current_task: &CurrentTask, socket: &Socket) -> Vec<u8> {
1322 track_hook_duration!("security.hooks.socket_getpeersec_dgram");
1323 if_selinux_else(
1324 current_task,
1325 |security_server| {
1326 selinux_hooks::socket::socket_getpeersec_dgram(&security_server, current_task, socket)
1327 },
1328 Vec::default,
1329 )
1330}
1331
1332pub fn unix_may_send(
1336 current_task: &CurrentTask,
1337 sending_socket: &Socket,
1338 receiving_socket: &Socket,
1339) -> Result<(), Errno> {
1340 track_hook_duration!("security.hooks.unix_may_send");
1341 if_selinux_else_default_ok(current_task, |security_server| {
1342 selinux_hooks::socket::unix_may_send(
1343 &security_server,
1344 current_task,
1345 sending_socket,
1346 receiving_socket,
1347 )
1348 })
1349}
1350
1351pub fn unix_stream_connect(
1355 current_task: &CurrentTask,
1356 client_socket: &Socket,
1357 listening_socket: &Socket,
1358 server_socket: &Socket,
1359) -> Result<(), Errno> {
1360 track_hook_duration!("security.hooks.unix_stream_connect");
1361 if_selinux_else_default_ok(current_task, |security_server| {
1362 selinux_hooks::socket::unix_stream_connect(
1363 &security_server,
1364 current_task,
1365 client_socket,
1366 listening_socket,
1367 server_socket,
1368 )
1369 })
1370}
1371
1372pub fn check_netlink_send_access(
1376 current_task: &CurrentTask,
1377 socket: &Socket,
1378 message_type: u16,
1379) -> Result<(), Errno> {
1380 track_hook_duration!("security.hooks.check_netlink_send_access");
1381 if_selinux_else_default_ok(current_task, |security_server| {
1382 selinux_hooks::netlink_socket::check_netlink_send_access(
1383 &security_server,
1384 current_task,
1385 socket,
1386 message_type,
1387 )
1388 })
1389}
1390
1391pub fn check_tun_dev_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1394 track_hook_duration!("security.hooks.check_tun_dev_create_access");
1395 if_selinux_else_default_ok(current_task, |security_server| {
1396 selinux_hooks::socket::check_tun_dev_create_access(&security_server, current_task)
1397 })
1398}
1399
1400pub fn bprm_creds_for_exec(
1406 current_task: &CurrentTask,
1407 executable: &NamespaceNode,
1408 elf_state: &mut ResolvedElf,
1409) -> Result<(), Errno> {
1410 track_hook_duration!("security.hooks.bprm_creds_for_exec");
1411 if_selinux_else_default_ok(current_task, |security_server| {
1412 selinux_hooks::task::bprm_creds_for_exec(
1413 &security_server,
1414 current_task,
1415 executable,
1416 elf_state,
1417 )
1418 })
1419}
1420
1421pub fn bprm_committing_creds(
1427 locked: &mut Locked<Unlocked>,
1428 current_task: &CurrentTask,
1429 elf_state: &ResolvedElf,
1430) -> Result<(), Errno> {
1431 track_hook_duration!("security.hooks.bprm_committing_creds");
1432 if_selinux_else_default_ok(current_task, |security_server| {
1433 selinux_hooks::task::bprm_committing_creds(
1434 locked,
1435 security_server,
1436 current_task,
1437 elf_state,
1438 );
1439 Ok(())
1440 })
1441}
1442
1443pub fn bprm_committed_creds(
1447 _locked: &mut Locked<Unlocked>,
1448 current_task: &CurrentTask,
1449) -> Result<(), Errno> {
1450 track_hook_duration!("security.hooks.bprm_committed_creds");
1451 if_selinux_else_default_ok(current_task, |security_server| {
1452 selinux_hooks::task::bprm_committed_creds(security_server, current_task);
1453 Ok(())
1454 })
1455}
1456
1457pub fn check_getsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1460 track_hook_duration!("security.hooks.check_getsched_access");
1461 if_selinux_else_default_ok(source, |security_server| {
1462 selinux_hooks::task::check_getsched_access(
1463 &selinux_hooks::build_permission_check(source, security_server),
1464 &source,
1465 &target,
1466 )
1467 })
1468}
1469
1470pub fn check_setsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1473 track_hook_duration!("security.hooks.check_setsched_access");
1474 if_selinux_else_default_ok(source, |security_server| {
1475 selinux_hooks::task::check_setsched_access(
1476 &selinux_hooks::build_permission_check(source, security_server),
1477 &source,
1478 &target,
1479 )
1480 })
1481}
1482
1483pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1486 track_hook_duration!("security.hooks.check_getpgid_access");
1487 if_selinux_else_default_ok(source, |security_server| {
1488 selinux_hooks::task::check_getpgid_access(
1489 &selinux_hooks::build_permission_check(source, security_server),
1490 &source,
1491 &target,
1492 )
1493 })
1494}
1495
1496pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1499 track_hook_duration!("security.hooks.check_setpgid_access");
1500 if_selinux_else_default_ok(source, |security_server| {
1501 selinux_hooks::task::check_setpgid_access(
1502 &selinux_hooks::build_permission_check(source, security_server),
1503 &source,
1504 &target,
1505 )
1506 })
1507}
1508
1509pub fn check_task_getsid(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1512 track_hook_duration!("security.hooks.check_task_getsid");
1513 if_selinux_else_default_ok(source, |security_server| {
1514 selinux_hooks::task::check_task_getsid(
1515 &selinux_hooks::build_permission_check(source, security_server),
1516 &source,
1517 &target,
1518 )
1519 })
1520}
1521
1522pub fn check_getcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1525 track_hook_duration!("security.hooks.check_getcap_access");
1526 if_selinux_else_default_ok(source, |security_server| {
1527 selinux_hooks::task::check_getcap_access(
1528 &selinux_hooks::build_permission_check(source, security_server),
1529 &source,
1530 &target,
1531 )
1532 })
1533}
1534
1535pub fn check_setcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1539 track_hook_duration!("security.hooks.check_setcap_access");
1540 if_selinux_else_default_ok(source, |security_server| {
1541 selinux_hooks::task::check_setcap_access(
1542 &selinux_hooks::build_permission_check(source, security_server),
1543 &source,
1544 &target,
1545 )
1546 })
1547}
1548
1549pub fn check_signal_access(
1552 source: &CurrentTask,
1553 target: &Task,
1554 signal: Signal,
1555) -> Result<(), Errno> {
1556 track_hook_duration!("security.hooks.check_signal_access");
1557 if_selinux_else_default_ok(source, |security_server| {
1558 selinux_hooks::task::check_signal_access(
1559 &selinux_hooks::build_permission_check(source, security_server),
1560 &source,
1561 &target,
1562 signal,
1563 )
1564 })
1565}
1566
1567pub fn check_syslog_access(source: &CurrentTask, action: SyslogAction) -> Result<(), Errno> {
1570 track_hook_duration!("security.hooks.check_syslog_access");
1571 if_selinux_else_default_ok(source, |security_server| {
1572 selinux_hooks::task::check_syslog_access(
1573 &selinux_hooks::build_permission_check(source, security_server),
1574 &source,
1575 action,
1576 )
1577 })
1578}
1579
1580pub fn ptrace_traceme(current_task: &CurrentTask, parent_tracer_task: &Task) -> Result<(), Errno> {
1583 track_hook_duration!("security.hooks.ptrace_traceme");
1584 yama::ptrace_traceme(current_task, parent_tracer_task)?;
1585 common_cap::ptrace_traceme(current_task, parent_tracer_task)?;
1586 if_selinux_else_default_ok(current_task, |security_server| {
1587 selinux_hooks::task::ptrace_traceme(
1588 &selinux_hooks::build_permission_check(current_task, security_server),
1589 current_task,
1590 parent_tracer_task,
1591 )
1592 })
1593}
1594
1595pub fn ptrace_access_check(
1598 current_task: &CurrentTask,
1599 tracee_task: &Task,
1600 mode: PtraceAccessMode,
1601) -> Result<(), Errno> {
1602 track_hook_duration!("security.hooks.ptrace_access_check");
1603 yama::ptrace_access_check(current_task, tracee_task, mode)?;
1604 common_cap::ptrace_access_check(current_task, tracee_task, mode)?;
1605 if_selinux_else_default_ok(current_task, |security_server| {
1606 selinux_hooks::task::ptrace_access_check(
1607 &selinux_hooks::build_permission_check(current_task, security_server),
1608 current_task,
1609 tracee_task,
1610 mode,
1611 )
1612 })
1613}
1614
1615pub fn task_prlimit(
1618 source: &CurrentTask,
1619 target: &Task,
1620 check_get_rlimit: bool,
1621 check_set_rlimit: bool,
1622) -> Result<(), Errno> {
1623 track_hook_duration!("security.hooks.task_prlimit");
1624 if_selinux_else_default_ok(source, |security_server| {
1625 selinux_hooks::task::task_prlimit(
1626 &selinux_hooks::build_permission_check(source, security_server),
1627 &source,
1628 &target,
1629 check_get_rlimit,
1630 check_set_rlimit,
1631 )
1632 })
1633}
1634
1635pub fn task_setrlimit(
1638 source: &CurrentTask,
1639 target: &Task,
1640 old_limit: rlimit,
1641 new_limit: rlimit,
1642) -> Result<(), Errno> {
1643 track_hook_duration!("security.hooks.task_setrlimit");
1644 if_selinux_else_default_ok(source, |security_server| {
1645 selinux_hooks::task::task_setrlimit(
1646 &selinux_hooks::build_permission_check(source, security_server),
1647 &source,
1648 &target,
1649 old_limit,
1650 new_limit,
1651 )
1652 })
1653}
1654
1655pub fn sb_kern_mount(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1658 track_hook_duration!("security.hooks.sb_kern_mount");
1659 if_selinux_else_default_ok(current_task, |security_server| {
1660 selinux_hooks::superblock::sb_kern_mount(
1661 &selinux_hooks::build_permission_check(current_task, security_server),
1662 current_task,
1663 fs,
1664 )
1665 })
1666}
1667
1668pub fn sb_mount(
1672 current_task: &CurrentTask,
1673 path: &NamespaceNode,
1674 flags: MountFlags,
1675) -> Result<(), Errno> {
1676 track_hook_duration!("security.hooks.sb_mount");
1677 if_selinux_else_default_ok(current_task, |security_server| {
1678 selinux_hooks::superblock::sb_mount(
1679 &selinux_hooks::build_permission_check(current_task, security_server),
1680 current_task,
1681 path,
1682 flags,
1683 )
1684 })
1685}
1686
1687pub fn sb_remount(
1690 current_task: &CurrentTask,
1691 mount: &Mount,
1692 new_mount_options: FileSystemMountOptions,
1693) -> Result<(), Errno> {
1694 track_hook_duration!("security.hooks.sb_remount");
1695 if_selinux_else_default_ok(current_task, |security_server| {
1696 selinux_hooks::superblock::sb_remount(security_server, mount, new_mount_options)
1697 })
1698}
1699
1700pub fn sb_show_options<'a>(
1703 _kernel: &Kernel,
1704 fs: &'a FileSystem,
1705) -> Result<impl std::fmt::Display + 'a, Errno> {
1706 track_hook_duration!("security.hooks.sb_show_options");
1707 selinux_hooks::superblock::sb_show_options(fs)
1708}
1709
1710pub fn sb_statfs(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1713 track_hook_duration!("security.hooks.sb_statfs");
1714 if_selinux_else_default_ok(current_task, |security_server| {
1715 selinux_hooks::superblock::sb_statfs(
1716 &selinux_hooks::build_permission_check(current_task, security_server),
1717 current_task,
1718 fs,
1719 )
1720 })
1721}
1722
1723pub fn sb_umount(
1727 current_task: &CurrentTask,
1728 node: &NamespaceNode,
1729 flags: UnmountFlags,
1730) -> Result<(), Errno> {
1731 track_hook_duration!("security.hooks.sb_umount");
1732 if_selinux_else_default_ok(current_task, |security_server| {
1733 selinux_hooks::superblock::sb_umount(
1734 &selinux_hooks::build_permission_check(current_task, security_server),
1735 current_task,
1736 node,
1737 flags,
1738 )
1739 })
1740}
1741
1742pub fn check_fs_node_getattr_access(
1745 current_task: &CurrentTask,
1746 fs_node: &FsNode,
1747) -> Result<(), Errno> {
1748 track_hook_duration!("security.hooks.check_fs_node_getattr_access");
1749 if_selinux_else_default_ok(current_task, |security_server| {
1750 selinux_hooks::fs_node::check_fs_node_getattr_access(security_server, current_task, fs_node)
1751 })
1752}
1753
1754pub fn fs_node_xattr_skipcap(_current_task: &CurrentTask, name: &FsStr) -> bool {
1757 selinux_hooks::fs_node::fs_node_xattr_skipcap(name)
1758}
1759
1760pub fn check_fs_node_setxattr_access(
1766 current_task: &CurrentTask,
1767 fs_node: &FsNode,
1768 name: &FsStr,
1769 value: &FsStr,
1770 op: XattrOp,
1771) -> Result<(), Errno> {
1772 track_hook_duration!("security.hooks.check_fs_node_setxattr_access");
1773 common_cap::fs_node_setxattr(current_task, fs_node, name, value, op)?;
1774 if_selinux_else_default_ok(current_task, |security_server| {
1775 selinux_hooks::fs_node::check_fs_node_setxattr_access(
1776 security_server,
1777 current_task,
1778 fs_node,
1779 name,
1780 value,
1781 op,
1782 )
1783 })
1784}
1785
1786pub fn check_fs_node_getxattr_access(
1788 current_task: &CurrentTask,
1789 fs_node: &FsNode,
1790 name: &FsStr,
1791) -> Result<(), Errno> {
1792 track_hook_duration!("security.hooks.check_fs_node_getxattr_access");
1793 if_selinux_else_default_ok(current_task, |security_server| {
1794 selinux_hooks::fs_node::check_fs_node_getxattr_access(
1795 security_server,
1796 current_task,
1797 fs_node,
1798 name,
1799 )
1800 })
1801}
1802
1803pub fn check_fs_node_listxattr_access(
1805 current_task: &CurrentTask,
1806 fs_node: &FsNode,
1807) -> Result<(), Errno> {
1808 track_hook_duration!("security.hooks.check_fs_node_listxattr_access");
1809 if_selinux_else_default_ok(current_task, |security_server| {
1810 selinux_hooks::fs_node::check_fs_node_listxattr_access(
1811 security_server,
1812 current_task,
1813 fs_node,
1814 )
1815 })
1816}
1817
1818pub fn check_fs_node_removexattr_access(
1820 current_task: &CurrentTask,
1821 fs_node: &FsNode,
1822 name: &FsStr,
1823) -> Result<(), Errno> {
1824 track_hook_duration!("security.hooks.check_fs_node_removexattr_access");
1825 common_cap::fs_node_removexattr(current_task, fs_node, name)?;
1826 if_selinux_else_default_ok(current_task, |security_server| {
1827 selinux_hooks::fs_node::check_fs_node_removexattr_access(
1828 security_server,
1829 current_task,
1830 fs_node,
1831 name,
1832 )
1833 })
1834}
1835
1836pub fn fs_node_listsecurity(current_task: &CurrentTask, fs_node: &FsNode) -> Option<FsString> {
1843 track_hook_duration!("security.hooks.fs_node_listsecurity");
1844 if_selinux_else(
1845 current_task,
1846 |_| selinux_hooks::fs_node::fs_node_listsecurity(fs_node),
1847 || None,
1848 )
1849}
1850
1851pub fn fs_node_getsecurity<L>(
1859 locked: &mut Locked<L>,
1860 current_task: &CurrentTask,
1861 fs_node: &FsNode,
1862 name: &FsStr,
1863 max_size: usize,
1864) -> Result<ValueOrSize<FsString>, Errno>
1865where
1866 L: LockEqualOrBefore<FileOpsCore>,
1867{
1868 track_hook_duration!("security.hooks.fs_node_getsecurity");
1869 if_selinux_else_with_context(
1870 locked,
1871 current_task,
1872 |locked, security_server| {
1873 selinux_hooks::fs_node::fs_node_getsecurity(
1874 locked,
1875 security_server,
1876 current_task,
1877 fs_node,
1878 name,
1879 max_size,
1880 )
1881 },
1882 |locked| {
1883 fs_node.ops().get_xattr(
1884 locked.cast_locked::<FileOpsCore>(),
1885 fs_node,
1886 current_task,
1887 name,
1888 max_size,
1889 )
1890 },
1891 )
1892}
1893
1894pub fn fs_node_setsecurity<L>(
1900 locked: &mut Locked<L>,
1901 current_task: &CurrentTask,
1902 fs_node: &FsNode,
1903 name: &FsStr,
1904 value: &FsStr,
1905 op: XattrOp,
1906) -> Result<(), Errno>
1907where
1908 L: LockEqualOrBefore<FileOpsCore>,
1909{
1910 track_hook_duration!("security.hooks.fs_node_setsecurity");
1911 if_selinux_else_with_context(
1912 locked,
1913 current_task,
1914 |locked, security_server| {
1915 selinux_hooks::fs_node::fs_node_setsecurity(
1916 locked,
1917 security_server,
1918 current_task,
1919 fs_node,
1920 name,
1921 value,
1922 op,
1923 )
1924 },
1925 |locked| {
1926 fs_node.ops().set_xattr(
1927 locked.cast_locked::<FileOpsCore>(),
1928 fs_node,
1929 current_task,
1930 name,
1931 value,
1932 op,
1933 )
1934 },
1935 )
1936}
1937
1938pub fn check_bpf_access<Attr: FromBytes>(
1942 current_task: &CurrentTask,
1943 cmd: bpf_cmd,
1944 attr: &Attr,
1945 attr_size: u32,
1946) -> Result<(), Errno> {
1947 track_hook_duration!("security.hooks.check_bpf_access");
1948 if_selinux_else_default_ok(current_task, |security_server| {
1949 selinux_hooks::bpf::check_bpf_access(security_server, current_task, cmd, attr, attr_size)
1950 })
1951}
1952
1953pub fn check_bpf_map_access(
1957 current_task: &CurrentTask,
1958 bpf_map: &BpfMap,
1959 flags: PermissionFlags,
1960) -> Result<(), Errno> {
1961 track_hook_duration!("security.hooks.check_bpf_map_access");
1962 if_selinux_else_default_ok(current_task, |security_server| {
1963 let subject_sid = current_task_state(current_task).current_sid;
1964 selinux_hooks::bpf::check_bpf_map_access(
1965 security_server,
1966 current_task,
1967 subject_sid,
1968 bpf_map,
1969 flags,
1970 )
1971 })
1972}
1973
1974pub fn check_bpf_prog_access(
1979 current_task: &CurrentTask,
1980 bpf_program: &Program,
1981) -> Result<(), Errno> {
1982 track_hook_duration!("security.hooks.check_bpf_prog_access");
1983 if_selinux_else_default_ok(current_task, |security_server| {
1984 let subject_sid = current_task_state(current_task).current_sid;
1985 selinux_hooks::bpf::check_bpf_prog_access(
1986 security_server,
1987 current_task,
1988 subject_sid,
1989 bpf_program,
1990 )
1991 })
1992}
1993
1994pub fn check_perf_event_open_access(
1998 current_task: &CurrentTask,
1999 target_task_type: TargetTaskType<'_>,
2000 attr: &perf_event_attr,
2001 event_type: PerfEventType,
2002) -> Result<(), Errno> {
2003 track_hook_duration!("security.hooks.check_perf_event_open_access");
2004 if_selinux_else_default_ok(current_task, |security_server| {
2005 selinux_hooks::perf_event::check_perf_event_open_access(
2006 security_server,
2007 current_task,
2008 target_task_type,
2009 attr,
2010 event_type,
2011 )
2012 })
2013}
2014
2015pub fn perf_event_alloc(current_task: &CurrentTask) -> PerfEventState {
2019 track_hook_duration!("security.hooks.perf_event_alloc");
2020 PerfEventState { state: selinux_hooks::perf_event::perf_event_alloc(current_task) }
2021}
2022
2023pub fn check_perf_event_read_access(
2026 current_task: &CurrentTask,
2027 perf_event_file: &PerfEventFile,
2028) -> Result<(), Errno> {
2029 track_hook_duration!("security.hooks.check_perf_event_read_access");
2030 if_selinux_else_default_ok(current_task, |security_server| {
2031 selinux_hooks::perf_event::check_perf_event_read_access(
2032 security_server,
2033 current_task,
2034 perf_event_file,
2035 )
2036 })
2037}
2038
2039pub fn check_perf_event_write_access(
2042 current_task: &CurrentTask,
2043 perf_event_file: &PerfEventFile,
2044) -> Result<(), Errno> {
2045 track_hook_duration!("security.hooks.check_perf_event_write_access");
2046 if_selinux_else_default_ok(current_task, |security_server| {
2047 selinux_hooks::perf_event::check_perf_event_write_access(
2048 security_server,
2049 current_task,
2050 perf_event_file,
2051 )
2052 })
2053}
2054
2055#[derive(Debug, Clone, Copy, PartialEq)]
2057pub enum ProcAttr {
2058 Current,
2059 Exec,
2060 FsCreate,
2061 KeyCreate,
2062 Previous,
2063 SockCreate,
2064}
2065
2066pub fn get_procattr(
2069 current_task: &CurrentTask,
2070 target: &Task,
2071 attr: ProcAttr,
2072) -> Result<Vec<u8>, Errno> {
2073 track_hook_duration!("security.hooks.get_procattr");
2074 if_selinux_else(
2075 current_task,
2076 |security_server| {
2077 selinux_hooks::task::get_procattr(security_server, current_task, target, attr)
2078 },
2079 || error!(EINVAL),
2081 )
2082}
2083
2084pub fn set_procattr(
2087 current_task: &CurrentTask,
2088 attr: ProcAttr,
2089 context: &[u8],
2090) -> Result<(), Errno> {
2091 track_hook_duration!("security.hooks.set_procattr");
2092 if_selinux_else(
2093 current_task,
2094 |security_server| {
2095 selinux_hooks::task::set_procattr(security_server, current_task, attr, context)
2096 },
2097 || error!(EINVAL),
2099 )
2100}
2101
2102pub fn fs_is_xattr_labeled(fs: FileSystemHandle) -> bool {
2104 fs.security_state.state.supports_xattr()
2105}
2106
2107pub fn selinuxfs_init_null(current_task: &CurrentTask, null_fs_node: &FileHandle) {
2110 selinux_hooks::selinuxfs::selinuxfs_init_null(current_task, null_fs_node)
2113}
2114
2115pub fn selinuxfs_policy_loaded<L>(locked: &mut Locked<L>, current_task: &CurrentTask)
2121where
2122 L: LockEqualOrBefore<FileOpsCore>,
2123{
2124 track_hook_duration!("security.hooks.selinuxfs_policy_loaded");
2125 selinux_hooks::selinuxfs::selinuxfs_policy_loaded(locked, current_task)
2126}
2127
2128pub fn selinuxfs_get_admin_api(current_task: &CurrentTask) -> Option<Arc<SecurityServer>> {
2132 current_task.kernel().security_state.state.as_ref().map(|state| state.server.clone())
2133}
2134
2135pub fn selinuxfs_check_access(
2138 current_task: &CurrentTask,
2139 permission: SecurityPermission,
2140) -> Result<(), Errno> {
2141 track_hook_duration!("security.hooks.selinuxfs_check_access");
2142 if_selinux_else_default_ok(current_task, |security_server| {
2143 selinux_hooks::selinuxfs::selinuxfs_check_access(security_server, current_task, permission)
2144 })
2145}
2146
2147pub fn creds_start_internal_operation(current_task: &CurrentTask) -> Arc<Credentials> {
2150 track_hook_duration!("security.hooks.creds_start_internal_operation");
2151 let mut creds = Credentials::clone(¤t_task.current_creds());
2152 creds.security_state.internal_operation = true;
2153 creds.into()
2154}
2155
2156pub mod testing {
2157 use super::{Arc, KernelState, SecurityServer, selinux_hooks};
2158 use starnix_sync::Mutex;
2159 use std::sync::OnceLock;
2160 use std::sync::atomic::AtomicU64;
2161
2162 pub fn kernel_state(security_server: Option<Arc<SecurityServer>>) -> KernelState {
2165 let state = security_server.map(|server| selinux_hooks::KernelState {
2166 server,
2167 pending_file_systems: Mutex::default(),
2168 selinuxfs_null: OnceLock::default(),
2169 access_denial_count: AtomicU64::new(0u64),
2170 has_policy: false.into(),
2171 _inspect_node: fuchsia_inspect::Node::default(),
2172 });
2173 KernelState { state }
2174 }
2175}
2176
2177#[cfg(test)]
2178mod tests {
2179 use super::*;
2180 use crate::security;
2181 use crate::security::selinux_hooks::get_cached_sid;
2182 use crate::security::selinux_hooks::testing::{
2183 self, spawn_kernel_with_selinux_hooks_test_policy_and_run,
2184 };
2185 use crate::testing::{create_task, spawn_kernel_and_run, spawn_kernel_with_selinux_and_run};
2186 use linux_uapi::XATTR_NAME_SELINUX;
2187 use selinux::InitialSid;
2188 use starnix_uapi::auth::PTRACE_MODE_ATTACH;
2189 use starnix_uapi::signals::SIGTERM;
2190
2191 const VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_valid_t:s0";
2192 const VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] = b"u:object_r:test_valid_t:s0\0";
2193
2194 const DIFFERENT_VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_different_valid_t:s0";
2195 const DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] =
2196 b"u:object_r:test_different_valid_t:s0\0";
2197
2198 const INVALID_SECURITY_CONTEXT_INTERNAL_NUL: &[u8] = b"u:object_r:test_valid_\0t:s0";
2199
2200 const INVALID_SECURITY_CONTEXT: &[u8] = b"not_a_u:object_r:test_valid_t:s0";
2201
2202 #[derive(Default, Debug, PartialEq)]
2203 enum TestHookResult {
2204 WasRun,
2205 WasNotRun,
2206 #[default]
2207 WasNotRunDefault,
2208 }
2209
2210 #[fuchsia::test]
2211 async fn if_selinux_else_disabled() {
2212 spawn_kernel_and_run(async |_, current_task| {
2213 assert!(current_task.kernel().security_state.state.is_none());
2214
2215 let check_result =
2216 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2217 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2218
2219 let run_else_result = if_selinux_else(
2220 current_task,
2221 |_| TestHookResult::WasRun,
2222 || TestHookResult::WasNotRun,
2223 );
2224 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2225 })
2226 .await;
2227 }
2228
2229 #[fuchsia::test]
2230 async fn if_selinux_else_without_policy() {
2231 spawn_kernel_with_selinux_and_run(async |_locked, current_task, _security_server| {
2232 let check_result =
2233 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2234 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2235
2236 let run_else_result = if_selinux_else(
2237 current_task,
2238 |_| TestHookResult::WasRun,
2239 || TestHookResult::WasNotRun,
2240 );
2241 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2242 })
2243 .await;
2244 }
2245
2246 #[fuchsia::test]
2247 async fn if_selinux_else_with_policy() {
2248 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2249 |_locked, current_task, _security_server| {
2250 let check_result =
2251 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2252 assert_eq!(check_result, Ok(TestHookResult::WasRun));
2253
2254 let run_else_result = if_selinux_else(
2255 current_task,
2256 |_| TestHookResult::WasRun,
2257 || TestHookResult::WasNotRun,
2258 );
2259 assert_eq!(run_else_result, TestHookResult::WasRun);
2260 },
2261 )
2262 .await;
2263 }
2264
2265 #[fuchsia::test]
2266 async fn task_create_access_allowed_for_selinux_disabled() {
2267 spawn_kernel_and_run(async |_, current_task| {
2268 assert!(current_task.kernel().security_state.state.is_none());
2269 assert_eq!(check_task_create_access(current_task), Ok(()));
2270 })
2271 .await;
2272 }
2273
2274 #[fuchsia::test]
2275 async fn task_create_access_allowed_for_permissive_mode() {
2276 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2277 |_locked, current_task, security_server| {
2278 security_server.set_enforcing(false);
2279 assert_eq!(check_task_create_access(current_task), Ok(()));
2280 },
2281 )
2282 .await;
2283 }
2284
2285 #[fuchsia::test]
2286 async fn exec_access_allowed_for_selinux_disabled() {
2287 spawn_kernel_and_run(async |locked, current_task| {
2288 assert!(current_task.kernel().security_state.state.is_none());
2289 let executable = testing::create_test_file(locked, current_task);
2290 let mut resolved_elf =
2291 testing::make_resolved_elf(locked, current_task, executable.clone());
2292 assert_eq!(bprm_creds_for_exec(current_task, &executable, &mut resolved_elf), Ok(()));
2293 })
2294 .await;
2295 }
2296
2297 #[fuchsia::test]
2298 async fn exec_access_allowed_for_permissive_mode() {
2299 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2300 |locked, current_task, security_server| {
2301 security_server.set_enforcing(false);
2302 let executable = testing::create_test_file(locked, current_task);
2303 let mut resolved_elf =
2304 testing::make_resolved_elf(locked, current_task, executable.clone());
2305 let result = bprm_creds_for_exec(current_task, &executable, &mut resolved_elf);
2307 assert!(result.is_ok());
2308 },
2309 )
2310 .await;
2311 }
2312
2313 #[fuchsia::test]
2314 async fn no_state_update_for_selinux_disabled() {
2315 spawn_kernel_and_run(async |locked, current_task| {
2316 let target_sid = InitialSid::Unlabeled.into();
2317
2318 assert!(selinux_hooks::current_task_state(current_task).current_sid != target_sid);
2319
2320 testing::mutate_attrs_for_test(current_task, |attrs| {
2322 attrs.exec_sid = Some(target_sid);
2323 });
2324
2325 let executable = testing::create_test_file(locked, current_task);
2326 let mut resolved_elf =
2327 testing::make_resolved_elf(locked, current_task, executable.clone());
2328
2329 let before_hook_sid = selinux_hooks::current_task_state(current_task).current_sid;
2330
2331 bprm_creds_for_exec(current_task, &executable, &mut resolved_elf).unwrap();
2332 assert_eq!(resolved_elf.creds.security_state.current_sid, before_hook_sid);
2333 })
2334 .await;
2335 }
2336
2337 #[fuchsia::test]
2338 async fn no_state_update_for_selinux_without_policy() {
2339 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2340 let initial_state = current_task.current_creds().security_state.clone();
2341 let elf_sid = InitialSid::Unlabeled.into();
2342
2343 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).current_sid);
2344
2345 testing::mutate_attrs_for_test(current_task, |attrs| {
2347 attrs.exec_sid = Some(elf_sid);
2348 });
2349
2350 let executable = testing::create_test_file(locked, current_task);
2351 let mut resolved_elf =
2352 testing::make_resolved_elf(locked, current_task, executable.clone());
2353
2354 bprm_creds_for_exec(current_task, &executable, &mut resolved_elf).unwrap();
2355 assert_eq!(resolved_elf.creds.security_state.current_sid, initial_state.current_sid);
2357 })
2358 .await;
2359 }
2360
2361 #[fuchsia::test]
2362 async fn state_update_for_permissive_mode() {
2363 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2364 |locked, current_task, security_server| {
2365 security_server.set_enforcing(false);
2366 let elf_sid = security_server
2367 .security_context_to_sid(b"u:object_r:fork_no_t:s0".into())
2368 .expect("invalid security context");
2369
2370 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).current_sid);
2371
2372 testing::mutate_attrs_for_test(current_task, |attrs| {
2374 attrs.exec_sid = Some(elf_sid);
2375 });
2376
2377 let executable = testing::create_test_file(locked, current_task);
2378 let mut resolved_elf =
2379 testing::make_resolved_elf(locked, current_task, executable.clone());
2380
2381 bprm_creds_for_exec(current_task, &executable, &mut resolved_elf).unwrap();
2382 assert_eq!(resolved_elf.creds.security_state.current_sid, elf_sid);
2383 },
2384 )
2385 .await;
2386 }
2387
2388 #[fuchsia::test]
2389 async fn getsched_access_allowed_for_selinux_disabled() {
2390 spawn_kernel_and_run(async |locked, current_task| {
2391 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2392 assert_eq!(check_getsched_access(current_task, &another_task), Ok(()));
2393 })
2394 .await;
2395 }
2396
2397 #[fuchsia::test]
2398 async fn getsched_access_allowed_for_permissive_mode() {
2399 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2400 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2401 assert_eq!(check_getsched_access(current_task, &another_task), Ok(()));
2402 })
2403 .await;
2404 }
2405
2406 #[fuchsia::test]
2407 async fn setsched_access_allowed_for_selinux_disabled() {
2408 spawn_kernel_and_run(async |locked, current_task| {
2409 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2410 assert_eq!(check_setsched_access(current_task, &another_task), Ok(()));
2411 })
2412 .await;
2413 }
2414
2415 #[fuchsia::test]
2416 async fn setsched_access_allowed_for_permissive_mode() {
2417 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2418 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2419 assert_eq!(check_setsched_access(current_task, &another_task), Ok(()));
2420 })
2421 .await;
2422 }
2423
2424 #[fuchsia::test]
2425 async fn getpgid_access_allowed_for_selinux_disabled() {
2426 spawn_kernel_and_run(async |locked, current_task| {
2427 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2428 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2429 })
2430 .await;
2431 }
2432
2433 #[fuchsia::test]
2434 async fn getpgid_access_allowed_for_permissive_mode() {
2435 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2436 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2437 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2438 })
2439 .await;
2440 }
2441
2442 #[fuchsia::test]
2443 async fn setpgid_access_allowed_for_selinux_disabled() {
2444 spawn_kernel_and_run(async |locked, current_task| {
2445 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2446 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2447 })
2448 .await;
2449 }
2450
2451 #[fuchsia::test]
2452 async fn setpgid_access_allowed_for_permissive_mode() {
2453 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2454 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2455 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2456 })
2457 .await;
2458 }
2459
2460 #[fuchsia::test]
2461 async fn task_getsid_allowed_for_selinux_disabled() {
2462 spawn_kernel_and_run(async |locked, current_task| {
2463 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2464 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2465 })
2466 .await;
2467 }
2468
2469 #[fuchsia::test]
2470 async fn task_getsid_allowed_for_permissive_mode() {
2471 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2472 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2473 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2474 })
2475 .await;
2476 }
2477
2478 #[fuchsia::test]
2479 async fn signal_access_allowed_for_selinux_disabled() {
2480 spawn_kernel_and_run(async |locked, current_task| {
2481 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2482 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2483 })
2484 .await;
2485 }
2486
2487 #[fuchsia::test]
2488 async fn signal_access_allowed_for_permissive_mode() {
2489 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2490 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2491 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2492 })
2493 .await;
2494 }
2495
2496 #[fuchsia::test]
2497 async fn ptrace_traceme_access_allowed_for_selinux_disabled() {
2498 spawn_kernel_and_run(async |locked, current_task| {
2499 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2500 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2501 })
2502 .await;
2503 }
2504
2505 #[fuchsia::test]
2506 async fn ptrace_traceme_access_allowed_for_permissive_mode() {
2507 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2508 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2509 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2510 })
2511 .await;
2512 }
2513
2514 #[fuchsia::test]
2515 async fn ptrace_attach_access_allowed_for_selinux_disabled() {
2516 spawn_kernel_and_run(async |locked, current_task| {
2517 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2518 assert_eq!(
2519 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2520 Ok(())
2521 );
2522 })
2523 .await;
2524 }
2525
2526 #[fuchsia::test]
2527 async fn ptrace_attach_access_allowed_for_permissive_mode() {
2528 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2529 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2530 assert_eq!(
2531 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2532 Ok(())
2533 );
2534 })
2535 .await;
2536 }
2537
2538 #[fuchsia::test]
2539 async fn task_prlimit_access_allowed_for_selinux_disabled() {
2540 spawn_kernel_and_run(async |locked, current_task| {
2541 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2542 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2543 })
2544 .await;
2545 }
2546
2547 #[fuchsia::test]
2548 async fn task_prlimit_access_allowed_for_permissive_mode() {
2549 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2550 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2551 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2552 })
2553 .await;
2554 }
2555
2556 #[fuchsia::test]
2557 async fn fs_node_task_to_fs_node_noop_selinux_disabled() {
2558 spawn_kernel_and_run(async |locked, current_task| {
2559 let node = &testing::create_test_file(locked, current_task).entry.node;
2560 task_to_fs_node(current_task, ¤t_task.temp_task(), &node);
2561 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2562 })
2563 .await;
2564 }
2565
2566 #[fuchsia::test]
2567 async fn fs_node_setsecurity_selinux_disabled_only_sets_xattr() {
2568 spawn_kernel_and_run(async |locked, current_task| {
2569 let node = &testing::create_test_file(locked, current_task).entry.node;
2570
2571 fs_node_setsecurity(
2572 locked,
2573 current_task,
2574 &node,
2575 XATTR_NAME_SELINUX.to_bytes().into(),
2576 VALID_SECURITY_CONTEXT.into(),
2577 XattrOp::Set,
2578 )
2579 .expect("set_xattr(security.selinux) failed");
2580
2581 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2582 })
2583 .await;
2584 }
2585
2586 #[fuchsia::test]
2587 async fn fs_node_setsecurity_selinux_without_policy_only_sets_xattr() {
2588 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2589 let node = &testing::create_test_file(locked, current_task).entry.node;
2590 fs_node_setsecurity(
2591 locked,
2592 current_task,
2593 &node,
2594 XATTR_NAME_SELINUX.to_bytes().into(),
2595 VALID_SECURITY_CONTEXT.into(),
2596 XattrOp::Set,
2597 )
2598 .expect("set_xattr(security.selinux) failed");
2599
2600 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2601 })
2602 .await;
2603 }
2604
2605 #[fuchsia::test]
2606 async fn fs_node_setsecurity_selinux_permissive_sets_xattr_and_label() {
2607 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2608 |locked, current_task, security_server| {
2609 security_server.set_enforcing(false);
2610 let expected_sid = security_server
2611 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2612 .expect("no SID for VALID_SECURITY_CONTEXT");
2613 let node = &testing::create_test_file(locked, ¤t_task).entry.node;
2614
2615 assert_ne!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2617
2618 fs_node_setsecurity(
2619 locked,
2620 current_task,
2621 &node,
2622 XATTR_NAME_SELINUX.to_bytes().into(),
2623 VALID_SECURITY_CONTEXT.into(),
2624 XattrOp::Set,
2625 )
2626 .expect("set_xattr(security.selinux) failed");
2627
2628 assert_eq!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2631 },
2632 )
2633 .await;
2634 }
2635
2636 #[fuchsia::test]
2637 async fn fs_node_setsecurity_not_selinux_only_sets_xattr() {
2638 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2639 |locked, current_task, security_server| {
2640 let valid_security_context_sid = security_server
2641 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2642 .expect("no SID for VALID_SECURITY_CONTEXT");
2643 let node = &testing::create_test_file(locked, current_task).entry.node;
2644 let whatever_sid = selinux_hooks::get_cached_sid(node);
2648 assert_ne!(Some(valid_security_context_sid), whatever_sid);
2649
2650 fs_node_setsecurity(
2651 locked,
2652 current_task,
2653 &node,
2654 "security.selinu!".into(), VALID_SECURITY_CONTEXT.into(),
2656 XattrOp::Set,
2657 )
2658 .expect("set_xattr(security.selinux) failed");
2659
2660 assert_eq!(whatever_sid, selinux_hooks::get_cached_sid(node));
2662 },
2663 )
2664 .await;
2665 }
2666
2667 #[fuchsia::test]
2668 async fn fs_node_setsecurity_selinux_enforcing_invalid_context_fails() {
2669 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2670 |locked, current_task, _security_server| {
2671 let node = &testing::create_test_file(locked, current_task).entry.node;
2672
2673 let before_sid = selinux_hooks::get_cached_sid(node);
2674 assert_ne!(Some(InitialSid::Unlabeled.into()), before_sid);
2675
2676 assert!(
2677 check_fs_node_setxattr_access(
2678 ¤t_task,
2679 &node,
2680 XATTR_NAME_SELINUX.to_bytes().into(),
2681 "!".into(), XattrOp::Set,
2683 )
2684 .is_err()
2685 );
2686
2687 assert_eq!(before_sid, selinux_hooks::get_cached_sid(node));
2688 },
2689 )
2690 .await;
2691 }
2692
2693 #[fuchsia::test]
2694 async fn fs_node_setsecurity_selinux_permissive_invalid_context_sets_xattr_and_label() {
2695 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2696 |locked, current_task, security_server| {
2697 security_server.set_enforcing(false);
2698 let node = &testing::create_test_file(locked, current_task).entry.node;
2699
2700 assert_ne!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2701
2702 fs_node_setsecurity(
2703 locked,
2704 current_task,
2705 &node,
2706 XATTR_NAME_SELINUX.to_bytes().into(),
2707 "!".into(), XattrOp::Set,
2709 )
2710 .expect("set_xattr(security.selinux) failed");
2711
2712 assert_eq!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2713 },
2714 )
2715 .await;
2716 }
2717
2718 #[fuchsia::test]
2719 async fn fs_node_setsecurity_different_sid_for_different_context() {
2720 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2721 |locked, current_task, _security_server| {
2722 let node = &testing::create_test_file(locked, current_task).entry.node;
2723
2724 fs_node_setsecurity(
2725 locked,
2726 current_task,
2727 &node,
2728 XATTR_NAME_SELINUX.to_bytes().into(),
2729 VALID_SECURITY_CONTEXT.into(),
2730 XattrOp::Set,
2731 )
2732 .expect("set_xattr(security.selinux) failed");
2733
2734 assert!(selinux_hooks::get_cached_sid(node).is_some());
2735
2736 let first_sid = selinux_hooks::get_cached_sid(node).unwrap();
2737 fs_node_setsecurity(
2738 locked,
2739 current_task,
2740 &node,
2741 XATTR_NAME_SELINUX.to_bytes().into(),
2742 DIFFERENT_VALID_SECURITY_CONTEXT.into(),
2743 XattrOp::Set,
2744 )
2745 .expect("set_xattr(security.selinux) failed");
2746
2747 assert!(selinux_hooks::get_cached_sid(node).is_some());
2748
2749 let second_sid = selinux_hooks::get_cached_sid(node).unwrap();
2750
2751 assert_ne!(first_sid, second_sid);
2752 },
2753 )
2754 .await;
2755 }
2756
2757 #[fuchsia::test]
2758 async fn fs_node_getsecurity_returns_cached_context() {
2759 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2760 |locked, current_task, security_server| {
2761 let node = &testing::create_test_file(locked, current_task).entry.node;
2762
2763 const TEST_VALUE: &str = "Something Random";
2765 node.ops()
2766 .set_xattr(
2767 locked.cast_locked::<FileOpsCore>(),
2768 node,
2769 current_task,
2770 XATTR_NAME_SELINUX.to_bytes().into(),
2771 TEST_VALUE.into(),
2772 XattrOp::Set,
2773 )
2774 .expect("set_xattr(security.selinux) failed");
2775
2776 let sid = security_server
2778 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2779 .expect("security context to SID");
2780 selinux_hooks::set_cached_sid(&node, sid);
2781
2782 let result = fs_node_getsecurity(
2784 locked,
2785 current_task,
2786 node,
2787 XATTR_NAME_SELINUX.to_bytes().into(),
2788 4096,
2789 );
2790 assert_eq!(
2791 result,
2792 Ok(ValueOrSize::Value(FsString::new(VALID_SECURITY_CONTEXT_WITH_NUL.into())))
2793 );
2794 },
2795 )
2796 .await;
2797 }
2798
2799 #[fuchsia::test]
2800 async fn fs_node_getsecurity_delegates_to_get_xattr() {
2801 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2802 |locked, current_task, security_server| {
2803 let node = &testing::create_test_file(locked, current_task).entry.node;
2804
2805 security_server.set_enforcing(false);
2808 const TEST_VALUE: &str = "Something Random";
2809 fs_node_setsecurity(
2810 locked,
2811 current_task,
2812 node,
2813 XATTR_NAME_SELINUX.to_bytes().into(),
2814 TEST_VALUE.into(),
2815 XattrOp::Set,
2816 )
2817 .expect("set_xattr(security.selinux) failed");
2818 security_server.set_enforcing(true);
2819
2820 let result = fs_node_getsecurity(
2822 locked,
2823 current_task,
2824 node,
2825 XATTR_NAME_SELINUX.to_bytes().into(),
2826 4096,
2827 );
2828 assert_eq!(result, Ok(ValueOrSize::Value(FsString::new(TEST_VALUE.into()))));
2829 },
2830 )
2831 .await;
2832 }
2833
2834 #[fuchsia::test]
2835 async fn set_get_procattr() {
2836 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2837 |_locked, current_task, _security_server| {
2838 assert_eq!(
2839 get_procattr(current_task, current_task, ProcAttr::Exec),
2840 Ok(Vec::new())
2841 );
2842
2843 assert_eq!(
2844 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2846 Ok(())
2847 );
2848
2849 assert_eq!(
2850 set_procattr(
2852 current_task,
2853 ProcAttr::SockCreate,
2854 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2855 ),
2856 error!(EACCES)
2857 );
2858
2859 assert_eq!(
2860 set_procattr(
2862 current_task,
2863 ProcAttr::Previous,
2864 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2865 ),
2866 error!(EINVAL)
2867 );
2868
2869 assert_eq!(
2870 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2872 error!(EINVAL)
2873 );
2874
2875 assert_eq!(
2876 get_procattr(current_task, current_task, ProcAttr::Exec),
2877 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2878 );
2879
2880 assert!(get_procattr(current_task, current_task, ProcAttr::Current).is_ok());
2881 },
2882 )
2883 .await;
2884 }
2885
2886 #[fuchsia::test]
2887 async fn set_get_procattr_with_nulls() {
2888 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2889 |_locked, current_task, _security_server| {
2890 assert_eq!(
2891 get_procattr(current_task, current_task, ProcAttr::Exec),
2892 Ok(Vec::new())
2893 );
2894
2895 assert_eq!(
2896 set_procattr(
2898 current_task,
2899 ProcAttr::Exec,
2900 VALID_SECURITY_CONTEXT_WITH_NUL.into()
2901 ),
2902 Ok(())
2903 );
2904
2905 assert_eq!(
2906 set_procattr(
2908 current_task,
2909 ProcAttr::FsCreate,
2910 INVALID_SECURITY_CONTEXT_INTERNAL_NUL.into()
2911 ),
2912 error!(EINVAL)
2913 );
2914
2915 assert_eq!(
2916 get_procattr(current_task, current_task, ProcAttr::Exec),
2917 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2918 );
2919
2920 assert_eq!(
2921 get_procattr(current_task, current_task, ProcAttr::FsCreate),
2922 Ok(Vec::new())
2923 );
2924 },
2925 )
2926 .await;
2927 }
2928
2929 #[fuchsia::test]
2930 async fn set_get_procattr_clear_context() {
2931 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2932 |_locked, current_task, _security_server| {
2933 assert_eq!(
2935 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2936 Ok(())
2937 );
2938 assert_eq!(
2939 set_procattr(
2940 current_task,
2941 ProcAttr::FsCreate,
2942 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2943 ),
2944 Ok(())
2945 );
2946
2947 assert_eq!(set_procattr(current_task, ProcAttr::Exec, b"\0"), Ok(()));
2949 assert_eq!(current_task.current_creds().security_state.exec_sid, None);
2950
2951 assert_eq!(set_procattr(current_task, ProcAttr::FsCreate, b"\x0a"), Ok(()));
2953 assert_eq!(current_task.current_creds().security_state.fscreate_sid, None);
2954 },
2955 )
2956 .await;
2957 }
2958
2959 #[fuchsia::test]
2960 async fn set_get_procattr_setcurrent() {
2961 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2962 |_locked, current_task, _security_server| {
2963 let initial_previous =
2965 get_procattr(current_task, current_task, ProcAttr::Previous).unwrap();
2966
2967 assert_eq!(
2968 set_procattr(current_task, ProcAttr::Current, VALID_SECURITY_CONTEXT.into()),
2970 Ok(())
2971 );
2972
2973 assert_eq!(
2974 get_procattr(current_task, current_task, ProcAttr::Current),
2976 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2977 );
2978
2979 assert_eq!(
2980 get_procattr(current_task, current_task, ProcAttr::Previous),
2982 Ok(initial_previous.clone())
2983 );
2984
2985 assert_eq!(
2986 set_procattr(
2988 current_task,
2989 ProcAttr::Current,
2990 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2991 ),
2992 Ok(())
2993 );
2994
2995 assert_eq!(
2996 get_procattr(current_task, current_task, ProcAttr::Current),
2998 Ok(DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL.into())
2999 );
3000
3001 assert_eq!(
3002 get_procattr(current_task, current_task, ProcAttr::Previous),
3004 Ok(initial_previous.clone())
3005 );
3006 },
3007 )
3008 .await;
3009 }
3010
3011 #[fuchsia::test]
3012 async fn set_get_procattr_selinux_permissive() {
3013 spawn_kernel_with_selinux_hooks_test_policy_and_run(
3014 |_locked, current_task, security_server| {
3015 security_server.set_enforcing(false);
3016 assert_eq!(
3017 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Exec),
3018 Ok(Vec::new())
3019 );
3020
3021 assert_eq!(
3022 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3024 Ok(())
3025 );
3026
3027 assert_eq!(
3028 set_procattr(
3031 current_task,
3032 ProcAttr::FsCreate,
3033 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3034 ),
3035 Ok(())
3036 );
3037
3038 assert_eq!(
3039 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3041 error!(EINVAL)
3042 );
3043
3044 assert_eq!(
3045 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Exec),
3046 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3047 );
3048
3049 assert!(
3050 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Current)
3051 .is_ok()
3052 );
3053 },
3054 )
3055 .await;
3056 }
3057
3058 #[fuchsia::test]
3059 async fn set_get_procattr_selinux_disabled() {
3060 spawn_kernel_and_run(async |_, current_task| {
3061 assert_eq!(
3062 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3063 error!(EINVAL)
3064 );
3065
3066 assert_eq!(
3067 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3069 error!(EINVAL)
3070 );
3071
3072 assert_eq!(
3073 set_procattr(¤t_task, ProcAttr::FsCreate, VALID_SECURITY_CONTEXT.into()),
3075 error!(EINVAL)
3076 );
3077
3078 assert_eq!(
3079 set_procattr(¤t_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3081 error!(EINVAL)
3082 );
3083
3084 assert_eq!(
3085 get_procattr(¤t_task, ¤t_task.temp_task(), ProcAttr::Current),
3086 error!(EINVAL)
3087 );
3088 })
3089 .await;
3090 }
3091
3092 #[fuchsia::test]
3093 async fn create_file_with_fscreate_sid() {
3094 spawn_kernel_with_selinux_hooks_test_policy_and_run(
3095 |locked, current_task, security_server| {
3096 let sid =
3097 security_server.security_context_to_sid(VALID_SECURITY_CONTEXT.into()).unwrap();
3098 let source_node = &testing::create_test_file(locked, current_task).entry.node;
3099
3100 fs_node_setsecurity(
3101 locked,
3102 current_task,
3103 &source_node,
3104 XATTR_NAME_SELINUX.to_bytes().into(),
3105 VALID_SECURITY_CONTEXT.into(),
3106 XattrOp::Set,
3107 )
3108 .expect("set_xattr(security.selinux) failed");
3109
3110 let mut creds = Credentials::clone(¤t_task.current_creds());
3111 security::fs_node_copy_up(current_task, source_node, &source_node.fs(), &mut creds);
3112 let dir_entry = current_task
3113 .override_creds(creds.into(), || {
3114 current_task
3115 .fs()
3116 .root()
3117 .create_node(
3118 locked,
3119 ¤t_task,
3120 "test_file2".into(),
3121 FileMode::IFREG,
3122 DeviceId::NONE,
3123 )
3124 .unwrap()
3125 })
3126 .entry;
3127
3128 assert_eq!(get_cached_sid(&dir_entry.node), Some(sid));
3129 },
3130 )
3131 .await;
3132 }
3133}