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::ResolvedElf;
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 elf_state: &mut ResolvedElf,
1372) -> Result<(), Errno> {
1373 track_hook_duration!("security.hooks.bprm_creds_from_file");
1374
1375 let (no_new_privs, is_ptraced) = {
1376 let state = current_task.read();
1377 (state.no_new_privs(), state.is_ptraced())
1378 };
1379
1380 let enable_suid = current_task.kernel().features.enable_suid && !no_new_privs && !is_ptraced;
1381 if enable_suid {
1382 elf_state.file.name.apply_suid_and_sgid(&mut elf_state.creds);
1383 }
1384
1385 elf_state.creds.fsuid = elf_state.creds.euid;
1387 elf_state.creds.fsgid = elf_state.creds.egid;
1388
1389 elf_state.creds.saved_uid = elf_state.creds.euid;
1395 elf_state.creds.saved_gid = elf_state.creds.egid;
1396
1397 let prev = current_task.current_creds();
1398 let file_is_privileged = elf_state.creds.euid != prev.euid || elf_state.creds.egid != prev.egid;
1399 let is_secure_exec = file_is_privileged
1400 || elf_state.creds.uid != elf_state.creds.euid
1401 || elf_state.creds.gid != elf_state.creds.egid;
1402
1403 elf_state.secure_exec |= is_secure_exec;
1404
1405 common_cap::bprm_creds_from_file(current_task, elf_state)?;
1406
1407 Ok(())
1408}
1409
1410pub fn bprm_creds_for_exec(
1416 current_task: &CurrentTask,
1417 executable: &NamespaceNode,
1418 elf_state: &mut ResolvedElf,
1419) -> Result<(), Errno> {
1420 track_hook_duration!("security.hooks.bprm_creds_for_exec");
1421 if let Some(state) = ¤t_task.kernel().security_state.state {
1422 if state.has_policy() {
1423 return selinux_hooks::task::bprm_creds_for_exec(
1424 &state.server,
1425 current_task,
1426 executable,
1427 elf_state,
1428 );
1429 } else {
1430 let previous_sid = current_task.current_creds().security_state.current_sid;
1432 elf_state.creds.security_state =
1433 TaskAttrs::for_transition(InitialSid::Init.into(), previous_sid);
1434 }
1435 }
1436 Ok(())
1437}
1438
1439pub fn bprm_committing_creds(
1445 current_task: &CurrentTask,
1446 elf_state: &ResolvedElf,
1447) -> Result<(), Errno> {
1448 track_hook_duration!("security.hooks.bprm_committing_creds");
1449 if_selinux_else_default_ok(current_task, |security_server| {
1450 selinux_hooks::task::bprm_committing_creds(security_server, current_task, elf_state);
1451 Ok(())
1452 })
1453}
1454
1455pub fn bprm_committed_creds(current_task: &CurrentTask) -> Result<(), Errno> {
1459 track_hook_duration!("security.hooks.bprm_committed_creds");
1460 if_selinux_else_default_ok(current_task, |security_server| {
1461 selinux_hooks::task::bprm_committed_creds(security_server, current_task);
1462 Ok(())
1463 })
1464}
1465
1466pub fn check_task_getscheduler_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1469 track_hook_duration!("security.hooks.task_getscheduler");
1470 if_selinux_else_default_ok(source, |security_server| {
1471 selinux_hooks::task::check_getsched_access(
1472 &selinux_hooks::build_permission_check(source, security_server),
1473 &source,
1474 &target,
1475 )
1476 })
1477}
1478
1479pub fn check_task_setscheduler_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1482 track_hook_duration!("security.hooks.task_setscheduler");
1483 if_selinux_else_default_ok(source, |security_server| {
1484 selinux_hooks::task::check_setsched_access(
1485 &selinux_hooks::build_permission_check(source, security_server),
1486 &source,
1487 &target,
1488 )
1489 })
1490}
1491
1492pub fn check_task_setnice_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1495 track_hook_duration!("security.hooks.task_setnice");
1496 if_selinux_else_default_ok(source, |security_server| {
1497 selinux_hooks::task::check_setsched_access(
1498 &selinux_hooks::build_permission_check(source, security_server),
1499 &source,
1500 &target,
1501 )
1502 })
1503}
1504
1505pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1508 track_hook_duration!("security.hooks.check_getpgid_access");
1509 if_selinux_else_default_ok(source, |security_server| {
1510 selinux_hooks::task::check_getpgid_access(
1511 &selinux_hooks::build_permission_check(source, security_server),
1512 &source,
1513 &target,
1514 )
1515 })
1516}
1517
1518pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1521 track_hook_duration!("security.hooks.check_setpgid_access");
1522 if_selinux_else_default_ok(source, |security_server| {
1523 selinux_hooks::task::check_setpgid_access(
1524 &selinux_hooks::build_permission_check(source, security_server),
1525 &source,
1526 &target,
1527 )
1528 })
1529}
1530
1531pub fn check_task_getsid(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1534 track_hook_duration!("security.hooks.check_task_getsid");
1535 if_selinux_else_default_ok(source, |security_server| {
1536 selinux_hooks::task::check_task_getsid(
1537 &selinux_hooks::build_permission_check(source, security_server),
1538 &source,
1539 &target,
1540 )
1541 })
1542}
1543
1544pub fn check_getcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1547 track_hook_duration!("security.hooks.check_getcap_access");
1548 if_selinux_else_default_ok(source, |security_server| {
1549 selinux_hooks::task::check_getcap_access(
1550 &selinux_hooks::build_permission_check(source, security_server),
1551 &source,
1552 &target,
1553 )
1554 })
1555}
1556
1557pub fn check_setcap_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
1561 track_hook_duration!("security.hooks.check_setcap_access");
1562 if_selinux_else_default_ok(source, |security_server| {
1563 selinux_hooks::task::check_setcap_access(
1564 &selinux_hooks::build_permission_check(source, security_server),
1565 &source,
1566 &target,
1567 )
1568 })
1569}
1570
1571pub fn check_signal_access(
1574 source: &CurrentTask,
1575 target: &Task,
1576 signal: Signal,
1577) -> Result<(), Errno> {
1578 track_hook_duration!("security.hooks.check_signal_access");
1579 if_selinux_else_default_ok(source, |security_server| {
1580 selinux_hooks::task::check_signal_access(
1581 &selinux_hooks::build_permission_check(source, security_server),
1582 &source,
1583 &target,
1584 signal,
1585 )
1586 })
1587}
1588
1589pub fn check_syslog_access(source: &CurrentTask, action: SyslogAction) -> Result<(), Errno> {
1592 track_hook_duration!("security.hooks.check_syslog_access");
1593 if_selinux_else_default_ok(source, |security_server| {
1594 selinux_hooks::task::check_syslog_access(
1595 &selinux_hooks::build_permission_check(source, security_server),
1596 &source,
1597 action,
1598 )
1599 })
1600}
1601
1602pub fn ptrace_traceme(current_task: &CurrentTask, parent_tracer_task: &Task) -> Result<(), Errno> {
1605 track_hook_duration!("security.hooks.ptrace_traceme");
1606 yama::ptrace_traceme(current_task, parent_tracer_task)?;
1607 common_cap::ptrace_traceme(current_task, parent_tracer_task)?;
1608 if_selinux_else_default_ok(current_task, |security_server| {
1609 selinux_hooks::task::ptrace_traceme(
1610 &selinux_hooks::build_permission_check(current_task, security_server),
1611 current_task,
1612 parent_tracer_task,
1613 )
1614 })
1615}
1616
1617pub fn ptrace_access_check(
1620 current_task: &CurrentTask,
1621 tracee_task: &Task,
1622 mode: PtraceAccessMode,
1623) -> Result<(), Errno> {
1624 track_hook_duration!("security.hooks.ptrace_access_check");
1625 yama::ptrace_access_check(current_task, tracee_task, mode)?;
1626 common_cap::ptrace_access_check(current_task, tracee_task, mode)?;
1627 if_selinux_else_default_ok(current_task, |security_server| {
1628 selinux_hooks::task::ptrace_access_check(
1629 &selinux_hooks::build_permission_check(current_task, security_server),
1630 current_task,
1631 tracee_task,
1632 mode,
1633 )
1634 })
1635}
1636
1637pub fn task_prlimit(
1640 source: &CurrentTask,
1641 target: &Task,
1642 check_get_rlimit: bool,
1643 check_set_rlimit: bool,
1644) -> Result<(), Errno> {
1645 track_hook_duration!("security.hooks.task_prlimit");
1646 if_selinux_else_default_ok(source, |security_server| {
1647 selinux_hooks::task::task_prlimit(
1648 &selinux_hooks::build_permission_check(source, security_server),
1649 &source,
1650 &target,
1651 check_get_rlimit,
1652 check_set_rlimit,
1653 )
1654 })
1655}
1656
1657pub fn task_setrlimit(
1660 source: &CurrentTask,
1661 target: &Task,
1662 old_limit: rlimit,
1663 new_limit: rlimit,
1664) -> Result<(), Errno> {
1665 track_hook_duration!("security.hooks.task_setrlimit");
1666 if_selinux_else_default_ok(source, |security_server| {
1667 selinux_hooks::task::task_setrlimit(
1668 &selinux_hooks::build_permission_check(source, security_server),
1669 &source,
1670 &target,
1671 old_limit,
1672 new_limit,
1673 )
1674 })
1675}
1676
1677pub fn sb_kern_mount(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1680 track_hook_duration!("security.hooks.sb_kern_mount");
1681 if_selinux_else_default_ok(current_task, |security_server| {
1682 selinux_hooks::superblock::sb_kern_mount(
1683 &selinux_hooks::build_permission_check(current_task, security_server),
1684 current_task,
1685 fs,
1686 )
1687 })
1688}
1689
1690pub fn sb_mount(
1694 current_task: &CurrentTask,
1695 path: &NamespaceNode,
1696 flags: MountFlags,
1697) -> Result<(), Errno> {
1698 track_hook_duration!("security.hooks.sb_mount");
1699 if_selinux_else_default_ok(current_task, |security_server| {
1700 selinux_hooks::superblock::sb_mount(
1701 &selinux_hooks::build_permission_check(current_task, security_server),
1702 current_task,
1703 path,
1704 flags,
1705 )
1706 })
1707}
1708
1709pub fn sb_remount(
1712 current_task: &CurrentTask,
1713 mount: &Mount,
1714 new_mount_options: FileSystemMountOptions,
1715) -> Result<(), Errno> {
1716 track_hook_duration!("security.hooks.sb_remount");
1717 if_selinux_else_default_ok(current_task, |security_server| {
1718 selinux_hooks::superblock::sb_remount(security_server, mount, new_mount_options)
1719 })
1720}
1721
1722pub fn sb_show_options<'a>(
1725 _kernel: &Kernel,
1726 fs: &'a FileSystem,
1727) -> Result<impl std::fmt::Display + 'a, Errno> {
1728 track_hook_duration!("security.hooks.sb_show_options");
1729 selinux_hooks::superblock::sb_show_options(fs)
1730}
1731
1732pub fn sb_statfs(current_task: &CurrentTask, fs: &FileSystem) -> Result<(), Errno> {
1735 track_hook_duration!("security.hooks.sb_statfs");
1736 if_selinux_else_default_ok(current_task, |security_server| {
1737 selinux_hooks::superblock::sb_statfs(
1738 &selinux_hooks::build_permission_check(current_task, security_server),
1739 current_task,
1740 fs,
1741 )
1742 })
1743}
1744
1745pub fn sb_umount(
1749 current_task: &CurrentTask,
1750 node: &NamespaceNode,
1751 flags: UnmountFlags,
1752) -> Result<(), Errno> {
1753 track_hook_duration!("security.hooks.sb_umount");
1754 if_selinux_else_default_ok(current_task, |security_server| {
1755 selinux_hooks::superblock::sb_umount(
1756 &selinux_hooks::build_permission_check(current_task, security_server),
1757 current_task,
1758 node,
1759 flags,
1760 )
1761 })
1762}
1763
1764pub fn check_fs_node_getattr_access(
1767 current_task: &CurrentTask,
1768 fs_node: &FsNode,
1769) -> Result<(), Errno> {
1770 track_hook_duration!("security.hooks.check_fs_node_getattr_access");
1771 if_selinux_else_default_ok(current_task, |security_server| {
1772 selinux_hooks::fs_node::check_fs_node_getattr_access(security_server, current_task, fs_node)
1773 })
1774}
1775
1776pub fn fs_node_xattr_skipcap(name: &FsStr) -> bool {
1779 selinux_hooks::fs_node::fs_node_xattr_skipcap(name)
1780}
1781
1782pub fn check_fs_node_setxattr_access(
1788 current_task: &CurrentTask,
1789 fs_node: &FsNode,
1790 name: &FsStr,
1791 value: &FsStr,
1792 op: XattrOp,
1793) -> Result<(), Errno> {
1794 track_hook_duration!("security.hooks.check_fs_node_setxattr_access");
1795 common_cap::fs_node_setxattr(current_task, fs_node, name, value, op)?;
1796 if_selinux_else_default_ok(current_task, |security_server| {
1797 selinux_hooks::fs_node::check_fs_node_setxattr_access(
1798 security_server,
1799 current_task,
1800 fs_node,
1801 name,
1802 value,
1803 op,
1804 )
1805 })
1806}
1807
1808pub fn check_fs_node_getxattr_access(
1810 current_task: &CurrentTask,
1811 fs_node: &FsNode,
1812 name: &FsStr,
1813) -> Result<(), Errno> {
1814 track_hook_duration!("security.hooks.check_fs_node_getxattr_access");
1815 if_selinux_else_default_ok(current_task, |security_server| {
1816 selinux_hooks::fs_node::check_fs_node_getxattr_access(
1817 security_server,
1818 current_task,
1819 fs_node,
1820 name,
1821 )
1822 })
1823}
1824
1825pub fn check_fs_node_listxattr_access(
1827 current_task: &CurrentTask,
1828 fs_node: &FsNode,
1829) -> Result<(), Errno> {
1830 track_hook_duration!("security.hooks.check_fs_node_listxattr_access");
1831 if_selinux_else_default_ok(current_task, |security_server| {
1832 selinux_hooks::fs_node::check_fs_node_listxattr_access(
1833 security_server,
1834 current_task,
1835 fs_node,
1836 )
1837 })
1838}
1839
1840pub fn check_fs_node_removexattr_access(
1842 current_task: &CurrentTask,
1843 fs_node: &FsNode,
1844 name: &FsStr,
1845) -> Result<(), Errno> {
1846 track_hook_duration!("security.hooks.check_fs_node_removexattr_access");
1847 common_cap::fs_node_removexattr(current_task, fs_node, name)?;
1848 if_selinux_else_default_ok(current_task, |security_server| {
1849 selinux_hooks::fs_node::check_fs_node_removexattr_access(
1850 security_server,
1851 current_task,
1852 fs_node,
1853 name,
1854 )
1855 })
1856}
1857
1858pub fn fs_node_listsecurity(current_task: &CurrentTask, fs_node: &FsNode) -> Option<FsString> {
1865 track_hook_duration!("security.hooks.fs_node_listsecurity");
1866 if_selinux_else(
1867 current_task,
1868 |_| selinux_hooks::fs_node::fs_node_listsecurity(fs_node),
1869 || None,
1870 )
1871}
1872
1873pub fn fs_node_getsecurity(
1881 current_task: &CurrentTask,
1882 fs_node: &FsNode,
1883 name: &FsStr,
1884 max_size: usize,
1885) -> Result<ValueOrSize<FsString>, Errno> {
1886 track_hook_duration!("security.hooks.fs_node_getsecurity");
1887 if_selinux_else(
1888 current_task,
1889 |security_server| {
1890 selinux_hooks::fs_node::fs_node_getsecurity(
1891 security_server,
1892 current_task,
1893 fs_node,
1894 name,
1895 max_size,
1896 )
1897 },
1898 || fs_node.ops().get_xattr(fs_node, current_task, name, max_size),
1899 )
1900}
1901
1902pub fn fs_node_setsecurity(
1908 current_task: &CurrentTask,
1909 fs_node: &FsNode,
1910 name: &FsStr,
1911 value: &FsStr,
1912 op: XattrOp,
1913) -> Result<(), Errno> {
1914 track_hook_duration!("security.hooks.fs_node_setsecurity");
1915 if_selinux_else(
1916 current_task,
1917 |security_server| {
1918 selinux_hooks::fs_node::fs_node_setsecurity(
1919 security_server,
1920 current_task,
1921 fs_node,
1922 name,
1923 value,
1924 op,
1925 )
1926 },
1927 || fs_node.ops().set_xattr(fs_node, current_task, name, value, op),
1928 )
1929}
1930
1931pub fn check_bpf_access<Attr: FromBytes>(
1935 current_task: &CurrentTask,
1936 cmd: bpf_cmd,
1937 attr: &Attr,
1938 attr_size: u32,
1939) -> Result<(), Errno> {
1940 track_hook_duration!("security.hooks.check_bpf_access");
1941 if_selinux_else_default_ok(current_task, |security_server| {
1942 selinux_hooks::bpf::check_bpf_access(security_server, current_task, cmd, attr, attr_size)
1943 })
1944}
1945
1946pub fn check_bpf_map_access(
1950 current_task: &CurrentTask,
1951 bpf_map_state: &BpfMapState,
1952 flags: PermissionFlags,
1953) -> Result<(), Errno> {
1954 track_hook_duration!("security.hooks.check_bpf_map_access");
1955 if_selinux_else_default_ok(current_task, |security_server| {
1956 let subject_sid = current_task_state(current_task).current_sid;
1957 selinux_hooks::bpf::check_bpf_map_access(
1958 security_server,
1959 current_task,
1960 subject_sid,
1961 bpf_map_state,
1962 flags,
1963 )
1964 })
1965}
1966
1967pub fn check_bpf_prog_access(
1972 current_task: &CurrentTask,
1973 bpf_program_state: &BpfProgState,
1974) -> Result<(), Errno> {
1975 track_hook_duration!("security.hooks.check_bpf_prog_access");
1976 if_selinux_else_default_ok(current_task, |security_server| {
1977 let subject_sid = current_task_state(current_task).current_sid;
1978 selinux_hooks::bpf::check_bpf_prog_access(
1979 security_server,
1980 current_task,
1981 subject_sid,
1982 bpf_program_state,
1983 )
1984 })
1985}
1986
1987pub fn check_perf_event_open_access(
1991 current_task: &CurrentTask,
1992 target_task_type: TargetTaskType<'_>,
1993 attr: &perf_event_attr,
1994 event_type: PerfEventType,
1995) -> Result<(), Errno> {
1996 track_hook_duration!("security.hooks.check_perf_event_open_access");
1997 if_selinux_else_default_ok(current_task, |security_server| {
1998 selinux_hooks::perf_event::check_perf_event_open_access(
1999 security_server,
2000 current_task,
2001 target_task_type,
2002 attr,
2003 event_type,
2004 )
2005 })
2006}
2007
2008pub fn perf_event_alloc(current_task: &CurrentTask) -> PerfEventState {
2012 track_hook_duration!("security.hooks.perf_event_alloc");
2013 PerfEventState { state: selinux_hooks::perf_event::perf_event_alloc(current_task) }
2014}
2015
2016pub fn check_perf_event_read_access(
2019 current_task: &CurrentTask,
2020 perf_event_file: &PerfEventFile,
2021) -> Result<(), Errno> {
2022 track_hook_duration!("security.hooks.check_perf_event_read_access");
2023 if_selinux_else_default_ok(current_task, |security_server| {
2024 selinux_hooks::perf_event::check_perf_event_read_access(
2025 security_server,
2026 current_task,
2027 perf_event_file,
2028 )
2029 })
2030}
2031
2032pub fn check_perf_event_write_access(
2035 current_task: &CurrentTask,
2036 perf_event_file: &PerfEventFile,
2037) -> Result<(), Errno> {
2038 track_hook_duration!("security.hooks.check_perf_event_write_access");
2039 if_selinux_else_default_ok(current_task, |security_server| {
2040 selinux_hooks::perf_event::check_perf_event_write_access(
2041 security_server,
2042 current_task,
2043 perf_event_file,
2044 )
2045 })
2046}
2047
2048#[derive(Debug, Clone, Copy, PartialEq)]
2050pub enum ProcAttr {
2051 Current,
2052 Exec,
2053 FsCreate,
2054 KeyCreate,
2055 Previous,
2056 SockCreate,
2057}
2058
2059pub fn get_procattr(
2062 current_task: &CurrentTask,
2063 target: &Task,
2064 attr: ProcAttr,
2065) -> Result<Vec<u8>, Errno> {
2066 track_hook_duration!("security.hooks.get_procattr");
2067 if_selinux_else(
2068 current_task,
2069 |security_server| {
2070 selinux_hooks::task::get_procattr(security_server, current_task, target, attr)
2071 },
2072 || error!(EINVAL),
2074 )
2075}
2076
2077pub fn set_procattr(
2080 current_task: &CurrentTask,
2081 attr: ProcAttr,
2082 context: &[u8],
2083) -> Result<(), Errno> {
2084 track_hook_duration!("security.hooks.set_procattr");
2085 if_selinux_else(
2086 current_task,
2087 |security_server| {
2088 selinux_hooks::task::set_procattr(security_server, current_task, attr, context)
2089 },
2090 || error!(EINVAL),
2092 )
2093}
2094
2095pub fn fs_is_xattr_labeled(fs: FileSystemHandle) -> bool {
2097 fs.security_state.state.supports_xattr()
2098}
2099
2100pub fn selinuxfs_init_null(current_task: &CurrentTask, null_fs_node: &FileHandle) {
2103 selinux_hooks::selinuxfs::selinuxfs_init_null(current_task, null_fs_node)
2106}
2107
2108pub fn selinuxfs_policy_loaded(current_task: &CurrentTask) {
2114 track_hook_duration!("security.hooks.selinuxfs_policy_loaded");
2115 selinux_hooks::selinuxfs::selinuxfs_policy_loaded(current_task)
2116}
2117
2118pub fn selinuxfs_get_admin_api(current_task: &CurrentTask) -> Option<Arc<SecurityServer>> {
2122 current_task.kernel().security_state.state.as_ref().map(|state| state.server.clone())
2123}
2124
2125pub fn selinuxfs_check_access(
2128 current_task: &CurrentTask,
2129 permission: SecurityPermission,
2130) -> Result<(), Errno> {
2131 track_hook_duration!("security.hooks.selinuxfs_check_access");
2132 if_selinux_else_default_ok(current_task, |security_server| {
2133 selinux_hooks::selinuxfs::selinuxfs_check_access(security_server, current_task, permission)
2134 })
2135}
2136
2137pub fn creds_start_internal_operation(current_task: &CurrentTask) -> Arc<Credentials> {
2140 track_hook_duration!("security.hooks.creds_start_internal_operation");
2141 let mut creds = Credentials::clone(¤t_task.current_creds());
2142 creds.security_state.internal_operation = true;
2143 creds.into()
2144}
2145
2146pub mod testing {
2147 use super::{Arc, KernelState, SecurityServer, selinux_hooks};
2148 use starnix_sync::LockDepMutex;
2149 use std::sync::OnceLock;
2150 use std::sync::atomic::AtomicU64;
2151
2152 pub fn kernel_state(security_server: Option<Arc<SecurityServer>>) -> KernelState {
2155 let state = security_server.map(|server| selinux_hooks::KernelState {
2156 server,
2157 pending_file_systems: LockDepMutex::default(),
2158 selinuxfs_null: OnceLock::default(),
2159 access_denial_count: AtomicU64::new(0u64),
2160 has_policy: false.into(),
2161 _inspect_node: fuchsia_inspect::Node::default(),
2162 });
2163 KernelState { state }
2164 }
2165}
2166
2167#[cfg(test)]
2168mod tests {
2169 use super::*;
2170 use crate::security;
2171 use crate::security::selinux_hooks::get_cached_sid;
2172 use crate::security::selinux_hooks::testing::{
2173 self, spawn_kernel_with_selinux_hooks_test_policy_and_run,
2174 };
2175 use crate::testing::{create_task, spawn_kernel_and_run, spawn_kernel_with_selinux_and_run};
2176 use linux_uapi::XATTR_NAME_SELINUX;
2177 use selinux::InitialSid;
2178 use starnix_uapi::auth::PTRACE_MODE_ATTACH;
2179 use starnix_uapi::signals::SIGTERM;
2180
2181 const VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_valid_t:s0";
2182 const VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] = b"u:object_r:test_valid_t:s0\0";
2183
2184 const DIFFERENT_VALID_SECURITY_CONTEXT: &[u8] = b"u:object_r:test_different_valid_t:s0";
2185 const DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL: &[u8] =
2186 b"u:object_r:test_different_valid_t:s0\0";
2187
2188 const INVALID_SECURITY_CONTEXT_INTERNAL_NUL: &[u8] = b"u:object_r:test_valid_\0t:s0";
2189
2190 const INVALID_SECURITY_CONTEXT: &[u8] = b"not_a_u:object_r:test_valid_t:s0";
2191
2192 #[derive(Default, Debug, PartialEq)]
2193 enum TestHookResult {
2194 WasRun,
2195 WasNotRun,
2196 #[default]
2197 WasNotRunDefault,
2198 }
2199
2200 #[fuchsia::test]
2201 async fn if_selinux_else_disabled() {
2202 spawn_kernel_and_run(async |current_task| {
2203 assert!(current_task.kernel().security_state.state.is_none());
2204
2205 let check_result =
2206 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2207 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2208
2209 let run_else_result = if_selinux_else(
2210 current_task,
2211 |_| TestHookResult::WasRun,
2212 || TestHookResult::WasNotRun,
2213 );
2214 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2215 })
2216 .await;
2217 }
2218
2219 #[fuchsia::test]
2220 async fn if_selinux_else_without_policy() {
2221 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2222 let check_result =
2223 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2224 assert_eq!(check_result, Ok(TestHookResult::WasNotRunDefault));
2225
2226 let run_else_result = if_selinux_else(
2227 current_task,
2228 |_| TestHookResult::WasRun,
2229 || TestHookResult::WasNotRun,
2230 );
2231 assert_eq!(run_else_result, TestHookResult::WasNotRun);
2232 })
2233 .await;
2234 }
2235
2236 #[fuchsia::test]
2237 async fn if_selinux_else_with_policy() {
2238 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2239 let check_result =
2240 if_selinux_else_default_ok(current_task, |_| Ok(TestHookResult::WasRun));
2241 assert_eq!(check_result, Ok(TestHookResult::WasRun));
2242
2243 let run_else_result = if_selinux_else(
2244 current_task,
2245 |_| TestHookResult::WasRun,
2246 || TestHookResult::WasNotRun,
2247 );
2248 assert_eq!(run_else_result, TestHookResult::WasRun);
2249 })
2250 .await;
2251 }
2252
2253 #[fuchsia::test]
2254 async fn task_create_access_allowed_for_selinux_disabled() {
2255 spawn_kernel_and_run(async |current_task| {
2256 assert!(current_task.kernel().security_state.state.is_none());
2257 assert_eq!(check_task_create_access(current_task), Ok(()));
2258 })
2259 .await;
2260 }
2261
2262 #[fuchsia::test]
2263 async fn task_create_access_allowed_for_permissive_mode() {
2264 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2265 security_server.set_enforcing(false);
2266 assert_eq!(check_task_create_access(current_task), Ok(()));
2267 })
2268 .await;
2269 }
2270
2271 #[fuchsia::test]
2272 async fn exec_access_allowed_for_selinux_disabled() {
2273 spawn_kernel_and_run(async |current_task| {
2274 assert!(current_task.kernel().security_state.state.is_none());
2275 let executable = testing::create_test_file(current_task);
2276 let mut resolved_elf = testing::make_resolved_elf(current_task, executable.clone());
2277 assert_eq!(bprm_creds_for_exec(current_task, &executable, &mut resolved_elf), Ok(()));
2278 })
2279 .await;
2280 }
2281
2282 #[fuchsia::test]
2283 async fn exec_access_allowed_for_permissive_mode() {
2284 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2285 security_server.set_enforcing(false);
2286 let executable = testing::create_test_file(current_task);
2287 let mut resolved_elf = testing::make_resolved_elf(current_task, executable.clone());
2288 let result = bprm_creds_for_exec(current_task, &executable, &mut resolved_elf);
2290 assert!(result.is_ok());
2291 })
2292 .await;
2293 }
2294
2295 #[fuchsia::test]
2296 async fn exec_no_state_update_for_selinux_disabled() {
2297 spawn_kernel_and_run(async |current_task| {
2298 let target_sid = InitialSid::Unlabeled.into();
2299
2300 assert!(selinux_hooks::current_task_state(current_task).current_sid != target_sid);
2301
2302 testing::mutate_attrs_for_test(current_task, |attrs| {
2304 attrs.exec_sid = Some(target_sid);
2305 });
2306
2307 let executable = testing::create_test_file(current_task);
2308 let mut resolved_elf = testing::make_resolved_elf(current_task, executable.clone());
2309
2310 let before_hook_sid = selinux_hooks::current_task_state(current_task).current_sid;
2311
2312 bprm_creds_for_exec(current_task, &executable, &mut resolved_elf).unwrap();
2313 assert_eq!(resolved_elf.creds.security_state.current_sid, before_hook_sid);
2314 })
2315 .await;
2316 }
2317
2318 #[fuchsia::test]
2319 async fn exec_initial_context_for_selinux_without_policy() {
2320 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2321 let elf_sid = InitialSid::Unlabeled.into();
2322 assert_ne!(selinux_hooks::current_task_state(current_task).current_sid, elf_sid);
2323 assert_ne!(
2324 selinux_hooks::current_task_state(current_task).current_sid,
2325 InitialSid::Init.into()
2326 );
2327
2328 testing::mutate_attrs_for_test(current_task, |attrs| {
2330 attrs.exec_sid = Some(elf_sid);
2331 });
2332
2333 let executable = testing::create_test_file(current_task);
2334 let mut resolved_elf = testing::make_resolved_elf(current_task, executable.clone());
2335
2336 bprm_creds_for_exec(current_task, &executable, &mut resolved_elf).unwrap();
2337
2338 assert_eq!(resolved_elf.creds.security_state.current_sid, InitialSid::Init.into());
2339 })
2340 .await;
2341 }
2342
2343 #[fuchsia::test]
2344 async fn exec_state_update_for_permissive_mode() {
2345 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2346 security_server.set_enforcing(false);
2347 let elf_sid = security_server
2348 .security_context_to_sid(b"u:object_r:fork_no_t:s0".into())
2349 .expect("invalid security context");
2350
2351 assert_ne!(elf_sid, selinux_hooks::current_task_state(current_task).current_sid);
2352
2353 testing::mutate_attrs_for_test(current_task, |attrs| {
2355 attrs.exec_sid = Some(elf_sid);
2356 });
2357
2358 let executable = testing::create_test_file(current_task);
2359 let mut resolved_elf = testing::make_resolved_elf(current_task, executable.clone());
2360
2361 bprm_creds_for_exec(current_task, &executable, &mut resolved_elf).unwrap();
2362 assert_eq!(resolved_elf.creds.security_state.current_sid, elf_sid);
2363 })
2364 .await;
2365 }
2366
2367 #[fuchsia::test]
2368 async fn getsched_access_allowed_for_selinux_disabled() {
2369 spawn_kernel_and_run(async |current_task| {
2370 let another_task = create_task(¤t_task.kernel(), "another-task");
2371 assert_eq!(check_task_getscheduler_access(current_task, &another_task), Ok(()));
2372 })
2373 .await;
2374 }
2375
2376 #[fuchsia::test]
2377 async fn getsched_access_allowed_for_permissive_mode() {
2378 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2379 let another_task = create_task(¤t_task.kernel(), "another-task");
2380 assert_eq!(check_task_getscheduler_access(current_task, &another_task), Ok(()));
2381 })
2382 .await;
2383 }
2384
2385 #[fuchsia::test]
2386 async fn setsched_access_allowed_for_selinux_disabled() {
2387 spawn_kernel_and_run(async |current_task| {
2388 let another_task = create_task(¤t_task.kernel(), "another-task");
2389 assert_eq!(check_task_setscheduler_access(current_task, &another_task), Ok(()));
2390 })
2391 .await;
2392 }
2393
2394 #[fuchsia::test]
2395 async fn setsched_access_allowed_for_permissive_mode() {
2396 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2397 let another_task = create_task(¤t_task.kernel(), "another-task");
2398 assert_eq!(check_task_setscheduler_access(current_task, &another_task), Ok(()));
2399 })
2400 .await;
2401 }
2402
2403 #[fuchsia::test]
2404 async fn getpgid_access_allowed_for_selinux_disabled() {
2405 spawn_kernel_and_run(async |current_task| {
2406 let another_task = create_task(¤t_task.kernel(), "another-task");
2407 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2408 })
2409 .await;
2410 }
2411
2412 #[fuchsia::test]
2413 async fn getpgid_access_allowed_for_permissive_mode() {
2414 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2415 let another_task = create_task(¤t_task.kernel(), "another-task");
2416 assert_eq!(check_getpgid_access(current_task, &another_task), Ok(()));
2417 })
2418 .await;
2419 }
2420
2421 #[fuchsia::test]
2422 async fn setpgid_access_allowed_for_selinux_disabled() {
2423 spawn_kernel_and_run(async |current_task| {
2424 let another_task = create_task(¤t_task.kernel(), "another-task");
2425 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2426 })
2427 .await;
2428 }
2429
2430 #[fuchsia::test]
2431 async fn setpgid_access_allowed_for_permissive_mode() {
2432 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2433 let another_task = create_task(¤t_task.kernel(), "another-task");
2434 assert_eq!(check_setpgid_access(current_task, &another_task), Ok(()));
2435 })
2436 .await;
2437 }
2438
2439 #[fuchsia::test]
2440 async fn task_getsid_allowed_for_selinux_disabled() {
2441 spawn_kernel_and_run(async |current_task| {
2442 let another_task = create_task(¤t_task.kernel(), "another-task");
2443 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2444 })
2445 .await;
2446 }
2447
2448 #[fuchsia::test]
2449 async fn task_getsid_allowed_for_permissive_mode() {
2450 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2451 let another_task = create_task(¤t_task.kernel(), "another-task");
2452 assert_eq!(check_task_getsid(current_task, &another_task), Ok(()));
2453 })
2454 .await;
2455 }
2456
2457 #[fuchsia::test]
2458 async fn signal_access_allowed_for_selinux_disabled() {
2459 spawn_kernel_and_run(async |current_task| {
2460 let another_task = create_task(¤t_task.kernel(), "another-task");
2461 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2462 })
2463 .await;
2464 }
2465
2466 #[fuchsia::test]
2467 async fn signal_access_allowed_for_permissive_mode() {
2468 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2469 let another_task = create_task(¤t_task.kernel(), "another-task");
2470 assert_eq!(check_signal_access(current_task, &another_task, SIGTERM), Ok(()));
2471 })
2472 .await;
2473 }
2474
2475 #[fuchsia::test]
2476 async fn ptrace_traceme_access_allowed_for_selinux_disabled() {
2477 spawn_kernel_and_run(async |current_task| {
2478 let another_task = create_task(¤t_task.kernel(), "another-task");
2479 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2480 })
2481 .await;
2482 }
2483
2484 #[fuchsia::test]
2485 async fn ptrace_traceme_access_allowed_for_permissive_mode() {
2486 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2487 let another_task = create_task(¤t_task.kernel(), "another-task");
2488 assert_eq!(ptrace_traceme(current_task, &another_task), Ok(()));
2489 })
2490 .await;
2491 }
2492
2493 #[fuchsia::test]
2494 async fn ptrace_attach_access_allowed_for_selinux_disabled() {
2495 spawn_kernel_and_run(async |current_task| {
2496 let another_task = create_task(¤t_task.kernel(), "another-task");
2497 assert_eq!(
2498 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2499 Ok(())
2500 );
2501 })
2502 .await;
2503 }
2504
2505 #[fuchsia::test]
2506 async fn ptrace_attach_access_allowed_for_permissive_mode() {
2507 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2508 let another_task = create_task(¤t_task.kernel(), "another-task");
2509 assert_eq!(
2510 ptrace_access_check(current_task, &another_task, PTRACE_MODE_ATTACH),
2511 Ok(())
2512 );
2513 })
2514 .await;
2515 }
2516
2517 #[fuchsia::test]
2518 async fn task_prlimit_access_allowed_for_selinux_disabled() {
2519 spawn_kernel_and_run(async |current_task| {
2520 let another_task = create_task(¤t_task.kernel(), "another-task");
2521 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2522 })
2523 .await;
2524 }
2525
2526 #[fuchsia::test]
2527 async fn task_prlimit_access_allowed_for_permissive_mode() {
2528 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2529 let another_task = create_task(¤t_task.kernel(), "another-task");
2530 assert_eq!(task_prlimit(current_task, &another_task, true, true), Ok(()));
2531 })
2532 .await;
2533 }
2534
2535 #[fuchsia::test]
2536 async fn fs_node_task_to_fs_node_noop_selinux_disabled() {
2537 spawn_kernel_and_run(async |current_task| {
2538 let node = &testing::create_test_file(current_task).entry.node;
2539 task_to_fs_node(current_task, ¤t_task.task, &node);
2540 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2541 })
2542 .await;
2543 }
2544
2545 #[fuchsia::test]
2546 async fn fs_node_setsecurity_selinux_disabled_only_sets_xattr() {
2547 spawn_kernel_and_run(async |current_task| {
2548 let node = &testing::create_test_file(current_task).entry.node;
2549
2550 fs_node_setsecurity(
2551 ¤t_task,
2552 &node,
2553 XATTR_NAME_SELINUX.to_bytes().into(),
2554 VALID_SECURITY_CONTEXT.into(),
2555 XattrOp::Set,
2556 )
2557 .expect("set_xattr(security.selinux) failed");
2558
2559 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2560 })
2561 .await;
2562 }
2563
2564 #[fuchsia::test]
2565 async fn fs_node_setsecurity_selinux_without_policy_only_sets_xattr() {
2566 spawn_kernel_with_selinux_and_run(async |current_task, _security_server| {
2567 let node = &testing::create_test_file(current_task).entry.node;
2568 fs_node_setsecurity(
2569 ¤t_task,
2570 &node,
2571 XATTR_NAME_SELINUX.to_bytes().into(),
2572 VALID_SECURITY_CONTEXT.into(),
2573 XattrOp::Set,
2574 )
2575 .expect("set_xattr(security.selinux) failed");
2576
2577 assert_eq!(None, selinux_hooks::get_cached_sid(node));
2578 })
2579 .await;
2580 }
2581
2582 #[fuchsia::test]
2583 async fn fs_node_setsecurity_selinux_permissive_sets_xattr_and_label() {
2584 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2585 security_server.set_enforcing(false);
2586 let expected_sid = security_server
2587 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2588 .expect("no SID for VALID_SECURITY_CONTEXT");
2589 let node = &testing::create_test_file(¤t_task).entry.node;
2590
2591 assert_ne!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2593
2594 fs_node_setsecurity(
2595 ¤t_task,
2596 &node,
2597 XATTR_NAME_SELINUX.to_bytes().into(),
2598 VALID_SECURITY_CONTEXT.into(),
2599 XattrOp::Set,
2600 )
2601 .expect("set_xattr(security.selinux) failed");
2602
2603 assert_eq!(Some(expected_sid), selinux_hooks::get_cached_sid(node));
2606 })
2607 .await;
2608 }
2609
2610 #[fuchsia::test]
2611 async fn fs_node_setsecurity_not_selinux_only_sets_xattr() {
2612 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2613 let valid_security_context_sid = security_server
2614 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2615 .expect("no SID for VALID_SECURITY_CONTEXT");
2616 let node = &testing::create_test_file(current_task).entry.node;
2617 let whatever_sid = selinux_hooks::get_cached_sid(node);
2621 assert_ne!(Some(valid_security_context_sid), whatever_sid);
2622
2623 fs_node_setsecurity(
2624 ¤t_task,
2625 &node,
2626 "security.selinu!".into(), VALID_SECURITY_CONTEXT.into(),
2628 XattrOp::Set,
2629 )
2630 .expect("set_xattr(security.selinux) failed");
2631
2632 assert_eq!(whatever_sid, selinux_hooks::get_cached_sid(node));
2634 })
2635 .await;
2636 }
2637
2638 #[fuchsia::test]
2639 async fn fs_node_setsecurity_selinux_enforcing_invalid_context_fails() {
2640 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2641 let node = &testing::create_test_file(current_task).entry.node;
2642
2643 let before_sid = selinux_hooks::get_cached_sid(node);
2644 assert_ne!(Some(InitialSid::Unlabeled.into()), before_sid);
2645
2646 assert!(
2647 check_fs_node_setxattr_access(
2648 ¤t_task,
2649 &node,
2650 XATTR_NAME_SELINUX.to_bytes().into(),
2651 "!".into(), XattrOp::Set,
2653 )
2654 .is_err()
2655 );
2656
2657 assert_eq!(before_sid, selinux_hooks::get_cached_sid(node));
2658 })
2659 .await;
2660 }
2661
2662 #[fuchsia::test]
2663 async fn fs_node_setsecurity_selinux_permissive_invalid_context_sets_xattr_and_label() {
2664 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2665 security_server.set_enforcing(false);
2666 let node = &testing::create_test_file(current_task).entry.node;
2667
2668 assert_ne!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2669
2670 fs_node_setsecurity(
2671 ¤t_task,
2672 &node,
2673 XATTR_NAME_SELINUX.to_bytes().into(),
2674 "!".into(), XattrOp::Set,
2676 )
2677 .expect("set_xattr(security.selinux) failed");
2678
2679 assert_eq!(Some(InitialSid::Unlabeled.into()), selinux_hooks::get_cached_sid(node));
2680 })
2681 .await;
2682 }
2683
2684 #[fuchsia::test]
2685 async fn fs_node_setsecurity_different_sid_for_different_context() {
2686 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2687 let node = &testing::create_test_file(current_task).entry.node;
2688
2689 fs_node_setsecurity(
2690 ¤t_task,
2691 &node,
2692 XATTR_NAME_SELINUX.to_bytes().into(),
2693 VALID_SECURITY_CONTEXT.into(),
2694 XattrOp::Set,
2695 )
2696 .expect("set_xattr(security.selinux) failed");
2697
2698 assert!(selinux_hooks::get_cached_sid(node).is_some());
2699
2700 let first_sid = selinux_hooks::get_cached_sid(node).unwrap();
2701 fs_node_setsecurity(
2702 ¤t_task,
2703 &node,
2704 XATTR_NAME_SELINUX.to_bytes().into(),
2705 DIFFERENT_VALID_SECURITY_CONTEXT.into(),
2706 XattrOp::Set,
2707 )
2708 .expect("set_xattr(security.selinux) failed");
2709
2710 assert!(selinux_hooks::get_cached_sid(node).is_some());
2711
2712 let second_sid = selinux_hooks::get_cached_sid(node).unwrap();
2713
2714 assert_ne!(first_sid, second_sid);
2715 })
2716 .await;
2717 }
2718
2719 #[fuchsia::test]
2720 async fn fs_node_getsecurity_returns_cached_context() {
2721 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2722 let node = &testing::create_test_file(current_task).entry.node;
2723
2724 const TEST_VALUE: &str = "Something Random";
2726 node.ops()
2727 .set_xattr(
2728 node,
2729 current_task,
2730 XATTR_NAME_SELINUX.to_bytes().into(),
2731 TEST_VALUE.into(),
2732 XattrOp::Set,
2733 )
2734 .expect("set_xattr(security.selinux) failed");
2735
2736 let sid = security_server
2738 .security_context_to_sid(VALID_SECURITY_CONTEXT.into())
2739 .expect("security context to SID");
2740 selinux_hooks::set_cached_sid(&node, sid);
2741
2742 let result =
2744 fs_node_getsecurity(current_task, node, XATTR_NAME_SELINUX.to_bytes().into(), 4096);
2745 assert_eq!(
2746 result,
2747 Ok(ValueOrSize::Value(FsString::new(VALID_SECURITY_CONTEXT_WITH_NUL.into())))
2748 );
2749 })
2750 .await;
2751 }
2752
2753 #[fuchsia::test]
2754 async fn fs_node_getsecurity_delegates_to_get_xattr() {
2755 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2756 let node = &testing::create_test_file(current_task).entry.node;
2757
2758 security_server.set_enforcing(false);
2761 const TEST_VALUE: &str = "Something Random";
2762 fs_node_setsecurity(
2763 ¤t_task,
2764 node,
2765 XATTR_NAME_SELINUX.to_bytes().into(),
2766 TEST_VALUE.into(),
2767 XattrOp::Set,
2768 )
2769 .expect("set_xattr(security.selinux) failed");
2770 security_server.set_enforcing(true);
2771
2772 let result =
2774 fs_node_getsecurity(current_task, node, XATTR_NAME_SELINUX.to_bytes().into(), 4096);
2775 assert_eq!(result, Ok(ValueOrSize::Value(FsString::new(TEST_VALUE.into()))));
2776 })
2777 .await;
2778 }
2779
2780 #[fuchsia::test]
2781 async fn set_get_procattr() {
2782 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2783 assert_eq!(get_procattr(current_task, current_task, ProcAttr::Exec), Ok(Vec::new()));
2784
2785 assert_eq!(
2786 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2788 Ok(())
2789 );
2790
2791 assert_eq!(
2792 set_procattr(
2794 current_task,
2795 ProcAttr::SockCreate,
2796 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2797 ),
2798 error!(EACCES)
2799 );
2800
2801 assert_eq!(
2802 set_procattr(
2804 current_task,
2805 ProcAttr::Previous,
2806 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2807 ),
2808 error!(EINVAL)
2809 );
2810
2811 assert_eq!(
2812 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2814 error!(EINVAL)
2815 );
2816
2817 assert_eq!(
2818 get_procattr(current_task, current_task, ProcAttr::Exec),
2819 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2820 );
2821
2822 assert!(get_procattr(current_task, current_task, ProcAttr::Current).is_ok());
2823 })
2824 .await;
2825 }
2826
2827 #[fuchsia::test]
2828 async fn set_get_procattr_with_nulls() {
2829 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2830 assert_eq!(get_procattr(current_task, current_task, ProcAttr::Exec), Ok(Vec::new()));
2831
2832 assert_eq!(
2833 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT_WITH_NUL.into()),
2835 Ok(())
2836 );
2837
2838 assert_eq!(
2839 set_procattr(
2841 current_task,
2842 ProcAttr::FsCreate,
2843 INVALID_SECURITY_CONTEXT_INTERNAL_NUL.into()
2844 ),
2845 error!(EINVAL)
2846 );
2847
2848 assert_eq!(
2849 get_procattr(current_task, current_task, ProcAttr::Exec),
2850 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2851 );
2852
2853 assert_eq!(
2854 get_procattr(current_task, current_task, ProcAttr::FsCreate),
2855 Ok(Vec::new())
2856 );
2857 })
2858 .await;
2859 }
2860
2861 #[fuchsia::test]
2862 async fn set_get_procattr_clear_context() {
2863 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2864 assert_eq!(
2866 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2867 Ok(())
2868 );
2869 assert_eq!(
2870 set_procattr(
2871 current_task,
2872 ProcAttr::FsCreate,
2873 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2874 ),
2875 Ok(())
2876 );
2877
2878 assert_eq!(set_procattr(current_task, ProcAttr::Exec, b"\0"), Ok(()));
2880 assert_eq!(current_task.current_creds().security_state.exec_sid, None);
2881
2882 assert_eq!(set_procattr(current_task, ProcAttr::FsCreate, b"\x0a"), Ok(()));
2884 assert_eq!(current_task.current_creds().security_state.fscreate_sid, None);
2885 })
2886 .await;
2887 }
2888
2889 #[fuchsia::test]
2890 async fn set_get_procattr_setcurrent() {
2891 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, _security_server| {
2892 let initial_previous =
2894 get_procattr(current_task, current_task, ProcAttr::Previous).unwrap();
2895
2896 assert_eq!(
2897 set_procattr(current_task, ProcAttr::Current, VALID_SECURITY_CONTEXT.into()),
2899 Ok(())
2900 );
2901
2902 assert_eq!(
2903 get_procattr(current_task, current_task, ProcAttr::Current),
2905 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2906 );
2907
2908 assert_eq!(
2909 get_procattr(current_task, current_task, ProcAttr::Previous),
2911 Ok(initial_previous.clone())
2912 );
2913
2914 assert_eq!(
2915 set_procattr(
2917 current_task,
2918 ProcAttr::Current,
2919 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2920 ),
2921 Ok(())
2922 );
2923
2924 assert_eq!(
2925 get_procattr(current_task, current_task, ProcAttr::Current),
2927 Ok(DIFFERENT_VALID_SECURITY_CONTEXT_WITH_NUL.into())
2928 );
2929
2930 assert_eq!(
2931 get_procattr(current_task, current_task, ProcAttr::Previous),
2933 Ok(initial_previous.clone())
2934 );
2935 })
2936 .await;
2937 }
2938
2939 #[fuchsia::test]
2940 async fn set_get_procattr_selinux_permissive() {
2941 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
2942 security_server.set_enforcing(false);
2943 assert_eq!(
2944 get_procattr(current_task, ¤t_task.task, ProcAttr::Exec),
2945 Ok(Vec::new())
2946 );
2947
2948 assert_eq!(
2949 set_procattr(current_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2951 Ok(())
2952 );
2953
2954 assert_eq!(
2955 set_procattr(
2958 current_task,
2959 ProcAttr::FsCreate,
2960 DIFFERENT_VALID_SECURITY_CONTEXT.into()
2961 ),
2962 Ok(())
2963 );
2964
2965 assert_eq!(
2966 set_procattr(current_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
2968 error!(EINVAL)
2969 );
2970
2971 assert_eq!(
2972 get_procattr(current_task, ¤t_task.task, ProcAttr::Exec),
2973 Ok(VALID_SECURITY_CONTEXT_WITH_NUL.into())
2974 );
2975
2976 assert!(get_procattr(current_task, ¤t_task.task, ProcAttr::Current).is_ok());
2977 })
2978 .await;
2979 }
2980
2981 #[fuchsia::test]
2982 async fn set_get_procattr_selinux_disabled() {
2983 spawn_kernel_and_run(async |current_task| {
2984 assert_eq!(
2985 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2986 error!(EINVAL)
2987 );
2988
2989 assert_eq!(
2990 set_procattr(¤t_task, ProcAttr::Exec, VALID_SECURITY_CONTEXT.into()),
2992 error!(EINVAL)
2993 );
2994
2995 assert_eq!(
2996 set_procattr(¤t_task, ProcAttr::FsCreate, VALID_SECURITY_CONTEXT.into()),
2998 error!(EINVAL)
2999 );
3000
3001 assert_eq!(
3002 set_procattr(¤t_task, ProcAttr::Exec, INVALID_SECURITY_CONTEXT.into()),
3004 error!(EINVAL)
3005 );
3006
3007 assert_eq!(
3008 get_procattr(¤t_task, ¤t_task.task, ProcAttr::Current),
3009 error!(EINVAL)
3010 );
3011 })
3012 .await;
3013 }
3014
3015 #[fuchsia::test]
3016 async fn create_file_with_fscreate_sid() {
3017 spawn_kernel_with_selinux_hooks_test_policy_and_run(|current_task, security_server| {
3018 let sid =
3019 security_server.security_context_to_sid(VALID_SECURITY_CONTEXT.into()).unwrap();
3020 let source_node = &testing::create_test_file(current_task).entry.node;
3021
3022 fs_node_setsecurity(
3023 ¤t_task,
3024 &source_node,
3025 XATTR_NAME_SELINUX.to_bytes().into(),
3026 VALID_SECURITY_CONTEXT.into(),
3027 XattrOp::Set,
3028 )
3029 .expect("set_xattr(security.selinux) failed");
3030
3031 let mut creds = Credentials::clone(¤t_task.current_creds());
3032 security::fs_node_copy_up(current_task, source_node, &source_node.fs(), &mut creds);
3033 let dir_entry = current_task
3034 .override_creds(creds.into(), || {
3035 current_task
3036 .fs()
3037 .root()
3038 .create_node(
3039 ¤t_task,
3040 "test_file2".into(),
3041 FileMode::IFREG,
3042 DeviceId::NONE,
3043 )
3044 .unwrap()
3045 })
3046 .entry;
3047
3048 assert_eq!(get_cached_sid(&dir_entry.node), Some(sid));
3049 })
3050 .await;
3051 }
3052}