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