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, LockBefore, LockEqualOrBefore, Locked, ThreadGroupLimits};
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) -> KernelState {
266 track_hook_duration!("security.hooks.kernel_init_security");
267 KernelState { state: enabled.then(|| selinux_hooks::kernel_init_security(options, exceptions)) }
268}
269
270pub fn binder_set_context_mgr(current_task: &CurrentTask) -> Result<(), Errno> {
273 track_hook_duration!("security.hooks.binder_set_context_mgr");
274 if_selinux_else_default_ok(current_task, |security_server| {
275 selinux_hooks::binder::binder_set_context_mgr(security_server, current_task)
276 })
277}
278
279pub fn binder_transaction(
282 current_task: &CurrentTask,
283 target_task: &Task,
284 connection_state: &BinderConnectionState,
285) -> Result<(), Errno> {
286 track_hook_duration!("security.hooks.binder_transaction");
287 if_selinux_else_default_ok(current_task, |security_server| {
288 selinux_hooks::binder::binder_transaction(
289 security_server,
290 &connection_state.state,
291 current_task,
292 target_task,
293 )
294 })
295}
296
297pub fn binder_transfer_binder(current_task: &CurrentTask, target_task: &Task) -> Result<(), Errno> {
300 track_hook_duration!("security.hooks.binder_transfer_binder");
301 if_selinux_else_default_ok(current_task, |security_server| {
302 selinux_hooks::binder::binder_transfer_binder(security_server, current_task, target_task)
303 })
304}
305
306pub fn binder_transfer_file(
309 current_task: &CurrentTask,
310 receiving_task: &Task,
311 file: &FileObject,
312) -> Result<(), Errno> {
313 track_hook_duration!("security.hooks.binder_transfer_file");
314 if_selinux_else_default_ok(current_task, |security_server| {
315 selinux_hooks::binder::binder_transfer_file(
316 security_server,
317 current_task,
318 receiving_task,
319 file,
320 )
321 })
322}
323
324pub fn binder_get_context(
327 current_task: &CurrentTask,
328 connection_state: &BinderConnectionState,
329) -> Option<Vec<u8>> {
330 track_hook_duration!("security.hooks.binder_get_context");
331 if_selinux_else(
332 current_task,
333 |security_server| {
334 selinux_hooks::binder::binder_get_context(&security_server, &connection_state.state)
335 },
336 || None,
337 )
338}
339
340pub fn sb_eat_lsm_opts(
344 kernel: &Kernel,
345 mount_params: &mut MountParams,
346) -> Result<FileSystemMountOptions, Errno> {
347 track_hook_duration!("security.hooks.sb_eat_lsm_opts");
348 if kernel.security_state.state.is_some() {
349 return selinux_hooks::superblock::sb_eat_lsm_opts(mount_params);
350 }
351 Ok(FileSystemMountOptions::default())
352}
353
354pub fn file_system_init_security(
357 mount_options: &FileSystemMountOptions,
358 ops: &dyn FileSystemOps,
359) -> Result<FileSystemState, Errno> {
360 track_hook_duration!("security.hooks.file_system_init_security");
361 Ok(FileSystemState {
362 state: selinux_hooks::superblock::file_system_init_security(mount_options, ops)?,
363 })
364}
365
366pub fn file_system_post_init_security(kernel: &Kernel, file_system: &FileSystemHandle) {
371 track_hook_duration!("security.hooks.file_system_post_init_security");
372 if let Some(state) = &kernel.security_state.state {
373 if !state.has_policy() {
374 log_debug!("Queuing {} FileSystem for labeling", file_system.name());
377 state.pending_file_systems.lock().insert(WeakKey::from(&file_system));
378 }
379 }
380}
381
382pub fn file_system_resolve_security<L>(
387 locked: &mut Locked<L>,
388 current_task: &CurrentTask,
389 file_system: &FileSystemHandle,
390) -> Result<(), Errno>
391where
392 L: LockEqualOrBefore<FileOpsCore>,
393{
394 track_hook_duration!("security.hooks.file_system_resolve_security");
395 if_selinux_else_default_ok_with_context(locked, current_task, |locked, security_server| {
396 selinux_hooks::superblock::file_system_resolve_security(
397 locked,
398 security_server,
399 current_task,
400 file_system,
401 )
402 })
403}
404
405pub struct FsNodeSecurityXattr {
407 pub name: &'static FsStr,
408 pub value: FsString,
409}
410
411pub fn mmap_file(
415 current_task: &CurrentTask,
416 file: Option<&FileHandle>,
417 protection_flags: ProtectionFlags,
418 options: MappingOptions,
419) -> Result<(), Errno> {
420 track_hook_duration!("security.hooks.mmap_file");
421 if_selinux_else_default_ok(current_task, |security_server| {
422 selinux_hooks::file::mmap_file(
423 security_server,
424 current_task,
425 file,
426 protection_flags,
427 options,
428 )
429 })
430}
431
432pub fn file_mprotect(
436 current_task: &CurrentTask,
437 range: &Range<UserAddress>,
438 mapping: &Mapping,
439 prot: ProtectionFlags,
440) -> Result<(), Errno> {
441 track_hook_duration!("security.hooks.file_mprotect");
442 if_selinux_else_default_ok(current_task, |security_server| {
443 selinux_hooks::file::file_mprotect(security_server, current_task, range, mapping, prot)
444 })
445}
446
447pub fn file_permission(
450 current_task: &CurrentTask,
451 file: &FileObject,
452 permission_flags: PermissionFlags,
453) -> Result<(), Errno> {
454 track_hook_duration!("security.hooks.file_permission");
455 if_selinux_else_default_ok(current_task, |security_server| {
456 selinux_hooks::file::file_permission(security_server, current_task, file, permission_flags)
457 })
458}
459
460pub fn fs_node_init_with_dentry<L>(
466 locked: &mut Locked<L>,
467 current_task: &CurrentTask,
468 dir_entry: &DirEntryHandle,
469) -> Result<(), Errno>
470where
471 L: LockEqualOrBefore<FileOpsCore>,
472{
473 track_hook_duration!("security.hooks.fs_node_init_with_dentry");
474 if let Some(state) = ¤t_task.kernel().security_state.state {
479 selinux_hooks::fs_node::fs_node_init_with_dentry(
480 Some(locked.cast_locked()),
481 &state.server,
482 current_task,
483 dir_entry,
484 )
485 } else {
486 Ok(())
487 }
488}
489
490pub fn fs_node_init_with_dentry_no_xattr(
491 current_task: &CurrentTask,
492 dir_entry: &DirEntryHandle,
493) -> Result<(), Errno> {
494 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
495 if let Some(state) = ¤t_task.kernel().security_state.state {
500 if Anon::is_private(&dir_entry.node) {
503 return selinux_hooks::fs_node::fs_node_init_anon(
504 &state.server,
505 current_task,
506 &dir_entry.node,
507 "",
508 );
509 }
510
511 selinux_hooks::fs_node::fs_node_init_with_dentry(
512 None,
513 &state.server,
514 current_task,
515 dir_entry,
516 )
517 } else {
518 Ok(())
519 }
520}
521
522pub fn fs_node_init_with_dentry_deferred(kernel: &Kernel, dir_entry: &DirEntryHandle) {
526 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
527 if kernel.security_state.state.is_some() {
528 selinux_hooks::fs_node::fs_node_init_with_dentry_deferred(dir_entry);
529 }
530}
531
532pub fn fs_node_notify_security_context(
539 current_task: &CurrentTask,
540 fs_node: &FsNode,
541 context: &FsStr,
542) -> Result<(), Errno> {
543 if_selinux_else(
544 current_task,
545 |security_server| {
546 selinux_hooks::fs_node::fs_node_notify_security_context(
547 security_server,
548 fs_node,
549 context,
550 )
551 },
552 || error!(ENOTSUP),
553 )
554}
555
556pub fn fs_node_init_on_create(
568 current_task: &CurrentTask,
569 new_node: &FsNode,
570 parent: &FsNode,
571 name: &FsStr,
572) -> Result<Option<FsNodeSecurityXattr>, Errno> {
573 track_hook_duration!("security.hooks.fs_node_init_on_create");
574 if_selinux_else_default_ok(current_task, |security_server| {
575 selinux_hooks::fs_node::fs_node_init_on_create(
576 security_server,
577 current_task,
578 new_node,
579 Some(parent),
580 name,
581 )
582 })
583}
584
585pub fn fs_node_init_anon(
590 current_task: &CurrentTask,
591 new_node: &FsNode,
592 node_type: &str,
593) -> Result<(), Errno> {
594 track_hook_duration!("security.hooks.fs_node_init_anon");
595 if let Some(state) = current_task.kernel().security_state.state.as_ref() {
596 selinux_hooks::fs_node::fs_node_init_anon(&state.server, current_task, new_node, node_type)
597 } else {
598 Ok(())
599 }
600}
601
602pub fn fs_node_init_memfd(current_task: &CurrentTask, new_node: &FsNode) {
605 track_hook_duration!("security.hooks.fs_node_init_anon");
606 if let Some(state) = current_task.kernel().security_state.state.as_ref() {
607 selinux_hooks::fs_node::fs_node_init_memfd(&state.server, current_task, new_node)
608 }
609}
610
611pub fn check_fs_node_create_access(
615 current_task: &CurrentTask,
616 parent: &FsNode,
617 mode: FileMode,
618 name: &FsStr,
619) -> Result<(), Errno> {
620 track_hook_duration!("security.hooks.check_fs_node_create_access");
621 if_selinux_else_default_ok(current_task, |security_server| {
622 selinux_hooks::fs_node::check_fs_node_create_access(
623 security_server,
624 current_task,
625 parent,
626 mode,
627 name,
628 )
629 })
630}
631
632pub fn check_fs_node_symlink_access(
636 current_task: &CurrentTask,
637 parent: &FsNode,
638 name: &FsStr,
639 old_path: &FsStr,
640) -> Result<(), Errno> {
641 track_hook_duration!("security.hooks.check_fs_node_symlink_access");
642 if_selinux_else_default_ok(current_task, |security_server| {
643 selinux_hooks::fs_node::check_fs_node_symlink_access(
644 security_server,
645 current_task,
646 parent,
647 name,
648 old_path,
649 )
650 })
651}
652
653pub fn check_fs_node_mkdir_access(
657 current_task: &CurrentTask,
658 parent: &FsNode,
659 mode: FileMode,
660 name: &FsStr,
661) -> Result<(), Errno> {
662 track_hook_duration!("security.hooks.check_fs_node_mkdir_access");
663 if_selinux_else_default_ok(current_task, |security_server| {
664 selinux_hooks::fs_node::check_fs_node_mkdir_access(
665 security_server,
666 current_task,
667 parent,
668 mode,
669 name,
670 )
671 })
672}
673
674pub fn check_fs_node_mknod_access(
680 current_task: &CurrentTask,
681 parent: &FsNode,
682 mode: FileMode,
683 name: &FsStr,
684 device_id: DeviceType,
685) -> Result<(), Errno> {
686 track_hook_duration!("security.hooks.check_fs_node_mknod_access");
687 assert!(!mode.is_reg());
688
689 if_selinux_else_default_ok(current_task, |security_server| {
690 selinux_hooks::fs_node::check_fs_node_mknod_access(
691 security_server,
692 current_task,
693 parent,
694 mode,
695 name,
696 device_id,
697 )
698 })
699}
700
701pub fn check_fs_node_link_access(
704 current_task: &CurrentTask,
705 parent: &FsNode,
706 child: &FsNode,
707) -> Result<(), Errno> {
708 track_hook_duration!("security.hooks.check_fs_node_link_access");
709 if_selinux_else_default_ok(current_task, |security_server| {
710 selinux_hooks::fs_node::check_fs_node_link_access(
711 security_server,
712 current_task,
713 parent,
714 child,
715 )
716 })
717}
718
719pub fn check_fs_node_unlink_access(
722 current_task: &CurrentTask,
723 parent: &FsNode,
724 child: &FsNode,
725 name: &FsStr,
726) -> Result<(), Errno> {
727 track_hook_duration!("security.hooks.check_fs_node_unlink_access");
728 if_selinux_else_default_ok(current_task, |security_server| {
729 selinux_hooks::fs_node::check_fs_node_unlink_access(
730 security_server,
731 current_task,
732 parent,
733 child,
734 name,
735 )
736 })
737}
738
739pub fn check_fs_node_rmdir_access(
742 current_task: &CurrentTask,
743 parent: &FsNode,
744 child: &FsNode,
745 name: &FsStr,
746) -> Result<(), Errno> {
747 track_hook_duration!("security.hooks.check_fs_node_rmdir_access");
748 if_selinux_else_default_ok(current_task, |security_server| {
749 selinux_hooks::fs_node::check_fs_node_rmdir_access(
750 security_server,
751 current_task,
752 parent,
753 child,
754 name,
755 )
756 })
757}
758
759pub fn check_fs_node_rename_access(
764 current_task: &CurrentTask,
765 old_parent: &FsNode,
766 moving_node: &FsNode,
767 new_parent: &FsNode,
768 replaced_node: Option<&FsNode>,
769 old_basename: &FsStr,
770 new_basename: &FsStr,
771) -> Result<(), Errno> {
772 track_hook_duration!("security.hooks.check_fs_node_rename_access");
773 if_selinux_else_default_ok(current_task, |security_server| {
774 selinux_hooks::fs_node::check_fs_node_rename_access(
775 security_server,
776 current_task,
777 old_parent,
778 moving_node,
779 new_parent,
780 replaced_node,
781 old_basename,
782 new_basename,
783 )
784 })
785}
786
787pub fn check_fs_node_read_link_access(
790 current_task: &CurrentTask,
791 fs_node: &FsNode,
792) -> Result<(), Errno> {
793 track_hook_duration!("security.hooks.check_fs_node_read_link_access");
794 if_selinux_else_default_ok(current_task, |security_server| {
795 selinux_hooks::fs_node::check_fs_node_read_link_access(
796 security_server,
797 current_task,
798 fs_node,
799 )
800 })
801}
802
803pub fn fs_node_permission(
806 current_task: &CurrentTask,
807 fs_node: &FsNode,
808 permission_flags: PermissionFlags,
809 audit_context: Auditable<'_>,
810) -> Result<(), Errno> {
811 track_hook_duration!("security.hooks.fs_node_permission");
812 if_selinux_else_default_ok(current_task, |security_server| {
813 selinux_hooks::fs_node::fs_node_permission(
814 security_server,
815 current_task,
816 fs_node,
817 permission_flags,
818 audit_context,
819 )
820 })
821}
822
823pub fn file_receive(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
826 track_hook_duration!("security.hooks.file_receive");
827 if_selinux_else_default_ok(current_task, |security_server| {
828 let receiving_sid = current_task_state(current_task).lock().current_sid;
829 selinux_hooks::file::file_receive(security_server, current_task, receiving_sid, file)
830 })
831}
832
833pub fn file_alloc_security(current_task: &CurrentTask) -> FileObjectState {
836 track_hook_duration!("security.hooks.file_alloc_security");
837 FileObjectState { state: selinux_hooks::file::file_alloc_security(current_task) }
838}
839
840pub fn binder_connection_alloc(current_task: &CurrentTask) -> BinderConnectionState {
843 track_hook_duration!("security.hooks.binder_connection_alloc");
844 BinderConnectionState { state: selinux_hooks::binder::binder_connection_alloc(current_task) }
845}
846
847pub fn bpf_map_alloc(current_task: &CurrentTask) -> BpfMapState {
851 track_hook_duration!("security.hooks.bpf_map_alloc");
852 BpfMapState { state: selinux_hooks::bpf::bpf_map_alloc(current_task) }
853}
854
855pub fn bpf_prog_alloc(current_task: &CurrentTask) -> BpfProgState {
859 track_hook_duration!("security.hooks.bpf_prog_alloc");
860 BpfProgState { state: selinux_hooks::bpf::bpf_prog_alloc(current_task) }
861}
862
863pub fn check_file_ioctl_access(
866 current_task: &CurrentTask,
867 file: &FileObject,
868 request: u32,
869) -> Result<(), Errno> {
870 track_hook_duration!("security.hooks.check_file_ioctl_access");
871 if_selinux_else_default_ok(current_task, |security_server| {
872 selinux_hooks::file::check_file_ioctl_access(security_server, current_task, file, request)
873 })
874}
875
876pub fn fs_node_copy_up<R>(
882 current_task: &CurrentTask,
883 fs_node: &FsNode,
884 do_copy_up: impl FnOnce() -> R,
885) -> R {
886 if_selinux_else_with_context(
887 do_copy_up,
888 current_task,
889 |do_copy_up, _security_server| {
890 selinux_hooks::fs_node::fs_node_copy_up(current_task, fs_node, do_copy_up)
891 },
892 |do_copy_up| do_copy_up(),
893 )
894}
895
896pub fn check_file_lock_access(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
904 track_hook_duration!("security.hooks.check_file_lock_access");
905 if_selinux_else_default_ok(current_task, |security_server| {
906 selinux_hooks::file::check_file_lock_access(security_server, current_task, file)
907 })
908}
909
910pub fn check_file_fcntl_access(
913 current_task: &CurrentTask,
914 file: &FileObject,
915 fcntl_cmd: u32,
916 fcntl_arg: u64,
917) -> Result<(), Errno> {
918 track_hook_duration!("security.hooks.check_file_fcntl_access");
919 if_selinux_else_default_ok(current_task, |security_server| {
920 selinux_hooks::file::check_file_fcntl_access(
921 security_server,
922 current_task,
923 file,
924 fcntl_cmd,
925 fcntl_arg,
926 )
927 })
928}
929
930pub fn check_fs_node_setattr_access(
933 current_task: &CurrentTask,
934 node: &FsNode,
935 attributes: &zxio_node_attr_has_t,
936) -> Result<(), Errno> {
937 track_hook_duration!("security.hooks.check_fs_node_setattr_access");
938 if_selinux_else_default_ok(current_task, |security_server| {
939 selinux_hooks::fs_node::check_fs_node_setattr_access(
940 security_server,
941 current_task,
942 node,
943 attributes,
944 )
945 })
946}
947
948pub fn task_alloc_for_kernel() -> TaskState {
951 track_hook_duration!("security.hooks.task_alloc_for_kernel");
952 TaskState(Arc::new(selinux_hooks::TaskAttrs::for_kernel().into()))
953}
954
955pub fn task_alloc(current_task: &CurrentTask, clone_flags: u64) -> TaskState {
959 track_hook_duration!("security.hooks.task_alloc");
960 TaskState(Arc::new(selinux_hooks::task::task_alloc(current_task, clone_flags).into()))
961}
962
963pub fn task_to_fs_node(current_task: &CurrentTask, task: &TempRef<'_, Task>, fs_node: &FsNode) {
969 track_hook_duration!("security.hooks.task_to_fs_node");
970 if current_task.kernel().security_state.state.is_some() {
973 selinux_hooks::task::fs_node_init_with_task(task, &fs_node);
974 }
975}
976
977pub fn task_for_context(task: &Task, context: &FsStr) -> Result<TaskState, Errno> {
983 track_hook_duration!("security.hooks.task_for_context");
984 Ok(TaskState(Arc::new(
985 if let Some(kernel_state) = task.kernel().security_state.state.as_ref() {
986 selinux_hooks::task::task_alloc_from_context(&kernel_state.server, context)
987 } else {
988 Ok(selinux_hooks::TaskAttrs::for_selinux_disabled())
989 }?
990 .into(),
991 )))
992}
993
994pub fn has_dontaudit_access(current_task: &CurrentTask, fs_node: &FsNode) -> bool {
998 track_hook_duration!("security.hooks.has_dontaudit_access");
999 if_selinux_else(
1000 current_task,
1001 |security_server| {
1002 selinux_hooks::fs_node::has_dontaudit_access(security_server, current_task, fs_node)
1003 },
1004 || false,
1005 )
1006}
1007
1008pub fn is_task_capable_noaudit(
1011 current_task: &CurrentTask,
1012 capability: starnix_uapi::auth::Capabilities,
1013) -> bool {
1014 track_hook_duration!("security.hooks.is_task_capable_noaudit");
1015 return common_cap::capable(current_task, capability).is_ok()
1016 && if_selinux_else(
1017 current_task,
1018 |security_server| {
1019 selinux_hooks::task::is_task_capable_noaudit(
1020 &security_server.as_permission_check(),
1021 ¤t_task,
1022 capability,
1023 )
1024 },
1025 || true,
1026 );
1027}
1028
1029pub fn check_task_capable(
1032 current_task: &CurrentTask,
1033 capability: starnix_uapi::auth::Capabilities,
1034) -> Result<(), Errno> {
1035 track_hook_duration!("security.hooks.check_task_capable");
1036 common_cap::capable(current_task, capability)?;
1037 if_selinux_else_default_ok(current_task, |security_server| {
1038 selinux_hooks::task::check_task_capable(
1039 &security_server.as_permission_check(),
1040 ¤t_task,
1041 capability,
1042 )
1043 })
1044}
1045
1046pub fn check_task_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1052 track_hook_duration!("security.hooks.check_task_create_access");
1053 if_selinux_else_default_ok(current_task, |security_server| {
1054 selinux_hooks::task::check_task_create_access(
1055 &security_server.as_permission_check(),
1056 current_task,
1057 )
1058 })
1059}
1060
1061pub fn bprm_creds_for_exec(
1066 current_task: &CurrentTask,
1067 executable: &NamespaceNode,
1068) -> Result<ResolvedElfState, Errno> {
1069 track_hook_duration!("security.hooks.bprm_creds_for_exec");
1070 if_selinux_else(
1071 current_task,
1072 |security_server| {
1073 selinux_hooks::task::bprm_creds_for_exec(&security_server, current_task, executable)
1074 },
1075 || Ok(ResolvedElfState { sid: None, require_secure_exec: false }),
1076 )
1077}
1078
1079pub fn check_socket_create_access<L>(
1082 locked: &mut Locked<L>,
1083 current_task: &CurrentTask,
1084 domain: SocketDomain,
1085 socket_type: SocketType,
1086 protocol: SocketProtocol,
1087 kernel_private: bool,
1088) -> Result<(), Errno>
1089where
1090 L: LockEqualOrBefore<FileOpsCore>,
1091{
1092 track_hook_duration!("security.hooks.socket_create");
1093 if_selinux_else_default_ok(current_task, |security_server| {
1094 selinux_hooks::socket::check_socket_create_access(
1095 locked,
1096 &security_server,
1097 current_task,
1098 domain,
1099 socket_type,
1100 protocol,
1101 kernel_private,
1102 )
1103 })
1104}
1105
1106pub fn socket_socketpair(
1109 current_task: &CurrentTask,
1110 left: DowncastedFile<'_, SocketFile>,
1111 right: DowncastedFile<'_, SocketFile>,
1112) -> Result<(), Errno> {
1113 track_hook_duration!("security.hooks.socket_socketpair");
1114 if_selinux_else_default_ok(current_task, |_| {
1115 selinux_hooks::socket::socket_socketpair(left, right)
1116 })
1117}
1118
1119pub fn socket_post_create(socket: &Socket) {
1122 track_hook_duration!("security.hooks.socket_post_create");
1123 selinux_hooks::socket::socket_post_create(socket);
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 exec_binprm<L>(
1405 locked: &mut Locked<L>,
1406 current_task: &CurrentTask,
1407 elf_security_state: &ResolvedElfState,
1408) where
1409 L: LockBefore<ThreadGroupLimits>,
1410{
1411 track_hook_duration!("security.hooks.exec_binprm");
1412 if_selinux_else(
1413 current_task,
1414 |security_server| {
1415 selinux_hooks::task::exec_binprm(
1416 locked,
1417 security_server,
1418 current_task,
1419 elf_security_state,
1420 )
1421 },
1422 || (),
1423 );
1424}
1425
1426pub fn check_getsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1429 track_hook_duration!("security.hooks.check_getsched_access");
1430 if_selinux_else_default_ok(source, |security_server| {
1431 selinux_hooks::task::check_getsched_access(
1432 &security_server.as_permission_check(),
1433 &source,
1434 &target,
1435 )
1436 })
1437}
1438
1439pub fn check_setsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1442 track_hook_duration!("security.hooks.check_setsched_access");
1443 if_selinux_else_default_ok(source, |security_server| {
1444 selinux_hooks::task::check_setsched_access(
1445 &security_server.as_permission_check(),
1446 &source,
1447 &target,
1448 )
1449 })
1450}
1451
1452pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1455 track_hook_duration!("security.hooks.check_getpgid_access");
1456 if_selinux_else_default_ok(source, |security_server| {
1457 selinux_hooks::task::check_getpgid_access(
1458 &security_server.as_permission_check(),
1459 &source,
1460 &target,
1461 )
1462 })
1463}
1464
1465pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1468 track_hook_duration!("security.hooks.check_setpgid_access");
1469 if_selinux_else_default_ok(source, |security_server| {
1470 selinux_hooks::task::check_setpgid_access(
1471 &security_server.as_permission_check(),
1472 &source,
1473 &target,
1474 )
1475 })
1476}
1477
1478pub fn check_task_getsid(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1481 track_hook_duration!("security.hooks.check_task_getsid");
1482 if_selinux_else_default_ok(source, |security_server| {
1483 selinux_hooks::task::check_task_getsid(
1484 &security_server.as_permission_check(),
1485 &source,
1486 &target,
1487 )
1488 })
1489}
1490
1491pub fn check_getcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1494 track_hook_duration!("security.hooks.check_getcap_access");
1495 if_selinux_else_default_ok(source, |security_server| {
1496 selinux_hooks::task::check_getcap_access(
1497 &security_server.as_permission_check(),
1498 &source,
1499 &target,
1500 )
1501 })
1502}
1503
1504pub fn check_setcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1508 track_hook_duration!("security.hooks.check_setcap_access");
1509 if_selinux_else_default_ok(source, |security_server| {
1510 selinux_hooks::task::check_setcap_access(
1511 &security_server.as_permission_check(),
1512 &source,
1513 &target,
1514 )
1515 })
1516}
1517
1518pub fn check_signal_access(
1521 source: &CurrentTask,
1522 target: &Task,
1523 signal: Signal,
1524) -> Result<(), Errno> {
1525 track_hook_duration!("security.hooks.check_signal_access");
1526 if_selinux_else_default_ok(source, |security_server| {
1527 selinux_hooks::task::check_signal_access(
1528 &security_server.as_permission_check(),
1529 &source,
1530 &target,
1531 signal,
1532 )
1533 })
1534}
1535
1536pub fn check_syslog_access(source: &CurrentTask, action: SyslogAction) -> Result<(), Errno> {
1539 track_hook_duration!("security.hooks.check_syslog_access");
1540 if_selinux_else_default_ok(source, |security_server| {
1541 selinux_hooks::task::check_syslog_access(
1542 &security_server.as_permission_check(),
1543 &source,
1544 action,
1545 )
1546 })
1547}
1548
1549pub fn ptrace_traceme(current_task: &CurrentTask, parent_tracer_task: &Task) -> Result<(), Errno> {
1552 track_hook_duration!("security.hooks.ptrace_traceme");
1553 yama::ptrace_traceme(current_task, parent_tracer_task)?;
1554 common_cap::ptrace_traceme(current_task, parent_tracer_task)?;
1555 if_selinux_else_default_ok(current_task, |security_server| {
1556 selinux_hooks::task::ptrace_traceme(
1557 &security_server.as_permission_check(),
1558 current_task,
1559 parent_tracer_task,
1560 )
1561 })
1562}
1563
1564pub fn ptrace_access_check(
1567 current_task: &CurrentTask,
1568 tracee_task: &Task,
1569 mode: PtraceAccessMode,
1570) -> Result<(), Errno> {
1571 track_hook_duration!("security.hooks.ptrace_access_check");
1572 yama::ptrace_access_check(current_task, tracee_task, mode)?;
1573 common_cap::ptrace_access_check(current_task, tracee_task, mode)?;
1574 if_selinux_else_default_ok(current_task, |security_server| {
1575 selinux_hooks::task::ptrace_access_check(
1576 &security_server.as_permission_check(),
1577 current_task,
1578 tracee_task,
1579 mode,
1580 )
1581 })
1582}
1583
1584pub fn task_prlimit(
1587 source: &CurrentTask,
1588 target: &Task,
1589 check_get_rlimit: bool,
1590 check_set_rlimit: bool,
1591) -> Result<(), Errno> {
1592 track_hook_duration!("security.hooks.task_prlimit");
1593 if_selinux_else_default_ok(source, |security_server| {
1594 selinux_hooks::task::task_prlimit(
1595 &security_server.as_permission_check(),
1596 &source,
1597 &target,
1598 check_get_rlimit,
1599 check_set_rlimit,
1600 )
1601 })
1602}
1603
1604pub fn task_setrlimit(
1607 source: &CurrentTask,
1608 target: &Task,
1609 old_limit: rlimit,
1610 new_limit: rlimit,
1611) -> Result<(), Errno> {
1612 track_hook_duration!("security.hooks.task_setrlimit");
1613 if_selinux_else_default_ok(source, |security_server| {
1614 selinux_hooks::task::task_setrlimit(
1615 &security_server.as_permission_check(),
1616 &source,
1617 &target,
1618 old_limit,
1619 new_limit,
1620 )
1621 })
1622}
1623
1624pub fn sb_kern_mount(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1627 track_hook_duration!("security.hooks.sb_kern_mount");
1628 if_selinux_else_default_ok(current_task, |security_server| {
1629 selinux_hooks::superblock::sb_kern_mount(
1630 &security_server.as_permission_check(),
1631 current_task,
1632 fs,
1633 )
1634 })
1635}
1636
1637pub fn sb_mount(
1641 current_task: &CurrentTask,
1642 path: &NamespaceNode,
1643 flags: MountFlags,
1644) -> Result<(), Errno> {
1645 track_hook_duration!("security.hooks.sb_mount");
1646 if_selinux_else_default_ok(current_task, |security_server| {
1647 selinux_hooks::superblock::sb_mount(
1648 &security_server.as_permission_check(),
1649 current_task,
1650 path,
1651 flags,
1652 )
1653 })
1654}
1655
1656pub fn sb_remount(
1659 current_task: &CurrentTask,
1660 mount: &Mount,
1661 new_mount_options: FileSystemMountOptions,
1662) -> Result<(), Errno> {
1663 track_hook_duration!("security.hooks.sb_remount");
1664 if_selinux_else_default_ok(current_task, |security_server| {
1665 selinux_hooks::superblock::sb_remount(security_server, mount, new_mount_options)
1666 })
1667}
1668
1669pub fn sb_show_options(
1672 kernel: &Kernel,
1673 buf: &mut impl OutputBuffer,
1674 mount: &Mount,
1675) -> Result<(), Errno> {
1676 track_hook_duration!("security.hooks.sb_show_options");
1677 if let Some(state) = &kernel.security_state.state {
1678 selinux_hooks::superblock::sb_show_options(&state.server, buf, mount)?;
1679 }
1680 Ok(())
1681}
1682
1683pub fn sb_statfs(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1686 track_hook_duration!("security.hooks.sb_statfs");
1687 if_selinux_else_default_ok(current_task, |security_server| {
1688 selinux_hooks::superblock::sb_statfs(
1689 &security_server.as_permission_check(),
1690 current_task,
1691 fs,
1692 )
1693 })
1694}
1695
1696pub fn sb_umount(
1700 current_task: &CurrentTask,
1701 node: &NamespaceNode,
1702 flags: UnmountFlags,
1703) -> Result<(), Errno> {
1704 track_hook_duration!("security.hooks.sb_umount");
1705 if_selinux_else_default_ok(current_task, |security_server| {
1706 selinux_hooks::superblock::sb_umount(
1707 &security_server.as_permission_check(),
1708 current_task,
1709 node,
1710 flags,
1711 )
1712 })
1713}
1714
1715pub fn check_fs_node_getattr_access(
1718 current_task: &CurrentTask,
1719 fs_node: &FsNode,
1720) -> Result<(), Errno> {
1721 track_hook_duration!("security.hooks.check_fs_node_getattr_access");
1722 if_selinux_else_default_ok(current_task, |security_server| {
1723 selinux_hooks::fs_node::check_fs_node_getattr_access(security_server, current_task, fs_node)
1724 })
1725}
1726
1727pub fn fs_node_xattr_skipcap(_current_task: &CurrentTask, name: &FsStr) -> bool {
1730 selinux_hooks::fs_node::fs_node_xattr_skipcap(name)
1731}
1732
1733pub fn check_fs_node_setxattr_access(
1739 current_task: &CurrentTask,
1740 fs_node: &FsNode,
1741 name: &FsStr,
1742 value: &FsStr,
1743 op: XattrOp,
1744) -> Result<(), Errno> {
1745 track_hook_duration!("security.hooks.check_fs_node_setxattr_access");
1746 common_cap::fs_node_setxattr(current_task, fs_node, name, value, op)?;
1747 if_selinux_else_default_ok(current_task, |security_server| {
1748 selinux_hooks::fs_node::check_fs_node_setxattr_access(
1749 security_server,
1750 current_task,
1751 fs_node,
1752 name,
1753 value,
1754 op,
1755 )
1756 })
1757}
1758
1759pub fn check_fs_node_getxattr_access(
1761 current_task: &CurrentTask,
1762 fs_node: &FsNode,
1763 name: &FsStr,
1764) -> Result<(), Errno> {
1765 track_hook_duration!("security.hooks.check_fs_node_getxattr_access");
1766 if_selinux_else_default_ok(current_task, |security_server| {
1767 selinux_hooks::fs_node::check_fs_node_getxattr_access(
1768 security_server,
1769 current_task,
1770 fs_node,
1771 name,
1772 )
1773 })
1774}
1775
1776pub fn check_fs_node_listxattr_access(
1778 current_task: &CurrentTask,
1779 fs_node: &FsNode,
1780) -> Result<(), Errno> {
1781 track_hook_duration!("security.hooks.check_fs_node_listxattr_access");
1782 if_selinux_else_default_ok(current_task, |security_server| {
1783 selinux_hooks::fs_node::check_fs_node_listxattr_access(
1784 security_server,
1785 current_task,
1786 fs_node,
1787 )
1788 })
1789}
1790
1791pub fn check_fs_node_removexattr_access(
1793 current_task: &CurrentTask,
1794 fs_node: &FsNode,
1795 name: &FsStr,
1796) -> Result<(), Errno> {
1797 track_hook_duration!("security.hooks.check_fs_node_removexattr_access");
1798 common_cap::fs_node_removexattr(current_task, fs_node, name)?;
1799 if_selinux_else_default_ok(current_task, |security_server| {
1800 selinux_hooks::fs_node::check_fs_node_removexattr_access(
1801 security_server,
1802 current_task,
1803 fs_node,
1804 name,
1805 )
1806 })
1807}
1808
1809pub fn fs_node_listsecurity(current_task: &CurrentTask, fs_node: &FsNode) -> Option<FsString> {
1816 track_hook_duration!("security.hooks.fs_node_listsecurity");
1817 if_selinux_else(
1818 current_task,
1819 |_| selinux_hooks::fs_node::fs_node_listsecurity(fs_node),
1820 || None,
1821 )
1822}
1823
1824pub fn fs_node_getsecurity<L>(
1832 locked: &mut Locked<L>,
1833 current_task: &CurrentTask,
1834 fs_node: &FsNode,
1835 name: &FsStr,
1836 max_size: usize,
1837) -> Result<ValueOrSize<FsString>, Errno>
1838where
1839 L: LockEqualOrBefore<FileOpsCore>,
1840{
1841 track_hook_duration!("security.hooks.fs_node_getsecurity");
1842 if_selinux_else_with_context(
1843 locked,
1844 current_task,
1845 |locked, security_server| {
1846 selinux_hooks::fs_node::fs_node_getsecurity(
1847 locked,
1848 security_server,
1849 current_task,
1850 fs_node,
1851 name,
1852 max_size,
1853 )
1854 },
1855 |locked| {
1856 fs_node.ops().get_xattr(
1857 locked.cast_locked::<FileOpsCore>(),
1858 fs_node,
1859 current_task,
1860 name,
1861 max_size,
1862 )
1863 },
1864 )
1865}
1866
1867pub fn fs_node_setsecurity<L>(
1873 locked: &mut Locked<L>,
1874 current_task: &CurrentTask,
1875 fs_node: &FsNode,
1876 name: &FsStr,
1877 value: &FsStr,
1878 op: XattrOp,
1879) -> Result<(), Errno>
1880where
1881 L: LockEqualOrBefore<FileOpsCore>,
1882{
1883 track_hook_duration!("security.hooks.fs_node_setsecurity");
1884 if_selinux_else_with_context(
1885 locked,
1886 current_task,
1887 |locked, security_server| {
1888 selinux_hooks::fs_node::fs_node_setsecurity(
1889 locked,
1890 security_server,
1891 current_task,
1892 fs_node,
1893 name,
1894 value,
1895 op,
1896 )
1897 },
1898 |locked| {
1899 fs_node.ops().set_xattr(
1900 locked.cast_locked::<FileOpsCore>(),
1901 fs_node,
1902 current_task,
1903 name,
1904 value,
1905 op,
1906 )
1907 },
1908 )
1909}
1910
1911pub fn check_bpf_access<Attr: FromBytes>(
1915 current_task: &CurrentTask,
1916 cmd: bpf_cmd,
1917 attr: &Attr,
1918 attr_size: u32,
1919) -> Result<(), Errno> {
1920 track_hook_duration!("security.hooks.check_bpf_access");
1921 if_selinux_else_default_ok(current_task, |security_server| {
1922 selinux_hooks::bpf::check_bpf_access(security_server, current_task, cmd, attr, attr_size)
1923 })
1924}
1925
1926pub fn check_bpf_map_access(
1930 current_task: &CurrentTask,
1931 bpf_map: &BpfMap,
1932 flags: PermissionFlags,
1933) -> Result<(), Errno> {
1934 track_hook_duration!("security.hooks.check_bpf_map_access");
1935 if_selinux_else_default_ok(current_task, |security_server| {
1936 let subject_sid = current_task_state(current_task).lock().current_sid;
1937 selinux_hooks::bpf::check_bpf_map_access(
1938 security_server,
1939 current_task,
1940 subject_sid,
1941 bpf_map,
1942 flags,
1943 )
1944 })
1945}
1946
1947pub fn check_bpf_prog_access(
1952 current_task: &CurrentTask,
1953 bpf_program: &Program,
1954) -> Result<(), Errno> {
1955 track_hook_duration!("security.hooks.check_bpf_prog_access");
1956 if_selinux_else_default_ok(current_task, |security_server| {
1957 let subject_sid = current_task_state(current_task).lock().current_sid;
1958 selinux_hooks::bpf::check_bpf_prog_access(
1959 security_server,
1960 current_task,
1961 subject_sid,
1962 bpf_program,
1963 )
1964 })
1965}
1966
1967pub fn check_perf_event_open_access(
1971 current_task: &CurrentTask,
1972 target_task_type: TargetTaskType<'_>,
1973 attr: &perf_event_attr,
1974 event_type: PerfEventType,
1975) -> Result<(), Errno> {
1976 track_hook_duration!("security.hooks.check_perf_event_open_access");
1977 if_selinux_else_default_ok(current_task, |security_server| {
1978 selinux_hooks::perf_event::check_perf_event_open_access(
1979 security_server,
1980 current_task,
1981 target_task_type,
1982 attr,
1983 event_type,
1984 )
1985 })
1986}
1987
1988pub fn perf_event_alloc(current_task: &CurrentTask) -> PerfEventState {
1992 track_hook_duration!("security.hooks.perf_event_alloc");
1993 PerfEventState { state: selinux_hooks::perf_event::perf_event_alloc(current_task) }
1994}
1995
1996pub fn check_perf_event_read_access(
1999 current_task: &CurrentTask,
2000 perf_event_file: &PerfEventFile,
2001) -> Result<(), Errno> {
2002 track_hook_duration!("security.hooks.check_perf_event_read_access");
2003 if_selinux_else_default_ok(current_task, |security_server| {
2004 selinux_hooks::perf_event::check_perf_event_read_access(
2005 security_server,
2006 current_task,
2007 perf_event_file,
2008 )
2009 })
2010}
2011
2012pub fn check_perf_event_write_access(
2015 current_task: &CurrentTask,
2016 perf_event_file: &PerfEventFile,
2017) -> Result<(), Errno> {
2018 track_hook_duration!("security.hooks.check_perf_event_write_access");
2019 if_selinux_else_default_ok(current_task, |security_server| {
2020 selinux_hooks::perf_event::check_perf_event_write_access(
2021 security_server,
2022 current_task,
2023 perf_event_file,
2024 )
2025 })
2026}
2027
2028#[derive(Debug, Clone, Copy, PartialEq)]
2030pub enum ProcAttr {
2031 Current,
2032 Exec,
2033 FsCreate,
2034 KeyCreate,
2035 Previous,
2036 SockCreate,
2037}
2038
2039pub fn get_procattr(
2042 current_task: &CurrentTask,
2043 target: &Task,
2044 attr: ProcAttr,
2045) -> Result<Vec<u8>, Errno> {
2046 track_hook_duration!("security.hooks.get_procattr");
2047 if_selinux_else(
2048 current_task,
2049 |security_server| {
2050 selinux_hooks::task::get_procattr(security_server, current_task, target, attr)
2051 },
2052 || error!(EINVAL),
2054 )
2055}
2056
2057pub fn set_procattr(
2060 current_task: &CurrentTask,
2061 attr: ProcAttr,
2062 context: &[u8],
2063) -> Result<(), Errno> {
2064 track_hook_duration!("security.hooks.set_procattr");
2065 if_selinux_else(
2066 current_task,
2067 |security_server| {
2068 selinux_hooks::task::set_procattr(security_server, current_task, attr, context)
2069 },
2070 || error!(EINVAL),
2072 )
2073}
2074
2075pub fn fs_is_xattr_labeled(fs: FileSystemHandle) -> bool {
2077 fs.security_state.state.supports_xattr()
2078}
2079
2080pub fn selinuxfs_init_null(current_task: &CurrentTask, null_fs_node: &FileHandle) {
2083 selinux_hooks::selinuxfs::selinuxfs_init_null(current_task, null_fs_node)
2086}
2087
2088pub fn selinuxfs_policy_loaded<L>(locked: &mut Locked<L>, current_task: &CurrentTask)
2094where
2095 L: LockEqualOrBefore<FileOpsCore>,
2096{
2097 track_hook_duration!("security.hooks.selinuxfs_policy_loaded");
2098 selinux_hooks::selinuxfs::selinuxfs_policy_loaded(locked, current_task)
2099}
2100
2101pub fn selinuxfs_get_admin_api(current_task: &CurrentTask) -> Option<Arc<SecurityServer>> {
2105 current_task.kernel().security_state.state.as_ref().map(|state| state.server.clone())
2106}
2107
2108pub fn selinuxfs_check_access(
2111 current_task: &CurrentTask,
2112 permission: SecurityPermission,
2113) -> Result<(), Errno> {
2114 track_hook_duration!("security.hooks.selinuxfs_check_access");
2115 if_selinux_else_default_ok(current_task, |security_server| {
2116 selinux_hooks::selinuxfs::selinuxfs_check_access(security_server, current_task, permission)
2117 })
2118}
2119
2120pub fn creds_start_internal_operation(creds: &mut FullCredentials) {
2123 track_hook_duration!("security.hooks.creds_start_internal_operation");
2124 creds.security_state.lock().internal_operation = true;
2125}
2126
2127pub mod testing {
2128 use super::{Arc, KernelState, SecurityServer, selinux_hooks};
2129 use starnix_sync::Mutex;
2130 use std::sync::OnceLock;
2131 use std::sync::atomic::AtomicU64;
2132
2133 pub fn kernel_state(security_server: Option<Arc<SecurityServer>>) -> KernelState {
2136 KernelState {
2137 state: security_server.map(|server| selinux_hooks::KernelState {
2138 server,
2139 pending_file_systems: Mutex::default(),
2140 selinuxfs_null: OnceLock::default(),
2141 access_denial_count: AtomicU64::new(0u64),
2142 has_policy: false.into(),
2143 }),
2144 }
2145 }
2146}
2147
2148#[cfg(test)]
2149mod tests {
2150 use super::*;
2151 use crate::security::selinux_hooks::get_cached_sid;
2152 use crate::security::selinux_hooks::testing::{
2153 self, spawn_kernel_with_selinux_hooks_test_policy_and_run,
2154 };
2155 use crate::testing::{create_task, spawn_kernel_and_run, spawn_kernel_with_selinux_and_run};
2156 use linux_uapi::XATTR_NAME_SELINUX;
2157 use selinux::InitialSid;
2158 use starnix_uapi::auth::PTRACE_MODE_ATTACH;
2159 use starnix_uapi::signals::SIGTERM;
2160
2161 const VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_valid_t:s0";
2162 const VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] = b"u:object_r:test_valid_t:s0\0";
2163
2164 const DIFFERENT_VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_different_valid_t:s0";
2165 const DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] =
2166 b"u:object_r:test_different_valid_t:s0\0";
2167
2168 const INVALID_SECURITY_CONTEXT_INTERNAL_NUL: &[u8] = b"u:object_r:test_valid_\0t:s0";
2169
2170 const INVALID_SECURITY_CONTEXT: &[u8] = b"not_a_u:object_r:test_valid_t:s0";
2171
2172 #[derive(Default, Debug, PartialEq)]
2173 enum TestHookResult {
2174 WasRun,
2175 WasNotRun,
2176 #[default]
2177 WasNotRunDefault,
2178 }
2179
2180 #[fuchsia::test]
2181 async fn if_selinux_else_disabled() {
2182 spawn_kernel_and_run(async |_, current_task| {
2183 assert!(current_task.kernel().security_state.state.is_none());
2184
2185 let check_result =
2186 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2187 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2188
2189 let run_else_result = if_selinux_else(
2190 current_task,
2191 |_| TestHookResult::WasRun,
2192 || TestHookResult::WasNotRun,
2193 );
2194 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2195 })
2196 .await;
2197 }
2198
2199 #[fuchsia::test]
2200 async fn if_selinux_else_without_policy() {
2201 spawn_kernel_with_selinux_and_run(async |_locked, current_task, _security_server| {
2202 let check_result =
2203 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2204 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2205
2206 let run_else_result = if_selinux_else(
2207 current_task,
2208 |_| TestHookResult::WasRun,
2209 || TestHookResult::WasNotRun,
2210 );
2211 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2212 })
2213 .await;
2214 }
2215
2216 #[fuchsia::test]
2217 async fn if_selinux_else_with_policy() {
2218 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2219 |_locked, current_task, _security_server| {
2220 let check_result =
2221 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2222 assert_eq!(check_result, Ok(TestHookResult::WasRun));
2223
2224 let run_else_result = if_selinux_else(
2225 current_task,
2226 |_| TestHookResult::WasRun,
2227 || TestHookResult::WasNotRun,
2228 );
2229 assert_eq!(run_else_result, TestHookResult::WasRun);
2230 },
2231 )
2232 .await;
2233 }
2234
2235 #[fuchsia::test]
2236 async fn task_alloc_selinux_disabled() {
2237 spawn_kernel_and_run(async |_, current_task| {
2238 task_alloc(current_task, 0);
2239 })
2240 .await;
2241 }
2242
2243 #[fuchsia::test]
2244 async fn task_create_access_allowed_for_selinux_disabled() {
2245 spawn_kernel_and_run(async |_, current_task| {
2246 assert!(current_task.kernel().security_state.state.is_none());
2247 assert_eq!(check_task_create_access(current_task), Ok(()));
2248 })
2249 .await;
2250 }
2251
2252 #[fuchsia::test]
2253 async fn task_create_access_allowed_for_permissive_mode() {
2254 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2255 |_locked, current_task, security_server| {
2256 security_server.set_enforcing(false);
2257 assert_eq!(check_task_create_access(current_task), Ok(()));
2258 },
2259 )
2260 .await;
2261 }
2262
2263 #[fuchsia::test]
2264 async fn exec_access_allowed_for_selinux_disabled() {
2265 spawn_kernel_and_run(async |locked, current_task| {
2266 assert!(current_task.kernel().security_state.state.is_none());
2267 let executable = &testing::create_test_file(locked, current_task);
2268 assert_eq!(
2269 bprm_creds_for_exec(current_task, executable),
2270 Ok(ResolvedElfState { sid: None, require_secure_exec: false })
2271 );
2272 })
2273 .await;
2274 }
2275
2276 #[fuchsia::test]
2277 async fn exec_access_allowed_for_permissive_mode() {
2278 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2279 |locked, current_task, security_server| {
2280 security_server.set_enforcing(false);
2281 let executable = &testing::create_test_file(locked, current_task);
2282 let result = bprm_creds_for_exec(current_task, executable);
2284 assert!(result.expect("Exec check should succeed").sid.is_some());
2285 },
2286 )
2287 .await;
2288 }
2289
2290 #[fuchsia::test]
2291 async fn no_state_update_for_selinux_disabled() {
2292 spawn_kernel_and_run(async |locked, current_task| {
2293 let target_sid = InitialSid::Unlabeled.into();
2296 let elf_state = ResolvedElfState { sid: Some(target_sid), require_secure_exec: false };
2297
2298 assert!(
2299 selinux_hooks::current_task_state(current_task).lock().current_sid != target_sid
2300 );
2301
2302 let before_hook_sid =
2303 selinux_hooks::current_task_state(current_task).lock().current_sid;
2304 exec_binprm(locked, current_task, &elf_state);
2305 assert_eq!(
2306 selinux_hooks::current_task_state(current_task).lock().current_sid,
2307 before_hook_sid
2308 );
2309 assert_eq!(current_task.security_state.lock().current_sid, before_hook_sid)
2310 })
2311 .await;
2312 }
2313
2314 #[fuchsia::test]
2315 async fn no_state_update_for_selinux_without_policy() {
2316 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2317 let initial_state = current_task.security_state.lock().clone();
2320 let elf_sid = InitialSid::Unlabeled.into();
2321 let elf_state = ResolvedElfState { sid: Some(elf_sid), require_secure_exec: false };
2322 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).lock().current_sid);
2323 exec_binprm(locked, current_task, &elf_state);
2324 assert_eq!(*current_task.security_state.lock(), initial_state);
2325 })
2326 .await;
2327 }
2328
2329 #[fuchsia::test]
2330 async fn state_update_for_permissive_mode() {
2331 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2332 |locked, current_task, security_server| {
2333 security_server.set_enforcing(false);
2334 let initial_state = selinux_hooks::TaskAttrs::for_kernel();
2335 *current_task.security_state.lock() = initial_state.clone();
2336 let elf_sid = security_server
2337 .security_context_to_sid(b"u:object_r:fork_no_t:s0".into())
2338 .expect("invalid security context");
2339 let elf_state = ResolvedElfState { sid: Some(elf_sid), require_secure_exec: false };
2340 assert_ne!(
2341 elf_sid,
2342 selinux_hooks::current_task_state(current_task).lock().current_sid
2343 );
2344 exec_binprm(locked, current_task, &elf_state);
2345 assert_eq!(
2346 selinux_hooks::current_task_state(current_task).lock().current_sid,
2347 elf_sid
2348 );
2349 assert_eq!(current_task.security_state.lock().current_sid, elf_sid);
2350 },
2351 )
2352 .await;
2353 }
2354
2355 #[fuchsia::test]
2356 async fn getsched_access_allowed_for_selinux_disabled() {
2357 spawn_kernel_and_run(async |locked, current_task| {
2358 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2359 assert_eq!(check_getsched_access(current_task, &another_task), Ok(()));
2360 })
2361 .await;
2362 }
2363
2364 #[fuchsia::test]
2365 async fn getsched_access_allowed_for_permissive_mode() {
2366 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2367 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2368 assert_eq!(check_getsched_access(current_task, &another_task), Ok(()));
2369 })
2370 .await;
2371 }
2372
2373 #[fuchsia::test]
2374 async fn setsched_access_allowed_for_selinux_disabled() {
2375 spawn_kernel_and_run(async |locked, current_task| {
2376 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2377 assert_eq!(check_setsched_access(current_task, &another_task), Ok(()));
2378 })
2379 .await;
2380 }
2381
2382 #[fuchsia::test]
2383 async fn setsched_access_allowed_for_permissive_mode() {
2384 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2385 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2386 assert_eq!(check_setsched_access(current_task, &another_task), Ok(()));
2387 })
2388 .await;
2389 }
2390
2391 #[fuchsia::test]
2392 async fn getpgid_access_allowed_for_selinux_disabled() {
2393 spawn_kernel_and_run(async |locked, current_task| {
2394 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2395 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2396 })
2397 .await;
2398 }
2399
2400 #[fuchsia::test]
2401 async fn getpgid_access_allowed_for_permissive_mode() {
2402 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2403 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2404 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2405 })
2406 .await;
2407 }
2408
2409 #[fuchsia::test]
2410 async fn setpgid_access_allowed_for_selinux_disabled() {
2411 spawn_kernel_and_run(async |locked, current_task| {
2412 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2413 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2414 })
2415 .await;
2416 }
2417
2418 #[fuchsia::test]
2419 async fn setpgid_access_allowed_for_permissive_mode() {
2420 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2421 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2422 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2423 })
2424 .await;
2425 }
2426
2427 #[fuchsia::test]
2428 async fn task_getsid_allowed_for_selinux_disabled() {
2429 spawn_kernel_and_run(async |locked, current_task| {
2430 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2431 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2432 })
2433 .await;
2434 }
2435
2436 #[fuchsia::test]
2437 async fn task_getsid_allowed_for_permissive_mode() {
2438 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2439 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2440 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2441 })
2442 .await;
2443 }
2444
2445 #[fuchsia::test]
2446 async fn signal_access_allowed_for_selinux_disabled() {
2447 spawn_kernel_and_run(async |locked, current_task| {
2448 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2449 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2450 })
2451 .await;
2452 }
2453
2454 #[fuchsia::test]
2455 async fn signal_access_allowed_for_permissive_mode() {
2456 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2457 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2458 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2459 })
2460 .await;
2461 }
2462
2463 #[fuchsia::test]
2464 async fn ptrace_traceme_access_allowed_for_selinux_disabled() {
2465 spawn_kernel_and_run(async |locked, current_task| {
2466 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2467 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2468 })
2469 .await;
2470 }
2471
2472 #[fuchsia::test]
2473 async fn ptrace_traceme_access_allowed_for_permissive_mode() {
2474 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2475 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2476 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2477 })
2478 .await;
2479 }
2480
2481 #[fuchsia::test]
2482 async fn ptrace_attach_access_allowed_for_selinux_disabled() {
2483 spawn_kernel_and_run(async |locked, current_task| {
2484 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2485 assert_eq!(
2486 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2487 Ok(())
2488 );
2489 })
2490 .await;
2491 }
2492
2493 #[fuchsia::test]
2494 async fn ptrace_attach_access_allowed_for_permissive_mode() {
2495 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2496 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2497 assert_eq!(
2498 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2499 Ok(())
2500 );
2501 })
2502 .await;
2503 }
2504
2505 #[fuchsia::test]
2506 async fn task_prlimit_access_allowed_for_selinux_disabled() {
2507 spawn_kernel_and_run(async |locked, current_task| {
2508 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2509 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2510 })
2511 .await;
2512 }
2513
2514 #[fuchsia::test]
2515 async fn task_prlimit_access_allowed_for_permissive_mode() {
2516 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2517 let another_task = create_task(locked, ¤t_task.kernel(), "another-task");
2518 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2519 })
2520 .await;
2521 }
2522
2523 #[fuchsia::test]
2524 async fn fs_node_task_to_fs_node_noop_selinux_disabled() {
2525 spawn_kernel_and_run(async |locked, current_task| {
2526 let node = &testing::create_test_file(locked, current_task).entry.node;
2527 task_to_fs_node(current_task, ¤t_task.temp_task(), &node);
2528 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2529 })
2530 .await;
2531 }
2532
2533 #[fuchsia::test]
2534 async fn fs_node_setsecurity_selinux_disabled_only_sets_xattr() {
2535 spawn_kernel_and_run(async |locked, current_task| {
2536 let node = &testing::create_test_file(locked, current_task).entry.node;
2537
2538 fs_node_setsecurity(
2539 locked,
2540 current_task,
2541 &node,
2542 XATTR_NAME_SELINUX.to_bytes().into(),
2543 VALID_SECURITY_CONTEXT.into(),
2544 XattrOp::Set,
2545 )
2546 .expect("set_xattr(security.selinux) failed");
2547
2548 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2549 })
2550 .await;
2551 }
2552
2553 #[fuchsia::test]
2554 async fn fs_node_setsecurity_selinux_without_policy_only_sets_xattr() {
2555 spawn_kernel_with_selinux_and_run(async |locked, current_task, _security_server| {
2556 let node = &testing::create_test_file(locked, current_task).entry.node;
2557 fs_node_setsecurity(
2558 locked,
2559 current_task,
2560 &node,
2561 XATTR_NAME_SELINUX.to_bytes().into(),
2562 VALID_SECURITY_CONTEXT.into(),
2563 XattrOp::Set,
2564 )
2565 .expect("set_xattr(security.selinux) failed");
2566
2567 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2568 })
2569 .await;
2570 }
2571
2572 #[fuchsia::test]
2573 async fn fs_node_setsecurity_selinux_permissive_sets_xattr_and_label() {
2574 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2575 |locked, current_task, security_server| {
2576 security_server.set_enforcing(false);
2577 let expected_sid = security_server
2578 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2579 .expect("no SID for VALID_SECURITY_CONTEXT");
2580 let node = &testing::create_test_file(locked, ¤t_task).entry.node;
2581
2582 assert_ne!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2584
2585 fs_node_setsecurity(
2586 locked,
2587 current_task,
2588 &node,
2589 XATTR_NAME_SELINUX.to_bytes().into(),
2590 VALID_SECURITY_CONTEXT.into(),
2591 XattrOp::Set,
2592 )
2593 .expect("set_xattr(security.selinux) failed");
2594
2595 assert_eq!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2598 },
2599 )
2600 .await;
2601 }
2602
2603 #[fuchsia::test]
2604 async fn fs_node_setsecurity_not_selinux_only_sets_xattr() {
2605 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2606 |locked, current_task, security_server| {
2607 let valid_security_context_sid = security_server
2608 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2609 .expect("no SID for VALID_SECURITY_CONTEXT");
2610 let node = &testing::create_test_file(locked, current_task).entry.node;
2611 let whatever_sid = selinux_hooks::get_cached_sid(node);
2615 assert_ne!(Some(valid_security_context_sid), whatever_sid);
2616
2617 fs_node_setsecurity(
2618 locked,
2619 current_task,
2620 &node,
2621 "security.selinu!".into(), VALID_SECURITY_CONTEXT.into(),
2623 XattrOp::Set,
2624 )
2625 .expect("set_xattr(security.selinux) failed");
2626
2627 assert_eq!(whatever_sid, selinux_hooks::get_cached_sid(node));
2629 },
2630 )
2631 .await;
2632 }
2633
2634 #[fuchsia::test]
2635 async fn fs_node_setsecurity_selinux_enforcing_invalid_context_fails() {
2636 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2637 |locked, current_task, _security_server| {
2638 let node = &testing::create_test_file(locked, current_task).entry.node;
2639
2640 let before_sid = selinux_hooks::get_cached_sid(node);
2641 assert_ne!(Some(InitialSid::Unlabeled.into()), before_sid);
2642
2643 assert!(
2644 check_fs_node_setxattr_access(
2645 ¤t_task,
2646 &node,
2647 XATTR_NAME_SELINUX.to_bytes().into(),
2648 "!".into(), XattrOp::Set,
2650 )
2651 .is_err()
2652 );
2653
2654 assert_eq!(before_sid, selinux_hooks::get_cached_sid(node));
2655 },
2656 )
2657 .await;
2658 }
2659
2660 #[fuchsia::test]
2661 async fn fs_node_setsecurity_selinux_permissive_invalid_context_sets_xattr_and_label() {
2662 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2663 |locked, current_task, security_server| {
2664 security_server.set_enforcing(false);
2665 let node = &testing::create_test_file(locked, current_task).entry.node;
2666
2667 assert_ne!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2668
2669 fs_node_setsecurity(
2670 locked,
2671 current_task,
2672 &node,
2673 XATTR_NAME_SELINUX.to_bytes().into(),
2674 "!".into(), XattrOp::Set,
2676 )
2677 .expect("set_xattr(security.selinux) failed");
2678
2679 assert_eq!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2680 },
2681 )
2682 .await;
2683 }
2684
2685 #[fuchsia::test]
2686 async fn fs_node_setsecurity_different_sid_for_different_context() {
2687 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2688 |locked, current_task, _security_server| {
2689 let node = &testing::create_test_file(locked, current_task).entry.node;
2690
2691 fs_node_setsecurity(
2692 locked,
2693 current_task,
2694 &node,
2695 XATTR_NAME_SELINUX.to_bytes().into(),
2696 VALID_SECURITY_CONTEXT.into(),
2697 XattrOp::Set,
2698 )
2699 .expect("set_xattr(security.selinux) failed");
2700
2701 assert!(selinux_hooks::get_cached_sid(node).is_some());
2702
2703 let first_sid = selinux_hooks::get_cached_sid(node).unwrap();
2704 fs_node_setsecurity(
2705 locked,
2706 current_task,
2707 &node,
2708 XATTR_NAME_SELINUX.to_bytes().into(),
2709 DIFFERENT_VALID_SECURITY_CONTEXT.into(),
2710 XattrOp::Set,
2711 )
2712 .expect("set_xattr(security.selinux) failed");
2713
2714 assert!(selinux_hooks::get_cached_sid(node).is_some());
2715
2716 let second_sid = selinux_hooks::get_cached_sid(node).unwrap();
2717
2718 assert_ne!(first_sid, second_sid);
2719 },
2720 )
2721 .await;
2722 }
2723
2724 #[fuchsia::test]
2725 async fn fs_node_getsecurity_returns_cached_context() {
2726 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2727 |locked, current_task, security_server| {
2728 let node = &testing::create_test_file(locked, current_task).entry.node;
2729
2730 const TEST_VALUE: &str = "Something Random";
2732 node.ops()
2733 .set_xattr(
2734 locked.cast_locked::<FileOpsCore>(),
2735 node,
2736 current_task,
2737 XATTR_NAME_SELINUX.to_bytes().into(),
2738 TEST_VALUE.into(),
2739 XattrOp::Set,
2740 )
2741 .expect("set_xattr(security.selinux) failed");
2742
2743 let sid = security_server
2745 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2746 .expect("security context to SID");
2747 selinux_hooks::set_cached_sid(&node, sid);
2748
2749 let result = fs_node_getsecurity(
2751 locked,
2752 current_task,
2753 node,
2754 XATTR_NAME_SELINUX.to_bytes().into(),
2755 4096,
2756 );
2757 assert_eq!(
2758 result,
2759 Ok(ValueOrSize::Value(FsString::new(VALID_SECURITY_CONTEXT_WITH_NUL.into())))
2760 );
2761 },
2762 )
2763 .await;
2764 }
2765
2766 #[fuchsia::test]
2767 async fn fs_node_getsecurity_delegates_to_get_xattr() {
2768 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2769 |locked, current_task, security_server| {
2770 let node = &testing::create_test_file(locked, current_task).entry.node;
2771
2772 security_server.set_enforcing(false);
2775 const TEST_VALUE: &str = "Something Random";
2776 fs_node_setsecurity(
2777 locked,
2778 current_task,
2779 node,
2780 XATTR_NAME_SELINUX.to_bytes().into(),
2781 TEST_VALUE.into(),
2782 XattrOp::Set,
2783 )
2784 .expect("set_xattr(security.selinux) failed");
2785 security_server.set_enforcing(true);
2786
2787 let result = fs_node_getsecurity(
2789 locked,
2790 current_task,
2791 node,
2792 XATTR_NAME_SELINUX.to_bytes().into(),
2793 4096,
2794 );
2795 assert_eq!(result, Ok(ValueOrSize::Value(FsString::new(TEST_VALUE.into()))));
2796 },
2797 )
2798 .await;
2799 }
2800
2801 #[fuchsia::test]
2802 async fn set_get_procattr() {
2803 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2804 |_locked, current_task, _security_server| {
2805 assert_eq!(
2806 get_procattr(current_task, current_task, ProcAttr::Exec),
2807 Ok(Vec::new())
2808 );
2809
2810 assert_eq!(
2811 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2813 Ok(())
2814 );
2815
2816 assert_eq!(
2817 set_procattr(
2819 current_task,
2820 ProcAttr::SockCreate,
2821 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2822 ),
2823 error!(EACCES)
2824 );
2825
2826 assert_eq!(
2827 set_procattr(
2829 current_task,
2830 ProcAttr::Previous,
2831 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2832 ),
2833 error!(EINVAL)
2834 );
2835
2836 assert_eq!(
2837 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2839 error!(EINVAL)
2840 );
2841
2842 assert_eq!(
2843 get_procattr(current_task, current_task, ProcAttr::Exec),
2844 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2845 );
2846
2847 assert!(get_procattr(current_task, current_task, ProcAttr::Current).is_ok());
2848 },
2849 )
2850 .await;
2851 }
2852
2853 #[fuchsia::test]
2854 async fn set_get_procattr_with_nulls() {
2855 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2856 |_locked, current_task, _security_server| {
2857 assert_eq!(
2858 get_procattr(current_task, current_task, ProcAttr::Exec),
2859 Ok(Vec::new())
2860 );
2861
2862 assert_eq!(
2863 set_procattr(
2865 current_task,
2866 ProcAttr::Exec,
2867 VALID_SECURITY_CONTEXT_WITH_NUL.into()
2868 ),
2869 Ok(())
2870 );
2871
2872 assert_eq!(
2873 set_procattr(
2875 current_task,
2876 ProcAttr::FsCreate,
2877 INVALID_SECURITY_CONTEXT_INTERNAL_NUL.into()
2878 ),
2879 error!(EINVAL)
2880 );
2881
2882 assert_eq!(
2883 get_procattr(current_task, current_task, ProcAttr::Exec),
2884 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2885 );
2886
2887 assert_eq!(
2888 get_procattr(current_task, current_task, ProcAttr::FsCreate),
2889 Ok(Vec::new())
2890 );
2891 },
2892 )
2893 .await;
2894 }
2895
2896 #[fuchsia::test]
2897 async fn set_get_procattr_clear_context() {
2898 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2899 |_locked, current_task, _security_server| {
2900 assert_eq!(
2902 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2903 Ok(())
2904 );
2905 assert_eq!(
2906 set_procattr(
2907 current_task,
2908 ProcAttr::FsCreate,
2909 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2910 ),
2911 Ok(())
2912 );
2913
2914 assert_eq!(set_procattr(current_task, ProcAttr::Exec, b"\0"), Ok(()));
2916 assert_eq!(current_task.security_state.lock().exec_sid, None);
2917
2918 assert_eq!(set_procattr(current_task, ProcAttr::FsCreate, b"\x0a"), Ok(()));
2920 assert_eq!(current_task.security_state.lock().fscreate_sid, None);
2921 },
2922 )
2923 .await;
2924 }
2925
2926 #[fuchsia::test]
2927 async fn set_get_procattr_setcurrent() {
2928 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2929 |_locked, current_task, _security_server| {
2930 let initial_previous =
2932 get_procattr(current_task, current_task, ProcAttr::Previous).unwrap();
2933
2934 assert_eq!(
2935 set_procattr(current_task, ProcAttr::Current, VALID_SECURITY_CONTEXT.into()),
2937 Ok(())
2938 );
2939
2940 assert_eq!(
2941 get_procattr(current_task, current_task, ProcAttr::Current),
2943 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2944 );
2945
2946 assert_eq!(
2947 get_procattr(current_task, current_task, ProcAttr::Previous),
2949 Ok(initial_previous.clone())
2950 );
2951
2952 assert_eq!(
2953 set_procattr(
2955 current_task,
2956 ProcAttr::Current,
2957 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2958 ),
2959 Ok(())
2960 );
2961
2962 assert_eq!(
2963 get_procattr(current_task, current_task, ProcAttr::Current),
2965 Ok(DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL.into())
2966 );
2967
2968 assert_eq!(
2969 get_procattr(current_task, current_task, ProcAttr::Previous),
2971 Ok(initial_previous.clone())
2972 );
2973 },
2974 )
2975 .await;
2976 }
2977
2978 #[fuchsia::test]
2979 async fn set_get_procattr_selinux_permissive() {
2980 spawn_kernel_with_selinux_hooks_test_policy_and_run(
2981 |_locked, current_task, security_server| {
2982 security_server.set_enforcing(false);
2983 assert_eq!(
2984 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Exec),
2985 Ok(Vec::new())
2986 );
2987
2988 assert_eq!(
2989 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2991 Ok(())
2992 );
2993
2994 assert_eq!(
2995 set_procattr(
2998 current_task,
2999 ProcAttr::FsCreate,
3000 DIFFERENT_VALID_SECURITY_CONTEXT.into()
3001 ),
3002 Ok(())
3003 );
3004
3005 assert_eq!(
3006 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3008 error!(EINVAL)
3009 );
3010
3011 assert_eq!(
3012 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Exec),
3013 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
3014 );
3015
3016 assert!(
3017 get_procattr(current_task, ¤t_task.temp_task(), ProcAttr::Current)
3018 .is_ok()
3019 );
3020 },
3021 )
3022 .await;
3023 }
3024
3025 #[fuchsia::test]
3026 async fn set_get_procattr_selinux_disabled() {
3027 spawn_kernel_and_run(async |_, current_task| {
3028 assert_eq!(
3029 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3030 error!(EINVAL)
3031 );
3032
3033 assert_eq!(
3034 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
3036 error!(EINVAL)
3037 );
3038
3039 assert_eq!(
3040 set_procattr(¤t_task, ProcAttr::FsCreate, VALID_SECURITY_CONTEXT.into()),
3042 error!(EINVAL)
3043 );
3044
3045 assert_eq!(
3046 set_procattr(¤t_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3048 error!(EINVAL)
3049 );
3050
3051 assert_eq!(
3052 get_procattr(¤t_task, ¤t_task.temp_task(), ProcAttr::Current),
3053 error!(EINVAL)
3054 );
3055 })
3056 .await;
3057 }
3058
3059 #[fuchsia::test]
3060 async fn create_file_with_fscreate_sid() {
3061 spawn_kernel_with_selinux_hooks_test_policy_and_run(
3062 |locked, current_task, security_server| {
3063 let sid =
3064 security_server.security_context_to_sid(VALID_SECURITY_CONTEXT.into()).unwrap();
3065 let source_node = &testing::create_test_file(locked, current_task).entry.node;
3066
3067 fs_node_setsecurity(
3068 locked,
3069 current_task,
3070 &source_node,
3071 XATTR_NAME_SELINUX.to_bytes().into(),
3072 VALID_SECURITY_CONTEXT.into(),
3073 XattrOp::Set,
3074 )
3075 .expect("set_xattr(security.selinux) failed");
3076
3077 let dir_entry = fs_node_copy_up(current_task, source_node, || {
3078 current_task
3079 .fs()
3080 .root()
3081 .create_node(
3082 locked,
3083 ¤t_task,
3084 "test_file2".into(),
3085 FileMode::IFREG,
3086 DeviceType::NONE,
3087 )
3088 .unwrap()
3089 })
3090 .entry;
3091
3092 assert_eq!(get_cached_sid(&dir_entry.node), Some(sid));
3093 },
3094 )
3095 .await;
3096 }
3097}