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(current_task: &CurrentTask, socket: &Socket) {
1117 track_hook_duration!("security.hooks.socket_post_create");
1118 if let Some(state) = ¤t_task.kernel().security_state.state {
1119 selinux_hooks::socket::socket_post_create(&state.server, socket);
1120 }
1121}
1122
1123pub fn check_socket_bind_access(
1126 current_task: &CurrentTask,
1127 socket: &Socket,
1128 socket_address: &SocketAddress,
1129) -> Result<(), Errno> {
1130 track_hook_duration!("security.hooks.check_socket_bind_access");
1131 if_selinux_else_default_ok(current_task, |security_server| {
1132 selinux_hooks::socket::check_socket_bind_access(
1133 &security_server,
1134 current_task,
1135 socket,
1136 socket_address,
1137 )
1138 })
1139}
1140
1141pub fn check_socket_connect_access(
1144 current_task: &CurrentTask,
1145 socket: DowncastedFile<'_, SocketFile>,
1146 socket_peer: &SocketPeer,
1147) -> Result<(), Errno> {
1148 track_hook_duration!("security.hooks.check_socket_connect_access");
1149 if_selinux_else_default_ok(current_task, |security_server| {
1150 selinux_hooks::socket::check_socket_connect_access(
1151 &security_server,
1152 current_task,
1153 socket,
1154 socket_peer,
1155 )
1156 })
1157}
1158
1159pub fn check_socket_listen_access(
1162 current_task: &CurrentTask,
1163 socket: &Socket,
1164 backlog: i32,
1165) -> Result<(), Errno> {
1166 track_hook_duration!("security.hooks.check_socket_listen_access");
1167 if_selinux_else_default_ok(current_task, |security_server| {
1168 selinux_hooks::socket::check_socket_listen_access(
1169 &security_server,
1170 current_task,
1171 socket,
1172 backlog,
1173 )
1174 })
1175}
1176
1177pub fn socket_accept(
1181 current_task: &CurrentTask,
1182 listening_socket: DowncastedFile<'_, SocketFile>,
1183 accepted_socket: DowncastedFile<'_, SocketFile>,
1184) -> Result<(), Errno> {
1185 track_hook_duration!("security.hooks.check_socket_getname_access");
1186 if_selinux_else_default_ok(current_task, |security_server| {
1187 selinux_hooks::socket::socket_accept(
1188 &security_server,
1189 current_task,
1190 listening_socket,
1191 accepted_socket,
1192 )
1193 })
1194}
1195
1196pub fn check_socket_getsockopt_access(
1199 current_task: &CurrentTask,
1200 socket: &Socket,
1201 level: u32,
1202 optname: u32,
1203) -> Result<(), Errno> {
1204 track_hook_duration!("security.hooks.check_socket_getsockopt_access");
1205 if_selinux_else_default_ok(current_task, |security_server| {
1206 selinux_hooks::socket::check_socket_getsockopt_access(
1207 &security_server,
1208 current_task,
1209 socket,
1210 level,
1211 optname,
1212 )
1213 })
1214}
1215
1216pub fn check_socket_setsockopt_access(
1219 current_task: &CurrentTask,
1220 socket: &Socket,
1221 level: u32,
1222 optname: u32,
1223) -> Result<(), Errno> {
1224 track_hook_duration!("security.hooks.check_socket_setsockopt_access");
1225 if_selinux_else_default_ok(current_task, |security_server| {
1226 selinux_hooks::socket::check_socket_setsockopt_access(
1227 &security_server,
1228 current_task,
1229 socket,
1230 level,
1231 optname,
1232 )
1233 })
1234}
1235
1236pub fn check_socket_sendmsg_access(
1239 current_task: &CurrentTask,
1240 socket: &Socket,
1241) -> Result<(), Errno> {
1242 track_hook_duration!("security.hooks.check_socket_sendmsg_access");
1243 if_selinux_else_default_ok(current_task, |security_server| {
1244 selinux_hooks::socket::check_socket_sendmsg_access(&security_server, current_task, socket)
1245 })
1246}
1247
1248pub fn check_socket_recvmsg_access(
1251 current_task: &CurrentTask,
1252 socket: &Socket,
1253) -> Result<(), Errno> {
1254 track_hook_duration!("security.hooks.check_socket_recvmsg_access");
1255 if_selinux_else_default_ok(current_task, |security_server| {
1256 selinux_hooks::socket::check_socket_recvmsg_access(&security_server, current_task, socket)
1257 })
1258}
1259
1260pub fn check_socket_getsockname_access(
1263 current_task: &CurrentTask,
1264 socket: &Socket,
1265) -> Result<(), Errno> {
1266 track_hook_duration!("security.hooks.check_socket_getname_access");
1267 if_selinux_else_default_ok(current_task, |security_server| {
1268 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1269 })
1270}
1271
1272pub fn check_socket_getpeername_access(
1275 current_task: &CurrentTask,
1276 socket: &Socket,
1277) -> Result<(), Errno> {
1278 track_hook_duration!("security.hooks.check_socket_getname_access");
1279 if_selinux_else_default_ok(current_task, |security_server| {
1280 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1281 })
1282}
1283
1284pub fn check_socket_shutdown_access(
1287 current_task: &CurrentTask,
1288 socket: &Socket,
1289 how: SocketShutdownFlags,
1290) -> Result<(), Errno> {
1291 track_hook_duration!("security.hooks.check_socket_shutdown_access");
1292 if_selinux_else_default_ok(current_task, |security_server| {
1293 selinux_hooks::socket::check_socket_shutdown_access(
1294 &security_server,
1295 current_task,
1296 socket,
1297 how,
1298 )
1299 })
1300}
1301
1302pub fn socket_getpeersec_stream(
1305 current_task: &CurrentTask,
1306 socket: &Socket,
1307) -> Result<Vec<u8>, Errno> {
1308 track_hook_duration!("security.hooks.socket_getpeersec_stream");
1309 if_selinux_else_default_ok(current_task, |security_server| {
1310 selinux_hooks::socket::socket_getpeersec_stream(&security_server, current_task, socket)
1311 })
1312}
1313
1314pub fn socket_getpeersec_dgram(current_task: &CurrentTask, socket: &Socket) -> Vec<u8> {
1318 track_hook_duration!("security.hooks.socket_getpeersec_dgram");
1319 if_selinux_else(
1320 current_task,
1321 |security_server| {
1322 selinux_hooks::socket::socket_getpeersec_dgram(&security_server, current_task, socket)
1323 },
1324 Vec::default,
1325 )
1326}
1327
1328pub fn unix_may_send(
1332 current_task: &CurrentTask,
1333 sending_socket: &Socket,
1334 receiving_socket: &Socket,
1335) -> Result<(), Errno> {
1336 track_hook_duration!("security.hooks.unix_may_send");
1337 if_selinux_else_default_ok(current_task, |security_server| {
1338 selinux_hooks::socket::unix_may_send(
1339 &security_server,
1340 current_task,
1341 sending_socket,
1342 receiving_socket,
1343 )
1344 })
1345}
1346
1347pub fn unix_stream_connect(
1351 current_task: &CurrentTask,
1352 client_socket: &Socket,
1353 listening_socket: &Socket,
1354 server_socket: &Socket,
1355) -> Result<(), Errno> {
1356 track_hook_duration!("security.hooks.unix_stream_connect");
1357 if_selinux_else_default_ok(current_task, |security_server| {
1358 selinux_hooks::socket::unix_stream_connect(
1359 &security_server,
1360 current_task,
1361 client_socket,
1362 listening_socket,
1363 server_socket,
1364 )
1365 })
1366}
1367
1368pub fn check_netlink_send_access(
1372 current_task: &CurrentTask,
1373 socket: &Socket,
1374 message_type: u16,
1375) -> Result<(), Errno> {
1376 track_hook_duration!("security.hooks.check_netlink_send_access");
1377 if_selinux_else_default_ok(current_task, |security_server| {
1378 selinux_hooks::netlink_socket::check_netlink_send_access(
1379 &security_server,
1380 current_task,
1381 socket,
1382 message_type,
1383 )
1384 })
1385}
1386
1387pub fn check_tun_dev_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1390 track_hook_duration!("security.hooks.check_tun_dev_create_access");
1391 if_selinux_else_default_ok(current_task, |security_server| {
1392 selinux_hooks::socket::check_tun_dev_create_access(&security_server, current_task)
1393 })
1394}
1395
1396pub fn exec_binprm(
1402 locked: &mut Locked<Unlocked>,
1403 current_task: &CurrentTask,
1404 elf_security_state: &ResolvedElfState,
1405) {
1406 track_hook_duration!("security.hooks.exec_binprm");
1407 if_selinux_else(
1408 current_task,
1409 |security_server| {
1410 selinux_hooks::task::exec_binprm(
1411 locked,
1412 security_server,
1413 current_task,
1414 elf_security_state,
1415 )
1416 },
1417 || (),
1418 );
1419}
1420
1421pub fn check_getsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1424 track_hook_duration!("security.hooks.check_getsched_access");
1425 if_selinux_else_default_ok(source, |security_server| {
1426 selinux_hooks::task::check_getsched_access(
1427 &security_server.as_permission_check(),
1428 &source,
1429 &target,
1430 )
1431 })
1432}
1433
1434pub fn check_setsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1437 track_hook_duration!("security.hooks.check_setsched_access");
1438 if_selinux_else_default_ok(source, |security_server| {
1439 selinux_hooks::task::check_setsched_access(
1440 &security_server.as_permission_check(),
1441 &source,
1442 &target,
1443 )
1444 })
1445}
1446
1447pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1450 track_hook_duration!("security.hooks.check_getpgid_access");
1451 if_selinux_else_default_ok(source, |security_server| {
1452 selinux_hooks::task::check_getpgid_access(
1453 &security_server.as_permission_check(),
1454 &source,
1455 &target,
1456 )
1457 })
1458}
1459
1460pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1463 track_hook_duration!("security.hooks.check_setpgid_access");
1464 if_selinux_else_default_ok(source, |security_server| {
1465 selinux_hooks::task::check_setpgid_access(
1466 &security_server.as_permission_check(),
1467 &source,
1468 &target,
1469 )
1470 })
1471}
1472
1473pub fn check_task_getsid(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1476 track_hook_duration!("security.hooks.check_task_getsid");
1477 if_selinux_else_default_ok(source, |security_server| {
1478 selinux_hooks::task::check_task_getsid(
1479 &security_server.as_permission_check(),
1480 &source,
1481 &target,
1482 )
1483 })
1484}
1485
1486pub fn check_getcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1489 track_hook_duration!("security.hooks.check_getcap_access");
1490 if_selinux_else_default_ok(source, |security_server| {
1491 selinux_hooks::task::check_getcap_access(
1492 &security_server.as_permission_check(),
1493 &source,
1494 &target,
1495 )
1496 })
1497}
1498
1499pub fn check_setcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1503 track_hook_duration!("security.hooks.check_setcap_access");
1504 if_selinux_else_default_ok(source, |security_server| {
1505 selinux_hooks::task::check_setcap_access(
1506 &security_server.as_permission_check(),
1507 &source,
1508 &target,
1509 )
1510 })
1511}
1512
1513pub fn check_signal_access(
1516 source: &CurrentTask,
1517 target: &Task,
1518 signal: Signal,
1519) -> Result<(), Errno> {
1520 track_hook_duration!("security.hooks.check_signal_access");
1521 if_selinux_else_default_ok(source, |security_server| {
1522 selinux_hooks::task::check_signal_access(
1523 &security_server.as_permission_check(),
1524 &source,
1525 &target,
1526 signal,
1527 )
1528 })
1529}
1530
1531pub fn check_syslog_access(source: &CurrentTask, action: SyslogAction) -> Result<(), Errno> {
1534 track_hook_duration!("security.hooks.check_syslog_access");
1535 if_selinux_else_default_ok(source, |security_server| {
1536 selinux_hooks::task::check_syslog_access(
1537 &security_server.as_permission_check(),
1538 &source,
1539 action,
1540 )
1541 })
1542}
1543
1544pub fn ptrace_traceme(current_task: &CurrentTask, parent_tracer_task: &Task) -> Result<(), Errno> {
1547 track_hook_duration!("security.hooks.ptrace_traceme");
1548 yama::ptrace_traceme(current_task, parent_tracer_task)?;
1549 common_cap::ptrace_traceme(current_task, parent_tracer_task)?;
1550 if_selinux_else_default_ok(current_task, |security_server| {
1551 selinux_hooks::task::ptrace_traceme(
1552 &security_server.as_permission_check(),
1553 current_task,
1554 parent_tracer_task,
1555 )
1556 })
1557}
1558
1559pub fn ptrace_access_check(
1562 current_task: &CurrentTask,
1563 tracee_task: &Task,
1564 mode: PtraceAccessMode,
1565) -> Result<(), Errno> {
1566 track_hook_duration!("security.hooks.ptrace_access_check");
1567 yama::ptrace_access_check(current_task, tracee_task, mode)?;
1568 common_cap::ptrace_access_check(current_task, tracee_task, mode)?;
1569 if_selinux_else_default_ok(current_task, |security_server| {
1570 selinux_hooks::task::ptrace_access_check(
1571 &security_server.as_permission_check(),
1572 current_task,
1573 tracee_task,
1574 mode,
1575 )
1576 })
1577}
1578
1579pub fn task_prlimit(
1582 source: &CurrentTask,
1583 target: &Task,
1584 check_get_rlimit: bool,
1585 check_set_rlimit: bool,
1586) -> Result<(), Errno> {
1587 track_hook_duration!("security.hooks.task_prlimit");
1588 if_selinux_else_default_ok(source, |security_server| {
1589 selinux_hooks::task::task_prlimit(
1590 &security_server.as_permission_check(),
1591 &source,
1592 &target,
1593 check_get_rlimit,
1594 check_set_rlimit,
1595 )
1596 })
1597}
1598
1599pub fn task_setrlimit(
1602 source: &CurrentTask,
1603 target: &Task,
1604 old_limit: rlimit,
1605 new_limit: rlimit,
1606) -> Result<(), Errno> {
1607 track_hook_duration!("security.hooks.task_setrlimit");
1608 if_selinux_else_default_ok(source, |security_server| {
1609 selinux_hooks::task::task_setrlimit(
1610 &security_server.as_permission_check(),
1611 &source,
1612 &target,
1613 old_limit,
1614 new_limit,
1615 )
1616 })
1617}
1618
1619pub fn sb_kern_mount(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1622 track_hook_duration!("security.hooks.sb_kern_mount");
1623 if_selinux_else_default_ok(current_task, |security_server| {
1624 selinux_hooks::superblock::sb_kern_mount(
1625 &security_server.as_permission_check(),
1626 current_task,
1627 fs,
1628 )
1629 })
1630}
1631
1632pub fn sb_mount(
1636 current_task: &CurrentTask,
1637 path: &NamespaceNode,
1638 flags: MountFlags,
1639) -> Result<(), Errno> {
1640 track_hook_duration!("security.hooks.sb_mount");
1641 if_selinux_else_default_ok(current_task, |security_server| {
1642 selinux_hooks::superblock::sb_mount(
1643 &security_server.as_permission_check(),
1644 current_task,
1645 path,
1646 flags,
1647 )
1648 })
1649}
1650
1651pub fn sb_remount(
1654 current_task: &CurrentTask,
1655 mount: &Mount,
1656 new_mount_options: FileSystemMountOptions,
1657) -> Result<(), Errno> {
1658 track_hook_duration!("security.hooks.sb_remount");
1659 if_selinux_else_default_ok(current_task, |security_server| {
1660 selinux_hooks::superblock::sb_remount(security_server, mount, new_mount_options)
1661 })
1662}
1663
1664pub fn sb_show_options(
1667 kernel: &Kernel,
1668 buf: &mut impl OutputBuffer,
1669 mount: &Mount,
1670) -> Result<(), Errno> {
1671 track_hook_duration!("security.hooks.sb_show_options");
1672 if let Some(state) = &kernel.security_state.state {
1673 selinux_hooks::superblock::sb_show_options(&state.server, buf, mount)?;
1674 }
1675 Ok(())
1676}
1677
1678pub fn sb_statfs(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1681 track_hook_duration!("security.hooks.sb_statfs");
1682 if_selinux_else_default_ok(current_task, |security_server| {
1683 selinux_hooks::superblock::sb_statfs(
1684 &security_server.as_permission_check(),
1685 current_task,
1686 fs,
1687 )
1688 })
1689}
1690
1691pub fn sb_umount(
1695 current_task: &CurrentTask,
1696 node: &NamespaceNode,
1697 flags: UnmountFlags,
1698) -> Result<(), Errno> {
1699 track_hook_duration!("security.hooks.sb_umount");
1700 if_selinux_else_default_ok(current_task, |security_server| {
1701 selinux_hooks::superblock::sb_umount(
1702 &security_server.as_permission_check(),
1703 current_task,
1704 node,
1705 flags,
1706 )
1707 })
1708}
1709
1710pub fn check_fs_node_getattr_access(
1713 current_task: &CurrentTask,
1714 fs_node: &FsNode,
1715) -> Result<(), Errno> {
1716 track_hook_duration!("security.hooks.check_fs_node_getattr_access");
1717 if_selinux_else_default_ok(current_task, |security_server| {
1718 selinux_hooks::fs_node::check_fs_node_getattr_access(security_server, current_task, fs_node)
1719 })
1720}
1721
1722pub fn fs_node_xattr_skipcap(_current_task: &CurrentTask, name: &FsStr) -> bool {
1725 selinux_hooks::fs_node::fs_node_xattr_skipcap(name)
1726}
1727
1728pub fn check_fs_node_setxattr_access(
1734 current_task: &CurrentTask,
1735 fs_node: &FsNode,
1736 name: &FsStr,
1737 value: &FsStr,
1738 op: XattrOp,
1739) -> Result<(), Errno> {
1740 track_hook_duration!("security.hooks.check_fs_node_setxattr_access");
1741 common_cap::fs_node_setxattr(current_task, fs_node, name, value, op)?;
1742 if_selinux_else_default_ok(current_task, |security_server| {
1743 selinux_hooks::fs_node::check_fs_node_setxattr_access(
1744 security_server,
1745 current_task,
1746 fs_node,
1747 name,
1748 value,
1749 op,
1750 )
1751 })
1752}
1753
1754pub fn check_fs_node_getxattr_access(
1756 current_task: &CurrentTask,
1757 fs_node: &FsNode,
1758 name: &FsStr,
1759) -> Result<(), Errno> {
1760 track_hook_duration!("security.hooks.check_fs_node_getxattr_access");
1761 if_selinux_else_default_ok(current_task, |security_server| {
1762 selinux_hooks::fs_node::check_fs_node_getxattr_access(
1763 security_server,
1764 current_task,
1765 fs_node,
1766 name,
1767 )
1768 })
1769}
1770
1771pub fn check_fs_node_listxattr_access(
1773 current_task: &CurrentTask,
1774 fs_node: &FsNode,
1775) -> Result<(), Errno> {
1776 track_hook_duration!("security.hooks.check_fs_node_listxattr_access");
1777 if_selinux_else_default_ok(current_task, |security_server| {
1778 selinux_hooks::fs_node::check_fs_node_listxattr_access(
1779 security_server,
1780 current_task,
1781 fs_node,
1782 )
1783 })
1784}
1785
1786pub fn check_fs_node_removexattr_access(
1788 current_task: &CurrentTask,
1789 fs_node: &FsNode,
1790 name: &FsStr,
1791) -> Result<(), Errno> {
1792 track_hook_duration!("security.hooks.check_fs_node_removexattr_access");
1793 common_cap::fs_node_removexattr(current_task, fs_node, name)?;
1794 if_selinux_else_default_ok(current_task, |security_server| {
1795 selinux_hooks::fs_node::check_fs_node_removexattr_access(
1796 security_server,
1797 current_task,
1798 fs_node,
1799 name,
1800 )
1801 })
1802}
1803
1804pub fn fs_node_listsecurity(current_task: &CurrentTask, fs_node: &FsNode) -> Option<FsString> {
1811 track_hook_duration!("security.hooks.fs_node_listsecurity");
1812 if_selinux_else(
1813 current_task,
1814 |_| selinux_hooks::fs_node::fs_node_listsecurity(fs_node),
1815 || None,
1816 )
1817}
1818
1819pub fn fs_node_getsecurity<L>(
1827 locked: &mut Locked<L>,
1828 current_task: &CurrentTask,
1829 fs_node: &FsNode,
1830 name: &FsStr,
1831 max_size: usize,
1832) -> Result<ValueOrSize<FsString>, Errno>
1833where
1834 L: LockEqualOrBefore<FileOpsCore>,
1835{
1836 track_hook_duration!("security.hooks.fs_node_getsecurity");
1837 if_selinux_else_with_context(
1838 locked,
1839 current_task,
1840 |locked, security_server| {
1841 selinux_hooks::fs_node::fs_node_getsecurity(
1842 locked,
1843 security_server,
1844 current_task,
1845 fs_node,
1846 name,
1847 max_size,
1848 )
1849 },
1850 |locked| {
1851 fs_node.ops().get_xattr(
1852 locked.cast_locked::<FileOpsCore>(),
1853 fs_node,
1854 current_task,
1855 name,
1856 max_size,
1857 )
1858 },
1859 )
1860}
1861
1862pub fn fs_node_setsecurity<L>(
1868 locked: &mut Locked<L>,
1869 current_task: &CurrentTask,
1870 fs_node: &FsNode,
1871 name: &FsStr,
1872 value: &FsStr,
1873 op: XattrOp,
1874) -> Result<(), Errno>
1875where
1876 L: LockEqualOrBefore<FileOpsCore>,
1877{
1878 track_hook_duration!("security.hooks.fs_node_setsecurity");
1879 if_selinux_else_with_context(
1880 locked,
1881 current_task,
1882 |locked, security_server| {
1883 selinux_hooks::fs_node::fs_node_setsecurity(
1884 locked,
1885 security_server,
1886 current_task,
1887 fs_node,
1888 name,
1889 value,
1890 op,
1891 )
1892 },
1893 |locked| {
1894 fs_node.ops().set_xattr(
1895 locked.cast_locked::<FileOpsCore>(),
1896 fs_node,
1897 current_task,
1898 name,
1899 value,
1900 op,
1901 )
1902 },
1903 )
1904}
1905
1906pub fn check_bpf_access<Attr: FromBytes>(
1910 current_task: &CurrentTask,
1911 cmd: bpf_cmd,
1912 attr: &Attr,
1913 attr_size: u32,
1914) -> Result<(), Errno> {
1915 track_hook_duration!("security.hooks.check_bpf_access");
1916 if_selinux_else_default_ok(current_task, |security_server| {
1917 selinux_hooks::bpf::check_bpf_access(security_server, current_task, cmd, attr, attr_size)
1918 })
1919}
1920
1921pub fn check_bpf_map_access(
1925 current_task: &CurrentTask,
1926 bpf_map: &BpfMap,
1927 flags: PermissionFlags,
1928) -> Result<(), Errno> {
1929 track_hook_duration!("security.hooks.check_bpf_map_access");
1930 if_selinux_else_default_ok(current_task, |security_server| {
1931 let subject_sid = current_task_state(current_task).lock().current_sid;
1932 selinux_hooks::bpf::check_bpf_map_access(
1933 security_server,
1934 current_task,
1935 subject_sid,
1936 bpf_map,
1937 flags,
1938 )
1939 })
1940}
1941
1942pub fn check_bpf_prog_access(
1947 current_task: &CurrentTask,
1948 bpf_program: &Program,
1949) -> Result<(), Errno> {
1950 track_hook_duration!("security.hooks.check_bpf_prog_access");
1951 if_selinux_else_default_ok(current_task, |security_server| {
1952 let subject_sid = current_task_state(current_task).lock().current_sid;
1953 selinux_hooks::bpf::check_bpf_prog_access(
1954 security_server,
1955 current_task,
1956 subject_sid,
1957 bpf_program,
1958 )
1959 })
1960}
1961
1962pub fn check_perf_event_open_access(
1966 current_task: &CurrentTask,
1967 target_task_type: TargetTaskType<'_>,
1968 attr: &perf_event_attr,
1969 event_type: PerfEventType,
1970) -> Result<(), Errno> {
1971 track_hook_duration!("security.hooks.check_perf_event_open_access");
1972 if_selinux_else_default_ok(current_task, |security_server| {
1973 selinux_hooks::perf_event::check_perf_event_open_access(
1974 security_server,
1975 current_task,
1976 target_task_type,
1977 attr,
1978 event_type,
1979 )
1980 })
1981}
1982
1983pub fn perf_event_alloc(current_task: &CurrentTask) -> PerfEventState {
1987 track_hook_duration!("security.hooks.perf_event_alloc");
1988 PerfEventState { state: selinux_hooks::perf_event::perf_event_alloc(current_task) }
1989}
1990
1991pub fn check_perf_event_read_access(
1994 current_task: &CurrentTask,
1995 perf_event_file: &PerfEventFile,
1996) -> Result<(), Errno> {
1997 track_hook_duration!("security.hooks.check_perf_event_read_access");
1998 if_selinux_else_default_ok(current_task, |security_server| {
1999 selinux_hooks::perf_event::check_perf_event_read_access(
2000 security_server,
2001 current_task,
2002 perf_event_file,
2003 )
2004 })
2005}
2006
2007pub fn check_perf_event_write_access(
2010 current_task: &CurrentTask,
2011 perf_event_file: &PerfEventFile,
2012) -> Result<(), Errno> {
2013 track_hook_duration!("security.hooks.check_perf_event_write_access");
2014 if_selinux_else_default_ok(current_task, |security_server| {
2015 selinux_hooks::perf_event::check_perf_event_write_access(
2016 security_server,
2017 current_task,
2018 perf_event_file,
2019 )
2020 })
2021}
2022
2023#[derive(Debug, Clone, Copy, PartialEq)]
2025pub enum ProcAttr {
2026 Current,
2027 Exec,
2028 FsCreate,
2029 KeyCreate,
2030 Previous,
2031 SockCreate,
2032}
2033
2034pub fn get_procattr(
2037 current_task: &CurrentTask,
2038 target: &Task,
2039 attr: ProcAttr,
2040) -> Result<Vec<u8>, Errno> {
2041 track_hook_duration!("security.hooks.get_procattr");
2042 if_selinux_else(
2043 current_task,
2044 |security_server| {
2045 selinux_hooks::task::get_procattr(security_server, current_task, target, attr)
2046 },
2047 || error!(EINVAL),
2049 )
2050}
2051
2052pub fn set_procattr(
2055 current_task: &CurrentTask,
2056 attr: ProcAttr,
2057 context: &[u8],
2058) -> Result<(), Errno> {
2059 track_hook_duration!("security.hooks.set_procattr");
2060 if_selinux_else(
2061 current_task,
2062 |security_server| {
2063 selinux_hooks::task::set_procattr(security_server, current_task, attr, context)
2064 },
2065 || error!(EINVAL),
2067 )
2068}
2069
2070pub fn fs_is_xattr_labeled(fs: FileSystemHandle) -> bool {
2072 fs.security_state.state.supports_xattr()
2073}
2074
2075pub fn selinuxfs_init_null(current_task: &CurrentTask, null_fs_node: &FileHandle) {
2078 selinux_hooks::selinuxfs::selinuxfs_init_null(current_task, null_fs_node)
2081}
2082
2083pub fn selinuxfs_policy_loaded<L>(locked: &mut Locked<L>, current_task: &CurrentTask)
2089where
2090 L: LockEqualOrBefore<FileOpsCore>,
2091{
2092 track_hook_duration!("security.hooks.selinuxfs_policy_loaded");
2093 selinux_hooks::selinuxfs::selinuxfs_policy_loaded(locked, current_task)
2094}
2095
2096pub fn selinuxfs_get_admin_api(current_task: &CurrentTask) -> Option<Arc<SecurityServer>> {
2100 current_task.kernel().security_state.state.as_ref().map(|state| state.server.clone())
2101}
2102
2103pub fn selinuxfs_check_access(
2106 current_task: &CurrentTask,
2107 permission: SecurityPermission,
2108) -> Result<(), Errno> {
2109 track_hook_duration!("security.hooks.selinuxfs_check_access");
2110 if_selinux_else_default_ok(current_task, |security_server| {
2111 selinux_hooks::selinuxfs::selinuxfs_check_access(security_server, current_task, permission)
2112 })
2113}
2114
2115pub fn creds_start_internal_operation(current_task: &CurrentTask) -> FullCredentials {
2118 track_hook_duration!("security.hooks.creds_start_internal_operation");
2119 let creds = current_task.full_current_creds();
2120 creds.security_state.lock().internal_operation = true;
2121 creds
2122}
2123
2124pub mod testing {
2125 use super::{Arc, KernelState, SecurityServer, selinux_hooks};
2126 use starnix_sync::Mutex;
2127 use std::sync::OnceLock;
2128 use std::sync::atomic::AtomicU64;
2129
2130 pub fn kernel_state(security_server: Option<Arc<SecurityServer>>) -> KernelState {
2133 let state = security_server.map(|server| selinux_hooks::KernelState {
2134 server,
2135 pending_file_systems: Mutex::default(),
2136 selinuxfs_null: OnceLock::default(),
2137 access_denial_count: AtomicU64::new(0u64),
2138 has_policy: false.into(),
2139 _inspect_node: fuchsia_inspect::Node::default(),
2140 });
2141 KernelState { state }
2142 }
2143}
2144
2145#[cfg(test)]
2146mod tests {
2147 use super::*;
2148 use crate::security::selinux_hooks::get_cached_sid;
2149 use crate::security::selinux_hooks::testing::{
2150 self, spawn_kernel_with_selinux_hooks_test_policy_and_run,
2151 };
2152 use crate::testing::{create_task, spawn_kernel_and_run, spawn_kernel_with_selinux_and_run};
2153 use linux_uapi::XATTR_NAME_SELINUX;
2154 use selinux::InitialSid;
2155 use starnix_uapi::auth::PTRACE_MODE_ATTACH;
2156 use starnix_uapi::signals::SIGTERM;
2157
2158 const VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_valid_t:s0";
2159 const VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] = b"u:object_r:test_valid_t:s0\0";
2160
2161 const DIFFERENT_VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_different_valid_t:s0";
2162 const DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] =
2163 b"u:object_r:test_different_valid_t:s0\0";
2164
2165 const INVALID_SECURITY_CONTEXT_INTERNAL_NUL: &[u8] = b"u:object_r:test_valid_\0t:s0";
2166
2167 const INVALID_SECURITY_CONTEXT: &[u8] = b"not_a_u:object_r:test_valid_t:s0";
2168
2169 #[derive(Default, Debug, PartialEq)]
2170 enum TestHookResult {
2171 WasRun,
2172 WasNotRun,
2173 #[default]
2174 WasNotRunDefault,
2175 }
2176
2177 #[fuchsia::test]
2178 async fn if_selinux_else_disabled() {
2179 spawn_kernel_and_run(async |_, current_task| {
2180 assert!(current_task.kernel().security_state.state.is_none());
2181
2182 let check_result =
2183 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2184 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2185
2186 let run_else_result = if_selinux_else(
2187 current_task,
2188 |_| TestHookResult::WasRun,
2189 || TestHookResult::WasNotRun,
2190 );
2191 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2192 })
2193 .await;
2194 }
2195
2196 #[fuchsia::test]
2197 async fn if_selinux_else_without_policy() {
2198 spawn_kernel_with_selinux_and_run(async |_locked, current_task, _security_server| {
2199 let check_result =
2200 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2201 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2202
2203 let run_else_result = if_selinux_else(
2204 current_task,
2205 |_| TestHookResult::WasRun,
2206 || TestHookResult::WasNotRun,
2207 );
2208 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2209 })
2210 .await;
2211 }
2212
2213 #[fuchsia::test]
2214 async fn if_selinux_else_with_policy() {
2215 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2216 |_locked, current_task, _security_server| {
2217 let check_result =
2218 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2219 assert_eq!(check_result, Ok(TestHookResult::WasRun));
2220
2221 let run_else_result = if_selinux_else(
2222 current_task,
2223 |_| TestHookResult::WasRun,
2224 || TestHookResult::WasNotRun,
2225 );
2226 assert_eq!(run_else_result, TestHookResult::WasRun);
2227 },
2228 )
2229 .await;
2230 }
2231
2232 #[fuchsia::test]
2233 async fn task_alloc_selinux_disabled() {
2234 spawn_kernel_and_run(async |_, current_task| {
2235 task_alloc(current_task, 0);
2236 })
2237 .await;
2238 }
2239
2240 #[fuchsia::test]
2241 async fn task_create_access_allowed_for_selinux_disabled() {
2242 spawn_kernel_and_run(async |_, current_task| {
2243 assert!(current_task.kernel().security_state.state.is_none());
2244 assert_eq!(check_task_create_access(current_task), Ok(()));
2245 })
2246 .await;
2247 }
2248
2249 #[fuchsia::test]
2250 async fn task_create_access_allowed_for_permissive_mode() {
2251 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2252 |_locked, current_task, security_server| {
2253 security_server.set_enforcing(false);
2254 assert_eq!(check_task_create_access(current_task), Ok(()));
2255 },
2256 )
2257 .await;
2258 }
2259
2260 #[fuchsia::test]
2261 async fn exec_access_allowed_for_selinux_disabled() {
2262 spawn_kernel_and_run(async |locked, current_task| {
2263 assert!(current_task.kernel().security_state.state.is_none());
2264 let executable = &testing::create_test_file(locked, current_task);
2265 assert_eq!(
2266 bprm_creds_for_exec(current_task, executable),
2267 Ok(ResolvedElfState { sid: None, require_secure_exec: false })
2268 );
2269 })
2270 .await;
2271 }
2272
2273 #[fuchsia::test]
2274 async fn exec_access_allowed_for_permissive_mode() {
2275 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2276 |locked, current_task, security_server| {
2277 security_server.set_enforcing(false);
2278 let executable = &testing::create_test_file(locked, current_task);
2279 let result = bprm_creds_for_exec(current_task, executable);
2281 assert!(result.expect("Exec check should succeed").sid.is_some());
2282 },
2283 )
2284 .await;
2285 }
2286
2287 #[fuchsia::test]
2288 async fn no_state_update_for_selinux_disabled() {
2289 spawn_kernel_and_run(async |locked, current_task| {
2290 let target_sid = InitialSid::Unlabeled.into();
2293 let elf_state = ResolvedElfState { sid: Some(target_sid), require_secure_exec: false };
2294
2295 assert!(
2296 selinux_hooks::current_task_state(current_task).lock().current_sid != target_sid
2297 );
2298
2299 let before_hook_sid =
2300 selinux_hooks::current_task_state(current_task).lock().current_sid;
2301 exec_binprm(locked, current_task, &elf_state);
2302 assert_eq!(
2303 selinux_hooks::current_task_state(current_task).lock().current_sid,
2304 before_hook_sid
2305 );
2306 assert_eq!(current_task.security_state.lock().current_sid, before_hook_sid)
2307 })
2308 .await;
2309 }
2310
2311 #[fuchsia::test]
2312 async fn no_state_update_for_selinux_without_policy() {
2313 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2314 let initial_state = current_task.security_state.lock().clone();
2317 let elf_sid = InitialSid::Unlabeled.into();
2318 let elf_state = ResolvedElfState { sid: Some(elf_sid), require_secure_exec: false };
2319 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).lock().current_sid);
2320 exec_binprm(locked, current_task, &elf_state);
2321 assert_eq!(*current_task.security_state.lock(), initial_state);
2322 })
2323 .await;
2324 }
2325
2326 #[fuchsia::test]
2327 async fn state_update_for_permissive_mode() {
2328 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2329 |locked, current_task, security_server| {
2330 security_server.set_enforcing(false);
2331 let initial_state = selinux_hooks::TaskAttrs::for_kernel();
2332 *current_task.security_state.lock() = initial_state.clone();
2333 let elf_sid = security_server
2334 .security_context_to_sid(b"u:object_r:fork_no_t:s0".into())
2335 .expect("invalid security context");
2336 let elf_state = ResolvedElfState { sid: Some(elf_sid), require_secure_exec: false };
2337 assert_ne!(
2338 elf_sid,
2339 selinux_hooks::current_task_state(current_task).lock().current_sid
2340 );
2341 exec_binprm(locked, current_task, &elf_state);
2342 assert_eq!(
2343 selinux_hooks::current_task_state(current_task).lock().current_sid,
2344 elf_sid
2345 );
2346 assert_eq!(current_task.security_state.lock().current_sid, elf_sid);
2347 },
2348 )
2349 .await;
2350 }
2351
2352 #[fuchsia::test]
2353 async fn getsched_access_allowed_for_selinux_disabled() {
2354 spawn_kernel_and_run(async |locked, current_task| {
2355 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2356 assert_eq!(check_getsched_access(current_task, &another_task), Ok(()));
2357 })
2358 .await;
2359 }
2360
2361 #[fuchsia::test]
2362 async fn getsched_access_allowed_for_permissive_mode() {
2363 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2364 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2365 assert_eq!(check_getsched_access(current_task, &another_task), Ok(()));
2366 })
2367 .await;
2368 }
2369
2370 #[fuchsia::test]
2371 async fn setsched_access_allowed_for_selinux_disabled() {
2372 spawn_kernel_and_run(async |locked, current_task| {
2373 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2374 assert_eq!(check_setsched_access(current_task, &another_task), Ok(()));
2375 })
2376 .await;
2377 }
2378
2379 #[fuchsia::test]
2380 async fn setsched_access_allowed_for_permissive_mode() {
2381 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2382 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2383 assert_eq!(check_setsched_access(current_task, &another_task), Ok(()));
2384 })
2385 .await;
2386 }
2387
2388 #[fuchsia::test]
2389 async fn getpgid_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_getpgid_access(current_task, &another_task), Ok(()));
2393 })
2394 .await;
2395 }
2396
2397 #[fuchsia::test]
2398 async fn getpgid_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_getpgid_access(current_task, &another_task), Ok(()));
2402 })
2403 .await;
2404 }
2405
2406 #[fuchsia::test]
2407 async fn setpgid_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_setpgid_access(current_task, &another_task), Ok(()));
2411 })
2412 .await;
2413 }
2414
2415 #[fuchsia::test]
2416 async fn setpgid_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_setpgid_access(current_task, &another_task), Ok(()));
2420 })
2421 .await;
2422 }
2423
2424 #[fuchsia::test]
2425 async fn task_getsid_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_task_getsid(current_task, &another_task), Ok(()));
2429 })
2430 .await;
2431 }
2432
2433 #[fuchsia::test]
2434 async fn task_getsid_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_task_getsid(current_task, &another_task), Ok(()));
2438 })
2439 .await;
2440 }
2441
2442 #[fuchsia::test]
2443 async fn signal_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_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2447 })
2448 .await;
2449 }
2450
2451 #[fuchsia::test]
2452 async fn signal_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_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2456 })
2457 .await;
2458 }
2459
2460 #[fuchsia::test]
2461 async fn ptrace_traceme_access_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!(ptrace_traceme(current_task, &another_task), Ok(()));
2465 })
2466 .await;
2467 }
2468
2469 #[fuchsia::test]
2470 async fn ptrace_traceme_access_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!(ptrace_traceme(current_task, &another_task), Ok(()));
2474 })
2475 .await;
2476 }
2477
2478 #[fuchsia::test]
2479 async fn ptrace_attach_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!(
2483 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2484 Ok(())
2485 );
2486 })
2487 .await;
2488 }
2489
2490 #[fuchsia::test]
2491 async fn ptrace_attach_access_allowed_for_permissive_mode() {
2492 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2493 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2494 assert_eq!(
2495 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2496 Ok(())
2497 );
2498 })
2499 .await;
2500 }
2501
2502 #[fuchsia::test]
2503 async fn task_prlimit_access_allowed_for_selinux_disabled() {
2504 spawn_kernel_and_run(async |locked, current_task| {
2505 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2506 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2507 })
2508 .await;
2509 }
2510
2511 #[fuchsia::test]
2512 async fn task_prlimit_access_allowed_for_permissive_mode() {
2513 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2514 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2515 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2516 })
2517 .await;
2518 }
2519
2520 #[fuchsia::test]
2521 async fn fs_node_task_to_fs_node_noop_selinux_disabled() {
2522 spawn_kernel_and_run(async |locked, current_task| {
2523 let node = &testing::create_test_file(locked, current_task).entry.node;
2524 task_to_fs_node(current_task, ¤t_task.temp_task(), &node);
2525 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2526 })
2527 .await;
2528 }
2529
2530 #[fuchsia::test]
2531 async fn fs_node_setsecurity_selinux_disabled_only_sets_xattr() {
2532 spawn_kernel_and_run(async |locked, current_task| {
2533 let node = &testing::create_test_file(locked, current_task).entry.node;
2534
2535 fs_node_setsecurity(
2536 locked,
2537 current_task,
2538 &node,
2539 XATTR_NAME_SELINUX.to_bytes().into(),
2540 VALID_SECURITY_CONTEXT.into(),
2541 XattrOp::Set,
2542 )
2543 .expect("set_xattr(security.selinux) failed");
2544
2545 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2546 })
2547 .await;
2548 }
2549
2550 #[fuchsia::test]
2551 async fn fs_node_setsecurity_selinux_without_policy_only_sets_xattr() {
2552 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2553 let node = &testing::create_test_file(locked, current_task).entry.node;
2554 fs_node_setsecurity(
2555 locked,
2556 current_task,
2557 &node,
2558 XATTR_NAME_SELINUX.to_bytes().into(),
2559 VALID_SECURITY_CONTEXT.into(),
2560 XattrOp::Set,
2561 )
2562 .expect("set_xattr(security.selinux) failed");
2563
2564 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2565 })
2566 .await;
2567 }
2568
2569 #[fuchsia::test]
2570 async fn fs_node_setsecurity_selinux_permissive_sets_xattr_and_label() {
2571 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2572 |locked, current_task, security_server| {
2573 security_server.set_enforcing(false);
2574 let expected_sid = security_server
2575 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2576 .expect("no SID for VALID_SECURITY_CONTEXT");
2577 let node = &testing::create_test_file(locked, ¤t_task).entry.node;
2578
2579 assert_ne!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2581
2582 fs_node_setsecurity(
2583 locked,
2584 current_task,
2585 &node,
2586 XATTR_NAME_SELINUX.to_bytes().into(),
2587 VALID_SECURITY_CONTEXT.into(),
2588 XattrOp::Set,
2589 )
2590 .expect("set_xattr(security.selinux) failed");
2591
2592 assert_eq!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2595 },
2596 )
2597 .await;
2598 }
2599
2600 #[fuchsia::test]
2601 async fn fs_node_setsecurity_not_selinux_only_sets_xattr() {
2602 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2603 |locked, current_task, security_server| {
2604 let valid_security_context_sid = security_server
2605 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2606 .expect("no SID for VALID_SECURITY_CONTEXT");
2607 let node = &testing::create_test_file(locked, current_task).entry.node;
2608 let whatever_sid = selinux_hooks::get_cached_sid(node);
2612 assert_ne!(Some(valid_security_context_sid), whatever_sid);
2613
2614 fs_node_setsecurity(
2615 locked,
2616 current_task,
2617 &node,
2618 "security.selinu!".into(), VALID_SECURITY_CONTEXT.into(),
2620 XattrOp::Set,
2621 )
2622 .expect("set_xattr(security.selinux) failed");
2623
2624 assert_eq!(whatever_sid, selinux_hooks::get_cached_sid(node));
2626 },
2627 )
2628 .await;
2629 }
2630
2631 #[fuchsia::test]
2632 async fn fs_node_setsecurity_selinux_enforcing_invalid_context_fails() {
2633 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2634 |locked, current_task, _security_server| {
2635 let node = &testing::create_test_file(locked, current_task).entry.node;
2636
2637 let before_sid = selinux_hooks::get_cached_sid(node);
2638 assert_ne!(Some(InitialSid::Unlabeled.into()), before_sid);
2639
2640 assert!(
2641 check_fs_node_setxattr_access(
2642 ¤t_task,
2643 &node,
2644 XATTR_NAME_SELINUX.to_bytes().into(),
2645 "!".into(), XattrOp::Set,
2647 )
2648 .is_err()
2649 );
2650
2651 assert_eq!(before_sid, selinux_hooks::get_cached_sid(node));
2652 },
2653 )
2654 .await;
2655 }
2656
2657 #[fuchsia::test]
2658 async fn fs_node_setsecurity_selinux_permissive_invalid_context_sets_xattr_and_label() {
2659 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2660 |locked, current_task, security_server| {
2661 security_server.set_enforcing(false);
2662 let node = &testing::create_test_file(locked, current_task).entry.node;
2663
2664 assert_ne!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2665
2666 fs_node_setsecurity(
2667 locked,
2668 current_task,
2669 &node,
2670 XATTR_NAME_SELINUX.to_bytes().into(),
2671 "!".into(), XattrOp::Set,
2673 )
2674 .expect("set_xattr(security.selinux) failed");
2675
2676 assert_eq!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2677 },
2678 )
2679 .await;
2680 }
2681
2682 #[fuchsia::test]
2683 async fn fs_node_setsecurity_different_sid_for_different_context() {
2684 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2685 |locked, current_task, _security_server| {
2686 let node = &testing::create_test_file(locked, current_task).entry.node;
2687
2688 fs_node_setsecurity(
2689 locked,
2690 current_task,
2691 &node,
2692 XATTR_NAME_SELINUX.to_bytes().into(),
2693 VALID_SECURITY_CONTEXT.into(),
2694 XattrOp::Set,
2695 )
2696 .expect("set_xattr(security.selinux) failed");
2697
2698 assert!(selinux_hooks::get_cached_sid(node).is_some());
2699
2700 let first_sid = selinux_hooks::get_cached_sid(node).unwrap();
2701 fs_node_setsecurity(
2702 locked,
2703 current_task,
2704 &node,
2705 XATTR_NAME_SELINUX.to_bytes().into(),
2706 DIFFERENT_VALID_SECURITY_CONTEXT.into(),
2707 XattrOp::Set,
2708 )
2709 .expect("set_xattr(security.selinux) failed");
2710
2711 assert!(selinux_hooks::get_cached_sid(node).is_some());
2712
2713 let second_sid = selinux_hooks::get_cached_sid(node).unwrap();
2714
2715 assert_ne!(first_sid, second_sid);
2716 },
2717 )
2718 .await;
2719 }
2720
2721 #[fuchsia::test]
2722 async fn fs_node_getsecurity_returns_cached_context() {
2723 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2724 |locked, current_task, security_server| {
2725 let node = &testing::create_test_file(locked, current_task).entry.node;
2726
2727 const TEST_VALUE: &str = "Something Random";
2729 node.ops()
2730 .set_xattr(
2731 locked.cast_locked::<FileOpsCore>(),
2732 node,
2733 current_task,
2734 XATTR_NAME_SELINUX.to_bytes().into(),
2735 TEST_VALUE.into(),
2736 XattrOp::Set,
2737 )
2738 .expect("set_xattr(security.selinux) failed");
2739
2740 let sid = security_server
2742 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2743 .expect("security context to SID");
2744 selinux_hooks::set_cached_sid(&node, sid);
2745
2746 let result = fs_node_getsecurity(
2748 locked,
2749 current_task,
2750 node,
2751 XATTR_NAME_SELINUX.to_bytes().into(),
2752 4096,
2753 );
2754 assert_eq!(
2755 result,
2756 Ok(ValueOrSize::Value(FsString::new(VALID_SECURITY_CONTEXT_WITH_NUL.into())))
2757 );
2758 },
2759 )
2760 .await;
2761 }
2762
2763 #[fuchsia::test]
2764 async fn fs_node_getsecurity_delegates_to_get_xattr() {
2765 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2766 |locked, current_task, security_server| {
2767 let node = &testing::create_test_file(locked, current_task).entry.node;
2768
2769 security_server.set_enforcing(false);
2772 const TEST_VALUE: &str = "Something Random";
2773 fs_node_setsecurity(
2774 locked,
2775 current_task,
2776 node,
2777 XATTR_NAME_SELINUX.to_bytes().into(),
2778 TEST_VALUE.into(),
2779 XattrOp::Set,
2780 )
2781 .expect("set_xattr(security.selinux) failed");
2782 security_server.set_enforcing(true);
2783
2784 let result = fs_node_getsecurity(
2786 locked,
2787 current_task,
2788 node,
2789 XATTR_NAME_SELINUX.to_bytes().into(),
2790 4096,
2791 );
2792 assert_eq!(result, Ok(ValueOrSize::Value(FsString::new(TEST_VALUE.into()))));
2793 },
2794 )
2795 .await;
2796 }
2797
2798 #[fuchsia::test]
2799 async fn set_get_procattr() {
2800 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2801 |_locked, current_task, _security_server| {
2802 assert_eq!(
2803 get_procattr(current_task, current_task, ProcAttr::Exec),
2804 Ok(Vec::new())
2805 );
2806
2807 assert_eq!(
2808 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2810 Ok(())
2811 );
2812
2813 assert_eq!(
2814 set_procattr(
2816 current_task,
2817 ProcAttr::SockCreate,
2818 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2819 ),
2820 error!(EACCES)
2821 );
2822
2823 assert_eq!(
2824 set_procattr(
2826 current_task,
2827 ProcAttr::Previous,
2828 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2829 ),
2830 error!(EINVAL)
2831 );
2832
2833 assert_eq!(
2834 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2836 error!(EINVAL)
2837 );
2838
2839 assert_eq!(
2840 get_procattr(current_task, current_task, ProcAttr::Exec),
2841 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2842 );
2843
2844 assert!(get_procattr(current_task, current_task, ProcAttr::Current).is_ok());
2845 },
2846 )
2847 .await;
2848 }
2849
2850 #[fuchsia::test]
2851 async fn set_get_procattr_with_nulls() {
2852 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2853 |_locked, current_task, _security_server| {
2854 assert_eq!(
2855 get_procattr(current_task, current_task, ProcAttr::Exec),
2856 Ok(Vec::new())
2857 );
2858
2859 assert_eq!(
2860 set_procattr(
2862 current_task,
2863 ProcAttr::Exec,
2864 VALID_SECURITY_CONTEXT_WITH_NUL.into()
2865 ),
2866 Ok(())
2867 );
2868
2869 assert_eq!(
2870 set_procattr(
2872 current_task,
2873 ProcAttr::FsCreate,
2874 INVALID_SECURITY_CONTEXT_INTERNAL_NUL.into()
2875 ),
2876 error!(EINVAL)
2877 );
2878
2879 assert_eq!(
2880 get_procattr(current_task, current_task, ProcAttr::Exec),
2881 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2882 );
2883
2884 assert_eq!(
2885 get_procattr(current_task, current_task, ProcAttr::FsCreate),
2886 Ok(Vec::new())
2887 );
2888 },
2889 )
2890 .await;
2891 }
2892
2893 #[fuchsia::test]
2894 async fn set_get_procattr_clear_context() {
2895 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2896 |_locked, current_task, _security_server| {
2897 assert_eq!(
2899 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2900 Ok(())
2901 );
2902 assert_eq!(
2903 set_procattr(
2904 current_task,
2905 ProcAttr::FsCreate,
2906 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2907 ),
2908 Ok(())
2909 );
2910
2911 assert_eq!(set_procattr(current_task, ProcAttr::Exec, b"\0"), Ok(()));
2913 assert_eq!(current_task.security_state.lock().exec_sid, None);
2914
2915 assert_eq!(set_procattr(current_task, ProcAttr::FsCreate, b"\x0a"), Ok(()));
2917 assert_eq!(current_task.security_state.lock().fscreate_sid, None);
2918 },
2919 )
2920 .await;
2921 }
2922
2923 #[fuchsia::test]
2924 async fn set_get_procattr_setcurrent() {
2925 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2926 |_locked, current_task, _security_server| {
2927 let initial_previous =
2929 get_procattr(current_task, current_task, ProcAttr::Previous).unwrap();
2930
2931 assert_eq!(
2932 set_procattr(current_task, ProcAttr::Current, VALID_SECURITY_CONTEXT.into()),
2934 Ok(())
2935 );
2936
2937 assert_eq!(
2938 get_procattr(current_task, current_task, ProcAttr::Current),
2940 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2941 );
2942
2943 assert_eq!(
2944 get_procattr(current_task, current_task, ProcAttr::Previous),
2946 Ok(initial_previous.clone())
2947 );
2948
2949 assert_eq!(
2950 set_procattr(
2952 current_task,
2953 ProcAttr::Current,
2954 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2955 ),
2956 Ok(())
2957 );
2958
2959 assert_eq!(
2960 get_procattr(current_task, current_task, ProcAttr::Current),
2962 Ok(DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL.into())
2963 );
2964
2965 assert_eq!(
2966 get_procattr(current_task, current_task, ProcAttr::Previous),
2968 Ok(initial_previous.clone())
2969 );
2970 },
2971 )
2972 .await;
2973 }
2974
2975 #[fuchsia::test]
2976 async fn set_get_procattr_selinux_permissive() {
2977 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2978 |_locked, current_task, security_server| {
2979 security_server.set_enforcing(false);
2980 assert_eq!(
2981 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Exec),
2982 Ok(Vec::new())
2983 );
2984
2985 assert_eq!(
2986 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2988 Ok(())
2989 );
2990
2991 assert_eq!(
2992 set_procattr(
2995 current_task,
2996 ProcAttr::FsCreate,
2997 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2998 ),
2999 Ok(())
3000 );
3001
3002 assert_eq!(
3003 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3005 error!(EINVAL)
3006 );
3007
3008 assert_eq!(
3009 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Exec),
3010 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3011 );
3012
3013 assert!(
3014 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Current)
3015 .is_ok()
3016 );
3017 },
3018 )
3019 .await;
3020 }
3021
3022 #[fuchsia::test]
3023 async fn set_get_procattr_selinux_disabled() {
3024 spawn_kernel_and_run(async |_, current_task| {
3025 assert_eq!(
3026 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3027 error!(EINVAL)
3028 );
3029
3030 assert_eq!(
3031 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3033 error!(EINVAL)
3034 );
3035
3036 assert_eq!(
3037 set_procattr(¤t_task, ProcAttr::FsCreate, VALID_SECURITY_CONTEXT.into()),
3039 error!(EINVAL)
3040 );
3041
3042 assert_eq!(
3043 set_procattr(¤t_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3045 error!(EINVAL)
3046 );
3047
3048 assert_eq!(
3049 get_procattr(¤t_task, ¤t_task.temp_task(), ProcAttr::Current),
3050 error!(EINVAL)
3051 );
3052 })
3053 .await;
3054 }
3055
3056 #[fuchsia::test]
3057 async fn create_file_with_fscreate_sid() {
3058 spawn_kernel_with_selinux_hooks_test_policy_and_run(
3059 |locked, current_task, security_server| {
3060 let sid =
3061 security_server.security_context_to_sid(VALID_SECURITY_CONTEXT.into()).unwrap();
3062 let source_node = &testing::create_test_file(locked, current_task).entry.node;
3063
3064 fs_node_setsecurity(
3065 locked,
3066 current_task,
3067 &source_node,
3068 XATTR_NAME_SELINUX.to_bytes().into(),
3069 VALID_SECURITY_CONTEXT.into(),
3070 XattrOp::Set,
3071 )
3072 .expect("set_xattr(security.selinux) failed");
3073
3074 let dir_entry = fs_node_copy_up(current_task, source_node, || {
3075 current_task
3076 .fs()
3077 .root()
3078 .create_node(
3079 locked,
3080 ¤t_task,
3081 "test_file2".into(),
3082 FileMode::IFREG,
3083 DeviceType::NONE,
3084 )
3085 .unwrap()
3086 })
3087 .entry;
3088
3089 assert_eq!(get_cached_sid(&dir_entry.node), Some(sid));
3090 },
3091 )
3092 .await;
3093 }
3094}