1#![allow(non_upper_case_globals)]
7
8use super::selinux_hooks::audit::Auditable;
9use super::{
10 BinderConnectionState, BpfMapState, BpfProgState, FileObjectState, FileSystemState,
11 KernelState, PerfEventState, common_cap, selinux_hooks, yama,
12};
13use crate::mm::{Mapping, MappingOptions, ProtectionFlags};
14use crate::perf::PerfEventFile;
15use crate::security::selinux_hooks::current_task_state;
16use crate::task::loader::ResolvedProgram;
17use crate::task::{CurrentTask, Kernel, Task};
18use crate::vfs::fs_args::MountParams;
19use crate::vfs::socket::{
20 Socket, SocketAddress, SocketDomain, SocketFile, SocketPeer, SocketProtocol,
21 SocketShutdownFlags, SocketType,
22};
23use crate::vfs::{
24 DirEntryHandle, DowncastedFile, FileHandle, FileObject, FileSystem, FileSystemHandle,
25 FileSystemOps, FsNode, FsStr, FsString, Mount, NamespaceNode, ValueOrSize, XattrOp,
26};
27use ebpf::MapFlags;
28use linux_uapi::{
29 perf_event_attr, perf_type_id, perf_type_id_PERF_TYPE_BREAKPOINT,
30 perf_type_id_PERF_TYPE_HARDWARE, perf_type_id_PERF_TYPE_HW_CACHE, perf_type_id_PERF_TYPE_RAW,
31 perf_type_id_PERF_TYPE_SOFTWARE, perf_type_id_PERF_TYPE_TRACEPOINT,
32};
33use selinux::{FileSystemMountOptions, InitialSid, SecurityPermission, SecurityServer, TaskAttrs};
34use starnix_logging::{CATEGORY_STARNIX_SECURITY, log_debug};
35use starnix_uapi::arc_key::WeakKey;
36use starnix_uapi::auth::{Credentials, PtraceAccessMode};
37use starnix_uapi::device_id::DeviceId;
38use starnix_uapi::errors::Errno;
39use starnix_uapi::file_mode::{Access, FileMode};
40use starnix_uapi::mount_flags::MountFlags;
41use starnix_uapi::open_flags::OpenFlags;
42use starnix_uapi::signals::Signal;
43use starnix_uapi::syslog::SyslogAction;
44use starnix_uapi::unmount_flags::UnmountFlags;
45use starnix_uapi::user_address::UserAddress;
46use starnix_uapi::{bpf_cmd, error, rlimit};
47use std::ops::Range;
48use std::sync::Arc;
49use syncio::zxio_node_attr_has_t;
50use zerocopy::FromBytes;
51
52macro_rules! track_hook_duration {
53 ($cname:literal) => {
54 fuchsia_trace::duration!(CATEGORY_STARNIX_SECURITY, $cname);
55 };
56}
57
58bitflags::bitflags! {
59 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
62 pub struct PermissionFlags: u32 {
63 const EXEC = 1 as u32;
64 const WRITE = 2 as u32;
65 const READ = 4 as u32;
66 const APPEND = 8 as u32;
67
68 const ACCESS = 16 as u32;
71 }
72}
73
74impl PermissionFlags {
75 pub fn as_access(&self) -> Access {
76 let mut access = Access::empty();
77 if self.contains(PermissionFlags::READ) {
78 access |= Access::READ;
79 }
80 if self.contains(PermissionFlags::WRITE) {
81 access |= Access::WRITE;
84 }
85 if self.contains(PermissionFlags::EXEC) {
86 access |= Access::EXEC;
87 }
88 access
89 }
90}
91
92impl From<Access> for PermissionFlags {
93 fn from(access: Access) -> Self {
94 let mut permissions = PermissionFlags::empty();
96 if access.contains(Access::READ) {
97 permissions |= PermissionFlags::READ;
98 }
99 if access.contains(Access::WRITE) {
100 permissions |= PermissionFlags::WRITE;
101 }
102 if access.contains(Access::EXEC) {
103 permissions |= PermissionFlags::EXEC;
104 }
105 permissions
106 }
107}
108
109impl From<ProtectionFlags> for PermissionFlags {
110 fn from(protection_flags: ProtectionFlags) -> Self {
111 let mut flags = PermissionFlags::empty();
112 if protection_flags.contains(ProtectionFlags::READ) {
113 flags |= PermissionFlags::READ;
114 }
115 if protection_flags.contains(ProtectionFlags::WRITE) {
116 flags |= PermissionFlags::WRITE;
117 }
118 if protection_flags.contains(ProtectionFlags::EXEC) {
119 flags |= PermissionFlags::EXEC;
120 }
121 flags
122 }
123}
124
125impl From<OpenFlags> for PermissionFlags {
126 fn from(flags: OpenFlags) -> Self {
127 let mut permissions = PermissionFlags::empty();
128 if flags.can_read() {
129 permissions |= PermissionFlags::READ;
130 }
131 if flags.can_write() {
132 permissions |= PermissionFlags::WRITE;
133 if flags.contains(OpenFlags::APPEND) {
134 permissions |= PermissionFlags::APPEND;
135 }
136 }
137 permissions
138 }
139}
140
141impl From<MapFlags> for PermissionFlags {
142 fn from(bpf_flags: MapFlags) -> Self {
143 if bpf_flags.contains(MapFlags::SyscallReadOnly) {
144 PermissionFlags::READ
145 } else if bpf_flags.contains(MapFlags::SyscallWriteOnly) {
146 PermissionFlags::WRITE
147 } else {
148 PermissionFlags::READ | PermissionFlags::WRITE
149 }
150 }
151}
152
153#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
155pub enum PerfEventType {
156 Hardware,
157 Software,
158 Tracepoint,
159 Raw,
160 HwCache,
161 Breakpoint,
162}
163
164#[allow(non_upper_case_globals)]
166impl TryFrom<perf_type_id> for PerfEventType {
167 type Error = Errno;
168
169 fn try_from(type_id: perf_type_id) -> Result<Self, Errno> {
170 match type_id {
171 perf_type_id_PERF_TYPE_HARDWARE => Ok(Self::Hardware),
172 perf_type_id_PERF_TYPE_SOFTWARE => Ok(Self::Software),
173 perf_type_id_PERF_TYPE_TRACEPOINT => Ok(Self::Tracepoint),
174 perf_type_id_PERF_TYPE_RAW => Ok(Self::Raw),
175 perf_type_id_PERF_TYPE_HW_CACHE => Ok(Self::HwCache),
176 perf_type_id_PERF_TYPE_BREAKPOINT => Ok(Self::Breakpoint),
177 _ => {
178 return error!(ENOTSUP);
179 }
180 }
181 }
182}
183
184#[derive(PartialEq, Eq)]
186pub enum TargetTaskType<'a> {
187 AllTasks,
189 CurrentTask,
191 Task(&'a Task),
193}
194
195fn if_selinux_else<F, R, D>(task: &Task, hook: F, default: D) -> R
199where
200 F: FnOnce(&Arc<SecurityServer>) -> R,
201 D: Fn() -> R,
202{
203 if let Some(state) = task.kernel().security_state.state.as_ref() {
204 if state.has_policy() { hook(&state.server) } else { default() }
205 } else {
206 default()
207 }
208}
209
210fn if_selinux_else_default_ok<R, F>(task: &Task, hook: F) -> Result<R, Errno>
214where
215 F: FnOnce(&Arc<SecurityServer>) -> Result<R, Errno>,
216 R: Default,
217{
218 if_selinux_else(task, hook, || Ok(R::default()))
219}
220
221pub fn kernel_init_security(
224 enabled: bool,
225 options: String,
226 exceptions: Vec<String>,
227 inspect_node: &fuchsia_inspect::Node,
228) -> KernelState {
229 track_hook_duration!("security.hooks.kernel_init_security");
230 KernelState {
231 state: enabled
232 .then(|| selinux_hooks::kernel_init_security(options, exceptions, inspect_node)),
233 }
234}
235
236pub fn binder_set_context_mgr(current_task: &CurrentTask) -> Result<(), Errno> {
239 track_hook_duration!("security.hooks.binder_set_context_mgr");
240 if_selinux_else_default_ok(current_task, |security_server| {
241 selinux_hooks::binder::binder_set_context_mgr(security_server, current_task)
242 })
243}
244
245pub fn binder_transaction(
248 current_task: &CurrentTask,
249 target_task: &Task,
250 connection_state: &BinderConnectionState,
251) -> Result<(), Errno> {
252 track_hook_duration!("security.hooks.binder_transaction");
253 if_selinux_else_default_ok(current_task, |security_server| {
254 selinux_hooks::binder::binder_transaction(
255 security_server,
256 &connection_state.state,
257 current_task,
258 target_task,
259 )
260 })
261}
262
263pub fn binder_transfer_binder(current_task: &CurrentTask, target_task: &Task) -> Result<(), Errno> {
266 track_hook_duration!("security.hooks.binder_transfer_binder");
267 if_selinux_else_default_ok(current_task, |security_server| {
268 selinux_hooks::binder::binder_transfer_binder(security_server, current_task, target_task)
269 })
270}
271
272pub fn binder_transfer_file(
275 current_task: &CurrentTask,
276 receiving_task: &Task,
277 file: &FileObject,
278) -> Result<(), Errno> {
279 track_hook_duration!("security.hooks.binder_transfer_file");
280 if_selinux_else_default_ok(current_task, |security_server| {
281 selinux_hooks::binder::binder_transfer_file(
282 security_server,
283 current_task,
284 receiving_task,
285 file,
286 )
287 })
288}
289
290pub fn binder_get_context(
293 current_task: &CurrentTask,
294 connection_state: &BinderConnectionState,
295) -> Option<Vec<u8>> {
296 track_hook_duration!("security.hooks.binder_get_context");
297 if_selinux_else(
298 current_task,
299 |security_server| {
300 selinux_hooks::binder::binder_get_context(&security_server, &connection_state.state)
301 },
302 || None,
303 )
304}
305
306pub fn sb_eat_lsm_opts(
310 kernel: &Kernel,
311 mount_params: &mut MountParams,
312) -> Result<FileSystemMountOptions, Errno> {
313 track_hook_duration!("security.hooks.sb_eat_lsm_opts");
314 if kernel.security_state.state.is_some() {
315 return selinux_hooks::superblock::sb_eat_lsm_opts(mount_params);
316 }
317 Ok(FileSystemMountOptions::default())
318}
319
320pub fn file_system_init_security(
323 mount_options: &FileSystemMountOptions,
324 ops: &dyn FileSystemOps,
325) -> Result<FileSystemState, Errno> {
326 track_hook_duration!("security.hooks.file_system_init_security");
327 Ok(FileSystemState {
328 state: selinux_hooks::superblock::file_system_init_security(mount_options, ops)?,
329 })
330}
331
332pub fn file_system_post_init_security(kernel: &Kernel, file_system: &FileSystemHandle) {
337 track_hook_duration!("security.hooks.file_system_post_init_security");
338 if let Some(state) = &kernel.security_state.state {
339 if !state.has_policy() {
340 log_debug!("Queuing {} FileSystem for labeling", file_system.name());
343 state.pending_file_systems.lock().insert(WeakKey::from(&file_system));
344 }
345 }
346}
347
348pub fn file_system_resolve_security(
353 current_task: &CurrentTask,
354 file_system: &FileSystemHandle,
355) -> Result<(), Errno> {
356 track_hook_duration!("security.hooks.file_system_resolve_security");
357 if_selinux_else_default_ok(current_task, |security_server| {
358 selinux_hooks::superblock::file_system_resolve_security(
359 security_server,
360 current_task,
361 file_system,
362 )
363 })
364}
365
366pub struct FsNodeSecurityXattr {
368 pub name: &'static FsStr,
369 pub value: FsString,
370}
371
372pub fn mmap_file(
376 current_task: &CurrentTask,
377 file: Option<&FileHandle>,
378 protection_flags: ProtectionFlags,
379 options: MappingOptions,
380) -> Result<(), Errno> {
381 track_hook_duration!("security.hooks.mmap_file");
382 if_selinux_else_default_ok(current_task, |security_server| {
383 selinux_hooks::file::mmap_file(
384 security_server,
385 current_task,
386 file,
387 protection_flags,
388 options,
389 )
390 })
391}
392
393pub fn file_mprotect(
397 current_task: &CurrentTask,
398 range: &Range<UserAddress>,
399 mapping: &Mapping,
400 prot: ProtectionFlags,
401) -> Result<(), Errno> {
402 track_hook_duration!("security.hooks.file_mprotect");
403 if_selinux_else_default_ok(current_task, |security_server| {
404 selinux_hooks::file::file_mprotect(security_server, current_task, range, mapping, prot)
405 })
406}
407
408pub fn file_permission(
411 current_task: &CurrentTask,
412 file: &FileObject,
413 permission_flags: PermissionFlags,
414) -> Result<(), Errno> {
415 track_hook_duration!("security.hooks.file_permission");
416 if_selinux_else_default_ok(current_task, |security_server| {
417 selinux_hooks::file::file_permission(security_server, current_task, file, permission_flags)
418 })
419}
420
421pub fn file_open(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
424 track_hook_duration!("security.hooks.file_open");
425 if_selinux_else_default_ok(current_task, |security_server| {
426 selinux_hooks::file::file_open(security_server, current_task, file)
427 })
428}
429
430pub fn fs_node_init_with_dentry(
436 current_task: &CurrentTask,
437 dir_entry: &DirEntryHandle,
438) -> Result<(), Errno> {
439 track_hook_duration!("security.hooks.fs_node_init_with_dentry");
440 if let Some(state) = ¤t_task.kernel().security_state.state {
445 selinux_hooks::fs_node::fs_node_init_with_dentry(
446 &state.server,
447 current_task,
448 dir_entry,
449 true,
451 )
452 } else {
453 Ok(())
454 }
455}
456
457pub fn fs_node_init_with_dentry_no_xattr(
458 current_task: &CurrentTask,
459 dir_entry: &DirEntryHandle,
460) -> Result<(), Errno> {
461 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
462 if let Some(state) = ¤t_task.kernel().security_state.state {
467 if dir_entry.node.is_private() {
470 return selinux_hooks::fs_node::fs_node_init_anon(
471 &state.server,
472 current_task,
473 &dir_entry.node,
474 "",
475 );
476 }
477
478 selinux_hooks::fs_node::fs_node_init_with_dentry(
479 &state.server,
480 current_task,
481 dir_entry,
482 false,
484 )
485 } else {
486 Ok(())
487 }
488}
489
490pub fn fs_node_init_with_dentry_deferred(kernel: &Kernel, dir_entry: &DirEntryHandle) {
494 track_hook_duration!("security.hooks.fs_node_init_with_dentry_no_xattr");
495 if kernel.security_state.state.is_some() {
496 selinux_hooks::fs_node::fs_node_init_with_dentry_deferred(dir_entry);
497 }
498}
499
500pub fn fs_node_notify_security_context(
507 current_task: &CurrentTask,
508 fs_node: &FsNode,
509 context: &FsStr,
510) -> Result<(), Errno> {
511 track_hook_duration!("security.hooks.fs_node_notify_security_context");
512 if_selinux_else(
513 current_task,
514 |security_server| {
515 selinux_hooks::fs_node::fs_node_notify_security_context(
516 security_server,
517 fs_node,
518 context,
519 )
520 },
521 || error!(ENOTSUP),
522 )
523}
524
525pub fn fs_node_init_on_create(
537 current_task: &CurrentTask,
538 new_node: &FsNode,
539 parent: &FsNode,
540 name: &FsStr,
541) -> Result<Option<FsNodeSecurityXattr>, Errno> {
542 track_hook_duration!("security.hooks.fs_node_init_on_create");
543 if_selinux_else_default_ok(current_task, |security_server| {
544 selinux_hooks::fs_node::fs_node_init_on_create(
545 security_server,
546 current_task,
547 new_node,
548 Some(parent),
549 name,
550 )
551 })
552}
553
554pub fn dentry_create_files_as(
562 current_task: &CurrentTask,
563 parent: &FsNode,
564 new_node_mode: FileMode,
565 new_node_name: &FsStr,
566 new_creds: &mut Credentials,
567) -> Result<(), Errno> {
568 track_hook_duration!("security.hooks.dentry_create_files_as");
569 if_selinux_else_default_ok(current_task, |security_server| {
570 selinux_hooks::fs_node::dentry_create_files_as(
571 security_server,
572 current_task,
573 parent,
574 new_node_mode,
575 new_node_name,
576 new_creds,
577 )
578 })
579}
580
581pub fn fs_node_init_anon(
586 current_task: &CurrentTask,
587 new_node: &FsNode,
588 node_type: &str,
589) -> Result<(), Errno> {
590 track_hook_duration!("security.hooks.fs_node_init_anon");
591 if let Some(state) = current_task.kernel().security_state.state.as_ref() {
592 selinux_hooks::fs_node::fs_node_init_anon(&state.server, current_task, new_node, node_type)
593 } else {
594 Ok(())
595 }
596}
597
598pub fn check_fs_node_create_access(
602 current_task: &CurrentTask,
603 parent: &FsNode,
604 mode: FileMode,
605 name: &FsStr,
606) -> Result<(), Errno> {
607 track_hook_duration!("security.hooks.check_fs_node_create_access");
608 if_selinux_else_default_ok(current_task, |security_server| {
609 selinux_hooks::fs_node::check_fs_node_create_access(
610 security_server,
611 current_task,
612 parent,
613 mode,
614 name,
615 )
616 })
617}
618
619pub fn check_fs_node_symlink_access(
623 current_task: &CurrentTask,
624 parent: &FsNode,
625 name: &FsStr,
626 old_path: &FsStr,
627) -> Result<(), Errno> {
628 track_hook_duration!("security.hooks.check_fs_node_symlink_access");
629 if_selinux_else_default_ok(current_task, |security_server| {
630 selinux_hooks::fs_node::check_fs_node_symlink_access(
631 security_server,
632 current_task,
633 parent,
634 name,
635 old_path,
636 )
637 })
638}
639
640pub fn check_fs_node_mkdir_access(
644 current_task: &CurrentTask,
645 parent: &FsNode,
646 mode: FileMode,
647 name: &FsStr,
648) -> Result<(), Errno> {
649 track_hook_duration!("security.hooks.check_fs_node_mkdir_access");
650 if_selinux_else_default_ok(current_task, |security_server| {
651 selinux_hooks::fs_node::check_fs_node_mkdir_access(
652 security_server,
653 current_task,
654 parent,
655 mode,
656 name,
657 )
658 })
659}
660
661pub fn check_fs_node_mknod_access(
667 current_task: &CurrentTask,
668 parent: &FsNode,
669 mode: FileMode,
670 name: &FsStr,
671 device_id: DeviceId,
672) -> Result<(), Errno> {
673 track_hook_duration!("security.hooks.check_fs_node_mknod_access");
674 assert!(!mode.is_reg());
675
676 if_selinux_else_default_ok(current_task, |security_server| {
677 selinux_hooks::fs_node::check_fs_node_mknod_access(
678 security_server,
679 current_task,
680 parent,
681 mode,
682 name,
683 device_id,
684 )
685 })
686}
687
688pub fn check_fs_node_link_access(
691 current_task: &CurrentTask,
692 parent: &FsNode,
693 child: &FsNode,
694) -> Result<(), Errno> {
695 track_hook_duration!("security.hooks.check_fs_node_link_access");
696 if_selinux_else_default_ok(current_task, |security_server| {
697 selinux_hooks::fs_node::check_fs_node_link_access(
698 security_server,
699 current_task,
700 parent,
701 child,
702 )
703 })
704}
705
706pub fn check_fs_node_unlink_access(
709 current_task: &CurrentTask,
710 parent: &FsNode,
711 child: &FsNode,
712 name: &FsStr,
713) -> Result<(), Errno> {
714 track_hook_duration!("security.hooks.check_fs_node_unlink_access");
715 if_selinux_else_default_ok(current_task, |security_server| {
716 selinux_hooks::fs_node::check_fs_node_unlink_access(
717 security_server,
718 current_task,
719 parent,
720 child,
721 name,
722 )
723 })
724}
725
726pub fn check_fs_node_rmdir_access(
729 current_task: &CurrentTask,
730 parent: &FsNode,
731 child: &FsNode,
732 name: &FsStr,
733) -> Result<(), Errno> {
734 track_hook_duration!("security.hooks.check_fs_node_rmdir_access");
735 if_selinux_else_default_ok(current_task, |security_server| {
736 selinux_hooks::fs_node::check_fs_node_rmdir_access(
737 security_server,
738 current_task,
739 parent,
740 child,
741 name,
742 )
743 })
744}
745
746pub fn check_fs_node_rename_access(
751 current_task: &CurrentTask,
752 old_parent: &FsNode,
753 moving_node: &FsNode,
754 new_parent: &FsNode,
755 replaced_node: Option<&FsNode>,
756 old_basename: &FsStr,
757 new_basename: &FsStr,
758) -> Result<(), Errno> {
759 track_hook_duration!("security.hooks.check_fs_node_rename_access");
760 if_selinux_else_default_ok(current_task, |security_server| {
761 selinux_hooks::fs_node::check_fs_node_rename_access(
762 security_server,
763 current_task,
764 old_parent,
765 moving_node,
766 new_parent,
767 replaced_node,
768 old_basename,
769 new_basename,
770 )
771 })
772}
773
774pub fn check_fs_node_read_link_access(
777 current_task: &CurrentTask,
778 fs_node: &FsNode,
779) -> Result<(), Errno> {
780 track_hook_duration!("security.hooks.check_fs_node_read_link_access");
781 if_selinux_else_default_ok(current_task, |security_server| {
782 selinux_hooks::fs_node::check_fs_node_read_link_access(
783 security_server,
784 current_task,
785 fs_node,
786 )
787 })
788}
789
790pub fn fs_node_permission(
793 current_task: &CurrentTask,
794 fs_node: &FsNode,
795 permission_flags: PermissionFlags,
796 audit_context: Auditable<'_>,
797) -> Result<(), Errno> {
798 track_hook_duration!("security.hooks.fs_node_permission");
799 if_selinux_else_default_ok(current_task, |security_server| {
800 selinux_hooks::fs_node::fs_node_permission(
801 security_server,
802 current_task,
803 fs_node,
804 permission_flags,
805 audit_context,
806 )
807 })
808}
809
810pub fn file_receive(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
813 track_hook_duration!("security.hooks.file_receive");
814 if_selinux_else_default_ok(current_task, |security_server| {
815 let receiving_sid = current_task_state(current_task).current_sid;
816 selinux_hooks::file::file_receive(security_server, current_task, receiving_sid, file)
817 })
818}
819
820pub fn file_alloc_security(current_task: &CurrentTask) -> FileObjectState {
823 track_hook_duration!("security.hooks.file_alloc_security");
824 FileObjectState { state: selinux_hooks::file::file_alloc_security(current_task) }
825}
826
827pub fn binder_connection_alloc(current_task: &CurrentTask) -> BinderConnectionState {
830 track_hook_duration!("security.hooks.binder_connection_alloc");
831 BinderConnectionState { state: selinux_hooks::binder::binder_connection_alloc(current_task) }
832}
833
834pub fn bpf_map_alloc(current_task: &CurrentTask) -> BpfMapState {
838 track_hook_duration!("security.hooks.bpf_map_alloc");
839 BpfMapState { state: selinux_hooks::bpf::bpf_map_alloc(current_task) }
840}
841
842pub fn bpf_prog_alloc(current_task: &CurrentTask) -> BpfProgState {
846 track_hook_duration!("security.hooks.bpf_prog_alloc");
847 BpfProgState { state: selinux_hooks::bpf::bpf_prog_alloc(current_task) }
848}
849
850pub fn check_file_ioctl_access(
853 current_task: &CurrentTask,
854 file: &FileObject,
855 request: u32,
856) -> Result<(), Errno> {
857 track_hook_duration!("security.hooks.check_file_ioctl_access");
858 if_selinux_else_default_ok(current_task, |security_server| {
859 selinux_hooks::file::check_file_ioctl_access(security_server, current_task, file, request)
860 })
861}
862
863pub fn fs_node_copy_up(
873 current_task: &CurrentTask,
874 fs_node: &FsNode,
875 fs: &FileSystem,
876 new_creds: &mut Credentials,
877) {
878 if_selinux_else(
879 current_task,
880 |_security_server| {
881 selinux_hooks::fs_node::fs_node_copy_up(current_task, fs_node, fs, new_creds)
882 },
883 || {},
884 )
885}
886
887pub fn check_file_lock_access(current_task: &CurrentTask, file: &FileObject) -> Result<(), Errno> {
895 track_hook_duration!("security.hooks.check_file_lock_access");
896 if_selinux_else_default_ok(current_task, |security_server| {
897 selinux_hooks::file::check_file_lock_access(security_server, current_task, file)
898 })
899}
900
901pub fn check_file_fcntl_access(
904 current_task: &CurrentTask,
905 file: &FileObject,
906 fcntl_cmd: u32,
907 fcntl_arg: u64,
908) -> Result<(), Errno> {
909 track_hook_duration!("security.hooks.check_file_fcntl_access");
910 if_selinux_else_default_ok(current_task, |security_server| {
911 selinux_hooks::file::check_file_fcntl_access(
912 security_server,
913 current_task,
914 file,
915 fcntl_cmd,
916 fcntl_arg,
917 )
918 })
919}
920
921pub fn check_fs_node_setattr_access(
924 current_task: &CurrentTask,
925 node: &FsNode,
926 attributes: &zxio_node_attr_has_t,
927) -> Result<(), Errno> {
928 track_hook_duration!("security.hooks.check_fs_node_setattr_access");
929 if_selinux_else_default_ok(current_task, |security_server| {
930 selinux_hooks::fs_node::check_fs_node_setattr_access(
931 security_server,
932 current_task,
933 node,
934 attributes,
935 )
936 })
937}
938
939pub fn task_alloc_for_kernel() -> TaskAttrs {
942 track_hook_duration!("security.hooks.task_alloc_for_kernel");
943 TaskAttrs::for_kernel()
944}
945
946pub fn task_to_fs_node(current_task: &CurrentTask, task: &Task, fs_node: &FsNode) {
952 track_hook_duration!("security.hooks.task_to_fs_node");
953 if current_task.kernel().security_state.state.is_some() {
956 selinux_hooks::task::fs_node_init_with_task(task, &fs_node);
957 }
958}
959
960pub fn task_for_context(task: &Task, context: &FsStr) -> Result<TaskAttrs, Errno> {
966 track_hook_duration!("security.hooks.task_for_context");
967 Ok(if let Some(kernel_state) = task.kernel().security_state.state.as_ref() {
968 selinux_hooks::task::task_alloc_from_context(&kernel_state.server, context)
969 } else {
970 Ok(TaskAttrs::for_selinux_disabled())
971 }?)
972}
973
974pub fn has_dontaudit_access(current_task: &CurrentTask, fs_node: &FsNode) -> bool {
978 track_hook_duration!("security.hooks.has_dontaudit_access");
979 if_selinux_else(
980 current_task,
981 |security_server| {
982 selinux_hooks::fs_node::has_dontaudit_access(security_server, current_task, fs_node)
983 },
984 || false,
985 )
986}
987
988pub fn is_task_capable_noaudit(
991 current_task: &CurrentTask,
992 capability: starnix_uapi::auth::Capabilities,
993) -> bool {
994 track_hook_duration!("security.hooks.is_task_capable_noaudit");
995 return common_cap::capable(current_task, capability).is_ok()
996 && if_selinux_else(
997 current_task,
998 |security_server| {
999 selinux_hooks::task::is_task_capable_noaudit(
1000 &selinux_hooks::build_permission_check(current_task, security_server),
1001 ¤t_task,
1002 capability,
1003 )
1004 },
1005 || true,
1006 );
1007}
1008
1009pub fn check_creds_capable(
1012 current_task: &CurrentTask,
1013 creds: &Credentials,
1014 capability: starnix_uapi::auth::Capabilities,
1015) -> Result<(), Errno> {
1016 track_hook_duration!("security.hooks.check_creds_capable");
1017 common_cap::creds_capable(creds, capability)?;
1018 if_selinux_else_default_ok(current_task, |security_server| {
1019 selinux_hooks::task::check_creds_capable(
1020 &selinux_hooks::build_permission_check(current_task, security_server),
1021 ¤t_task,
1022 creds,
1023 capability,
1024 )
1025 })
1026}
1027
1028pub fn check_task_capable(
1031 current_task: &CurrentTask,
1032 capability: starnix_uapi::auth::Capabilities,
1033) -> Result<(), Errno> {
1034 check_creds_capable(current_task, &**current_task.current_creds(), capability)
1035}
1036
1037pub fn check_task_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1040 track_hook_duration!("security.hooks.check_task_create_access");
1041 if_selinux_else_default_ok(current_task, |security_server| {
1042 selinux_hooks::task::check_task_create_access(
1043 &selinux_hooks::build_permission_check(current_task, security_server),
1044 current_task,
1045 )
1046 })
1047}
1048
1049pub fn check_socket_create_access(
1052 current_task: &CurrentTask,
1053 domain: SocketDomain,
1054 socket_type: SocketType,
1055 protocol: SocketProtocol,
1056 kernel_private: bool,
1057) -> Result<(), Errno> {
1058 track_hook_duration!("security.hooks.socket_create");
1059 if_selinux_else_default_ok(current_task, |security_server| {
1060 selinux_hooks::socket::check_socket_create_access(
1061 &security_server,
1062 current_task,
1063 domain,
1064 socket_type,
1065 protocol,
1066 kernel_private,
1067 )
1068 })
1069}
1070
1071pub fn socket_socketpair(
1074 current_task: &CurrentTask,
1075 left: DowncastedFile<'_, SocketFile>,
1076 right: DowncastedFile<'_, SocketFile>,
1077) -> Result<(), Errno> {
1078 track_hook_duration!("security.hooks.socket_socketpair");
1079 if_selinux_else_default_ok(current_task, |_| {
1080 selinux_hooks::socket::socket_socketpair(left, right)
1081 })
1082}
1083
1084pub fn socket_post_create(current_task: &CurrentTask, socket: &Socket) {
1087 track_hook_duration!("security.hooks.socket_post_create");
1088 if let Some(state) = ¤t_task.kernel().security_state.state {
1089 selinux_hooks::socket::socket_post_create(&state.server, socket);
1090 }
1091}
1092
1093pub fn check_socket_bind_access(
1096 current_task: &CurrentTask,
1097 socket: &Socket,
1098 socket_address: &SocketAddress,
1099) -> Result<(), Errno> {
1100 track_hook_duration!("security.hooks.check_socket_bind_access");
1101 if_selinux_else_default_ok(current_task, |security_server| {
1102 selinux_hooks::socket::check_socket_bind_access(
1103 &security_server,
1104 current_task,
1105 socket,
1106 socket_address,
1107 )
1108 })
1109}
1110
1111pub fn check_socket_connect_access(
1114 current_task: &CurrentTask,
1115 socket: DowncastedFile<'_, SocketFile>,
1116 socket_peer: &SocketPeer,
1117) -> Result<(), Errno> {
1118 track_hook_duration!("security.hooks.check_socket_connect_access");
1119 if_selinux_else_default_ok(current_task, |security_server| {
1120 selinux_hooks::socket::check_socket_connect_access(
1121 &security_server,
1122 current_task,
1123 socket,
1124 socket_peer,
1125 )
1126 })
1127}
1128
1129pub fn check_socket_listen_access(
1132 current_task: &CurrentTask,
1133 socket: &Socket,
1134 backlog: i32,
1135) -> Result<(), Errno> {
1136 track_hook_duration!("security.hooks.check_socket_listen_access");
1137 if_selinux_else_default_ok(current_task, |security_server| {
1138 selinux_hooks::socket::check_socket_listen_access(
1139 &security_server,
1140 current_task,
1141 socket,
1142 backlog,
1143 )
1144 })
1145}
1146
1147pub fn socket_accept(
1151 current_task: &CurrentTask,
1152 listening_socket: DowncastedFile<'_, SocketFile>,
1153 accepted_socket: DowncastedFile<'_, SocketFile>,
1154) -> Result<(), Errno> {
1155 track_hook_duration!("security.hooks.check_socket_getname_access");
1156 if_selinux_else_default_ok(current_task, |security_server| {
1157 selinux_hooks::socket::socket_accept(
1158 &security_server,
1159 current_task,
1160 listening_socket,
1161 accepted_socket,
1162 )
1163 })
1164}
1165
1166pub fn check_socket_getsockopt_access(
1169 current_task: &CurrentTask,
1170 socket: &Socket,
1171 level: u32,
1172 optname: u32,
1173) -> Result<(), Errno> {
1174 track_hook_duration!("security.hooks.check_socket_getsockopt_access");
1175 if_selinux_else_default_ok(current_task, |security_server| {
1176 selinux_hooks::socket::check_socket_getsockopt_access(
1177 &security_server,
1178 current_task,
1179 socket,
1180 level,
1181 optname,
1182 )
1183 })
1184}
1185
1186pub fn check_socket_setsockopt_access(
1189 current_task: &CurrentTask,
1190 socket: &Socket,
1191 level: u32,
1192 optname: u32,
1193) -> Result<(), Errno> {
1194 track_hook_duration!("security.hooks.check_socket_setsockopt_access");
1195 if_selinux_else_default_ok(current_task, |security_server| {
1196 selinux_hooks::socket::check_socket_setsockopt_access(
1197 &security_server,
1198 current_task,
1199 socket,
1200 level,
1201 optname,
1202 )
1203 })
1204}
1205
1206pub fn check_socket_sendmsg_access(
1209 current_task: &CurrentTask,
1210 socket: &Socket,
1211) -> Result<(), Errno> {
1212 track_hook_duration!("security.hooks.check_socket_sendmsg_access");
1213 if_selinux_else_default_ok(current_task, |security_server| {
1214 selinux_hooks::socket::check_socket_sendmsg_access(&security_server, current_task, socket)
1215 })
1216}
1217
1218pub fn check_socket_recvmsg_access(
1221 current_task: &CurrentTask,
1222 socket: &Socket,
1223) -> Result<(), Errno> {
1224 track_hook_duration!("security.hooks.check_socket_recvmsg_access");
1225 if_selinux_else_default_ok(current_task, |security_server| {
1226 selinux_hooks::socket::check_socket_recvmsg_access(&security_server, current_task, socket)
1227 })
1228}
1229
1230pub fn check_socket_getsockname_access(
1233 current_task: &CurrentTask,
1234 socket: &Socket,
1235) -> Result<(), Errno> {
1236 track_hook_duration!("security.hooks.check_socket_getname_access");
1237 if_selinux_else_default_ok(current_task, |security_server| {
1238 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1239 })
1240}
1241
1242pub fn check_socket_getpeername_access(
1245 current_task: &CurrentTask,
1246 socket: &Socket,
1247) -> Result<(), Errno> {
1248 track_hook_duration!("security.hooks.check_socket_getname_access");
1249 if_selinux_else_default_ok(current_task, |security_server| {
1250 selinux_hooks::socket::check_socket_getname_access(&security_server, current_task, socket)
1251 })
1252}
1253
1254pub fn check_socket_shutdown_access(
1257 current_task: &CurrentTask,
1258 socket: &Socket,
1259 how: SocketShutdownFlags,
1260) -> Result<(), Errno> {
1261 track_hook_duration!("security.hooks.check_socket_shutdown_access");
1262 if_selinux_else_default_ok(current_task, |security_server| {
1263 selinux_hooks::socket::check_socket_shutdown_access(
1264 &security_server,
1265 current_task,
1266 socket,
1267 how,
1268 )
1269 })
1270}
1271
1272pub fn socket_getpeersec_stream(
1275 current_task: &CurrentTask,
1276 socket: &Socket,
1277) -> Result<Vec<u8>, Errno> {
1278 track_hook_duration!("security.hooks.socket_getpeersec_stream");
1279 if_selinux_else_default_ok(current_task, |security_server| {
1280 selinux_hooks::socket::socket_getpeersec_stream(&security_server, current_task, socket)
1281 })
1282}
1283
1284pub fn socket_getpeersec_dgram(current_task: &CurrentTask, socket: &Socket) -> Vec<u8> {
1288 track_hook_duration!("security.hooks.socket_getpeersec_dgram");
1289 if_selinux_else(
1290 current_task,
1291 |security_server| {
1292 selinux_hooks::socket::socket_getpeersec_dgram(&security_server, current_task, socket)
1293 },
1294 Vec::default,
1295 )
1296}
1297
1298pub fn unix_may_send(
1302 current_task: &CurrentTask,
1303 sending_socket: &Socket,
1304 receiving_socket: &Socket,
1305) -> Result<(), Errno> {
1306 track_hook_duration!("security.hooks.unix_may_send");
1307 if_selinux_else_default_ok(current_task, |security_server| {
1308 selinux_hooks::socket::unix_may_send(
1309 &security_server,
1310 current_task,
1311 sending_socket,
1312 receiving_socket,
1313 )
1314 })
1315}
1316
1317pub fn unix_stream_connect(
1321 current_task: &CurrentTask,
1322 client_socket: &Socket,
1323 listening_socket: &Socket,
1324 server_socket: &Socket,
1325) -> Result<(), Errno> {
1326 track_hook_duration!("security.hooks.unix_stream_connect");
1327 if_selinux_else_default_ok(current_task, |security_server| {
1328 selinux_hooks::socket::unix_stream_connect(
1329 &security_server,
1330 current_task,
1331 client_socket,
1332 listening_socket,
1333 server_socket,
1334 )
1335 })
1336}
1337
1338pub fn check_netlink_send_access(
1342 current_task: &CurrentTask,
1343 socket: &Socket,
1344 message_type: u16,
1345) -> Result<(), Errno> {
1346 track_hook_duration!("security.hooks.check_netlink_send_access");
1347 if_selinux_else_default_ok(current_task, |security_server| {
1348 selinux_hooks::netlink_socket::check_netlink_send_access(
1349 &security_server,
1350 current_task,
1351 socket,
1352 message_type,
1353 )
1354 })
1355}
1356
1357pub fn check_tun_dev_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
1360 track_hook_duration!("security.hooks.check_tun_dev_create_access");
1361 if_selinux_else_default_ok(current_task, |security_server| {
1362 selinux_hooks::socket::check_tun_dev_create_access(&security_server, current_task)
1363 })
1364}
1365
1366pub fn bprm_creds_from_file(
1370 current_task: &CurrentTask,
1371 resolved_program: &mut ResolvedProgram,
1372) -> Result<(), Errno> {
1373 track_hook_duration!("security.hooks.bprm_creds_from_file");
1374
1375 let (no_new_privs, is_ptraced_without_cap_sys_ptrace) = {
1376 let state = current_task.read();
1377 (state.no_new_privs(), state.is_ptraced_without_cap_sys_ptrace())
1378 };
1379
1380 let enable_suid = current_task.kernel().features.enable_suid
1381 && !no_new_privs
1382 && !is_ptraced_without_cap_sys_ptrace;
1383 if enable_suid {
1384 resolved_program.file.name().apply_suid_and_sgid(&mut resolved_program.creds);
1385 }
1386
1387 resolved_program.creds.fsuid = resolved_program.creds.euid;
1389 resolved_program.creds.fsgid = resolved_program.creds.egid;
1390
1391 resolved_program.creds.saved_uid = resolved_program.creds.euid;
1397 resolved_program.creds.saved_gid = resolved_program.creds.egid;
1398
1399 common_cap::bprm_creds_from_file(current_task, resolved_program)?;
1400
1401 Ok(())
1402}
1403
1404pub fn bprm_creds_for_exec(
1409 current_task: &CurrentTask,
1410 resolved_program: &mut ResolvedProgram,
1411) -> Result<(), Errno> {
1412 track_hook_duration!("security.hooks.bprm_creds_for_exec");
1413 if let Some(state) = ¤t_task.kernel().security_state.state {
1414 if state.has_policy() {
1415 return selinux_hooks::task::bprm_creds_for_exec(
1416 &state.server,
1417 current_task,
1418 resolved_program,
1419 );
1420 } else {
1421 let previous_sid = current_task.current_creds().security_state.current_sid;
1423 resolved_program.creds.security_state =
1424 TaskAttrs::for_transition(InitialSid::Init.into(), previous_sid);
1425 }
1426 }
1427 Ok(())
1428}
1429
1430pub fn bprm_committing_creds(
1435 current_task: &CurrentTask,
1436 resolved_program: &ResolvedProgram,
1437) -> Result<(), Errno> {
1438 track_hook_duration!("security.hooks.bprm_committing_creds");
1439 if_selinux_else_default_ok(current_task, |security_server| {
1440 selinux_hooks::task::bprm_committing_creds(security_server, current_task, resolved_program);
1441 Ok(())
1442 })
1443}
1444
1445pub fn bprm_committed_creds(current_task: &CurrentTask) -> Result<(), Errno> {
1449 track_hook_duration!("security.hooks.bprm_committed_creds");
1450 if_selinux_else_default_ok(current_task, |security_server| {
1451 selinux_hooks::task::bprm_committed_creds(security_server, current_task);
1452 Ok(())
1453 })
1454}
1455
1456pub fn check_task_getscheduler_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1459 track_hook_duration!("security.hooks.task_getscheduler");
1460 if_selinux_else_default_ok(source, |security_server| {
1461 selinux_hooks::task::check_getsched_access(
1462 &selinux_hooks::build_permission_check(source, security_server),
1463 &source,
1464 &target,
1465 )
1466 })
1467}
1468
1469pub fn check_task_setscheduler_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1472 track_hook_duration!("security.hooks.task_setscheduler");
1473 if_selinux_else_default_ok(source, |security_server| {
1474 selinux_hooks::task::check_setsched_access(
1475 &selinux_hooks::build_permission_check(source, security_server),
1476 &source,
1477 &target,
1478 )
1479 })
1480}
1481
1482pub fn check_task_setnice_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1485 track_hook_duration!("security.hooks.check_task_setnice_access");
1486 if_selinux_else_default_ok(source, |security_server| {
1487 selinux_hooks::task::check_setsched_access(
1488 &selinux_hooks::build_permission_check(source, security_server),
1489 &source,
1490 &target,
1491 )
1492 })
1493}
1494
1495pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1498 track_hook_duration!("security.hooks.check_getpgid_access");
1499 if_selinux_else_default_ok(source, |security_server| {
1500 selinux_hooks::task::check_getpgid_access(
1501 &selinux_hooks::build_permission_check(source, security_server),
1502 &source,
1503 &target,
1504 )
1505 })
1506}
1507
1508pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1511 track_hook_duration!("security.hooks.check_setpgid_access");
1512 if_selinux_else_default_ok(source, |security_server| {
1513 selinux_hooks::task::check_setpgid_access(
1514 &selinux_hooks::build_permission_check(source, security_server),
1515 &source,
1516 &target,
1517 )
1518 })
1519}
1520
1521pub fn check_task_getsid(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1524 track_hook_duration!("security.hooks.check_task_getsid");
1525 if_selinux_else_default_ok(source, |security_server| {
1526 selinux_hooks::task::check_task_getsid(
1527 &selinux_hooks::build_permission_check(source, security_server),
1528 &source,
1529 &target,
1530 )
1531 })
1532}
1533
1534pub fn check_getcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1537 track_hook_duration!("security.hooks.check_getcap_access");
1538 if_selinux_else_default_ok(source, |security_server| {
1539 selinux_hooks::task::check_getcap_access(
1540 &selinux_hooks::build_permission_check(source, security_server),
1541 &source,
1542 &target,
1543 )
1544 })
1545}
1546
1547pub fn check_setcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1551 track_hook_duration!("security.hooks.check_setcap_access");
1552 if_selinux_else_default_ok(source, |security_server| {
1553 selinux_hooks::task::check_setcap_access(
1554 &selinux_hooks::build_permission_check(source, security_server),
1555 &source,
1556 &target,
1557 )
1558 })
1559}
1560
1561pub fn check_signal_access(
1564 source: &CurrentTask,
1565 target: &Task,
1566 signal: Signal,
1567) -> Result<(), Errno> {
1568 track_hook_duration!("security.hooks.check_signal_access");
1569 if_selinux_else_default_ok(source, |security_server| {
1570 selinux_hooks::task::check_signal_access(
1571 &selinux_hooks::build_permission_check(source, security_server),
1572 &source,
1573 &target,
1574 signal,
1575 )
1576 })
1577}
1578
1579pub fn check_syslog_access(source: &CurrentTask, action: SyslogAction) -> Result<(), Errno> {
1582 track_hook_duration!("security.hooks.check_syslog_access");
1583 if_selinux_else_default_ok(source, |security_server| {
1584 selinux_hooks::task::check_syslog_access(
1585 &selinux_hooks::build_permission_check(source, security_server),
1586 &source,
1587 action,
1588 )
1589 })
1590}
1591
1592pub fn ptrace_traceme(current_task: &CurrentTask, parent_tracer_task: &Task) -> Result<(), Errno> {
1595 track_hook_duration!("security.hooks.ptrace_traceme");
1596 yama::ptrace_traceme(current_task, parent_tracer_task)?;
1597 common_cap::ptrace_traceme(current_task, parent_tracer_task)?;
1598 if_selinux_else_default_ok(current_task, |security_server| {
1599 selinux_hooks::task::ptrace_traceme(
1600 &selinux_hooks::build_permission_check(current_task, security_server),
1601 current_task,
1602 parent_tracer_task,
1603 )
1604 })
1605}
1606
1607pub fn ptrace_access_check(
1610 current_task: &CurrentTask,
1611 tracee_task: &Task,
1612 mode: PtraceAccessMode,
1613) -> Result<(), Errno> {
1614 track_hook_duration!("security.hooks.ptrace_access_check");
1615 yama::ptrace_access_check(current_task, tracee_task, mode)?;
1616 common_cap::ptrace_access_check(current_task, tracee_task, mode)?;
1617 if_selinux_else_default_ok(current_task, |security_server| {
1618 selinux_hooks::task::ptrace_access_check(
1619 &selinux_hooks::build_permission_check(current_task, security_server),
1620 current_task,
1621 tracee_task,
1622 mode,
1623 )
1624 })
1625}
1626
1627pub fn task_prlimit(
1630 source: &CurrentTask,
1631 target: &Task,
1632 check_get_rlimit: bool,
1633 check_set_rlimit: bool,
1634) -> Result<(), Errno> {
1635 track_hook_duration!("security.hooks.task_prlimit");
1636 if_selinux_else_default_ok(source, |security_server| {
1637 selinux_hooks::task::task_prlimit(
1638 &selinux_hooks::build_permission_check(source, security_server),
1639 &source,
1640 &target,
1641 check_get_rlimit,
1642 check_set_rlimit,
1643 )
1644 })
1645}
1646
1647pub fn task_setrlimit(
1650 source: &CurrentTask,
1651 target: &Task,
1652 old_limit: rlimit,
1653 new_limit: rlimit,
1654) -> Result<(), Errno> {
1655 track_hook_duration!("security.hooks.task_setrlimit");
1656 if_selinux_else_default_ok(source, |security_server| {
1657 selinux_hooks::task::task_setrlimit(
1658 &selinux_hooks::build_permission_check(source, security_server),
1659 &source,
1660 &target,
1661 old_limit,
1662 new_limit,
1663 )
1664 })
1665}
1666
1667pub fn sb_kern_mount(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1670 track_hook_duration!("security.hooks.sb_kern_mount");
1671 if_selinux_else_default_ok(current_task, |security_server| {
1672 selinux_hooks::superblock::sb_kern_mount(
1673 &selinux_hooks::build_permission_check(current_task, security_server),
1674 current_task,
1675 fs,
1676 )
1677 })
1678}
1679
1680pub fn sb_mount(
1684 current_task: &CurrentTask,
1685 path: &NamespaceNode,
1686 flags: MountFlags,
1687) -> Result<(), Errno> {
1688 track_hook_duration!("security.hooks.sb_mount");
1689 if_selinux_else_default_ok(current_task, |security_server| {
1690 selinux_hooks::superblock::sb_mount(
1691 &selinux_hooks::build_permission_check(current_task, security_server),
1692 current_task,
1693 path,
1694 flags,
1695 )
1696 })
1697}
1698
1699pub fn sb_remount(
1702 current_task: &CurrentTask,
1703 mount: &Mount,
1704 new_mount_options: FileSystemMountOptions,
1705) -> Result<(), Errno> {
1706 track_hook_duration!("security.hooks.sb_remount");
1707 if_selinux_else_default_ok(current_task, |security_server| {
1708 selinux_hooks::superblock::sb_remount(security_server, mount, new_mount_options)
1709 })
1710}
1711
1712pub fn sb_show_options<'a>(
1715 _kernel: &Kernel,
1716 fs: &'a FileSystem,
1717) -> Result<impl std::fmt::Display + 'a, Errno> {
1718 track_hook_duration!("security.hooks.sb_show_options");
1719 selinux_hooks::superblock::sb_show_options(fs)
1720}
1721
1722pub fn sb_statfs(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1725 track_hook_duration!("security.hooks.sb_statfs");
1726 if_selinux_else_default_ok(current_task, |security_server| {
1727 selinux_hooks::superblock::sb_statfs(
1728 &selinux_hooks::build_permission_check(current_task, security_server),
1729 current_task,
1730 fs,
1731 )
1732 })
1733}
1734
1735pub fn sb_umount(
1739 current_task: &CurrentTask,
1740 node: &NamespaceNode,
1741 flags: UnmountFlags,
1742) -> Result<(), Errno> {
1743 track_hook_duration!("security.hooks.sb_umount");
1744 if_selinux_else_default_ok(current_task, |security_server| {
1745 selinux_hooks::superblock::sb_umount(
1746 &selinux_hooks::build_permission_check(current_task, security_server),
1747 current_task,
1748 node,
1749 flags,
1750 )
1751 })
1752}
1753
1754pub fn check_fs_node_getattr_access(
1757 current_task: &CurrentTask,
1758 fs_node: &FsNode,
1759) -> Result<(), Errno> {
1760 track_hook_duration!("security.hooks.check_fs_node_getattr_access");
1761 if_selinux_else_default_ok(current_task, |security_server| {
1762 selinux_hooks::fs_node::check_fs_node_getattr_access(security_server, current_task, fs_node)
1763 })
1764}
1765
1766pub fn fs_node_xattr_skipcap(name: &FsStr) -> bool {
1769 selinux_hooks::fs_node::fs_node_xattr_skipcap(name)
1770}
1771
1772pub fn check_fs_node_setxattr_access(
1778 current_task: &CurrentTask,
1779 fs_node: &FsNode,
1780 name: &FsStr,
1781 value: &FsStr,
1782 op: XattrOp,
1783) -> Result<(), Errno> {
1784 track_hook_duration!("security.hooks.check_fs_node_setxattr_access");
1785 common_cap::fs_node_setxattr(current_task, fs_node, name, value, op)?;
1786 if_selinux_else_default_ok(current_task, |security_server| {
1787 selinux_hooks::fs_node::check_fs_node_setxattr_access(
1788 security_server,
1789 current_task,
1790 fs_node,
1791 name,
1792 value,
1793 op,
1794 )
1795 })
1796}
1797
1798pub fn check_fs_node_getxattr_access(
1800 current_task: &CurrentTask,
1801 fs_node: &FsNode,
1802 name: &FsStr,
1803) -> Result<(), Errno> {
1804 track_hook_duration!("security.hooks.check_fs_node_getxattr_access");
1805 if_selinux_else_default_ok(current_task, |security_server| {
1806 selinux_hooks::fs_node::check_fs_node_getxattr_access(
1807 security_server,
1808 current_task,
1809 fs_node,
1810 name,
1811 )
1812 })
1813}
1814
1815pub fn check_fs_node_listxattr_access(
1817 current_task: &CurrentTask,
1818 fs_node: &FsNode,
1819) -> Result<(), Errno> {
1820 track_hook_duration!("security.hooks.check_fs_node_listxattr_access");
1821 if_selinux_else_default_ok(current_task, |security_server| {
1822 selinux_hooks::fs_node::check_fs_node_listxattr_access(
1823 security_server,
1824 current_task,
1825 fs_node,
1826 )
1827 })
1828}
1829
1830pub fn check_fs_node_removexattr_access(
1832 current_task: &CurrentTask,
1833 fs_node: &FsNode,
1834 name: &FsStr,
1835) -> Result<(), Errno> {
1836 track_hook_duration!("security.hooks.check_fs_node_removexattr_access");
1837 common_cap::fs_node_removexattr(current_task, fs_node, name)?;
1838 if_selinux_else_default_ok(current_task, |security_server| {
1839 selinux_hooks::fs_node::check_fs_node_removexattr_access(
1840 security_server,
1841 current_task,
1842 fs_node,
1843 name,
1844 )
1845 })
1846}
1847
1848pub fn fs_node_listsecurity(current_task: &CurrentTask, fs_node: &FsNode) -> Option<FsString> {
1855 track_hook_duration!("security.hooks.fs_node_listsecurity");
1856 if_selinux_else(
1857 current_task,
1858 |_| selinux_hooks::fs_node::fs_node_listsecurity(fs_node),
1859 || None,
1860 )
1861}
1862
1863pub fn fs_node_getsecurity(
1871 current_task: &CurrentTask,
1872 fs_node: &FsNode,
1873 name: &FsStr,
1874 max_size: usize,
1875) -> Result<ValueOrSize<FsString>, Errno> {
1876 track_hook_duration!("security.hooks.fs_node_getsecurity");
1877 if_selinux_else(
1878 current_task,
1879 |security_server| {
1880 selinux_hooks::fs_node::fs_node_getsecurity(
1881 security_server,
1882 current_task,
1883 fs_node,
1884 name,
1885 max_size,
1886 )
1887 },
1888 || fs_node.ops().get_xattr(fs_node, current_task, name, max_size),
1889 )
1890}
1891
1892pub fn fs_node_setsecurity(
1898 current_task: &CurrentTask,
1899 fs_node: &FsNode,
1900 name: &FsStr,
1901 value: &FsStr,
1902 op: XattrOp,
1903) -> Result<(), Errno> {
1904 track_hook_duration!("security.hooks.fs_node_setsecurity");
1905 if_selinux_else(
1906 current_task,
1907 |security_server| {
1908 selinux_hooks::fs_node::fs_node_setsecurity(
1909 security_server,
1910 current_task,
1911 fs_node,
1912 name,
1913 value,
1914 op,
1915 )
1916 },
1917 || fs_node.ops().set_xattr(fs_node, current_task, name, value, op),
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_state: &BpfMapState,
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_state,
1952 flags,
1953 )
1954 })
1955}
1956
1957pub fn check_bpf_prog_access(
1962 current_task: &CurrentTask,
1963 bpf_program_state: &BpfProgState,
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_state,
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(current_task: &CurrentTask) {
2104 track_hook_duration!("security.hooks.selinuxfs_policy_loaded");
2105 selinux_hooks::selinuxfs::selinuxfs_policy_loaded(current_task)
2106}
2107
2108pub fn selinuxfs_get_admin_api(current_task: &CurrentTask) -> Option<Arc<SecurityServer>> {
2112 current_task.kernel().security_state.state.as_ref().map(|state| state.server.clone())
2113}
2114
2115pub fn selinuxfs_check_access(
2118 current_task: &CurrentTask,
2119 permission: SecurityPermission,
2120) -> Result<(), Errno> {
2121 track_hook_duration!("security.hooks.selinuxfs_check_access");
2122 if_selinux_else_default_ok(current_task, |security_server| {
2123 selinux_hooks::selinuxfs::selinuxfs_check_access(security_server, current_task, permission)
2124 })
2125}
2126
2127pub fn creds_start_internal_operation(current_task: &CurrentTask) -> Arc<Credentials> {
2130 track_hook_duration!("security.hooks.creds_start_internal_operation");
2131 let mut creds = Credentials::clone(¤t_task.current_creds());
2132 creds.security_state.internal_operation = true;
2133 creds.into()
2134}
2135
2136pub mod testing {
2137 use super::{Arc, KernelState, SecurityServer, selinux_hooks};
2138 use starnix_sync::LockDepMutex;
2139 use std::sync::OnceLock;
2140 use std::sync::atomic::AtomicU64;
2141
2142 pub fn kernel_state(security_server: Option<Arc<SecurityServer>>) -> KernelState {
2145 let state = security_server.map(|server| selinux_hooks::KernelState {
2146 server,
2147 pending_file_systems: LockDepMutex::default(),
2148 selinuxfs_null: OnceLock::default(),
2149 access_denial_count: AtomicU64::new(0u64),
2150 has_policy: false.into(),
2151 _inspect_node: fuchsia_inspect::Node::default(),
2152 });
2153 KernelState { state }
2154 }
2155}
2156
2157#[cfg(test)]
2158mod tests {
2159 use super::*;
2160 use crate::security;
2161 use crate::security::selinux_hooks::get_cached_sid;
2162 use crate::security::selinux_hooks::testing::{
2163 self, spawn_kernel_with_selinux_hooks_test_policy_and_run,
2164 };
2165 use crate::testing::{create_task, spawn_kernel_and_run, spawn_kernel_with_selinux_and_run};
2166 use linux_uapi::XATTR_NAME_SELINUX;
2167 use selinux::InitialSid;
2168 use starnix_uapi::auth::PTRACE_MODE_ATTACH;
2169 use starnix_uapi::signals::SIGTERM;
2170
2171 const VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_valid_t:s0";
2172 const VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] = b"u:object_r:test_valid_t:s0\0";
2173
2174 const DIFFERENT_VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_different_valid_t:s0";
2175 const DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] =
2176 b"u:object_r:test_different_valid_t:s0\0";
2177
2178 const INVALID_SECURITY_CONTEXT_INTERNAL_NUL: &[u8] = b"u:object_r:test_valid_\0t:s0";
2179
2180 const INVALID_SECURITY_CONTEXT: &[u8] = b"not_a_u:object_r:test_valid_t:s0";
2181
2182 #[derive(Default, Debug, PartialEq)]
2183 enum TestHookResult {
2184 WasRun,
2185 WasNotRun,
2186 #[default]
2187 WasNotRunDefault,
2188 }
2189
2190 #[fuchsia::test]
2191 async fn if_selinux_else_disabled() {
2192 spawn_kernel_and_run(async |current_task| {
2193 assert!(current_task.kernel().security_state.state.is_none());
2194
2195 let check_result =
2196 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2197 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2198
2199 let run_else_result = if_selinux_else(
2200 current_task,
2201 |_| TestHookResult::WasRun,
2202 || TestHookResult::WasNotRun,
2203 );
2204 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2205 })
2206 .await;
2207 }
2208
2209 #[fuchsia::test]
2210 async fn if_selinux_else_without_policy() {
2211 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2212 let check_result =
2213 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2214 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2215
2216 let run_else_result = if_selinux_else(
2217 current_task,
2218 |_| TestHookResult::WasRun,
2219 || TestHookResult::WasNotRun,
2220 );
2221 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2222 })
2223 .await;
2224 }
2225
2226 #[fuchsia::test]
2227 async fn if_selinux_else_with_policy() {
2228 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2229 let check_result =
2230 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2231 assert_eq!(check_result, Ok(TestHookResult::WasRun));
2232
2233 let run_else_result = if_selinux_else(
2234 current_task,
2235 |_| TestHookResult::WasRun,
2236 || TestHookResult::WasNotRun,
2237 );
2238 assert_eq!(run_else_result, TestHookResult::WasRun);
2239 })
2240 .await;
2241 }
2242
2243 #[fuchsia::test]
2244 async fn task_create_access_allowed_for_selinux_disabled() {
2245 spawn_kernel_and_run(async |current_task| {
2246 assert!(current_task.kernel().security_state.state.is_none());
2247 assert_eq!(check_task_create_access(current_task), Ok(()));
2248 })
2249 .await;
2250 }
2251
2252 #[fuchsia::test]
2253 async fn task_create_access_allowed_for_permissive_mode() {
2254 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2255 security_server.set_enforcing(false);
2256 assert_eq!(check_task_create_access(current_task), Ok(()));
2257 })
2258 .await;
2259 }
2260
2261 #[fuchsia::test]
2262 async fn exec_access_allowed_for_selinux_disabled() {
2263 spawn_kernel_and_run(async |current_task| {
2264 assert!(current_task.kernel().security_state.state.is_none());
2265 let executable = testing::create_test_file(current_task);
2266 let file = testing::open_test_file(current_task, &executable);
2267 let mut resolved_program = testing::make_resolved_program(current_task, file);
2268 assert_eq!(bprm_creds_for_exec(current_task, &mut resolved_program), Ok(()));
2269 })
2270 .await;
2271 }
2272
2273 #[fuchsia::test]
2274 async fn exec_access_allowed_for_permissive_mode() {
2275 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2276 security_server.set_enforcing(false);
2277 let executable = testing::create_test_file(current_task);
2278 let file = testing::open_test_file(current_task, &executable);
2279 let mut resolved_program = testing::make_resolved_program(current_task, file);
2280 let result = bprm_creds_for_exec(current_task, &mut resolved_program);
2282 assert!(result.is_ok());
2283 })
2284 .await;
2285 }
2286
2287 #[fuchsia::test]
2288 async fn exec_no_state_update_for_selinux_disabled() {
2289 spawn_kernel_and_run(async |current_task| {
2290 let target_sid = InitialSid::Unlabeled.into();
2291
2292 assert!(selinux_hooks::current_task_state(current_task).current_sid != target_sid);
2293
2294 testing::mutate_attrs_for_test(current_task, |attrs| {
2296 attrs.exec_sid = Some(target_sid);
2297 });
2298
2299 let executable = testing::create_test_file(current_task);
2300 let file = testing::open_test_file(current_task, &executable);
2301 let mut resolved_program = testing::make_resolved_program(current_task, file);
2302
2303 let before_hook_sid = selinux_hooks::current_task_state(current_task).current_sid;
2304
2305 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2306 assert_eq!(resolved_program.creds.security_state.current_sid, before_hook_sid);
2307 })
2308 .await;
2309 }
2310
2311 #[fuchsia::test]
2312 async fn exec_initial_context_for_selinux_without_policy() {
2313 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2314 let elf_sid = InitialSid::Unlabeled.into();
2315 assert_ne!(selinux_hooks::current_task_state(current_task).current_sid, elf_sid);
2316 assert_ne!(
2317 selinux_hooks::current_task_state(current_task).current_sid,
2318 InitialSid::Init.into()
2319 );
2320
2321 testing::mutate_attrs_for_test(current_task, |attrs| {
2323 attrs.exec_sid = Some(elf_sid);
2324 });
2325
2326 let executable = testing::create_test_file(current_task);
2327 let file = testing::open_test_file(current_task, &executable);
2328 let mut resolved_program = testing::make_resolved_program(current_task, file);
2329
2330 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2331
2332 assert_eq!(resolved_program.creds.security_state.current_sid, InitialSid::Init.into());
2333 })
2334 .await;
2335 }
2336
2337 #[fuchsia::test]
2338 async fn exec_state_update_for_permissive_mode() {
2339 spawn_kernel_with_selinux_hooks_test_policy_and_run(|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
2345 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).current_sid);
2346
2347 testing::mutate_attrs_for_test(current_task, |attrs| {
2349 attrs.exec_sid = Some(elf_sid);
2350 });
2351
2352 let executable = testing::create_test_file(current_task);
2353 let file = testing::open_test_file(current_task, &executable);
2354 let mut resolved_program = testing::make_resolved_program(current_task, file);
2355
2356 bprm_creds_for_exec(current_task, &mut resolved_program).unwrap();
2357 assert_eq!(resolved_program.creds.security_state.current_sid, elf_sid);
2358 })
2359 .await;
2360 }
2361
2362 #[fuchsia::test]
2363 async fn getsched_access_allowed_for_selinux_disabled() {
2364 spawn_kernel_and_run(async |current_task| {
2365 let another_task = create_task(¤t_task.kernel(), "another-task");
2366 assert_eq!(check_task_getscheduler_access(current_task, &another_task), Ok(()));
2367 })
2368 .await;
2369 }
2370
2371 #[fuchsia::test]
2372 async fn getsched_access_allowed_for_permissive_mode() {
2373 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2374 let another_task = create_task(¤t_task.kernel(), "another-task");
2375 assert_eq!(check_task_getscheduler_access(current_task, &another_task), Ok(()));
2376 })
2377 .await;
2378 }
2379
2380 #[fuchsia::test]
2381 async fn setsched_access_allowed_for_selinux_disabled() {
2382 spawn_kernel_and_run(async |current_task| {
2383 let another_task = create_task(¤t_task.kernel(), "another-task");
2384 assert_eq!(check_task_setscheduler_access(current_task, &another_task), Ok(()));
2385 })
2386 .await;
2387 }
2388
2389 #[fuchsia::test]
2390 async fn setsched_access_allowed_for_permissive_mode() {
2391 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2392 let another_task = create_task(¤t_task.kernel(), "another-task");
2393 assert_eq!(check_task_setscheduler_access(current_task, &another_task), Ok(()));
2394 })
2395 .await;
2396 }
2397
2398 #[fuchsia::test]
2399 async fn getpgid_access_allowed_for_selinux_disabled() {
2400 spawn_kernel_and_run(async |current_task| {
2401 let another_task = create_task(¤t_task.kernel(), "another-task");
2402 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2403 })
2404 .await;
2405 }
2406
2407 #[fuchsia::test]
2408 async fn getpgid_access_allowed_for_permissive_mode() {
2409 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2410 let another_task = create_task(¤t_task.kernel(), "another-task");
2411 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2412 })
2413 .await;
2414 }
2415
2416 #[fuchsia::test]
2417 async fn setpgid_access_allowed_for_selinux_disabled() {
2418 spawn_kernel_and_run(async |current_task| {
2419 let another_task = create_task(¤t_task.kernel(), "another-task");
2420 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2421 })
2422 .await;
2423 }
2424
2425 #[fuchsia::test]
2426 async fn setpgid_access_allowed_for_permissive_mode() {
2427 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2428 let another_task = create_task(¤t_task.kernel(), "another-task");
2429 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2430 })
2431 .await;
2432 }
2433
2434 #[fuchsia::test]
2435 async fn task_getsid_allowed_for_selinux_disabled() {
2436 spawn_kernel_and_run(async |current_task| {
2437 let another_task = create_task(¤t_task.kernel(), "another-task");
2438 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2439 })
2440 .await;
2441 }
2442
2443 #[fuchsia::test]
2444 async fn task_getsid_allowed_for_permissive_mode() {
2445 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2446 let another_task = create_task(¤t_task.kernel(), "another-task");
2447 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2448 })
2449 .await;
2450 }
2451
2452 #[fuchsia::test]
2453 async fn signal_access_allowed_for_selinux_disabled() {
2454 spawn_kernel_and_run(async |current_task| {
2455 let another_task = create_task(¤t_task.kernel(), "another-task");
2456 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2457 })
2458 .await;
2459 }
2460
2461 #[fuchsia::test]
2462 async fn signal_access_allowed_for_permissive_mode() {
2463 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2464 let another_task = create_task(¤t_task.kernel(), "another-task");
2465 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2466 })
2467 .await;
2468 }
2469
2470 #[fuchsia::test]
2471 async fn ptrace_traceme_access_allowed_for_selinux_disabled() {
2472 spawn_kernel_and_run(async |current_task| {
2473 let another_task = create_task(¤t_task.kernel(), "another-task");
2474 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2475 })
2476 .await;
2477 }
2478
2479 #[fuchsia::test]
2480 async fn ptrace_traceme_access_allowed_for_permissive_mode() {
2481 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2482 let another_task = create_task(¤t_task.kernel(), "another-task");
2483 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2484 })
2485 .await;
2486 }
2487
2488 #[fuchsia::test]
2489 async fn ptrace_attach_access_allowed_for_selinux_disabled() {
2490 spawn_kernel_and_run(async |current_task| {
2491 let another_task = create_task(¤t_task.kernel(), "another-task");
2492 assert_eq!(
2493 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2494 Ok(())
2495 );
2496 })
2497 .await;
2498 }
2499
2500 #[fuchsia::test]
2501 async fn ptrace_attach_access_allowed_for_permissive_mode() {
2502 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2503 let another_task = create_task(¤t_task.kernel(), "another-task");
2504 assert_eq!(
2505 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2506 Ok(())
2507 );
2508 })
2509 .await;
2510 }
2511
2512 #[fuchsia::test]
2513 async fn task_prlimit_access_allowed_for_selinux_disabled() {
2514 spawn_kernel_and_run(async |current_task| {
2515 let another_task = create_task(¤t_task.kernel(), "another-task");
2516 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2517 })
2518 .await;
2519 }
2520
2521 #[fuchsia::test]
2522 async fn task_prlimit_access_allowed_for_permissive_mode() {
2523 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2524 let another_task = create_task(¤t_task.kernel(), "another-task");
2525 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2526 })
2527 .await;
2528 }
2529
2530 #[fuchsia::test]
2531 async fn fs_node_task_to_fs_node_noop_selinux_disabled() {
2532 spawn_kernel_and_run(async |current_task| {
2533 let node = &testing::create_test_file(current_task).entry.node;
2534 task_to_fs_node(current_task, ¤t_task.task, &node);
2535 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2536 })
2537 .await;
2538 }
2539
2540 #[fuchsia::test]
2541 async fn fs_node_setsecurity_selinux_disabled_only_sets_xattr() {
2542 spawn_kernel_and_run(async |current_task| {
2543 let node = &testing::create_test_file(current_task).entry.node;
2544
2545 fs_node_setsecurity(
2546 ¤t_task,
2547 &node,
2548 XATTR_NAME_SELINUX.to_bytes().into(),
2549 VALID_SECURITY_CONTEXT.into(),
2550 XattrOp::Set,
2551 )
2552 .expect("set_xattr(security.selinux) failed");
2553
2554 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2555 })
2556 .await;
2557 }
2558
2559 #[fuchsia::test]
2560 async fn fs_node_setsecurity_selinux_without_policy_only_sets_xattr() {
2561 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2562 let node = &testing::create_test_file(current_task).entry.node;
2563 fs_node_setsecurity(
2564 ¤t_task,
2565 &node,
2566 XATTR_NAME_SELINUX.to_bytes().into(),
2567 VALID_SECURITY_CONTEXT.into(),
2568 XattrOp::Set,
2569 )
2570 .expect("set_xattr(security.selinux) failed");
2571
2572 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2573 })
2574 .await;
2575 }
2576
2577 #[fuchsia::test]
2578 async fn fs_node_setsecurity_selinux_permissive_sets_xattr_and_label() {
2579 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2580 security_server.set_enforcing(false);
2581 let expected_sid = security_server
2582 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2583 .expect("no SID for VALID_SECURITY_CONTEXT");
2584 let node = &testing::create_test_file(¤t_task).entry.node;
2585
2586 assert_ne!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2588
2589 fs_node_setsecurity(
2590 ¤t_task,
2591 &node,
2592 XATTR_NAME_SELINUX.to_bytes().into(),
2593 VALID_SECURITY_CONTEXT.into(),
2594 XattrOp::Set,
2595 )
2596 .expect("set_xattr(security.selinux) failed");
2597
2598 assert_eq!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2601 })
2602 .await;
2603 }
2604
2605 #[fuchsia::test]
2606 async fn fs_node_setsecurity_not_selinux_only_sets_xattr() {
2607 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2608 let valid_security_context_sid = security_server
2609 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2610 .expect("no SID for VALID_SECURITY_CONTEXT");
2611 let node = &testing::create_test_file(current_task).entry.node;
2612 let whatever_sid = selinux_hooks::get_cached_sid(node);
2616 assert_ne!(Some(valid_security_context_sid), whatever_sid);
2617
2618 fs_node_setsecurity(
2619 ¤t_task,
2620 &node,
2621 "security.selinu!".into(), VALID_SECURITY_CONTEXT.into(),
2623 XattrOp::Set,
2624 )
2625 .expect("set_xattr(security.selinux) failed");
2626
2627 assert_eq!(whatever_sid, selinux_hooks::get_cached_sid(node));
2629 })
2630 .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(|current_task, _security_server| {
2636 let node = &testing::create_test_file(current_task).entry.node;
2637
2638 let before_sid = selinux_hooks::get_cached_sid(node);
2639 assert_ne!(Some(InitialSid::Unlabeled.into()), before_sid);
2640
2641 assert!(
2642 check_fs_node_setxattr_access(
2643 ¤t_task,
2644 &node,
2645 XATTR_NAME_SELINUX.to_bytes().into(),
2646 "!".into(), XattrOp::Set,
2648 )
2649 .is_err()
2650 );
2651
2652 assert_eq!(before_sid, selinux_hooks::get_cached_sid(node));
2653 })
2654 .await;
2655 }
2656
2657 #[fuchsia::test]
2658 async fn fs_node_setsecurity_selinux_permissive_invalid_context_sets_xattr_and_label() {
2659 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2660 security_server.set_enforcing(false);
2661 let node = &testing::create_test_file(current_task).entry.node;
2662
2663 assert_ne!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2664
2665 fs_node_setsecurity(
2666 ¤t_task,
2667 &node,
2668 XATTR_NAME_SELINUX.to_bytes().into(),
2669 "!".into(), XattrOp::Set,
2671 )
2672 .expect("set_xattr(security.selinux) failed");
2673
2674 assert_eq!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
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(|current_task, _security_server| {
2682 let node = &testing::create_test_file(current_task).entry.node;
2683
2684 fs_node_setsecurity(
2685 ¤t_task,
2686 &node,
2687 XATTR_NAME_SELINUX.to_bytes().into(),
2688 VALID_SECURITY_CONTEXT.into(),
2689 XattrOp::Set,
2690 )
2691 .expect("set_xattr(security.selinux) failed");
2692
2693 assert!(selinux_hooks::get_cached_sid(node).is_some());
2694
2695 let first_sid = selinux_hooks::get_cached_sid(node).unwrap();
2696 fs_node_setsecurity(
2697 ¤t_task,
2698 &node,
2699 XATTR_NAME_SELINUX.to_bytes().into(),
2700 DIFFERENT_VALID_SECURITY_CONTEXT.into(),
2701 XattrOp::Set,
2702 )
2703 .expect("set_xattr(security.selinux) failed");
2704
2705 assert!(selinux_hooks::get_cached_sid(node).is_some());
2706
2707 let second_sid = selinux_hooks::get_cached_sid(node).unwrap();
2708
2709 assert_ne!(first_sid, second_sid);
2710 })
2711 .await;
2712 }
2713
2714 #[fuchsia::test]
2715 async fn fs_node_getsecurity_returns_cached_context() {
2716 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2717 let node = &testing::create_test_file(current_task).entry.node;
2718
2719 const TEST_VALUE: &str = "Something Random";
2721 node.ops()
2722 .set_xattr(
2723 node,
2724 current_task,
2725 XATTR_NAME_SELINUX.to_bytes().into(),
2726 TEST_VALUE.into(),
2727 XattrOp::Set,
2728 )
2729 .expect("set_xattr(security.selinux) failed");
2730
2731 let sid = security_server
2733 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2734 .expect("security context to SID");
2735 selinux_hooks::set_cached_sid(&node, sid);
2736
2737 let result =
2739 fs_node_getsecurity(current_task, node, XATTR_NAME_SELINUX.to_bytes().into(), 4096);
2740 assert_eq!(
2741 result,
2742 Ok(ValueOrSize::Value(FsString::new(VALID_SECURITY_CONTEXT_WITH_NUL.into())))
2743 );
2744 })
2745 .await;
2746 }
2747
2748 #[fuchsia::test]
2749 async fn fs_node_getsecurity_delegates_to_get_xattr() {
2750 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2751 let node = &testing::create_test_file(current_task).entry.node;
2752
2753 security_server.set_enforcing(false);
2756 const TEST_VALUE: &str = "Something Random";
2757 fs_node_setsecurity(
2758 ¤t_task,
2759 node,
2760 XATTR_NAME_SELINUX.to_bytes().into(),
2761 TEST_VALUE.into(),
2762 XattrOp::Set,
2763 )
2764 .expect("set_xattr(security.selinux) failed");
2765 security_server.set_enforcing(true);
2766
2767 let result =
2769 fs_node_getsecurity(current_task, node, XATTR_NAME_SELINUX.to_bytes().into(), 4096);
2770 assert_eq!(result, Ok(ValueOrSize::Value(FsString::new(TEST_VALUE.into()))));
2771 })
2772 .await;
2773 }
2774
2775 #[fuchsia::test]
2776 async fn set_get_procattr() {
2777 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2778 assert_eq!(get_procattr(current_task, current_task, ProcAttr::Exec), Ok(Vec::new()));
2779
2780 assert_eq!(
2781 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2783 Ok(())
2784 );
2785
2786 assert_eq!(
2787 set_procattr(
2789 current_task,
2790 ProcAttr::SockCreate,
2791 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2792 ),
2793 error!(EACCES)
2794 );
2795
2796 assert_eq!(
2797 set_procattr(
2799 current_task,
2800 ProcAttr::Previous,
2801 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2802 ),
2803 error!(EINVAL)
2804 );
2805
2806 assert_eq!(
2807 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2809 error!(EINVAL)
2810 );
2811
2812 assert_eq!(
2813 get_procattr(current_task, current_task, ProcAttr::Exec),
2814 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2815 );
2816
2817 assert!(get_procattr(current_task, current_task, ProcAttr::Current).is_ok());
2818 })
2819 .await;
2820 }
2821
2822 #[fuchsia::test]
2823 async fn set_get_procattr_with_nulls() {
2824 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2825 assert_eq!(get_procattr(current_task, current_task, ProcAttr::Exec), Ok(Vec::new()));
2826
2827 assert_eq!(
2828 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT_WITH_NUL.into()),
2830 Ok(())
2831 );
2832
2833 assert_eq!(
2834 set_procattr(
2836 current_task,
2837 ProcAttr::FsCreate,
2838 INVALID_SECURITY_CONTEXT_INTERNAL_NUL.into()
2839 ),
2840 error!(EINVAL)
2841 );
2842
2843 assert_eq!(
2844 get_procattr(current_task, current_task, ProcAttr::Exec),
2845 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2846 );
2847
2848 assert_eq!(
2849 get_procattr(current_task, current_task, ProcAttr::FsCreate),
2850 Ok(Vec::new())
2851 );
2852 })
2853 .await;
2854 }
2855
2856 #[fuchsia::test]
2857 async fn set_get_procattr_clear_context() {
2858 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2859 assert_eq!(
2861 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2862 Ok(())
2863 );
2864 assert_eq!(
2865 set_procattr(
2866 current_task,
2867 ProcAttr::FsCreate,
2868 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2869 ),
2870 Ok(())
2871 );
2872
2873 assert_eq!(set_procattr(current_task, ProcAttr::Exec, b"\0"), Ok(()));
2875 assert_eq!(current_task.current_creds().security_state.exec_sid, None);
2876
2877 assert_eq!(set_procattr(current_task, ProcAttr::FsCreate, b"\x0a"), Ok(()));
2879 assert_eq!(current_task.current_creds().security_state.fscreate_sid, None);
2880 })
2881 .await;
2882 }
2883
2884 #[fuchsia::test]
2885 async fn set_get_procattr_setcurrent() {
2886 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2887 let initial_previous =
2889 get_procattr(current_task, current_task, ProcAttr::Previous).unwrap();
2890
2891 assert_eq!(
2892 set_procattr(current_task, ProcAttr::Current, VALID_SECURITY_CONTEXT.into()),
2894 Ok(())
2895 );
2896
2897 assert_eq!(
2898 get_procattr(current_task, current_task, ProcAttr::Current),
2900 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2901 );
2902
2903 assert_eq!(
2904 get_procattr(current_task, current_task, ProcAttr::Previous),
2906 Ok(initial_previous.clone())
2907 );
2908
2909 assert_eq!(
2910 set_procattr(
2912 current_task,
2913 ProcAttr::Current,
2914 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2915 ),
2916 Ok(())
2917 );
2918
2919 assert_eq!(
2920 get_procattr(current_task, current_task, ProcAttr::Current),
2922 Ok(DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL.into())
2923 );
2924
2925 assert_eq!(
2926 get_procattr(current_task, current_task, ProcAttr::Previous),
2928 Ok(initial_previous.clone())
2929 );
2930 })
2931 .await;
2932 }
2933
2934 #[fuchsia::test]
2935 async fn set_get_procattr_selinux_permissive() {
2936 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2937 security_server.set_enforcing(false);
2938 assert_eq!(
2939 get_procattr(current_task, ¤t_task.task, ProcAttr::Exec),
2940 Ok(Vec::new())
2941 );
2942
2943 assert_eq!(
2944 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2946 Ok(())
2947 );
2948
2949 assert_eq!(
2950 set_procattr(
2953 current_task,
2954 ProcAttr::FsCreate,
2955 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2956 ),
2957 Ok(())
2958 );
2959
2960 assert_eq!(
2961 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2963 error!(EINVAL)
2964 );
2965
2966 assert_eq!(
2967 get_procattr(current_task, ¤t_task.task, ProcAttr::Exec),
2968 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2969 );
2970
2971 assert!(get_procattr(current_task, ¤t_task.task, ProcAttr::Current).is_ok());
2972 })
2973 .await;
2974 }
2975
2976 #[fuchsia::test]
2977 async fn set_get_procattr_selinux_disabled() {
2978 spawn_kernel_and_run(async |current_task| {
2979 assert_eq!(
2980 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2981 error!(EINVAL)
2982 );
2983
2984 assert_eq!(
2985 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2987 error!(EINVAL)
2988 );
2989
2990 assert_eq!(
2991 set_procattr(¤t_task, ProcAttr::FsCreate, VALID_SECURITY_CONTEXT.into()),
2993 error!(EINVAL)
2994 );
2995
2996 assert_eq!(
2997 set_procattr(¤t_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2999 error!(EINVAL)
3000 );
3001
3002 assert_eq!(
3003 get_procattr(¤t_task, ¤t_task.task, ProcAttr::Current),
3004 error!(EINVAL)
3005 );
3006 })
3007 .await;
3008 }
3009
3010 #[fuchsia::test]
3011 async fn create_file_with_fscreate_sid() {
3012 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3013 let sid =
3014 security_server.security_context_to_sid(VALID_SECURITY_CONTEXT.into()).unwrap();
3015 let source_node = &testing::create_test_file(current_task).entry.node;
3016
3017 fs_node_setsecurity(
3018 ¤t_task,
3019 &source_node,
3020 XATTR_NAME_SELINUX.to_bytes().into(),
3021 VALID_SECURITY_CONTEXT.into(),
3022 XattrOp::Set,
3023 )
3024 .expect("set_xattr(security.selinux) failed");
3025
3026 let mut creds = Credentials::clone(¤t_task.current_creds());
3027 security::fs_node_copy_up(current_task, source_node, &source_node.fs(), &mut creds);
3028 let dir_entry = current_task
3029 .override_creds(creds.into(), || {
3030 current_task
3031 .fs()
3032 .root()
3033 .create_node(
3034 ¤t_task,
3035 "test_file2".into(),
3036 FileMode::IFREG,
3037 DeviceId::NONE,
3038 )
3039 .unwrap()
3040 })
3041 .entry;
3042
3043 assert_eq!(get_cached_sid(&dir_entry.node), Some(sid));
3044 })
3045 .await;
3046 }
3047}