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