1#![allow(non_upper_case_globals)]
7
8use super::selinux_hooks::audit::Auditable;
9use super::{
10 BinderConnectionState, BpfMapState, BpfProgState, FileObjectState, FileSystemState,
11 KernelState, PerfEventState, ResolvedElfState, TaskState, common_cap, selinux_hooks, yama,
12};
13use crate::bpf::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::{CurrentTask, FullCredentials, Kernel, Task};
19use crate::vfs::fs_args::MountParams;
20use crate::vfs::socket::{
21 Socket, SocketAddress, SocketDomain, SocketFile, SocketPeer, SocketProtocol,
22 SocketShutdownFlags, SocketType,
23};
24use crate::vfs::{
25 Anon, DirEntryHandle, DowncastedFile, FileHandle, FileObject, FileSystem, FileSystemHandle,
26 FileSystemOps, FsNode, FsStr, FsString, Mount, NamespaceNode, OutputBuffer, ValueOrSize,
27 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};
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::PtraceAccessMode;
41use starnix_uapi::device_type::DeviceType;
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
192pub enum TargetTaskType<'a> {
194 AllTasks,
196 CurrentTask,
198 Task(&'a Task),
200}
201
202fn if_selinux_else_with_context<F, R, D, C>(context: C, task: &Task, hook: F, default: D) -> R
206where
207 F: FnOnce(C, &Arc<SecurityServer>) -> R,
208 D: Fn(C) -> R,
209{
210 if let Some(state) = task.kernel().security_state.state.as_ref() {
211 if state.has_policy() { hook(context, &state.server) } else { default(context) }
212 } else {
213 default(context)
214 }
215}
216
217fn if_selinux_else<F, R, D>(task: &Task, hook: F, default: D) -> R
221where
222 F: FnOnce(&Arc<SecurityServer>) -> R,
223 D: Fn() -> R,
224{
225 if_selinux_else_with_context(
226 (),
227 task,
228 |_, security_server| hook(security_server),
229 |_| default(),
230 )
231}
232
233fn if_selinux_else_default_ok_with_context<R, F, C>(
237 context: C,
238 task: &Task,
239 hook: F,
240) -> Result<R, Errno>
241where
242 F: FnOnce(C, &Arc<SecurityServer>) -> Result<R, Errno>,
243 R: Default,
244{
245 if_selinux_else_with_context(context, task, hook, |_| Ok(R::default()))
246}
247
248fn if_selinux_else_default_ok<R, F>(task: &Task, hook: F) -> Result<R, Errno>
252where
253 F: FnOnce(&Arc<SecurityServer>) -> Result<R, Errno>,
254 R: Default,
255{
256 if_selinux_else(task, hook, || Ok(R::default()))
257}
258
259pub fn kernel_init_security(
262 enabled: bool,
263 options: String,
264 exceptions: Vec<String>,
265 inspect_node: &fuchsia_inspect::Node,
266) -> KernelState {
267 track_hook_duration!("security.hooks.kernel_init_security");
268 KernelState {
269 state: enabled
270 .then(|| selinux_hooks::kernel_init_security(options, exceptions, inspect_node)),
271 }
272}
273
274pub fn binder_set_context_mgr(current_task: &CurrentTask) -> Result<(), Errno> {
277 track_hook_duration!("security.hooks.binder_set_context_mgr");
278 if_selinux_else_default_ok(current_task, |security_server| {
279 selinux_hooks::binder::binder_set_context_mgr(security_server, current_task)
280 })
281}
282
283pub fn binder_transaction(
286 current_task: &CurrentTask,
287 target_task: &Task,
288 connection_state: &BinderConnectionState,
289) -> Result<(), Errno> {
290 track_hook_duration!("security.hooks.binder_transaction");
291 if_selinux_else_default_ok(current_task, |security_server| {
292 selinux_hooks::binder::binder_transaction(
293 security_server,
294 &connection_state.state,
295 current_task,
296 target_task,
297 )
298 })
299}
300
301pub fn binder_transfer_binder(current_task: &CurrentTask, target_task: &Task) -> Result<(), Errno> {
304 track_hook_duration!("security.hooks.binder_transfer_binder");
305 if_selinux_else_default_ok(current_task, |security_server| {
306 selinux_hooks::binder::binder_transfer_binder(security_server, current_task, target_task)
307 })
308}
309
310pub fn binder_transfer_file(
313 current_task: &CurrentTask,
314 receiving_task: &Task,
315 file: &FileObject,
316) -> Result<(), Errno> {
317 track_hook_duration!("security.hooks.binder_transfer_file");
318 if_selinux_else_default_ok(current_task, |security_server| {
319 selinux_hooks::binder::binder_transfer_file(
320 security_server,
321 current_task,
322 receiving_task,
323 file,
324 )
325 })
326}
327
328pub fn binder_get_context(
331 current_task: &CurrentTask,
332 connection_state: &BinderConnectionState,
333) -> Option<Vec<u8>> {
334 track_hook_duration!("security.hooks.binder_get_context");
335 if_selinux_else(
336 current_task,
337 |security_server| {
338 selinux_hooks::binder::binder_get_context(&security_server, &connection_state.state)
339 },
340 || None,
341 )
342}
343
344pub fn sb_eat_lsm_opts(
348 kernel: &Kernel,
349 mount_params: &mut MountParams,
350) -> Result<FileSystemMountOptions, Errno> {
351 track_hook_duration!("security.hooks.sb_eat_lsm_opts");
352 if kernel.security_state.state.is_some() {
353 return selinux_hooks::superblock::sb_eat_lsm_opts(mount_params);
354 }
355 Ok(FileSystemMountOptions::default())
356}
357
358pub fn file_system_init_security(
361 mount_options: &FileSystemMountOptions,
362 ops: &dyn FileSystemOps,
363) -> Result<FileSystemState, Errno> {
364 track_hook_duration!("security.hooks.file_system_init_security");
365 Ok(FileSystemState {
366 state: selinux_hooks::superblock::file_system_init_security(mount_options, ops)?,
367 })
368}
369
370pub fn file_system_post_init_security(kernel: &Kernel, file_system: &FileSystemHandle) {
375 track_hook_duration!("security.hooks.file_system_post_init_security");
376 if let Some(state) = &kernel.security_state.state {
377 if !state.has_policy() {
378 log_debug!("Queuing {} FileSystem for labeling", file_system.name());
381 state.pending_file_systems.lock().insert(WeakKey::from(&file_system));
382 }
383 }
384}
385
386pub fn file_system_resolve_security<L>(
391 locked: &mut Locked<L>,
392 current_task: &CurrentTask,
393 file_system: &FileSystemHandle,
394) -> Result<(), Errno>
395where
396 L: LockEqualOrBefore<FileOpsCore>,
397{
398 track_hook_duration!("security.hooks.file_system_resolve_security");
399 if_selinux_else_default_ok_with_context(locked, current_task, |locked, security_server| {
400 selinux_hooks::superblock::file_system_resolve_security(
401 locked,
402 security_server,
403 current_task,
404 file_system,
405 )
406 })
407}
408
409pub struct FsNodeSecurityXattr {
411 pub name: &'static FsStr,
412 pub value: FsString,
413}
414
415pub fn mmap_file(
419 current_task: &CurrentTask,
420 file: Option<&FileHandle>,
421 protection_flags: ProtectionFlags,
422 options: MappingOptions,
423) -> Result<(), Errno> {
424 track_hook_duration!("security.hooks.mmap_file");
425 if_selinux_else_default_ok(current_task, |security_server| {
426 selinux_hooks::file::mmap_file(
427 security_server,
428 current_task,
429 file,
430 protection_flags,
431 options,
432 )
433 })
434}
435
436pub fn file_mprotect(
440 current_task: &CurrentTask,
441 range: &Range<UserAddress>,
442 mapping: &Mapping,
443 prot: ProtectionFlags,
444) -> Result<(), Errno> {
445 track_hook_duration!("security.hooks.file_mprotect");
446 if_selinux_else_default_ok(current_task, |security_server| {
447 selinux_hooks::file::file_mprotect(security_server, current_task, range, mapping, prot)
448 })
449}
450
451pub fn file_permission(
454 current_task: &CurrentTask,
455 file: &FileObject,
456 permission_flags: PermissionFlags,
457) -> Result<(), Errno> {
458 track_hook_duration!("security.hooks.file_permission");
459 if_selinux_else_default_ok(current_task, |security_server| {
460 selinux_hooks::file::file_permission(security_server, current_task, file, permission_flags)
461 })
462}
463
464pub fn fs_node_init_with_dentry<L>(
470 locked: &mut Locked<L>,
471 current_task: &CurrentTask,
472 dir_entry: &DirEntryHandle,
473) -> Result<(), Errno>
474where
475 L: LockEqualOrBefore<FileOpsCore>,
476{
477 track_hook_duration!("security.hooks.fs_node_init_with_dentry");
478 if let Some(state) = ¤t_task.kernel().security_state.state {
483 selinux_hooks::fs_node::fs_node_init_with_dentry(
484 Some(locked.cast_locked()),
485 &state.server,
486 current_task,
487 dir_entry,
488 )
489 } else {
490 Ok(())
491 }
492}
493
494pub fn fs_node_init_with_dentry_no_xattr(
495 current_task: &CurrentTask,
496 dir_entry: &DirEntryHandle,
497) -> Result<(), Errno> {
498 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
499 if let Some(state) = ¤t_task.kernel().security_state.state {
504 if Anon::is_private(&dir_entry.node) {
507 return selinux_hooks::fs_node::fs_node_init_anon(
508 &state.server,
509 current_task,
510 &dir_entry.node,
511 "",
512 );
513 }
514
515 selinux_hooks::fs_node::fs_node_init_with_dentry(
516 None,
517 &state.server,
518 current_task,
519 dir_entry,
520 )
521 } else {
522 Ok(())
523 }
524}
525
526pub fn fs_node_init_with_dentry_deferred(kernel: &Kernel, dir_entry: &DirEntryHandle) {
530 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
531 if kernel.security_state.state.is_some() {
532 selinux_hooks::fs_node::fs_node_init_with_dentry_deferred(dir_entry);
533 }
534}
535
536pub fn fs_node_notify_security_context(
543 current_task: &CurrentTask,
544 fs_node: &FsNode,
545 context: &FsStr,
546) -> Result<(), Errno> {
547 if_selinux_else(
548 current_task,
549 |security_server| {
550 selinux_hooks::fs_node::fs_node_notify_security_context(
551 security_server,
552 fs_node,
553 context,
554 )
555 },
556 || error!(ENOTSUP),
557 )
558}
559
560pub fn fs_node_init_on_create(
572 current_task: &CurrentTask,
573 new_node: &FsNode,
574 parent: &FsNode,
575 name: &FsStr,
576) -> Result<Option<FsNodeSecurityXattr>, Errno> {
577 track_hook_duration!("security.hooks.fs_node_init_on_create");
578 if_selinux_else_default_ok(current_task, |security_server| {
579 selinux_hooks::fs_node::fs_node_init_on_create(
580 security_server,
581 current_task,
582 new_node,
583 Some(parent),
584 name,
585 )
586 })
587}
588
589pub fn fs_node_init_anon(
594 current_task: &CurrentTask,
595 new_node: &FsNode,
596 node_type: &str,
597) -> Result<(), Errno> {
598 track_hook_duration!("security.hooks.fs_node_init_anon");
599 if let Some(state) = current_task.kernel().security_state.state.as_ref() {
600 selinux_hooks::fs_node::fs_node_init_anon(&state.server, current_task, new_node, node_type)
601 } else {
602 Ok(())
603 }
604}
605
606pub fn check_fs_node_create_access(
610 current_task: &CurrentTask,
611 parent: &FsNode,
612 mode: FileMode,
613 name: &FsStr,
614) -> Result<(), Errno> {
615 track_hook_duration!("security.hooks.check_fs_node_create_access");
616 if_selinux_else_default_ok(current_task, |security_server| {
617 selinux_hooks::fs_node::check_fs_node_create_access(
618 security_server,
619 current_task,
620 parent,
621 mode,
622 name,
623 )
624 })
625}
626
627pub fn check_fs_node_symlink_access(
631 current_task: &CurrentTask,
632 parent: &FsNode,
633 name: &FsStr,
634 old_path: &FsStr,
635) -> Result<(), Errno> {
636 track_hook_duration!("security.hooks.check_fs_node_symlink_access");
637 if_selinux_else_default_ok(current_task, |security_server| {
638 selinux_hooks::fs_node::check_fs_node_symlink_access(
639 security_server,
640 current_task,
641 parent,
642 name,
643 old_path,
644 )
645 })
646}
647
648pub fn check_fs_node_mkdir_access(
652 current_task: &CurrentTask,
653 parent: &FsNode,
654 mode: FileMode,
655 name: &FsStr,
656) -> Result<(), Errno> {
657 track_hook_duration!("security.hooks.check_fs_node_mkdir_access");
658 if_selinux_else_default_ok(current_task, |security_server| {
659 selinux_hooks::fs_node::check_fs_node_mkdir_access(
660 security_server,
661 current_task,
662 parent,
663 mode,
664 name,
665 )
666 })
667}
668
669pub fn check_fs_node_mknod_access(
675 current_task: &CurrentTask,
676 parent: &FsNode,
677 mode: FileMode,
678 name: &FsStr,
679 device_id: DeviceType,
680) -> Result<(), Errno> {
681 track_hook_duration!("security.hooks.check_fs_node_mknod_access");
682 assert!(!mode.is_reg());
683
684 if_selinux_else_default_ok(current_task, |security_server| {
685 selinux_hooks::fs_node::check_fs_node_mknod_access(
686 security_server,
687 current_task,
688 parent,
689 mode,
690 name,
691 device_id,
692 )
693 })
694}
695
696pub fn check_fs_node_link_access(
699 current_task: &CurrentTask,
700 parent: &FsNode,
701 child: &FsNode,
702) -> Result<(), Errno> {
703 track_hook_duration!("security.hooks.check_fs_node_link_access");
704 if_selinux_else_default_ok(current_task, |security_server| {
705 selinux_hooks::fs_node::check_fs_node_link_access(
706 security_server,
707 current_task,
708 parent,
709 child,
710 )
711 })
712}
713
714pub fn check_fs_node_unlink_access(
717 current_task: &CurrentTask,
718 parent: &FsNode,
719 child: &FsNode,
720 name: &FsStr,
721) -> Result<(), Errno> {
722 track_hook_duration!("security.hooks.check_fs_node_unlink_access");
723 if_selinux_else_default_ok(current_task, |security_server| {
724 selinux_hooks::fs_node::check_fs_node_unlink_access(
725 security_server,
726 current_task,
727 parent,
728 child,
729 name,
730 )
731 })
732}
733
734pub fn check_fs_node_rmdir_access(
737 current_task: &CurrentTask,
738 parent: &FsNode,
739 child: &FsNode,
740 name: &FsStr,
741) -> Result<(), Errno> {
742 track_hook_duration!("security.hooks.check_fs_node_rmdir_access");
743 if_selinux_else_default_ok(current_task, |security_server| {
744 selinux_hooks::fs_node::check_fs_node_rmdir_access(
745 security_server,
746 current_task,
747 parent,
748 child,
749 name,
750 )
751 })
752}
753
754pub fn check_fs_node_rename_access(
759 current_task: &CurrentTask,
760 old_parent: &FsNode,
761 moving_node: &FsNode,
762 new_parent: &FsNode,
763 replaced_node: Option<&FsNode>,
764 old_basename: &FsStr,
765 new_basename: &FsStr,
766) -> Result<(), Errno> {
767 track_hook_duration!("security.hooks.check_fs_node_rename_access");
768 if_selinux_else_default_ok(current_task, |security_server| {
769 selinux_hooks::fs_node::check_fs_node_rename_access(
770 security_server,
771 current_task,
772 old_parent,
773 moving_node,
774 new_parent,
775 replaced_node,
776 old_basename,
777 new_basename,
778 )
779 })
780}
781
782pub fn check_fs_node_read_link_access(
785 current_task: &CurrentTask,
786 fs_node: &FsNode,
787) -> Result<(), Errno> {
788 track_hook_duration!("security.hooks.check_fs_node_read_link_access");
789 if_selinux_else_default_ok(current_task, |security_server| {
790 selinux_hooks::fs_node::check_fs_node_read_link_access(
791 security_server,
792 current_task,
793 fs_node,
794 )
795 })
796}
797
798pub fn fs_node_permission(
801 current_task: &CurrentTask,
802 fs_node: &FsNode,
803 permission_flags: PermissionFlags,
804 audit_context: Auditable<'_>,
805) -> Result<(), Errno> {
806 track_hook_duration!("security.hooks.fs_node_permission");
807 if_selinux_else_default_ok(current_task, |security_server| {
808 selinux_hooks::fs_node::fs_node_permission(
809 security_server,
810 current_task,
811 fs_node,
812 permission_flags,
813 audit_context,
814 )
815 })
816}
817
818pub fn file_receive(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
821 track_hook_duration!("security.hooks.file_receive");
822 if_selinux_else_default_ok(current_task, |security_server| {
823 let receiving_sid = current_task_state(current_task).lock().current_sid;
824 selinux_hooks::file::file_receive(security_server, current_task, receiving_sid, file)
825 })
826}
827
828pub fn file_alloc_security(current_task: &CurrentTask) -> FileObjectState {
831 track_hook_duration!("security.hooks.file_alloc_security");
832 FileObjectState { state: selinux_hooks::file::file_alloc_security(current_task) }
833}
834
835pub fn binder_connection_alloc(current_task: &CurrentTask) -> BinderConnectionState {
838 track_hook_duration!("security.hooks.binder_connection_alloc");
839 BinderConnectionState { state: selinux_hooks::binder::binder_connection_alloc(current_task) }
840}
841
842pub fn bpf_map_alloc(current_task: &CurrentTask) -> BpfMapState {
846 track_hook_duration!("security.hooks.bpf_map_alloc");
847 BpfMapState { state: selinux_hooks::bpf::bpf_map_alloc(current_task) }
848}
849
850pub fn bpf_prog_alloc(current_task: &CurrentTask) -> BpfProgState {
854 track_hook_duration!("security.hooks.bpf_prog_alloc");
855 BpfProgState { state: selinux_hooks::bpf::bpf_prog_alloc(current_task) }
856}
857
858pub fn check_file_ioctl_access(
861 current_task: &CurrentTask,
862 file: &FileObject,
863 request: u32,
864) -> Result<(), Errno> {
865 track_hook_duration!("security.hooks.check_file_ioctl_access");
866 if_selinux_else_default_ok(current_task, |security_server| {
867 selinux_hooks::file::check_file_ioctl_access(security_server, current_task, file, request)
868 })
869}
870
871pub fn fs_node_copy_up<R>(
877 current_task: &CurrentTask,
878 fs_node: &FsNode,
879 do_copy_up: impl FnOnce() -> R,
880) -> R {
881 if_selinux_else_with_context(
882 do_copy_up,
883 current_task,
884 |do_copy_up, _security_server| {
885 selinux_hooks::fs_node::fs_node_copy_up(current_task, fs_node, do_copy_up)
886 },
887 |do_copy_up| do_copy_up(),
888 )
889}
890
891pub fn check_file_lock_access(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
899 track_hook_duration!("security.hooks.check_file_lock_access");
900 if_selinux_else_default_ok(current_task, |security_server| {
901 selinux_hooks::file::check_file_lock_access(security_server, current_task, file)
902 })
903}
904
905pub fn check_file_fcntl_access(
908 current_task: &CurrentTask,
909 file: &FileObject,
910 fcntl_cmd: u32,
911 fcntl_arg: u64,
912) -> Result<(), Errno> {
913 track_hook_duration!("security.hooks.check_file_fcntl_access");
914 if_selinux_else_default_ok(current_task, |security_server| {
915 selinux_hooks::file::check_file_fcntl_access(
916 security_server,
917 current_task,
918 file,
919 fcntl_cmd,
920 fcntl_arg,
921 )
922 })
923}
924
925pub fn check_fs_node_setattr_access(
928 current_task: &CurrentTask,
929 node: &FsNode,
930 attributes: &zxio_node_attr_has_t,
931) -> Result<(), Errno> {
932 track_hook_duration!("security.hooks.check_fs_node_setattr_access");
933 if_selinux_else_default_ok(current_task, |security_server| {
934 selinux_hooks::fs_node::check_fs_node_setattr_access(
935 security_server,
936 current_task,
937 node,
938 attributes,
939 )
940 })
941}
942
943pub fn task_alloc_for_kernel() -> TaskState {
946 track_hook_duration!("security.hooks.task_alloc_for_kernel");
947 TaskState(Arc::new(selinux_hooks::TaskAttrs::for_kernel().into()))
948}
949
950pub fn task_alloc(current_task: &CurrentTask, clone_flags: u64) -> TaskState {
954 track_hook_duration!("security.hooks.task_alloc");
955 TaskState(Arc::new(selinux_hooks::task::task_alloc(current_task, clone_flags).into()))
956}
957
958pub fn task_to_fs_node(current_task: &CurrentTask, task: &TempRef<'_, Task>, fs_node: &FsNode) {
964 track_hook_duration!("security.hooks.task_to_fs_node");
965 if current_task.kernel().security_state.state.is_some() {
968 selinux_hooks::task::fs_node_init_with_task(task, &fs_node);
969 }
970}
971
972pub fn task_for_context(task: &Task, context: &FsStr) -> Result<TaskState, Errno> {
978 track_hook_duration!("security.hooks.task_for_context");
979 Ok(TaskState(Arc::new(
980 if let Some(kernel_state) = task.kernel().security_state.state.as_ref() {
981 selinux_hooks::task::task_alloc_from_context(&kernel_state.server, context)
982 } else {
983 Ok(selinux_hooks::TaskAttrs::for_selinux_disabled())
984 }?
985 .into(),
986 )))
987}
988
989pub fn has_dontaudit_access(current_task: &CurrentTask, fs_node: &FsNode) -> bool {
993 track_hook_duration!("security.hooks.has_dontaudit_access");
994 if_selinux_else(
995 current_task,
996 |security_server| {
997 selinux_hooks::fs_node::has_dontaudit_access(security_server, current_task, fs_node)
998 },
999 || false,
1000 )
1001}
1002
1003pub fn is_task_capable_noaudit(
1006 current_task: &CurrentTask,
1007 capability: starnix_uapi::auth::Capabilities,
1008) -> bool {
1009 track_hook_duration!("security.hooks.is_task_capable_noaudit");
1010 return common_cap::capable(current_task, capability).is_ok()
1011 && if_selinux_else(
1012 current_task,
1013 |security_server| {
1014 selinux_hooks::task::is_task_capable_noaudit(
1015 &security_server.as_permission_check(),
1016 ¤t_task,
1017 capability,
1018 )
1019 },
1020 || true,
1021 );
1022}
1023
1024pub fn check_task_capable(
1027 current_task: &CurrentTask,
1028 capability: starnix_uapi::auth::Capabilities,
1029) -> Result<(), Errno> {
1030 track_hook_duration!("security.hooks.check_task_capable");
1031 common_cap::capable(current_task, capability)?;
1032 if_selinux_else_default_ok(current_task, |security_server| {
1033 selinux_hooks::task::check_task_capable(
1034 &security_server.as_permission_check(),
1035 ¤t_task,
1036 capability,
1037 )
1038 })
1039}
1040
1041pub fn check_task_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1047 track_hook_duration!("security.hooks.check_task_create_access");
1048 if_selinux_else_default_ok(current_task, |security_server| {
1049 selinux_hooks::task::check_task_create_access(
1050 &security_server.as_permission_check(),
1051 current_task,
1052 )
1053 })
1054}
1055
1056pub fn bprm_creds_for_exec(
1061 current_task: &CurrentTask,
1062 executable: &NamespaceNode,
1063) -> Result<ResolvedElfState, Errno> {
1064 track_hook_duration!("security.hooks.bprm_creds_for_exec");
1065 if_selinux_else(
1066 current_task,
1067 |security_server| {
1068 selinux_hooks::task::bprm_creds_for_exec(&security_server, current_task, executable)
1069 },
1070 || Ok(ResolvedElfState { sid: None, require_secure_exec: false }),
1071 )
1072}
1073
1074pub fn check_socket_create_access<L>(
1077 locked: &mut Locked<L>,
1078 current_task: &CurrentTask,
1079 domain: SocketDomain,
1080 socket_type: SocketType,
1081 protocol: SocketProtocol,
1082 kernel_private: bool,
1083) -> Result<(), Errno>
1084where
1085 L: LockEqualOrBefore<FileOpsCore>,
1086{
1087 track_hook_duration!("security.hooks.socket_create");
1088 if_selinux_else_default_ok(current_task, |security_server| {
1089 selinux_hooks::socket::check_socket_create_access(
1090 locked,
1091 &security_server,
1092 current_task,
1093 domain,
1094 socket_type,
1095 protocol,
1096 kernel_private,
1097 )
1098 })
1099}
1100
1101pub fn socket_socketpair(
1104 current_task: &CurrentTask,
1105 left: DowncastedFile<'_, SocketFile>,
1106 right: DowncastedFile<'_, SocketFile>,
1107) -> Result<(), Errno> {
1108 track_hook_duration!("security.hooks.socket_socketpair");
1109 if_selinux_else_default_ok(current_task, |_| {
1110 selinux_hooks::socket::socket_socketpair(left, right)
1111 })
1112}
1113
1114pub fn socket_post_create(socket: &Socket) {
1117 track_hook_duration!("security.hooks.socket_post_create");
1118 selinux_hooks::socket::socket_post_create(socket);
1119}
1120
1121pub fn check_socket_bind_access(
1124 current_task: &CurrentTask,
1125 socket: &Socket,
1126 socket_address: &SocketAddress,
1127) -> Result<(), Errno> {
1128 track_hook_duration!("security.hooks.check_socket_bind_access");
1129 if_selinux_else_default_ok(current_task, |security_server| {
1130 selinux_hooks::socket::check_socket_bind_access(
1131 &security_server,
1132 current_task,
1133 socket,
1134 socket_address,
1135 )
1136 })
1137}
1138
1139pub fn check_socket_connect_access(
1142 current_task: &CurrentTask,
1143 socket: DowncastedFile<'_, SocketFile>,
1144 socket_peer: &SocketPeer,
1145) -> Result<(), Errno> {
1146 track_hook_duration!("security.hooks.check_socket_connect_access");
1147 if_selinux_else_default_ok(current_task, |security_server| {
1148 selinux_hooks::socket::check_socket_connect_access(
1149 &security_server,
1150 current_task,
1151 socket,
1152 socket_peer,
1153 )
1154 })
1155}
1156
1157pub fn check_socket_listen_access(
1160 current_task: &CurrentTask,
1161 socket: &Socket,
1162 backlog: i32,
1163) -> Result<(), Errno> {
1164 track_hook_duration!("security.hooks.check_socket_listen_access");
1165 if_selinux_else_default_ok(current_task, |security_server| {
1166 selinux_hooks::socket::check_socket_listen_access(
1167 &security_server,
1168 current_task,
1169 socket,
1170 backlog,
1171 )
1172 })
1173}
1174
1175pub fn socket_accept(
1179 current_task: &CurrentTask,
1180 listening_socket: DowncastedFile<'_, SocketFile>,
1181 accepted_socket: DowncastedFile<'_, SocketFile>,
1182) -> Result<(), Errno> {
1183 track_hook_duration!("security.hooks.check_socket_getname_access");
1184 if_selinux_else_default_ok(current_task, |security_server| {
1185 selinux_hooks::socket::socket_accept(
1186 &security_server,
1187 current_task,
1188 listening_socket,
1189 accepted_socket,
1190 )
1191 })
1192}
1193
1194pub fn check_socket_getsockopt_access(
1197 current_task: &CurrentTask,
1198 socket: &Socket,
1199 level: u32,
1200 optname: u32,
1201) -> Result<(), Errno> {
1202 track_hook_duration!("security.hooks.check_socket_getsockopt_access");
1203 if_selinux_else_default_ok(current_task, |security_server| {
1204 selinux_hooks::socket::check_socket_getsockopt_access(
1205 &security_server,
1206 current_task,
1207 socket,
1208 level,
1209 optname,
1210 )
1211 })
1212}
1213
1214pub fn check_socket_setsockopt_access(
1217 current_task: &CurrentTask,
1218 socket: &Socket,
1219 level: u32,
1220 optname: u32,
1221) -> Result<(), Errno> {
1222 track_hook_duration!("security.hooks.check_socket_setsockopt_access");
1223 if_selinux_else_default_ok(current_task, |security_server| {
1224 selinux_hooks::socket::check_socket_setsockopt_access(
1225 &security_server,
1226 current_task,
1227 socket,
1228 level,
1229 optname,
1230 )
1231 })
1232}
1233
1234pub fn check_socket_sendmsg_access(
1237 current_task: &CurrentTask,
1238 socket: &Socket,
1239) -> Result<(), Errno> {
1240 track_hook_duration!("security.hooks.check_socket_sendmsg_access");
1241 if_selinux_else_default_ok(current_task, |security_server| {
1242 selinux_hooks::socket::check_socket_sendmsg_access(&security_server, current_task, socket)
1243 })
1244}
1245
1246pub fn check_socket_recvmsg_access(
1249 current_task: &CurrentTask,
1250 socket: &Socket,
1251) -> Result<(), Errno> {
1252 track_hook_duration!("security.hooks.check_socket_recvmsg_access");
1253 if_selinux_else_default_ok(current_task, |security_server| {
1254 selinux_hooks::socket::check_socket_recvmsg_access(&security_server, current_task, socket)
1255 })
1256}
1257
1258pub fn check_socket_getsockname_access(
1261 current_task: &CurrentTask,
1262 socket: &Socket,
1263) -> Result<(), Errno> {
1264 track_hook_duration!("security.hooks.check_socket_getname_access");
1265 if_selinux_else_default_ok(current_task, |security_server| {
1266 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1267 })
1268}
1269
1270pub fn check_socket_getpeername_access(
1273 current_task: &CurrentTask,
1274 socket: &Socket,
1275) -> Result<(), Errno> {
1276 track_hook_duration!("security.hooks.check_socket_getname_access");
1277 if_selinux_else_default_ok(current_task, |security_server| {
1278 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1279 })
1280}
1281
1282pub fn check_socket_shutdown_access(
1285 current_task: &CurrentTask,
1286 socket: &Socket,
1287 how: SocketShutdownFlags,
1288) -> Result<(), Errno> {
1289 track_hook_duration!("security.hooks.check_socket_shutdown_access");
1290 if_selinux_else_default_ok(current_task, |security_server| {
1291 selinux_hooks::socket::check_socket_shutdown_access(
1292 &security_server,
1293 current_task,
1294 socket,
1295 how,
1296 )
1297 })
1298}
1299
1300pub fn socket_getpeersec_stream(
1303 current_task: &CurrentTask,
1304 socket: &Socket,
1305) -> Result<Vec<u8>, Errno> {
1306 track_hook_duration!("security.hooks.socket_getpeersec_stream");
1307 if_selinux_else_default_ok(current_task, |security_server| {
1308 selinux_hooks::socket::socket_getpeersec_stream(&security_server, current_task, socket)
1309 })
1310}
1311
1312pub fn socket_getpeersec_dgram(current_task: &CurrentTask, socket: &Socket) -> Vec<u8> {
1316 track_hook_duration!("security.hooks.socket_getpeersec_dgram");
1317 if_selinux_else(
1318 current_task,
1319 |security_server| {
1320 selinux_hooks::socket::socket_getpeersec_dgram(&security_server, current_task, socket)
1321 },
1322 Vec::default,
1323 )
1324}
1325
1326pub fn unix_may_send(
1330 current_task: &CurrentTask,
1331 sending_socket: &Socket,
1332 receiving_socket: &Socket,
1333) -> Result<(), Errno> {
1334 track_hook_duration!("security.hooks.unix_may_send");
1335 if_selinux_else_default_ok(current_task, |security_server| {
1336 selinux_hooks::socket::unix_may_send(
1337 &security_server,
1338 current_task,
1339 sending_socket,
1340 receiving_socket,
1341 )
1342 })
1343}
1344
1345pub fn unix_stream_connect(
1349 current_task: &CurrentTask,
1350 client_socket: &Socket,
1351 listening_socket: &Socket,
1352 server_socket: &Socket,
1353) -> Result<(), Errno> {
1354 track_hook_duration!("security.hooks.unix_stream_connect");
1355 if_selinux_else_default_ok(current_task, |security_server| {
1356 selinux_hooks::socket::unix_stream_connect(
1357 &security_server,
1358 current_task,
1359 client_socket,
1360 listening_socket,
1361 server_socket,
1362 )
1363 })
1364}
1365
1366pub fn check_netlink_send_access(
1370 current_task: &CurrentTask,
1371 socket: &Socket,
1372 message_type: u16,
1373) -> Result<(), Errno> {
1374 track_hook_duration!("security.hooks.check_netlink_send_access");
1375 if_selinux_else_default_ok(current_task, |security_server| {
1376 selinux_hooks::netlink_socket::check_netlink_send_access(
1377 &security_server,
1378 current_task,
1379 socket,
1380 message_type,
1381 )
1382 })
1383}
1384
1385pub fn check_tun_dev_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1388 track_hook_duration!("security.hooks.check_tun_dev_create_access");
1389 if_selinux_else_default_ok(current_task, |security_server| {
1390 selinux_hooks::socket::check_tun_dev_create_access(&security_server, current_task)
1391 })
1392}
1393
1394pub fn exec_binprm(
1400 locked: &mut Locked<Unlocked>,
1401 current_task: &CurrentTask,
1402 elf_security_state: &ResolvedElfState,
1403) {
1404 track_hook_duration!("security.hooks.exec_binprm");
1405 if_selinux_else(
1406 current_task,
1407 |security_server| {
1408 selinux_hooks::task::exec_binprm(
1409 locked,
1410 security_server,
1411 current_task,
1412 elf_security_state,
1413 )
1414 },
1415 || (),
1416 );
1417}
1418
1419pub fn check_getsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1422 track_hook_duration!("security.hooks.check_getsched_access");
1423 if_selinux_else_default_ok(source, |security_server| {
1424 selinux_hooks::task::check_getsched_access(
1425 &security_server.as_permission_check(),
1426 &source,
1427 &target,
1428 )
1429 })
1430}
1431
1432pub fn check_setsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1435 track_hook_duration!("security.hooks.check_setsched_access");
1436 if_selinux_else_default_ok(source, |security_server| {
1437 selinux_hooks::task::check_setsched_access(
1438 &security_server.as_permission_check(),
1439 &source,
1440 &target,
1441 )
1442 })
1443}
1444
1445pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1448 track_hook_duration!("security.hooks.check_getpgid_access");
1449 if_selinux_else_default_ok(source, |security_server| {
1450 selinux_hooks::task::check_getpgid_access(
1451 &security_server.as_permission_check(),
1452 &source,
1453 &target,
1454 )
1455 })
1456}
1457
1458pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1461 track_hook_duration!("security.hooks.check_setpgid_access");
1462 if_selinux_else_default_ok(source, |security_server| {
1463 selinux_hooks::task::check_setpgid_access(
1464 &security_server.as_permission_check(),
1465 &source,
1466 &target,
1467 )
1468 })
1469}
1470
1471pub fn check_task_getsid(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1474 track_hook_duration!("security.hooks.check_task_getsid");
1475 if_selinux_else_default_ok(source, |security_server| {
1476 selinux_hooks::task::check_task_getsid(
1477 &security_server.as_permission_check(),
1478 &source,
1479 &target,
1480 )
1481 })
1482}
1483
1484pub fn check_getcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1487 track_hook_duration!("security.hooks.check_getcap_access");
1488 if_selinux_else_default_ok(source, |security_server| {
1489 selinux_hooks::task::check_getcap_access(
1490 &security_server.as_permission_check(),
1491 &source,
1492 &target,
1493 )
1494 })
1495}
1496
1497pub fn check_setcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1501 track_hook_duration!("security.hooks.check_setcap_access");
1502 if_selinux_else_default_ok(source, |security_server| {
1503 selinux_hooks::task::check_setcap_access(
1504 &security_server.as_permission_check(),
1505 &source,
1506 &target,
1507 )
1508 })
1509}
1510
1511pub fn check_signal_access(
1514 source: &CurrentTask,
1515 target: &Task,
1516 signal: Signal,
1517) -> Result<(), Errno> {
1518 track_hook_duration!("security.hooks.check_signal_access");
1519 if_selinux_else_default_ok(source, |security_server| {
1520 selinux_hooks::task::check_signal_access(
1521 &security_server.as_permission_check(),
1522 &source,
1523 &target,
1524 signal,
1525 )
1526 })
1527}
1528
1529pub fn check_syslog_access(source: &CurrentTask, action: SyslogAction) -> Result<(), Errno> {
1532 track_hook_duration!("security.hooks.check_syslog_access");
1533 if_selinux_else_default_ok(source, |security_server| {
1534 selinux_hooks::task::check_syslog_access(
1535 &security_server.as_permission_check(),
1536 &source,
1537 action,
1538 )
1539 })
1540}
1541
1542pub fn ptrace_traceme(current_task: &CurrentTask, parent_tracer_task: &Task) -> Result<(), Errno> {
1545 track_hook_duration!("security.hooks.ptrace_traceme");
1546 yama::ptrace_traceme(current_task, parent_tracer_task)?;
1547 common_cap::ptrace_traceme(current_task, parent_tracer_task)?;
1548 if_selinux_else_default_ok(current_task, |security_server| {
1549 selinux_hooks::task::ptrace_traceme(
1550 &security_server.as_permission_check(),
1551 current_task,
1552 parent_tracer_task,
1553 )
1554 })
1555}
1556
1557pub fn ptrace_access_check(
1560 current_task: &CurrentTask,
1561 tracee_task: &Task,
1562 mode: PtraceAccessMode,
1563) -> Result<(), Errno> {
1564 track_hook_duration!("security.hooks.ptrace_access_check");
1565 yama::ptrace_access_check(current_task, tracee_task, mode)?;
1566 common_cap::ptrace_access_check(current_task, tracee_task, mode)?;
1567 if_selinux_else_default_ok(current_task, |security_server| {
1568 selinux_hooks::task::ptrace_access_check(
1569 &security_server.as_permission_check(),
1570 current_task,
1571 tracee_task,
1572 mode,
1573 )
1574 })
1575}
1576
1577pub fn task_prlimit(
1580 source: &CurrentTask,
1581 target: &Task,
1582 check_get_rlimit: bool,
1583 check_set_rlimit: bool,
1584) -> Result<(), Errno> {
1585 track_hook_duration!("security.hooks.task_prlimit");
1586 if_selinux_else_default_ok(source, |security_server| {
1587 selinux_hooks::task::task_prlimit(
1588 &security_server.as_permission_check(),
1589 &source,
1590 &target,
1591 check_get_rlimit,
1592 check_set_rlimit,
1593 )
1594 })
1595}
1596
1597pub fn task_setrlimit(
1600 source: &CurrentTask,
1601 target: &Task,
1602 old_limit: rlimit,
1603 new_limit: rlimit,
1604) -> Result<(), Errno> {
1605 track_hook_duration!("security.hooks.task_setrlimit");
1606 if_selinux_else_default_ok(source, |security_server| {
1607 selinux_hooks::task::task_setrlimit(
1608 &security_server.as_permission_check(),
1609 &source,
1610 &target,
1611 old_limit,
1612 new_limit,
1613 )
1614 })
1615}
1616
1617pub fn sb_kern_mount(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1620 track_hook_duration!("security.hooks.sb_kern_mount");
1621 if_selinux_else_default_ok(current_task, |security_server| {
1622 selinux_hooks::superblock::sb_kern_mount(
1623 &security_server.as_permission_check(),
1624 current_task,
1625 fs,
1626 )
1627 })
1628}
1629
1630pub fn sb_mount(
1634 current_task: &CurrentTask,
1635 path: &NamespaceNode,
1636 flags: MountFlags,
1637) -> Result<(), Errno> {
1638 track_hook_duration!("security.hooks.sb_mount");
1639 if_selinux_else_default_ok(current_task, |security_server| {
1640 selinux_hooks::superblock::sb_mount(
1641 &security_server.as_permission_check(),
1642 current_task,
1643 path,
1644 flags,
1645 )
1646 })
1647}
1648
1649pub fn sb_remount(
1652 current_task: &CurrentTask,
1653 mount: &Mount,
1654 new_mount_options: FileSystemMountOptions,
1655) -> Result<(), Errno> {
1656 track_hook_duration!("security.hooks.sb_remount");
1657 if_selinux_else_default_ok(current_task, |security_server| {
1658 selinux_hooks::superblock::sb_remount(security_server, mount, new_mount_options)
1659 })
1660}
1661
1662pub fn sb_show_options(
1665 kernel: &Kernel,
1666 buf: &mut impl OutputBuffer,
1667 mount: &Mount,
1668) -> Result<(), Errno> {
1669 track_hook_duration!("security.hooks.sb_show_options");
1670 if let Some(state) = &kernel.security_state.state {
1671 selinux_hooks::superblock::sb_show_options(&state.server, buf, mount)?;
1672 }
1673 Ok(())
1674}
1675
1676pub fn sb_statfs(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1679 track_hook_duration!("security.hooks.sb_statfs");
1680 if_selinux_else_default_ok(current_task, |security_server| {
1681 selinux_hooks::superblock::sb_statfs(
1682 &security_server.as_permission_check(),
1683 current_task,
1684 fs,
1685 )
1686 })
1687}
1688
1689pub fn sb_umount(
1693 current_task: &CurrentTask,
1694 node: &NamespaceNode,
1695 flags: UnmountFlags,
1696) -> Result<(), Errno> {
1697 track_hook_duration!("security.hooks.sb_umount");
1698 if_selinux_else_default_ok(current_task, |security_server| {
1699 selinux_hooks::superblock::sb_umount(
1700 &security_server.as_permission_check(),
1701 current_task,
1702 node,
1703 flags,
1704 )
1705 })
1706}
1707
1708pub fn check_fs_node_getattr_access(
1711 current_task: &CurrentTask,
1712 fs_node: &FsNode,
1713) -> Result<(), Errno> {
1714 track_hook_duration!("security.hooks.check_fs_node_getattr_access");
1715 if_selinux_else_default_ok(current_task, |security_server| {
1716 selinux_hooks::fs_node::check_fs_node_getattr_access(security_server, current_task, fs_node)
1717 })
1718}
1719
1720pub fn fs_node_xattr_skipcap(_current_task: &CurrentTask, name: &FsStr) -> bool {
1723 selinux_hooks::fs_node::fs_node_xattr_skipcap(name)
1724}
1725
1726pub fn check_fs_node_setxattr_access(
1732 current_task: &CurrentTask,
1733 fs_node: &FsNode,
1734 name: &FsStr,
1735 value: &FsStr,
1736 op: XattrOp,
1737) -> Result<(), Errno> {
1738 track_hook_duration!("security.hooks.check_fs_node_setxattr_access");
1739 common_cap::fs_node_setxattr(current_task, fs_node, name, value, op)?;
1740 if_selinux_else_default_ok(current_task, |security_server| {
1741 selinux_hooks::fs_node::check_fs_node_setxattr_access(
1742 security_server,
1743 current_task,
1744 fs_node,
1745 name,
1746 value,
1747 op,
1748 )
1749 })
1750}
1751
1752pub fn check_fs_node_getxattr_access(
1754 current_task: &CurrentTask,
1755 fs_node: &FsNode,
1756 name: &FsStr,
1757) -> Result<(), Errno> {
1758 track_hook_duration!("security.hooks.check_fs_node_getxattr_access");
1759 if_selinux_else_default_ok(current_task, |security_server| {
1760 selinux_hooks::fs_node::check_fs_node_getxattr_access(
1761 security_server,
1762 current_task,
1763 fs_node,
1764 name,
1765 )
1766 })
1767}
1768
1769pub fn check_fs_node_listxattr_access(
1771 current_task: &CurrentTask,
1772 fs_node: &FsNode,
1773) -> Result<(), Errno> {
1774 track_hook_duration!("security.hooks.check_fs_node_listxattr_access");
1775 if_selinux_else_default_ok(current_task, |security_server| {
1776 selinux_hooks::fs_node::check_fs_node_listxattr_access(
1777 security_server,
1778 current_task,
1779 fs_node,
1780 )
1781 })
1782}
1783
1784pub fn check_fs_node_removexattr_access(
1786 current_task: &CurrentTask,
1787 fs_node: &FsNode,
1788 name: &FsStr,
1789) -> Result<(), Errno> {
1790 track_hook_duration!("security.hooks.check_fs_node_removexattr_access");
1791 common_cap::fs_node_removexattr(current_task, fs_node, name)?;
1792 if_selinux_else_default_ok(current_task, |security_server| {
1793 selinux_hooks::fs_node::check_fs_node_removexattr_access(
1794 security_server,
1795 current_task,
1796 fs_node,
1797 name,
1798 )
1799 })
1800}
1801
1802pub fn fs_node_listsecurity(current_task: &CurrentTask, fs_node: &FsNode) -> Option<FsString> {
1809 track_hook_duration!("security.hooks.fs_node_listsecurity");
1810 if_selinux_else(
1811 current_task,
1812 |_| selinux_hooks::fs_node::fs_node_listsecurity(fs_node),
1813 || None,
1814 )
1815}
1816
1817pub fn fs_node_getsecurity<L>(
1825 locked: &mut Locked<L>,
1826 current_task: &CurrentTask,
1827 fs_node: &FsNode,
1828 name: &FsStr,
1829 max_size: usize,
1830) -> Result<ValueOrSize<FsString>, Errno>
1831where
1832 L: LockEqualOrBefore<FileOpsCore>,
1833{
1834 track_hook_duration!("security.hooks.fs_node_getsecurity");
1835 if_selinux_else_with_context(
1836 locked,
1837 current_task,
1838 |locked, security_server| {
1839 selinux_hooks::fs_node::fs_node_getsecurity(
1840 locked,
1841 security_server,
1842 current_task,
1843 fs_node,
1844 name,
1845 max_size,
1846 )
1847 },
1848 |locked| {
1849 fs_node.ops().get_xattr(
1850 locked.cast_locked::<FileOpsCore>(),
1851 fs_node,
1852 current_task,
1853 name,
1854 max_size,
1855 )
1856 },
1857 )
1858}
1859
1860pub fn fs_node_setsecurity<L>(
1866 locked: &mut Locked<L>,
1867 current_task: &CurrentTask,
1868 fs_node: &FsNode,
1869 name: &FsStr,
1870 value: &FsStr,
1871 op: XattrOp,
1872) -> Result<(), Errno>
1873where
1874 L: LockEqualOrBefore<FileOpsCore>,
1875{
1876 track_hook_duration!("security.hooks.fs_node_setsecurity");
1877 if_selinux_else_with_context(
1878 locked,
1879 current_task,
1880 |locked, security_server| {
1881 selinux_hooks::fs_node::fs_node_setsecurity(
1882 locked,
1883 security_server,
1884 current_task,
1885 fs_node,
1886 name,
1887 value,
1888 op,
1889 )
1890 },
1891 |locked| {
1892 fs_node.ops().set_xattr(
1893 locked.cast_locked::<FileOpsCore>(),
1894 fs_node,
1895 current_task,
1896 name,
1897 value,
1898 op,
1899 )
1900 },
1901 )
1902}
1903
1904pub fn check_bpf_access<Attr: FromBytes>(
1908 current_task: &CurrentTask,
1909 cmd: bpf_cmd,
1910 attr: &Attr,
1911 attr_size: u32,
1912) -> Result<(), Errno> {
1913 track_hook_duration!("security.hooks.check_bpf_access");
1914 if_selinux_else_default_ok(current_task, |security_server| {
1915 selinux_hooks::bpf::check_bpf_access(security_server, current_task, cmd, attr, attr_size)
1916 })
1917}
1918
1919pub fn check_bpf_map_access(
1923 current_task: &CurrentTask,
1924 bpf_map: &BpfMap,
1925 flags: PermissionFlags,
1926) -> Result<(), Errno> {
1927 track_hook_duration!("security.hooks.check_bpf_map_access");
1928 if_selinux_else_default_ok(current_task, |security_server| {
1929 let subject_sid = current_task_state(current_task).lock().current_sid;
1930 selinux_hooks::bpf::check_bpf_map_access(
1931 security_server,
1932 current_task,
1933 subject_sid,
1934 bpf_map,
1935 flags,
1936 )
1937 })
1938}
1939
1940pub fn check_bpf_prog_access(
1945 current_task: &CurrentTask,
1946 bpf_program: &Program,
1947) -> Result<(), Errno> {
1948 track_hook_duration!("security.hooks.check_bpf_prog_access");
1949 if_selinux_else_default_ok(current_task, |security_server| {
1950 let subject_sid = current_task_state(current_task).lock().current_sid;
1951 selinux_hooks::bpf::check_bpf_prog_access(
1952 security_server,
1953 current_task,
1954 subject_sid,
1955 bpf_program,
1956 )
1957 })
1958}
1959
1960pub fn check_perf_event_open_access(
1964 current_task: &CurrentTask,
1965 target_task_type: TargetTaskType<'_>,
1966 attr: &perf_event_attr,
1967 event_type: PerfEventType,
1968) -> Result<(), Errno> {
1969 track_hook_duration!("security.hooks.check_perf_event_open_access");
1970 if_selinux_else_default_ok(current_task, |security_server| {
1971 selinux_hooks::perf_event::check_perf_event_open_access(
1972 security_server,
1973 current_task,
1974 target_task_type,
1975 attr,
1976 event_type,
1977 )
1978 })
1979}
1980
1981pub fn perf_event_alloc(current_task: &CurrentTask) -> PerfEventState {
1985 track_hook_duration!("security.hooks.perf_event_alloc");
1986 PerfEventState { state: selinux_hooks::perf_event::perf_event_alloc(current_task) }
1987}
1988
1989pub fn check_perf_event_read_access(
1992 current_task: &CurrentTask,
1993 perf_event_file: &PerfEventFile,
1994) -> Result<(), Errno> {
1995 track_hook_duration!("security.hooks.check_perf_event_read_access");
1996 if_selinux_else_default_ok(current_task, |security_server| {
1997 selinux_hooks::perf_event::check_perf_event_read_access(
1998 security_server,
1999 current_task,
2000 perf_event_file,
2001 )
2002 })
2003}
2004
2005pub fn check_perf_event_write_access(
2008 current_task: &CurrentTask,
2009 perf_event_file: &PerfEventFile,
2010) -> Result<(), Errno> {
2011 track_hook_duration!("security.hooks.check_perf_event_write_access");
2012 if_selinux_else_default_ok(current_task, |security_server| {
2013 selinux_hooks::perf_event::check_perf_event_write_access(
2014 security_server,
2015 current_task,
2016 perf_event_file,
2017 )
2018 })
2019}
2020
2021#[derive(Debug, Clone, Copy, PartialEq)]
2023pub enum ProcAttr {
2024 Current,
2025 Exec,
2026 FsCreate,
2027 KeyCreate,
2028 Previous,
2029 SockCreate,
2030}
2031
2032pub fn get_procattr(
2035 current_task: &CurrentTask,
2036 target: &Task,
2037 attr: ProcAttr,
2038) -> Result<Vec<u8>, Errno> {
2039 track_hook_duration!("security.hooks.get_procattr");
2040 if_selinux_else(
2041 current_task,
2042 |security_server| {
2043 selinux_hooks::task::get_procattr(security_server, current_task, target, attr)
2044 },
2045 || error!(EINVAL),
2047 )
2048}
2049
2050pub fn set_procattr(
2053 current_task: &CurrentTask,
2054 attr: ProcAttr,
2055 context: &[u8],
2056) -> Result<(), Errno> {
2057 track_hook_duration!("security.hooks.set_procattr");
2058 if_selinux_else(
2059 current_task,
2060 |security_server| {
2061 selinux_hooks::task::set_procattr(security_server, current_task, attr, context)
2062 },
2063 || error!(EINVAL),
2065 )
2066}
2067
2068pub fn fs_is_xattr_labeled(fs: FileSystemHandle) -> bool {
2070 fs.security_state.state.supports_xattr()
2071}
2072
2073pub fn selinuxfs_init_null(current_task: &CurrentTask, null_fs_node: &FileHandle) {
2076 selinux_hooks::selinuxfs::selinuxfs_init_null(current_task, null_fs_node)
2079}
2080
2081pub fn selinuxfs_policy_loaded<L>(locked: &mut Locked<L>, current_task: &CurrentTask)
2087where
2088 L: LockEqualOrBefore<FileOpsCore>,
2089{
2090 track_hook_duration!("security.hooks.selinuxfs_policy_loaded");
2091 selinux_hooks::selinuxfs::selinuxfs_policy_loaded(locked, current_task)
2092}
2093
2094pub fn selinuxfs_get_admin_api(current_task: &CurrentTask) -> Option<Arc<SecurityServer>> {
2098 current_task.kernel().security_state.state.as_ref().map(|state| state.server.clone())
2099}
2100
2101pub fn selinuxfs_check_access(
2104 current_task: &CurrentTask,
2105 permission: SecurityPermission,
2106) -> Result<(), Errno> {
2107 track_hook_duration!("security.hooks.selinuxfs_check_access");
2108 if_selinux_else_default_ok(current_task, |security_server| {
2109 selinux_hooks::selinuxfs::selinuxfs_check_access(security_server, current_task, permission)
2110 })
2111}
2112
2113pub fn creds_start_internal_operation(creds: &mut FullCredentials) {
2116 track_hook_duration!("security.hooks.creds_start_internal_operation");
2117 creds.security_state.lock().internal_operation = true;
2118}
2119
2120pub mod testing {
2121 use super::{Arc, KernelState, SecurityServer, selinux_hooks};
2122 use starnix_sync::Mutex;
2123 use std::sync::OnceLock;
2124 use std::sync::atomic::AtomicU64;
2125
2126 pub fn kernel_state(security_server: Option<Arc<SecurityServer>>) -> KernelState {
2129 let state = security_server.map(|server| selinux_hooks::KernelState {
2130 server,
2131 pending_file_systems: Mutex::default(),
2132 selinuxfs_null: OnceLock::default(),
2133 access_denial_count: AtomicU64::new(0u64),
2134 has_policy: false.into(),
2135 _inspect_node: fuchsia_inspect::Node::default(),
2136 });
2137 KernelState { state }
2138 }
2139}
2140
2141#[cfg(test)]
2142mod tests {
2143 use super::*;
2144 use crate::security::selinux_hooks::get_cached_sid;
2145 use crate::security::selinux_hooks::testing::{
2146 self, spawn_kernel_with_selinux_hooks_test_policy_and_run,
2147 };
2148 use crate::testing::{create_task, spawn_kernel_and_run, spawn_kernel_with_selinux_and_run};
2149 use linux_uapi::XATTR_NAME_SELINUX;
2150 use selinux::InitialSid;
2151 use starnix_uapi::auth::PTRACE_MODE_ATTACH;
2152 use starnix_uapi::signals::SIGTERM;
2153
2154 const VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_valid_t:s0";
2155 const VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] = b"u:object_r:test_valid_t:s0\0";
2156
2157 const DIFFERENT_VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_different_valid_t:s0";
2158 const DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] =
2159 b"u:object_r:test_different_valid_t:s0\0";
2160
2161 const INVALID_SECURITY_CONTEXT_INTERNAL_NUL: &[u8] = b"u:object_r:test_valid_\0t:s0";
2162
2163 const INVALID_SECURITY_CONTEXT: &[u8] = b"not_a_u:object_r:test_valid_t:s0";
2164
2165 #[derive(Default, Debug, PartialEq)]
2166 enum TestHookResult {
2167 WasRun,
2168 WasNotRun,
2169 #[default]
2170 WasNotRunDefault,
2171 }
2172
2173 #[fuchsia::test]
2174 async fn if_selinux_else_disabled() {
2175 spawn_kernel_and_run(async |_, current_task| {
2176 assert!(current_task.kernel().security_state.state.is_none());
2177
2178 let check_result =
2179 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2180 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2181
2182 let run_else_result = if_selinux_else(
2183 current_task,
2184 |_| TestHookResult::WasRun,
2185 || TestHookResult::WasNotRun,
2186 );
2187 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2188 })
2189 .await;
2190 }
2191
2192 #[fuchsia::test]
2193 async fn if_selinux_else_without_policy() {
2194 spawn_kernel_with_selinux_and_run(async |_locked, current_task, _security_server| {
2195 let check_result =
2196 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2197 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2198
2199 let run_else_result = if_selinux_else(
2200 current_task,
2201 |_| TestHookResult::WasRun,
2202 || TestHookResult::WasNotRun,
2203 );
2204 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2205 })
2206 .await;
2207 }
2208
2209 #[fuchsia::test]
2210 async fn if_selinux_else_with_policy() {
2211 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2212 |_locked, current_task, _security_server| {
2213 let check_result =
2214 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2215 assert_eq!(check_result, Ok(TestHookResult::WasRun));
2216
2217 let run_else_result = if_selinux_else(
2218 current_task,
2219 |_| TestHookResult::WasRun,
2220 || TestHookResult::WasNotRun,
2221 );
2222 assert_eq!(run_else_result, TestHookResult::WasRun);
2223 },
2224 )
2225 .await;
2226 }
2227
2228 #[fuchsia::test]
2229 async fn task_alloc_selinux_disabled() {
2230 spawn_kernel_and_run(async |_, current_task| {
2231 task_alloc(current_task, 0);
2232 })
2233 .await;
2234 }
2235
2236 #[fuchsia::test]
2237 async fn task_create_access_allowed_for_selinux_disabled() {
2238 spawn_kernel_and_run(async |_, current_task| {
2239 assert!(current_task.kernel().security_state.state.is_none());
2240 assert_eq!(check_task_create_access(current_task), Ok(()));
2241 })
2242 .await;
2243 }
2244
2245 #[fuchsia::test]
2246 async fn task_create_access_allowed_for_permissive_mode() {
2247 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2248 |_locked, current_task, security_server| {
2249 security_server.set_enforcing(false);
2250 assert_eq!(check_task_create_access(current_task), Ok(()));
2251 },
2252 )
2253 .await;
2254 }
2255
2256 #[fuchsia::test]
2257 async fn exec_access_allowed_for_selinux_disabled() {
2258 spawn_kernel_and_run(async |locked, current_task| {
2259 assert!(current_task.kernel().security_state.state.is_none());
2260 let executable = &testing::create_test_file(locked, current_task);
2261 assert_eq!(
2262 bprm_creds_for_exec(current_task, executable),
2263 Ok(ResolvedElfState { sid: None, require_secure_exec: false })
2264 );
2265 })
2266 .await;
2267 }
2268
2269 #[fuchsia::test]
2270 async fn exec_access_allowed_for_permissive_mode() {
2271 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2272 |locked, current_task, security_server| {
2273 security_server.set_enforcing(false);
2274 let executable = &testing::create_test_file(locked, current_task);
2275 let result = bprm_creds_for_exec(current_task, executable);
2277 assert!(result.expect("Exec check should succeed").sid.is_some());
2278 },
2279 )
2280 .await;
2281 }
2282
2283 #[fuchsia::test]
2284 async fn no_state_update_for_selinux_disabled() {
2285 spawn_kernel_and_run(async |locked, current_task| {
2286 let target_sid = InitialSid::Unlabeled.into();
2289 let elf_state = ResolvedElfState { sid: Some(target_sid), require_secure_exec: false };
2290
2291 assert!(
2292 selinux_hooks::current_task_state(current_task).lock().current_sid != target_sid
2293 );
2294
2295 let before_hook_sid =
2296 selinux_hooks::current_task_state(current_task).lock().current_sid;
2297 exec_binprm(locked, current_task, &elf_state);
2298 assert_eq!(
2299 selinux_hooks::current_task_state(current_task).lock().current_sid,
2300 before_hook_sid
2301 );
2302 assert_eq!(current_task.security_state.lock().current_sid, before_hook_sid)
2303 })
2304 .await;
2305 }
2306
2307 #[fuchsia::test]
2308 async fn no_state_update_for_selinux_without_policy() {
2309 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2310 let initial_state = current_task.security_state.lock().clone();
2313 let elf_sid = InitialSid::Unlabeled.into();
2314 let elf_state = ResolvedElfState { sid: Some(elf_sid), require_secure_exec: false };
2315 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).lock().current_sid);
2316 exec_binprm(locked, current_task, &elf_state);
2317 assert_eq!(*current_task.security_state.lock(), initial_state);
2318 })
2319 .await;
2320 }
2321
2322 #[fuchsia::test]
2323 async fn state_update_for_permissive_mode() {
2324 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2325 |locked, current_task, security_server| {
2326 security_server.set_enforcing(false);
2327 let initial_state = selinux_hooks::TaskAttrs::for_kernel();
2328 *current_task.security_state.lock() = initial_state.clone();
2329 let elf_sid = security_server
2330 .security_context_to_sid(b"u:object_r:fork_no_t:s0".into())
2331 .expect("invalid security context");
2332 let elf_state = ResolvedElfState { sid: Some(elf_sid), require_secure_exec: false };
2333 assert_ne!(
2334 elf_sid,
2335 selinux_hooks::current_task_state(current_task).lock().current_sid
2336 );
2337 exec_binprm(locked, current_task, &elf_state);
2338 assert_eq!(
2339 selinux_hooks::current_task_state(current_task).lock().current_sid,
2340 elf_sid
2341 );
2342 assert_eq!(current_task.security_state.lock().current_sid, elf_sid);
2343 },
2344 )
2345 .await;
2346 }
2347
2348 #[fuchsia::test]
2349 async fn getsched_access_allowed_for_selinux_disabled() {
2350 spawn_kernel_and_run(async |locked, current_task| {
2351 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2352 assert_eq!(check_getsched_access(current_task, &another_task), Ok(()));
2353 })
2354 .await;
2355 }
2356
2357 #[fuchsia::test]
2358 async fn getsched_access_allowed_for_permissive_mode() {
2359 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2360 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2361 assert_eq!(check_getsched_access(current_task, &another_task), Ok(()));
2362 })
2363 .await;
2364 }
2365
2366 #[fuchsia::test]
2367 async fn setsched_access_allowed_for_selinux_disabled() {
2368 spawn_kernel_and_run(async |locked, current_task| {
2369 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2370 assert_eq!(check_setsched_access(current_task, &another_task), Ok(()));
2371 })
2372 .await;
2373 }
2374
2375 #[fuchsia::test]
2376 async fn setsched_access_allowed_for_permissive_mode() {
2377 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2378 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2379 assert_eq!(check_setsched_access(current_task, &another_task), Ok(()));
2380 })
2381 .await;
2382 }
2383
2384 #[fuchsia::test]
2385 async fn getpgid_access_allowed_for_selinux_disabled() {
2386 spawn_kernel_and_run(async |locked, current_task| {
2387 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2388 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2389 })
2390 .await;
2391 }
2392
2393 #[fuchsia::test]
2394 async fn getpgid_access_allowed_for_permissive_mode() {
2395 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2396 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2397 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2398 })
2399 .await;
2400 }
2401
2402 #[fuchsia::test]
2403 async fn setpgid_access_allowed_for_selinux_disabled() {
2404 spawn_kernel_and_run(async |locked, current_task| {
2405 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2406 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2407 })
2408 .await;
2409 }
2410
2411 #[fuchsia::test]
2412 async fn setpgid_access_allowed_for_permissive_mode() {
2413 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2414 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2415 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2416 })
2417 .await;
2418 }
2419
2420 #[fuchsia::test]
2421 async fn task_getsid_allowed_for_selinux_disabled() {
2422 spawn_kernel_and_run(async |locked, current_task| {
2423 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2424 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2425 })
2426 .await;
2427 }
2428
2429 #[fuchsia::test]
2430 async fn task_getsid_allowed_for_permissive_mode() {
2431 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2432 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2433 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2434 })
2435 .await;
2436 }
2437
2438 #[fuchsia::test]
2439 async fn signal_access_allowed_for_selinux_disabled() {
2440 spawn_kernel_and_run(async |locked, current_task| {
2441 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2442 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2443 })
2444 .await;
2445 }
2446
2447 #[fuchsia::test]
2448 async fn signal_access_allowed_for_permissive_mode() {
2449 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2450 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2451 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2452 })
2453 .await;
2454 }
2455
2456 #[fuchsia::test]
2457 async fn ptrace_traceme_access_allowed_for_selinux_disabled() {
2458 spawn_kernel_and_run(async |locked, current_task| {
2459 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2460 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2461 })
2462 .await;
2463 }
2464
2465 #[fuchsia::test]
2466 async fn ptrace_traceme_access_allowed_for_permissive_mode() {
2467 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2468 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2469 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2470 })
2471 .await;
2472 }
2473
2474 #[fuchsia::test]
2475 async fn ptrace_attach_access_allowed_for_selinux_disabled() {
2476 spawn_kernel_and_run(async |locked, current_task| {
2477 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2478 assert_eq!(
2479 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2480 Ok(())
2481 );
2482 })
2483 .await;
2484 }
2485
2486 #[fuchsia::test]
2487 async fn ptrace_attach_access_allowed_for_permissive_mode() {
2488 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2489 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2490 assert_eq!(
2491 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2492 Ok(())
2493 );
2494 })
2495 .await;
2496 }
2497
2498 #[fuchsia::test]
2499 async fn task_prlimit_access_allowed_for_selinux_disabled() {
2500 spawn_kernel_and_run(async |locked, current_task| {
2501 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2502 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2503 })
2504 .await;
2505 }
2506
2507 #[fuchsia::test]
2508 async fn task_prlimit_access_allowed_for_permissive_mode() {
2509 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2510 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2511 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2512 })
2513 .await;
2514 }
2515
2516 #[fuchsia::test]
2517 async fn fs_node_task_to_fs_node_noop_selinux_disabled() {
2518 spawn_kernel_and_run(async |locked, current_task| {
2519 let node = &testing::create_test_file(locked, current_task).entry.node;
2520 task_to_fs_node(current_task, ¤t_task.temp_task(), &node);
2521 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2522 })
2523 .await;
2524 }
2525
2526 #[fuchsia::test]
2527 async fn fs_node_setsecurity_selinux_disabled_only_sets_xattr() {
2528 spawn_kernel_and_run(async |locked, current_task| {
2529 let node = &testing::create_test_file(locked, current_task).entry.node;
2530
2531 fs_node_setsecurity(
2532 locked,
2533 current_task,
2534 &node,
2535 XATTR_NAME_SELINUX.to_bytes().into(),
2536 VALID_SECURITY_CONTEXT.into(),
2537 XattrOp::Set,
2538 )
2539 .expect("set_xattr(security.selinux) failed");
2540
2541 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2542 })
2543 .await;
2544 }
2545
2546 #[fuchsia::test]
2547 async fn fs_node_setsecurity_selinux_without_policy_only_sets_xattr() {
2548 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2549 let node = &testing::create_test_file(locked, current_task).entry.node;
2550 fs_node_setsecurity(
2551 locked,
2552 current_task,
2553 &node,
2554 XATTR_NAME_SELINUX.to_bytes().into(),
2555 VALID_SECURITY_CONTEXT.into(),
2556 XattrOp::Set,
2557 )
2558 .expect("set_xattr(security.selinux) failed");
2559
2560 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2561 })
2562 .await;
2563 }
2564
2565 #[fuchsia::test]
2566 async fn fs_node_setsecurity_selinux_permissive_sets_xattr_and_label() {
2567 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2568 |locked, current_task, security_server| {
2569 security_server.set_enforcing(false);
2570 let expected_sid = security_server
2571 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2572 .expect("no SID for VALID_SECURITY_CONTEXT");
2573 let node = &testing::create_test_file(locked, ¤t_task).entry.node;
2574
2575 assert_ne!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2577
2578 fs_node_setsecurity(
2579 locked,
2580 current_task,
2581 &node,
2582 XATTR_NAME_SELINUX.to_bytes().into(),
2583 VALID_SECURITY_CONTEXT.into(),
2584 XattrOp::Set,
2585 )
2586 .expect("set_xattr(security.selinux) failed");
2587
2588 assert_eq!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2591 },
2592 )
2593 .await;
2594 }
2595
2596 #[fuchsia::test]
2597 async fn fs_node_setsecurity_not_selinux_only_sets_xattr() {
2598 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2599 |locked, current_task, security_server| {
2600 let valid_security_context_sid = security_server
2601 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2602 .expect("no SID for VALID_SECURITY_CONTEXT");
2603 let node = &testing::create_test_file(locked, current_task).entry.node;
2604 let whatever_sid = selinux_hooks::get_cached_sid(node);
2608 assert_ne!(Some(valid_security_context_sid), whatever_sid);
2609
2610 fs_node_setsecurity(
2611 locked,
2612 current_task,
2613 &node,
2614 "security.selinu!".into(), VALID_SECURITY_CONTEXT.into(),
2616 XattrOp::Set,
2617 )
2618 .expect("set_xattr(security.selinux) failed");
2619
2620 assert_eq!(whatever_sid, selinux_hooks::get_cached_sid(node));
2622 },
2623 )
2624 .await;
2625 }
2626
2627 #[fuchsia::test]
2628 async fn fs_node_setsecurity_selinux_enforcing_invalid_context_fails() {
2629 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2630 |locked, current_task, _security_server| {
2631 let node = &testing::create_test_file(locked, current_task).entry.node;
2632
2633 let before_sid = selinux_hooks::get_cached_sid(node);
2634 assert_ne!(Some(InitialSid::Unlabeled.into()), before_sid);
2635
2636 assert!(
2637 check_fs_node_setxattr_access(
2638 ¤t_task,
2639 &node,
2640 XATTR_NAME_SELINUX.to_bytes().into(),
2641 "!".into(), XattrOp::Set,
2643 )
2644 .is_err()
2645 );
2646
2647 assert_eq!(before_sid, selinux_hooks::get_cached_sid(node));
2648 },
2649 )
2650 .await;
2651 }
2652
2653 #[fuchsia::test]
2654 async fn fs_node_setsecurity_selinux_permissive_invalid_context_sets_xattr_and_label() {
2655 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2656 |locked, current_task, security_server| {
2657 security_server.set_enforcing(false);
2658 let node = &testing::create_test_file(locked, current_task).entry.node;
2659
2660 assert_ne!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2661
2662 fs_node_setsecurity(
2663 locked,
2664 current_task,
2665 &node,
2666 XATTR_NAME_SELINUX.to_bytes().into(),
2667 "!".into(), XattrOp::Set,
2669 )
2670 .expect("set_xattr(security.selinux) failed");
2671
2672 assert_eq!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2673 },
2674 )
2675 .await;
2676 }
2677
2678 #[fuchsia::test]
2679 async fn fs_node_setsecurity_different_sid_for_different_context() {
2680 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2681 |locked, current_task, _security_server| {
2682 let node = &testing::create_test_file(locked, current_task).entry.node;
2683
2684 fs_node_setsecurity(
2685 locked,
2686 current_task,
2687 &node,
2688 XATTR_NAME_SELINUX.to_bytes().into(),
2689 VALID_SECURITY_CONTEXT.into(),
2690 XattrOp::Set,
2691 )
2692 .expect("set_xattr(security.selinux) failed");
2693
2694 assert!(selinux_hooks::get_cached_sid(node).is_some());
2695
2696 let first_sid = selinux_hooks::get_cached_sid(node).unwrap();
2697 fs_node_setsecurity(
2698 locked,
2699 current_task,
2700 &node,
2701 XATTR_NAME_SELINUX.to_bytes().into(),
2702 DIFFERENT_VALID_SECURITY_CONTEXT.into(),
2703 XattrOp::Set,
2704 )
2705 .expect("set_xattr(security.selinux) failed");
2706
2707 assert!(selinux_hooks::get_cached_sid(node).is_some());
2708
2709 let second_sid = selinux_hooks::get_cached_sid(node).unwrap();
2710
2711 assert_ne!(first_sid, second_sid);
2712 },
2713 )
2714 .await;
2715 }
2716
2717 #[fuchsia::test]
2718 async fn fs_node_getsecurity_returns_cached_context() {
2719 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2720 |locked, current_task, security_server| {
2721 let node = &testing::create_test_file(locked, current_task).entry.node;
2722
2723 const TEST_VALUE: &str = "Something Random";
2725 node.ops()
2726 .set_xattr(
2727 locked.cast_locked::<FileOpsCore>(),
2728 node,
2729 current_task,
2730 XATTR_NAME_SELINUX.to_bytes().into(),
2731 TEST_VALUE.into(),
2732 XattrOp::Set,
2733 )
2734 .expect("set_xattr(security.selinux) failed");
2735
2736 let sid = security_server
2738 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2739 .expect("security context to SID");
2740 selinux_hooks::set_cached_sid(&node, sid);
2741
2742 let result = fs_node_getsecurity(
2744 locked,
2745 current_task,
2746 node,
2747 XATTR_NAME_SELINUX.to_bytes().into(),
2748 4096,
2749 );
2750 assert_eq!(
2751 result,
2752 Ok(ValueOrSize::Value(FsString::new(VALID_SECURITY_CONTEXT_WITH_NUL.into())))
2753 );
2754 },
2755 )
2756 .await;
2757 }
2758
2759 #[fuchsia::test]
2760 async fn fs_node_getsecurity_delegates_to_get_xattr() {
2761 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2762 |locked, current_task, security_server| {
2763 let node = &testing::create_test_file(locked, current_task).entry.node;
2764
2765 security_server.set_enforcing(false);
2768 const TEST_VALUE: &str = "Something Random";
2769 fs_node_setsecurity(
2770 locked,
2771 current_task,
2772 node,
2773 XATTR_NAME_SELINUX.to_bytes().into(),
2774 TEST_VALUE.into(),
2775 XattrOp::Set,
2776 )
2777 .expect("set_xattr(security.selinux) failed");
2778 security_server.set_enforcing(true);
2779
2780 let result = fs_node_getsecurity(
2782 locked,
2783 current_task,
2784 node,
2785 XATTR_NAME_SELINUX.to_bytes().into(),
2786 4096,
2787 );
2788 assert_eq!(result, Ok(ValueOrSize::Value(FsString::new(TEST_VALUE.into()))));
2789 },
2790 )
2791 .await;
2792 }
2793
2794 #[fuchsia::test]
2795 async fn set_get_procattr() {
2796 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2797 |_locked, current_task, _security_server| {
2798 assert_eq!(
2799 get_procattr(current_task, current_task, ProcAttr::Exec),
2800 Ok(Vec::new())
2801 );
2802
2803 assert_eq!(
2804 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2806 Ok(())
2807 );
2808
2809 assert_eq!(
2810 set_procattr(
2812 current_task,
2813 ProcAttr::SockCreate,
2814 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2815 ),
2816 error!(EACCES)
2817 );
2818
2819 assert_eq!(
2820 set_procattr(
2822 current_task,
2823 ProcAttr::Previous,
2824 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2825 ),
2826 error!(EINVAL)
2827 );
2828
2829 assert_eq!(
2830 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2832 error!(EINVAL)
2833 );
2834
2835 assert_eq!(
2836 get_procattr(current_task, current_task, ProcAttr::Exec),
2837 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2838 );
2839
2840 assert!(get_procattr(current_task, current_task, ProcAttr::Current).is_ok());
2841 },
2842 )
2843 .await;
2844 }
2845
2846 #[fuchsia::test]
2847 async fn set_get_procattr_with_nulls() {
2848 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2849 |_locked, current_task, _security_server| {
2850 assert_eq!(
2851 get_procattr(current_task, current_task, ProcAttr::Exec),
2852 Ok(Vec::new())
2853 );
2854
2855 assert_eq!(
2856 set_procattr(
2858 current_task,
2859 ProcAttr::Exec,
2860 VALID_SECURITY_CONTEXT_WITH_NUL.into()
2861 ),
2862 Ok(())
2863 );
2864
2865 assert_eq!(
2866 set_procattr(
2868 current_task,
2869 ProcAttr::FsCreate,
2870 INVALID_SECURITY_CONTEXT_INTERNAL_NUL.into()
2871 ),
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_eq!(
2881 get_procattr(current_task, current_task, ProcAttr::FsCreate),
2882 Ok(Vec::new())
2883 );
2884 },
2885 )
2886 .await;
2887 }
2888
2889 #[fuchsia::test]
2890 async fn set_get_procattr_clear_context() {
2891 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2892 |_locked, current_task, _security_server| {
2893 assert_eq!(
2895 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2896 Ok(())
2897 );
2898 assert_eq!(
2899 set_procattr(
2900 current_task,
2901 ProcAttr::FsCreate,
2902 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2903 ),
2904 Ok(())
2905 );
2906
2907 assert_eq!(set_procattr(current_task, ProcAttr::Exec, b"\0"), Ok(()));
2909 assert_eq!(current_task.security_state.lock().exec_sid, None);
2910
2911 assert_eq!(set_procattr(current_task, ProcAttr::FsCreate, b"\x0a"), Ok(()));
2913 assert_eq!(current_task.security_state.lock().fscreate_sid, None);
2914 },
2915 )
2916 .await;
2917 }
2918
2919 #[fuchsia::test]
2920 async fn set_get_procattr_setcurrent() {
2921 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2922 |_locked, current_task, _security_server| {
2923 let initial_previous =
2925 get_procattr(current_task, current_task, ProcAttr::Previous).unwrap();
2926
2927 assert_eq!(
2928 set_procattr(current_task, ProcAttr::Current, VALID_SECURITY_CONTEXT.into()),
2930 Ok(())
2931 );
2932
2933 assert_eq!(
2934 get_procattr(current_task, current_task, ProcAttr::Current),
2936 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2937 );
2938
2939 assert_eq!(
2940 get_procattr(current_task, current_task, ProcAttr::Previous),
2942 Ok(initial_previous.clone())
2943 );
2944
2945 assert_eq!(
2946 set_procattr(
2948 current_task,
2949 ProcAttr::Current,
2950 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2951 ),
2952 Ok(())
2953 );
2954
2955 assert_eq!(
2956 get_procattr(current_task, current_task, ProcAttr::Current),
2958 Ok(DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL.into())
2959 );
2960
2961 assert_eq!(
2962 get_procattr(current_task, current_task, ProcAttr::Previous),
2964 Ok(initial_previous.clone())
2965 );
2966 },
2967 )
2968 .await;
2969 }
2970
2971 #[fuchsia::test]
2972 async fn set_get_procattr_selinux_permissive() {
2973 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2974 |_locked, current_task, security_server| {
2975 security_server.set_enforcing(false);
2976 assert_eq!(
2977 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Exec),
2978 Ok(Vec::new())
2979 );
2980
2981 assert_eq!(
2982 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2984 Ok(())
2985 );
2986
2987 assert_eq!(
2988 set_procattr(
2991 current_task,
2992 ProcAttr::FsCreate,
2993 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2994 ),
2995 Ok(())
2996 );
2997
2998 assert_eq!(
2999 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3001 error!(EINVAL)
3002 );
3003
3004 assert_eq!(
3005 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Exec),
3006 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3007 );
3008
3009 assert!(
3010 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Current)
3011 .is_ok()
3012 );
3013 },
3014 )
3015 .await;
3016 }
3017
3018 #[fuchsia::test]
3019 async fn set_get_procattr_selinux_disabled() {
3020 spawn_kernel_and_run(async |_, current_task| {
3021 assert_eq!(
3022 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3023 error!(EINVAL)
3024 );
3025
3026 assert_eq!(
3027 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3029 error!(EINVAL)
3030 );
3031
3032 assert_eq!(
3033 set_procattr(¤t_task, ProcAttr::FsCreate, VALID_SECURITY_CONTEXT.into()),
3035 error!(EINVAL)
3036 );
3037
3038 assert_eq!(
3039 set_procattr(¤t_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3041 error!(EINVAL)
3042 );
3043
3044 assert_eq!(
3045 get_procattr(¤t_task, ¤t_task.temp_task(), ProcAttr::Current),
3046 error!(EINVAL)
3047 );
3048 })
3049 .await;
3050 }
3051
3052 #[fuchsia::test]
3053 async fn create_file_with_fscreate_sid() {
3054 spawn_kernel_with_selinux_hooks_test_policy_and_run(
3055 |locked, current_task, security_server| {
3056 let sid =
3057 security_server.security_context_to_sid(VALID_SECURITY_CONTEXT.into()).unwrap();
3058 let source_node = &testing::create_test_file(locked, current_task).entry.node;
3059
3060 fs_node_setsecurity(
3061 locked,
3062 current_task,
3063 &source_node,
3064 XATTR_NAME_SELINUX.to_bytes().into(),
3065 VALID_SECURITY_CONTEXT.into(),
3066 XattrOp::Set,
3067 )
3068 .expect("set_xattr(security.selinux) failed");
3069
3070 let dir_entry = fs_node_copy_up(current_task, source_node, || {
3071 current_task
3072 .fs()
3073 .root()
3074 .create_node(
3075 locked,
3076 ¤t_task,
3077 "test_file2".into(),
3078 FileMode::IFREG,
3079 DeviceType::NONE,
3080 )
3081 .unwrap()
3082 })
3083 .entry;
3084
3085 assert_eq!(get_cached_sid(&dir_entry.node), Some(sid));
3086 },
3087 )
3088 .await;
3089 }
3090}