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