1use crate::arch::task::handle_hardware_exception;
6use crate::execution::{TaskInfo, create_zircon_process};
7use crate::mm::{DumpPolicy, MemoryAccessor, MemoryAccessorExt, MemoryManager, TaskMemoryAccessor};
8use crate::ptrace::{PtraceCoreState, PtraceEvent, PtraceEventData, PtraceOptions, StopState};
9use crate::security;
10use crate::signals::{SignalDetail, SignalInfo, send_signal_first, send_standard_signal};
11use crate::task::loader::{ResolvedElf, load_executable, resolve_executable};
12use crate::task::waiter::WaiterOptions;
13use crate::task::{
14 CurrentTaskCredentialsWriteGuard, ExitStatus, PageFaultExceptionReport, RobustListHeadPtr,
15 RunState, SeccompFilter, SeccompFilterContainer, SeccompState, SeccompStateValue, Task,
16 TaskFlags, TaskRunningState, ThreadState, Waiter,
17};
18use crate::vfs::{
19 CheckAccessReason, FdFlags, FdNumber, FdTable, FileHandle, FsContext, FsStr, LookupContext,
20 LookupVec, MAX_SYMLINK_FOLLOWS, NamespaceNode, ResolveBase, SymlinkMode, SymlinkTarget,
21 new_pidfd,
22};
23use futures::FutureExt;
24use linux_uapi::CLONE_PIDFD;
25use starnix_logging::{CATEGORY_STARNIX, log_error, log_warn, track_file_not_found, track_stub};
26use starnix_registers::{HeapRegs, RegisterStorageEnum};
27use starnix_stack::clean_stack;
28use starnix_sync::{EventWaitGuard, UninterruptibleLock, WakeReason, assert_lock_level};
29use starnix_syscalls::SyscallResult;
30use starnix_syscalls::decls::Syscall;
31use starnix_task_command::TaskCommand;
32use starnix_types::futex_address::FutexAddress;
33use starnix_types::ownership::{Releasable, release_on_error};
34use starnix_uapi::auth::{
35 CAP_KILL, CAP_SYS_ADMIN, CAP_SYS_PTRACE, Credentials, FsCred, PTRACE_MODE_FSCREDS,
36 PTRACE_MODE_REALCREDS, PtraceAccessMode,
37};
38use starnix_uapi::device_id::DeviceId;
39use starnix_uapi::errors::Errno;
40use starnix_uapi::file_mode::{Access, AccessCheck, FileMode};
41use starnix_uapi::open_flags::OpenFlags;
42use starnix_uapi::signals::{
43 SIGCHLD, SIGCONT, SIGILL, SIGKILL, SIGSEGV, SIGSYS, SIGTRAP, SigSet, Signal, UncheckedSignal,
44};
45use starnix_uapi::user_address::{ArchSpecific, UserAddress, UserRef};
46use starnix_uapi::vfs::ResolveFlags;
47use starnix_uapi::{
48 CLONE_CHILD_CLEARTID, CLONE_CHILD_SETTID, CLONE_CLEAR_SIGHAND, CLONE_FILES, CLONE_FS,
49 CLONE_INTO_CGROUP, CLONE_NEWUTS, CLONE_PARENT, CLONE_PARENT_SETTID, CLONE_PTRACE, CLONE_SETTLS,
50 CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_THREAD, CLONE_VFORK, CLONE_VM, FUTEX_OWNER_DIED,
51 FUTEX_TID_MASK, ROBUST_LIST_LIMIT, SECCOMP_FILTER_FLAG_LOG, SECCOMP_FILTER_FLAG_NEW_LISTENER,
52 SECCOMP_FILTER_FLAG_TSYNC, SECCOMP_FILTER_FLAG_TSYNC_ESRCH, clone_args, errno, error, pid_t,
53 sock_filter, ucred,
54};
55use std::cell::{Ref, RefCell};
56use std::collections::VecDeque;
57use std::ffi::CString;
58use std::fmt;
59use std::marker::PhantomData;
60use std::mem::MaybeUninit;
61use std::sync::{Arc, Weak};
62use zx::sys::zx_restricted_state_t;
63
64use super::ThreadGroupLifecycleWaitValue;
65
66pub struct TaskBuilder {
67 pub task: Arc<Task>,
69
70 pub thread_state: ThreadState<HeapRegs>,
71}
72
73impl TaskBuilder {
74 pub fn new(task: Arc<Task>) -> Self {
75 Self { task, thread_state: Default::default() }
76 }
77
78 #[inline(always)]
79 pub fn release(self, _context: ()) {
80 Releasable::release(self, ());
81 }
82}
83
84impl From<TaskBuilder> for CurrentTask {
85 fn from(builder: TaskBuilder) -> Self {
86 Self::new(builder.task, builder.thread_state.into())
87 }
88}
89
90impl Releasable for TaskBuilder {
91 type Context<'a> = ();
92
93 fn release<'a>(self, _context: Self::Context<'a>) {
94 let current_task = CurrentTask::new(self.task, self.thread_state.into());
96 current_task.exit();
97 }
98}
99
100impl std::ops::Deref for TaskBuilder {
101 type Target = Task;
102 fn deref(&self) -> &Self::Target {
103 &self.task
104 }
105}
106
107pub struct CurrentTask {
120 pub task: Arc<Task>,
122
123 pub thread_state: ThreadState<RegisterStorageEnum>,
124
125 pub current_creds: RefCell<CurrentCreds>,
129
130 pub security_state: security::CurrentTaskState,
131
132 _local_marker: PhantomData<*mut u8>,
134}
135
136pub enum CurrentCreds {
138 Cached(Arc<Credentials>),
143 Overridden(Arc<Credentials>),
145}
146
147impl CurrentCreds {
148 fn creds(&self) -> &Arc<Credentials> {
149 match self {
150 CurrentCreds::Cached(creds) => creds,
151 CurrentCreds::Overridden(creds) => creds,
152 }
153 }
154}
155
156impl Releasable for CurrentTask {
157 type Context<'a> = ();
158
159 fn release<'a>(self, _context: Self::Context<'a>) {
160 self.exit();
161 }
162}
163
164impl std::ops::Deref for CurrentTask {
165 type Target = Task;
166 fn deref(&self) -> &Self::Target {
167 &self.task
168 }
169}
170
171impl fmt::Debug for CurrentTask {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 self.task.fmt(f)
174 }
175}
176
177impl CurrentTask {
178 pub fn new(task: Arc<Task>, thread_state: ThreadState<RegisterStorageEnum>) -> Self {
179 let current_creds = RefCell::new(CurrentCreds::Cached(task.clone_creds()));
180 Self {
181 task,
182 thread_state,
183 current_creds,
184 security_state: Default::default(),
185 _local_marker: Default::default(),
186 }
187 }
188
189 pub fn exit(&self) {
191 self.notify_robust_list();
197 let _ignored = self.clear_child_tid_if_needed();
198
199 self.signal_vfork();
200
201 if let Ok(running_state) = self.task.running_state() {
203 *running_state.files.lock() = None;
204 running_state.mm.update(None);
205 }
206 self.running_state.update(None);
207
208 self.trigger_delayed_releaser();
209
210 self.task.thread_group().remove(self.kernel().pids.write(), &self.task);
216
217 self.ptrace_disconnect();
218 }
219
220 #[track_caller]
227 pub fn running_state(&self) -> Arc<TaskRunningState> {
228 self.task.running_state().expect("CurrentTask must have TaskRunningState")
229 }
230
231 #[track_caller]
238 pub fn files(&self) -> Arc<FdTable> {
239 self.task.files().expect("CurrentTask must have FdTable")
240 }
241
242 pub fn fs(&self) -> Arc<FsContext> {
243 self.running_state().fs()
244 }
245
246 pub fn has_shared_fs(&self) -> bool {
247 let fs = self.fs();
248 Arc::strong_count(&fs) > 2usize
251 }
252
253 pub fn unshare_fs(&self) {
254 let new_fs = self.fs().fork();
255 self.running_state().fs.update(new_fs);
256 }
257
258 pub fn current_creds(&self) -> Ref<'_, Arc<Credentials>> {
263 Ref::map(self.current_creds.borrow(), CurrentCreds::creds)
264 }
265
266 pub fn current_fscred(&self) -> FsCred {
267 self.current_creds().as_fscred()
268 }
269
270 pub fn current_ucred(&self) -> ucred {
271 let creds = self.current_creds();
272 ucred { pid: self.get_pid(), uid: creds.uid, gid: creds.gid }
273 }
274
275 pub async fn override_creds_async<R>(
284 &self,
285 new_creds: Arc<Credentials>,
286 callback: impl AsyncFnOnce() -> R,
287 ) -> R {
288 let saved = self.current_creds.replace(CurrentCreds::Overridden(new_creds));
289 let result = callback().await;
290 self.current_creds.replace(saved);
291 result
292 }
293
294 pub fn override_creds<R>(
303 &self,
304 new_creds: Arc<Credentials>,
305 callback: impl FnOnce() -> R,
306 ) -> R {
307 self.override_creds_async(new_creds, async move || callback())
308 .now_or_never()
309 .expect("Future should be ready")
310 }
311
312 pub fn has_overridden_creds(&self) -> bool {
313 matches!(*self.current_creds.borrow(), CurrentCreds::Overridden(_))
314 }
315
316 pub fn trigger_delayed_releaser(&self) {
317 self.kernel().delayed_releaser.apply(self);
318 }
319
320 pub fn weak_task(&self) -> Weak<Task> {
321 Arc::downgrade(&self.task)
322 }
323
324 pub fn write_creds(&self) -> CurrentTaskCredentialsWriteGuard {
328 assert!(!self.has_overridden_creds());
329 self.persistent_info.write_current_task_creds()
330 }
331
332 pub fn set_creds(&self, creds: Credentials) {
335 let creds = Arc::new(creds);
336 self.write_creds().update(self, creds);
337 }
338
339 #[inline(always)]
340 pub fn release(self, _context: ()) {
341 Releasable::release(self, ());
342 }
343
344 pub fn set_syscall_restart_func<R: Into<SyscallResult>>(
345 &mut self,
346 f: impl FnOnce(&mut CurrentTask) -> Result<R, Errno> + Send + Sync + 'static,
347 ) {
348 self.thread_state.syscall_restart_func =
349 Some(Box::new(|current_task| Ok(f(current_task)?.into())));
350 }
351
352 pub fn add_file(&self, file: FileHandle, flags: FdFlags) -> Result<FdNumber, Errno> {
353 self.files().add(self, file, flags)
354 }
355
356 pub fn wait_with_temporary_mask<F, T>(
363 &mut self,
364 signal_mask: SigSet,
365 wait_function: F,
366 ) -> Result<T, Errno>
367 where
368 F: FnOnce(&CurrentTask) -> Result<T, Errno>,
369 {
370 {
371 let mut state = self.write();
372 state.set_flags(TaskFlags::TEMPORARY_SIGNAL_MASK, true);
373 state.set_temporary_signal_mask(signal_mask);
374 }
375 wait_function(self)
376 }
377
378 pub fn wake_or_wait_until_unstopped_async(&self, waiter: &Waiter) -> bool {
381 let group_state = self.thread_group().read();
382 let mut task_state = self.write();
383
384 let task_stop_state = self.load_stopped();
391 let group_stop_state = self.thread_group().load_stopped();
392 if ((task_stop_state == StopState::GroupStopped && group_stop_state.is_waking_or_awake())
393 || task_stop_state.is_waking_or_awake())
394 && (!task_state.is_ptrace_listening() || task_stop_state.is_force())
395 {
396 let new_state = if task_stop_state.is_waking_or_awake() {
397 task_stop_state.finalize()
398 } else {
399 group_stop_state.finalize()
400 };
401 if let Ok(new_state) = new_state {
402 task_state.set_stopped(new_state, None, Some(self), None);
403 drop(group_state);
404 drop(task_state);
405 self.thread_group().set_stopped(new_state, None, false);
411 return true;
412 }
413 }
414
415 if self.thread_group().load_stopped().is_stopped() || task_stop_state.is_stopped() {
417 group_state
420 .lifecycle_waiters
421 .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::Stopped);
422 task_state.wait_on_ptracer(&waiter);
423 } else if task_state.can_accept_ptrace_commands() {
424 task_state.wait_on_ptracer(&waiter);
427 } else if task_state.is_ptrace_listening() {
428 if let Some(ptrace) = &mut task_state.ptrace {
431 ptrace.set_last_signal(Some(SignalInfo::kernel(SIGTRAP)));
432 ptrace.set_last_event(Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0)));
433 }
434 task_state.wait_on_ptracer(&waiter);
435 task_state.notify_ptracers();
436 }
437 false
438 }
439
440 pub fn run_in_state<F, T>(&self, run_state: RunState, callback: F) -> Result<T, Errno>
451 where
452 F: FnOnce() -> Result<T, Errno>,
453 {
454 assert_ne!(run_state, RunState::Running);
455
456 assert_lock_level::<UninterruptibleLock>();
458 clean_stack();
461
462 {
463 let mut state = self.write();
464 assert!(!state.is_blocked());
465
466 if matches!(run_state, RunState::Frozen(_)) {
467 if state.has_signal_pending(SIGKILL) {
470 return error!(EINTR);
471 }
472 } else if state.is_any_signal_pending() && !state.is_ptrace_listening() {
473 return error!(EINTR);
476 }
477 state.set_run_state(run_state.clone());
478 }
479
480 let _waiting_guard = crate::task::ThreadLockupDetector::pause_tracking();
481 let result = callback();
482
483 {
484 let mut state = self.write();
485 assert_eq!(
486 state.run_state(),
487 run_state,
488 "SignalState run state changed while waiting!"
489 );
490 state.set_run_state(RunState::Running);
491 };
492
493 result
494 }
495
496 pub fn block_until(
497 &self,
498 guard: EventWaitGuard<'_>,
499 deadline: zx::MonotonicInstant,
500 ) -> Result<(), Errno> {
501 self.run_in_state(RunState::Event(guard.event().clone()), move || {
502 guard.block_until(None, deadline).map_err(|e| match e {
503 WakeReason::Interrupted => errno!(EINTR),
504 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
505 })
506 })
507 }
508
509 pub fn block_with_owner_until(
510 &self,
511 guard: EventWaitGuard<'_>,
512 new_owner: &zx::Thread,
513 deadline: zx::MonotonicInstant,
514 ) -> Result<(), Errno> {
515 self.run_in_state(RunState::Event(guard.event().clone()), move || {
516 guard.block_until(Some(new_owner), deadline).map_err(|e| match e {
517 WakeReason::Interrupted => errno!(EINTR),
518 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
519 })
520 })
521 }
522
523 pub fn resolve_dir_fd<'a>(
527 &self,
528 dir_fd: FdNumber,
529 mut path: &'a FsStr,
530 flags: ResolveFlags,
531 ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
532 let path_is_absolute = path.starts_with(b"/");
533 if path_is_absolute {
534 if flags.contains(ResolveFlags::BENEATH) {
535 return error!(EXDEV);
536 }
537 path = &path[1..];
538 }
539
540 let dir = if path_is_absolute && !flags.contains(ResolveFlags::IN_ROOT) {
541 self.fs().root()
542 } else if dir_fd == FdNumber::AT_FDCWD {
543 self.fs().cwd()
544 } else {
545 let file = self.files().get_allowing_opath(dir_fd)?;
555 file.name.to_passive()
556 };
557
558 if !path.is_empty() {
559 if !dir.entry.node.is_dir() {
560 return error!(ENOTDIR);
561 }
562 dir.check_access(self, Access::EXEC, CheckAccessReason::InternalPermissionChecks)?;
563 }
564 Ok((dir, path.into()))
565 }
566
567 pub fn open_file(&self, path: &FsStr, flags: OpenFlags) -> Result<FileHandle, Errno> {
572 if flags.contains(OpenFlags::CREAT) {
573 return error!(EINVAL);
576 }
577 self.open_file_at(
578 FdNumber::AT_FDCWD,
579 path,
580 flags,
581 FileMode::default(),
582 ResolveFlags::empty(),
583 AccessCheck::default(),
584 )
585 }
586
587 fn resolve_open_path(
598 &self,
599 context: &mut LookupContext,
600 dir: &NamespaceNode,
601 path: &FsStr,
602 mode: FileMode,
603 flags: OpenFlags,
604 ) -> Result<(NamespaceNode, bool), Errno> {
605 context.update_for_path(path);
606 let mut parent_content = context.with(SymlinkMode::Follow);
607 let (parent, basename) = self.lookup_parent(&mut parent_content, dir, path)?;
608 context.remaining_follows = parent_content.remaining_follows;
609
610 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
611
612 let mut child_context = context.with(SymlinkMode::NoFollow);
614 child_context.must_be_directory = false;
615
616 match parent.lookup_child(self, &mut child_context, basename) {
617 Ok(name) => {
618 if name.entry.node.is_lnk() {
619 if flags.contains(OpenFlags::PATH)
620 && context.symlink_mode == SymlinkMode::NoFollow
621 {
622 return Ok((name, false));
635 }
636
637 if (!flags.contains(OpenFlags::PATH)
638 && context.symlink_mode == SymlinkMode::NoFollow)
639 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
640 || context.remaining_follows == 0
641 {
642 if must_create {
643 return error!(EEXIST);
646 }
647 return error!(ELOOP);
652 }
653
654 context.remaining_follows -= 1;
655 match name.readlink(self)? {
656 SymlinkTarget::Path(path) => {
657 let dir = if path[0] == b'/' { self.fs().root() } else { parent };
658 self.resolve_open_path(context, &dir, path.as_ref(), mode, flags)
659 }
660 SymlinkTarget::Node(name) => {
661 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS)
662 || name.entry.node.is_lnk()
663 {
664 error!(ELOOP)
665 } else {
666 Ok((name, false))
667 }
668 }
669 }
670 } else {
671 if must_create {
672 return error!(EEXIST);
673 }
674 Ok((name, false))
675 }
676 }
677 Err(e) if e == errno!(ENOENT) && flags.contains(OpenFlags::CREAT) => {
678 if context.must_be_directory {
679 return error!(EISDIR);
680 }
681 Ok((
682 parent.open_create_node(
683 self,
684 basename,
685 mode.with_type(FileMode::IFREG),
686 DeviceId::NONE,
687 flags,
688 )?,
689 true,
690 ))
691 }
692 Err(e) => Err(e),
693 }
694 }
695
696 pub fn open_file_at(
706 &self,
707 dir_fd: FdNumber,
708 path: &FsStr,
709 flags: OpenFlags,
710 mode: FileMode,
711 resolve_flags: ResolveFlags,
712 access_check: AccessCheck,
713 ) -> Result<FileHandle, Errno> {
714 if path.is_empty() {
715 return error!(ENOENT);
716 }
717
718 let (dir, path) = self.resolve_dir_fd(dir_fd, path, resolve_flags)?;
719 self.open_namespace_node_at(dir, path, flags, mode, resolve_flags, access_check)
720 }
721
722 pub fn open_namespace_node_at(
723 &self,
724 dir: NamespaceNode,
725 path: &FsStr,
726 flags: OpenFlags,
727 mode: FileMode,
728 mut resolve_flags: ResolveFlags,
729 access_check: AccessCheck,
730 ) -> Result<FileHandle, Errno> {
731 let mut flags = flags | OpenFlags::LARGEFILE;
733 let opath = flags.contains(OpenFlags::PATH);
734 if opath {
735 const ALLOWED_FLAGS: OpenFlags = OpenFlags::from_bits_truncate(
738 OpenFlags::PATH.bits()
739 | OpenFlags::CLOEXEC.bits()
740 | OpenFlags::DIRECTORY.bits()
741 | OpenFlags::NOFOLLOW.bits(),
742 );
743 flags &= ALLOWED_FLAGS;
744 }
745
746 if flags.contains(OpenFlags::TMPFILE) && !flags.can_write() {
747 return error!(EINVAL);
748 }
749
750 let nofollow = flags.contains(OpenFlags::NOFOLLOW);
751 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
752
753 let symlink_mode =
754 if nofollow || must_create { SymlinkMode::NoFollow } else { SymlinkMode::Follow };
755
756 let resolve_base = match (
757 resolve_flags.contains(ResolveFlags::BENEATH),
758 resolve_flags.contains(ResolveFlags::IN_ROOT),
759 ) {
760 (false, false) => ResolveBase::None,
761 (true, false) => ResolveBase::Beneath(dir.clone()),
762 (false, true) => ResolveBase::InRoot(dir.clone()),
763 (true, true) => return error!(EINVAL),
764 };
765
766 if resolve_base != ResolveBase::None {
770 resolve_flags.insert(ResolveFlags::NO_MAGICLINKS);
771 }
772
773 let mut context = LookupContext {
774 symlink_mode,
775 remaining_follows: MAX_SYMLINK_FOLLOWS,
776 must_be_directory: flags.contains(OpenFlags::DIRECTORY),
777 resolve_flags,
778 resolve_base,
779 };
780 let (name, created) = match self.resolve_open_path(&mut context, &dir, path, mode, flags) {
781 Ok((n, c)) => (n, c),
782 Err(e) => {
783 let mut abs_path = dir.path(&self.fs());
784 abs_path.extend(&**path);
785 track_file_not_found(abs_path);
786 return Err(e);
787 }
788 };
789
790 let name = if flags.contains(OpenFlags::TMPFILE) {
791 if flags.contains(OpenFlags::CREAT) {
793 return error!(EINVAL);
794 }
795 name.create_tmpfile(self, mode.with_type(FileMode::IFREG), flags)?
796 } else {
797 let mode = name.entry.node.info().mode;
798
799 if !opath && nofollow && mode.is_lnk() {
811 return error!(ELOOP);
812 }
813
814 if mode.is_dir() {
815 if flags.can_write()
816 || flags.contains(OpenFlags::CREAT)
817 || flags.contains(OpenFlags::TRUNC)
818 {
819 return error!(EISDIR);
820 }
821 if flags.contains(OpenFlags::DIRECT) {
822 return error!(EINVAL);
823 }
824 } else if context.must_be_directory {
825 return error!(ENOTDIR);
826 }
827
828 if flags.contains(OpenFlags::TRUNC) && mode.is_reg() && !created {
829 name.truncate(self, 0)?;
835 }
836
837 name
838 };
839
840 let access_check = if created { AccessCheck::skip() } else { access_check };
847 let file = name.open(self, flags, access_check)?;
848
849 if !opath {
853 security::file_open(self, &file)?;
854 }
855
856 Ok(file)
857 }
858
859 pub fn lookup_parent_at<'a>(
867 &self,
868 context: &mut LookupContext,
869 dir_fd: FdNumber,
870 path: &'a FsStr,
871 ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
872 let (dir, path) = self.resolve_dir_fd(dir_fd, path, ResolveFlags::empty())?;
873 self.lookup_parent(context, &dir, path)
874 }
875
876 pub fn lookup_parent<'a>(
891 &self,
892 context: &mut LookupContext,
893 dir: &NamespaceNode,
894 path: &'a FsStr,
895 ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
896 context.update_for_path(path);
897
898 let components = split_path(path);
899 if components.is_empty() {
900 return Ok((dir.clone(), Default::default()));
901 }
902 let result = dir.lookup_children(self, context, &components[0..components.len() - 1])?;
903 Ok((result, components.last().unwrap()))
904 }
905
906 pub fn lookup_path(
913 &self,
914 context: &mut LookupContext,
915 dir: NamespaceNode,
916 path: &FsStr,
917 ) -> Result<NamespaceNode, Errno> {
918 let components = split_path(path);
919 dir.lookup_children(self, context, &components)
920 }
921
922 pub fn lookup_path_from_root(&self, path: &FsStr) -> Result<NamespaceNode, Errno> {
926 let mut context = LookupContext::default();
927 self.lookup_path(&mut context, self.fs().root(), path)
928 }
929
930 pub fn exec(
931 &mut self,
932 executable: FileHandle,
933 path: CString,
934 argv: Vec<CString>,
935 environ: Vec<CString>,
936 ) -> Result<(), Errno> {
937 if !executable.name.entry.node.is_reg() {
941 return error!(EACCES);
942 }
943
944 executable.name.check_access(self, Access::EXEC, CheckAccessReason::Exec)?;
949
950 let mut resolved_elf =
953 resolve_executable(self, executable.clone(), path.clone(), argv, environ)?;
954
955 let writable_creds = self.write_creds();
957
958 security::bprm_creds_from_file(self, &mut resolved_elf)?;
971
972 security::bprm_creds_for_exec(self, &executable.name, &mut resolved_elf)?;
974
975 if self.thread_group().read().tasks_count() > 1 {
976 track_stub!(TODO("https://fxbug.dev/297434895"), "exec on multithread process");
977 return error!(EINVAL);
978 }
979
980 if let Err(err) = self.finish_exec(path, resolved_elf, writable_creds) {
982 log_warn!("unrecoverable error in exec: {err:?}");
983
984 send_standard_signal(self, SignalInfo::forced(SIGSEGV));
985 return Err(err);
986 }
987
988 self.ptrace_event(PtraceOptions::TRACEEXEC, self.task.tid as u64);
989 self.signal_vfork();
990 self.task.thread_group.sync_syscall_log_level();
991
992 Ok(())
993 }
994
995 fn finish_exec(
999 &mut self,
1000 path: CString,
1001 resolved_elf: ResolvedElf,
1002 writable_creds: CurrentTaskCredentialsWriteGuard,
1003 ) -> Result<(), Errno> {
1004 self.notify_robust_list();
1008
1009 let mm = {
1011 let new_mm = MemoryManager::exec(
1012 self.thread_group().root_vmar.unowned(),
1013 self.mm().ok(),
1014 resolved_elf.file.name.to_passive(),
1015 resolved_elf.arch_width,
1016 )?;
1017 self.running_state().mm.update(Some(new_mm.clone()));
1018 new_mm
1019 };
1020 self.running_state().unshare_files();
1041 self.files().exec();
1042
1043 {
1044 let mut state = self.write();
1045
1046 let dumpable =
1055 if resolved_elf.secure_exec { DumpPolicy::Disable } else { DumpPolicy::User };
1056 *mm.dumpable.lock() = dumpable;
1057
1058 state.set_sigaltstack(None);
1059 state.robust_list_head = RobustListHeadPtr::null(self);
1060 }
1069
1070 security::bprm_committing_creds(self, &resolved_elf)?;
1071
1072 let new_creds = Arc::new(resolved_elf.creds.clone());
1073 writable_creds.update(self, new_creds);
1074
1075 let start_info = load_executable(self, resolved_elf, &path)?;
1076
1077 let regs: zx_restricted_state_t = start_info.into();
1078 self.thread_state.registers.load(regs);
1079 self.thread_state.extended_pstate.reset();
1080 self.thread_group().signal_actions.reset_for_exec();
1081
1082 {
1084 let mut thread_group_state = self.thread_group().write();
1085 thread_group_state.exit_signal = Some(SIGCHLD);
1086 for (_, weak_child) in &mut thread_group_state.children {
1087 if let Some(child) = weak_child.upgrade() {
1088 let _token = starnix_sync::allow_subclass();
1092 let mut child_state = child.write();
1093 child_state.exit_signal = Some(SIGCHLD);
1094 }
1095 }
1096 }
1097
1098 security::bprm_committed_creds(self)?;
1099
1100 self.thread_group().write().did_exec = true;
1101
1102 self.set_command_name(TaskCommand::from_path_bytes(path.to_bytes()));
1103
1104 Ok(())
1105 }
1106
1107 pub fn set_command_name(&self, new_name: TaskCommand) {
1108 self.task.set_command_name(new_name.clone());
1110 let leader_command = self.thread_group().read().leader_command();
1111 starnix_logging::set_current_task_info(
1112 new_name,
1113 leader_command,
1114 self.thread_group().leader,
1115 self.tid,
1116 );
1117 }
1118
1119 pub fn add_seccomp_filter(
1120 &mut self,
1121 code: Vec<sock_filter>,
1122 flags: u32,
1123 ) -> Result<SyscallResult, Errno> {
1124 let mut notifier = None;
1125 if flags & SECCOMP_FILTER_FLAG_NEW_LISTENER != 0 {
1126 notifier = Some(SeccompFilterContainer::create_notifier());
1127 }
1128
1129 let new_filter = Arc::new(SeccompFilter::from_cbpf(
1130 &code,
1131 self.thread_group().next_seccomp_filter_id.add(1),
1132 flags & SECCOMP_FILTER_FLAG_LOG != 0,
1133 notifier.clone(),
1134 )?);
1135
1136 let mut maybe_fd: Option<FdNumber> = None;
1137 if let Some(notifier) = notifier {
1138 maybe_fd = Some(SeccompFilterContainer::register_listener(self, notifier)?);
1139 }
1140
1141 let state = self.thread_group().write();
1144
1145 if flags & SECCOMP_FILTER_FLAG_TSYNC != 0 {
1146 let mut filters: SeccompFilterContainer = self.read().seccomp_filters.clone();
1152
1153 let tasks = state.tasks();
1157 for task in &tasks {
1158 if task.tid == self.tid {
1159 continue;
1160 }
1161 let other_task_state = task.read();
1162
1163 if task.seccomp_filter_state.get() == SeccompStateValue::Strict {
1165 return Self::seccomp_tsync_error(task.tid, flags);
1166 }
1167
1168 if !other_task_state.seccomp_filters.can_sync_to(&filters) {
1170 return Self::seccomp_tsync_error(task.tid, flags);
1171 }
1172 }
1173
1174 filters.add_filter(new_filter, code.len() as u16)?;
1176
1177 for task in &tasks {
1178 let mut other_task_state = task.write();
1179
1180 other_task_state.enable_no_new_privs();
1181 other_task_state.seccomp_filters = filters.clone();
1182 task.set_seccomp_state(SeccompStateValue::UserDefined)?;
1183 }
1184 } else {
1185 let mut task_state = self.task.write();
1186
1187 task_state.seccomp_filters.add_filter(new_filter, code.len() as u16)?;
1188 self.set_seccomp_state(SeccompStateValue::UserDefined)?;
1189 }
1190
1191 if let Some(fd) = maybe_fd { Ok(fd.into()) } else { Ok(().into()) }
1192 }
1193
1194 pub fn run_seccomp_filters(
1195 &mut self,
1196 syscall: &Syscall,
1197 ) -> Option<Result<SyscallResult, Errno>> {
1198 if self.seccomp_filter_state.get() == SeccompStateValue::Strict {
1201 return SeccompState::do_strict(self, syscall);
1202 }
1203
1204 let result = self.task.read().seccomp_filters.run_all(self, syscall);
1206
1207 SeccompState::do_user_defined(result, self, syscall)
1208 }
1209
1210 fn seccomp_tsync_error(id: i32, flags: u32) -> Result<SyscallResult, Errno> {
1211 if flags & SECCOMP_FILTER_FLAG_TSYNC_ESRCH != 0 { error!(ESRCH) } else { Ok(id.into()) }
1217 }
1218
1219 pub fn notify_robust_list(&self) {
1225 let task_state = self.write();
1226 let robust_list_addr = task_state.robust_list_head.addr();
1227 if robust_list_addr == UserAddress::NULL {
1228 return;
1230 }
1231 let robust_list_res = self.read_multi_arch_object(task_state.robust_list_head);
1232
1233 let head = if let Ok(head) = robust_list_res {
1234 head
1235 } else {
1236 return;
1237 };
1238
1239 let offset = head.futex_offset;
1240
1241 let mut entries_count = 0;
1242 let mut curr_ptr = head.list.next;
1243 while curr_ptr.addr() != robust_list_addr.into() && entries_count < ROBUST_LIST_LIMIT {
1244 let curr_ref = self.read_multi_arch_object(curr_ptr);
1245
1246 let curr = if let Ok(curr) = curr_ref {
1247 curr
1248 } else {
1249 return;
1250 };
1251
1252 let Some(futex_base) = curr_ptr.addr().checked_add_signed(offset) else {
1253 return;
1254 };
1255
1256 let futex_addr = match FutexAddress::try_from(futex_base) {
1257 Ok(addr) => addr,
1258 Err(_) => {
1259 return;
1260 }
1261 };
1262
1263 let Ok(mm) = self.mm() else {
1264 log_error!("Asked to notify robust list futexes in system task.");
1265 return;
1266 };
1267 let futex = if let Ok(futex) = mm.atomic_load_u32_relaxed(futex_addr) {
1268 futex
1269 } else {
1270 return;
1271 };
1272
1273 if (futex & FUTEX_TID_MASK) as i32 == self.tid {
1274 let owner_died = FUTEX_OWNER_DIED | futex;
1275 if mm.atomic_store_u32_relaxed(futex_addr, owner_died).is_err() {
1276 return;
1277 }
1278 }
1279 curr_ptr = curr.next;
1280 entries_count += 1;
1281 }
1282 }
1283
1284 pub(crate) fn handle_page_fault(
1285 &self,
1286 decoded: PageFaultExceptionReport,
1287 status: zx::Status,
1288 ) -> ExceptionResult {
1289 if let Ok(mm) = self.mm() {
1290 mm.handle_page_fault(decoded, status)
1291 } else {
1292 panic!(
1293 "system task is handling a major page fault status={:?}, report={:?}",
1294 status, decoded
1295 );
1296 }
1297 }
1298
1299 pub fn process_exception(&self, report: &zx::ExceptionReport) -> ExceptionResult {
1301 if let Some(result) = handle_hardware_exception(self, report) {
1302 return result;
1303 }
1304
1305 match report.ty {
1306 zx::ExceptionType::General => {
1307 log_error!("Unrecognized general exception: {:?}", report);
1308 ExceptionResult::Signal(SignalInfo::kernel(SIGILL))
1309 }
1310 zx::ExceptionType::ProcessNameChanged => {
1311 log_error!("Received unexpected process name changed exception");
1312 ExceptionResult::Handled
1313 }
1314 zx::ExceptionType::ProcessStarting
1315 | zx::ExceptionType::ThreadStarting
1316 | zx::ExceptionType::ThreadExiting => {
1317 log_error!("Received unexpected task lifecycle exception");
1318 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1319 }
1320 zx::ExceptionType::PolicyError(policy_code) => {
1321 log_error!(policy_code:?; "Received Zircon policy error exception");
1322 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1323 }
1324 zx::ExceptionType::UnknownUserGenerated { code, data } => {
1325 log_error!(code:?, data:?; "Received unexpected unknown user generated exception");
1326 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1327 }
1328 zx::ExceptionType::Unknown { ty, code, data } => {
1329 log_error!(ty:?, code:?, data:?; "Received unexpected exception");
1330 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1331 }
1332 _ => {
1333 log_error!("Received unknown zircon exception: {:?}", report.ty);
1334 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1335 }
1336 }
1337 }
1338
1339 pub fn clone_task(
1349 &self,
1350 flags: u64,
1351 child_exit_signal: Option<Signal>,
1352 user_parent_tid: UserRef<pid_t>,
1353 user_child_tid: UserRef<pid_t>,
1354 user_pidfd: UserRef<FdNumber>,
1355 ) -> Result<TaskBuilder, Errno> {
1356 const IMPLEMENTED_FLAGS: u64 = ((CLONE_VM
1357 | CLONE_FS
1358 | CLONE_FILES
1359 | CLONE_SIGHAND
1360 | CLONE_THREAD
1361 | CLONE_SYSVSEM
1362 | CLONE_SETTLS
1363 | CLONE_PARENT
1364 | CLONE_PARENT_SETTID
1365 | CLONE_PIDFD
1366 | CLONE_CHILD_CLEARTID
1367 | CLONE_CHILD_SETTID
1368 | CLONE_VFORK
1369 | CLONE_NEWUTS
1370 | CLONE_PTRACE) as u64)
1371 | CLONE_CLEAR_SIGHAND;
1372
1373 const VALID_FLAGS: u64 = (CLONE_INTO_CGROUP << 1) - 1;
1378
1379 let clone_files = flags & (CLONE_FILES as u64) != 0;
1382 let clone_fs = flags & (CLONE_FS as u64) != 0;
1383 let clone_parent = flags & (CLONE_PARENT as u64) != 0;
1384 let clone_parent_settid = flags & (CLONE_PARENT_SETTID as u64) != 0;
1385 let clone_pidfd = flags & (CLONE_PIDFD as u64) != 0;
1386 let clone_child_cleartid = flags & (CLONE_CHILD_CLEARTID as u64) != 0;
1387 let clone_child_settid = flags & (CLONE_CHILD_SETTID as u64) != 0;
1388 let clone_sysvsem = flags & (CLONE_SYSVSEM as u64) != 0;
1389 let clone_ptrace = flags & (CLONE_PTRACE as u64) != 0;
1390 let clone_thread = flags & (CLONE_THREAD as u64) != 0;
1391 let clone_vm = flags & (CLONE_VM as u64) != 0;
1392 let clone_sighand = flags & (CLONE_SIGHAND as u64) != 0;
1393 let clone_vfork = flags & (CLONE_VFORK as u64) != 0;
1394 let clone_newuts = flags & (CLONE_NEWUTS as u64) != 0;
1395 let clone_into_cgroup = flags & CLONE_INTO_CGROUP != 0;
1396 let clone_clear_sighand = flags & (CLONE_CLEAR_SIGHAND as u64) != 0;
1397
1398 if clone_ptrace {
1399 track_stub!(TODO("https://fxbug.dev/322874630"), "CLONE_PTRACE");
1400 }
1401
1402 if clone_sysvsem {
1403 track_stub!(TODO("https://fxbug.dev/322875185"), "CLONE_SYSVSEM");
1404 }
1405
1406 if clone_into_cgroup {
1407 track_stub!(TODO("https://fxbug.dev/403612570"), "CLONE_INTO_CGROUP");
1408 }
1409
1410 if clone_sighand && !clone_vm {
1411 return error!(EINVAL);
1412 }
1413 if clone_clear_sighand && clone_sighand {
1414 return error!(EINVAL);
1415 }
1416 if clone_thread && !clone_sighand {
1417 return error!(EINVAL);
1418 }
1419
1420 if clone_pidfd && clone_thread {
1421 return error!(EINVAL);
1422 }
1423 if clone_pidfd && clone_parent_settid && user_parent_tid.addr() == user_pidfd.addr() {
1424 return error!(EINVAL);
1427 }
1428
1429 if flags & !VALID_FLAGS != 0 {
1430 return error!(EINVAL);
1431 }
1432
1433 if clone_vm && !clone_thread {
1434 if !clone_vfork {
1445 track_stub!(
1446 TODO("https://fxbug.dev/322875227"),
1447 "CLONE_VM without CLONE_THREAD or CLONE_VFORK"
1448 );
1449 }
1450 } else if clone_thread && !clone_vm {
1451 track_stub!(TODO("https://fxbug.dev/322875167"), "CLONE_THREAD without CLONE_VM");
1452 return error!(ENOSYS);
1453 }
1454
1455 if flags & !IMPLEMENTED_FLAGS != 0 {
1456 track_stub!(
1457 TODO("https://fxbug.dev/322875130"),
1458 "clone unknown flags",
1459 flags & !IMPLEMENTED_FLAGS
1460 );
1461 return error!(ENOSYS);
1462 }
1463
1464 let fs = if clone_fs { self.fs() } else { self.fs().fork() };
1465 let files = if clone_files {
1466 self.running_state().share_files()
1467 } else {
1468 self.running_state().fork_files()
1469 }
1470 .expect("Task must have FdTable");
1471
1472 let kernel = self.kernel();
1473
1474 let mut pids = kernel.pids.write();
1475
1476 let mut cgroup2_pid_table = kernel.cgroups.lock_cgroup2_pid_table();
1480 let child_kernel_signals = cgroup2_pid_table
1482 .maybe_create_freeze_signal(self.thread_group())
1483 .into_iter()
1484 .collect::<VecDeque<_>>();
1485
1486 let pid;
1487 let command;
1488 let creds;
1489 let scheduler_state;
1490 let no_new_privs;
1491 let seccomp_filters;
1492 let robust_list_head = RobustListHeadPtr::null(self);
1493 let child_signal_mask;
1494 let timerslack_ns;
1495 let uts_ns;
1496
1497 let TaskInfo { thread_group, memory_manager } = {
1498 let weak_original_parent;
1501 let original_parent;
1502
1503 let thread_group_state = {
1505 let thread_group_state = self.thread_group().write();
1506 if clone_parent {
1507 weak_original_parent =
1510 thread_group_state.parent.clone().ok_or_else(|| errno!(EINVAL))?;
1511 std::mem::drop(thread_group_state);
1512 original_parent = weak_original_parent.upgrade();
1513 original_parent.write()
1514 } else {
1515 thread_group_state
1516 }
1517 };
1518
1519 let state = self.read();
1520
1521 no_new_privs = state.no_new_privs();
1522 seccomp_filters = state.seccomp_filters.clone();
1523 child_signal_mask = state.signal_mask();
1524
1525 pid = pids.allocate_pid();
1526 command = self.command();
1527 creds = self.current_creds().clone();
1528 scheduler_state = state.scheduler_state.fork();
1529 timerslack_ns = state.timerslack_ns;
1530
1531 uts_ns = if clone_newuts {
1532 security::check_task_capable(self, CAP_SYS_ADMIN)?;
1533 state.uts_ns.read().fork()
1534 } else {
1535 state.uts_ns.clone()
1536 };
1537
1538 if clone_thread {
1539 TaskInfo {
1540 thread_group: self.thread_group().clone(),
1541 memory_manager: self.mm().ok(),
1542 }
1543 } else {
1544 std::mem::drop(state);
1548 let signal_actions = if clone_sighand {
1549 self.thread_group().signal_actions.clone()
1550 } else if clone_clear_sighand {
1551 let actions = self.thread_group().signal_actions.fork();
1552 actions.reset_for_exec();
1553 actions
1554 } else {
1555 self.thread_group().signal_actions.fork()
1556 };
1557 let process_group = thread_group_state.process_group.clone();
1558
1559 let task_info = {
1560 fuchsia_trace::duration!(CATEGORY_STARNIX, "create_zircon_process");
1561 create_zircon_process(
1562 kernel,
1563 Some(thread_group_state),
1564 pid,
1565 child_exit_signal,
1566 process_group,
1567 signal_actions,
1568 command.clone(),
1569 )?
1570 };
1571
1572 cgroup2_pid_table.inherit_cgroup(self.thread_group(), &task_info.thread_group);
1573
1574 task_info
1575 }
1576 };
1577
1578 std::mem::drop(cgroup2_pid_table);
1583
1584 let vfork_event = if clone_vfork { Some(Arc::new(zx::Event::create())) } else { None };
1586
1587 let abstract_socket_namespace;
1590 let abstract_vsock_namespace;
1591 {
1592 let running_state = self.running_state();
1593 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
1594 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
1595 }
1596
1597 let mut child = TaskBuilder::new(Task::new(
1598 pid,
1599 command,
1600 thread_group,
1601 files,
1602 memory_manager,
1603 fs,
1604 creds,
1605 abstract_socket_namespace,
1606 abstract_vsock_namespace,
1607 child_signal_mask,
1608 child_kernel_signals,
1609 vfork_event,
1610 scheduler_state,
1611 uts_ns,
1612 no_new_privs,
1613 SeccompState::from(&self.seccomp_filter_state),
1614 seccomp_filters,
1615 robust_list_head,
1616 timerslack_ns,
1617 ));
1618 let parent_cpuset_path = self.read().cpuset_path.clone();
1619 child.task.write().cpuset_path = parent_cpuset_path;
1620
1621 release_on_error!(child, {
1622 pids.add_task(Arc::clone(&child.task));
1626 std::mem::drop(pids);
1627
1628 #[cfg(any(test, debug_assertions))]
1632 {
1633 if !clone_thread {
1636 let _l1 = self.thread_group().read();
1637 let _token = starnix_sync::allow_subclass();
1641 let _l2 = child.thread_group().read();
1642 }
1643 }
1644
1645 if clone_thread {
1646 self.thread_group().add(Arc::clone(&child.task))?;
1647 } else {
1648 child.thread_group().add(Arc::clone(&child.task))?;
1649
1650 let (sigaltstack, signal_mask) = {
1656 let state = self.read();
1657 (state.sigaltstack(), state.signal_mask())
1658 };
1659 let mut child_state = child.write();
1660 child_state.set_sigaltstack(sigaltstack);
1661 child_state.set_signal_mask(signal_mask);
1662 }
1663
1664 if !clone_vm {
1665 assert!(!clone_thread);
1668 let child_mm = MemoryManager::snapshot_of(
1669 &self.mm()?,
1670 child.thread_group.root_vmar.unowned(),
1671 self.thread_state.arch_width(),
1672 )?;
1673 child.running_state()?.mm.update(Some(child_mm));
1674 }
1675
1676 if clone_parent_settid {
1677 self.write_object(user_parent_tid, &child.tid)?;
1678 }
1679
1680 if clone_child_cleartid {
1681 child.write().clear_child_tid = user_child_tid;
1682 }
1683
1684 if clone_child_settid {
1685 child.write_object(user_child_tid, &child.tid)?;
1686 }
1687
1688 if clone_pidfd {
1689 let file = new_pidfd(self, child.thread_group(), &*child.mm()?, OpenFlags::empty());
1690 let pidfd = self.add_file(file, FdFlags::CLOEXEC)?;
1691 self.write_object(user_pidfd, &pidfd)?;
1692 }
1693
1694 if clone_vm && !clone_thread {
1698 let child_mm = MemoryManager::snapshot_of(
1699 &self.mm()?,
1700 child.thread_group.root_vmar.unowned(),
1701 self.thread_state.arch_width(),
1702 )?;
1703 child.running_state()?.mm.update(Some(child_mm));
1704 }
1705
1706 child.thread_state = self.thread_state.snapshot::<HeapRegs>();
1707 Ok(())
1708 });
1709
1710 #[cfg(any(test, debug_assertions))]
1713 {
1714 let _l1 = child.thread_group().read();
1715 let _l2 = child.read();
1716 }
1717
1718 Ok(child)
1719 }
1720
1721 pub fn set_stopped_and_notify(&self, stopped: StopState, siginfo: Option<SignalInfo>) {
1724 let maybe_signal_info = {
1725 let mut state = self.write();
1726 state.copy_state_from(self);
1727 state.set_stopped(stopped, siginfo, Some(self), None);
1728 state.prepare_signal_info(stopped)
1729 };
1730
1731 if let Some((tracer, signal_info)) = maybe_signal_info {
1732 if let Some(tracer) = tracer.upgrade() {
1733 tracer.write().send_signal(signal_info);
1734 }
1735 }
1736
1737 if !stopped.is_in_progress() {
1738 let parent = self.thread_group().read().parent.clone();
1739 if let Some(parent) = parent {
1740 parent
1741 .upgrade()
1742 .write()
1743 .lifecycle_waiters
1744 .notify_value(ThreadGroupLifecycleWaitValue::ChildStatus);
1745 }
1746 }
1747 }
1748
1749 pub fn block_if_stopped(&mut self) -> bool {
1756 if self.finalize_stop_state() {
1757 self.block_while_stopped();
1758 true
1759 } else {
1760 false
1761 }
1762 }
1763
1764 fn finalize_stop_state(&mut self) -> bool {
1767 let stopped = self.load_stopped();
1768
1769 if !stopped.is_stopping_or_stopped() {
1770 let captured_state = self.write().take_captured_state();
1772 if let Some(captured) = captured_state {
1773 if captured.dirty {
1774 self.thread_state.replace_registers(&captured.thread_state);
1775 }
1776 }
1777 }
1778
1779 if self.thread_group().set_stopped(StopState::GroupStopped, None, true)
1782 == StopState::GroupStopped
1783 {
1784 let signal = self.thread_group().read().last_signal.clone();
1785 let event = Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0));
1787 self.write().set_stopped(StopState::GroupStopped, signal, Some(self), event);
1788 return true;
1789 }
1790
1791 if stopped.is_stopping_or_stopped() {
1793 if let Ok(stopped) = stopped.finalize() {
1794 self.set_stopped_and_notify(stopped, None);
1795 }
1796 return true;
1797 }
1798
1799 false
1800 }
1801
1802 fn block_while_stopped(&mut self) {
1805 let waiter = Waiter::with_options(WaiterOptions::IGNORE_SIGNALS);
1806 loop {
1807 if self.is_exitted() {
1810 self.thread_group().set_stopped(StopState::ForceAwake, None, false);
1811 self.write().set_stopped(StopState::ForceAwake, None, Some(self), None);
1812 return;
1813 }
1814
1815 if self.wake_or_wait_until_unstopped_async(&waiter) {
1816 return;
1817 }
1818
1819 let _: Result<(), Errno> = waiter.wait(self);
1821
1822 self.finalize_stop_state();
1825 }
1826 }
1827
1828 pub fn get_ptrace_core_state_for_clone(
1831 &mut self,
1832 clone_args: &clone_args,
1833 ) -> (PtraceOptions, Option<PtraceCoreState>) {
1834 let state = self.write();
1835 if let Some(ptrace) = &state.ptrace {
1836 ptrace.get_core_state_for_clone(clone_args)
1837 } else {
1838 (PtraceOptions::empty(), None)
1839 }
1840 }
1841
1842 pub fn ptrace_event(&mut self, trace_kind: PtraceOptions, msg: u64) {
1850 if !trace_kind.is_empty() {
1851 {
1852 let mut state = self.write();
1853 if let Some(ptrace) = &mut state.ptrace {
1854 if !ptrace.has_option(trace_kind) {
1855 if trace_kind == PtraceOptions::TRACEEXEC && !ptrace.is_seized() {
1858 send_signal_first(self, state, SignalInfo::kernel(SIGTRAP));
1860 }
1861
1862 return;
1863 }
1864 let ptrace_event = PtraceEvent::from_option(&trace_kind) as u32;
1865 let siginfo = SignalInfo::with_detail(
1866 SIGTRAP,
1867 ((ptrace_event << 8) | SIGTRAP.number()) as i32,
1868 SignalDetail::None,
1869 );
1870 state.set_stopped(
1871 StopState::PtraceEventStopping,
1872 Some(siginfo),
1873 None,
1874 Some(PtraceEventData::new(trace_kind, msg)),
1875 );
1876 } else {
1877 return;
1878 }
1879 }
1880 self.block_if_stopped();
1881 }
1882 }
1883
1884 pub fn kill_thread_group(&mut self, exit_status: ExitStatus) {
1887 self.ptrace_event(PtraceOptions::TRACEEXIT, exit_status.signal_info_status() as u64);
1888 self.thread_group().kill(exit_status, None);
1889 }
1890
1891 pub fn clone_task_builder_for_test(
1894 &self,
1895 flags: u64,
1896 exit_signal: Option<Signal>,
1897 ) -> TaskBuilder {
1898 let result = self
1899 .clone_task(
1900 flags,
1901 exit_signal,
1902 UserRef::default(),
1903 UserRef::default(),
1904 UserRef::default(),
1905 )
1906 .expect("failed to create task in test");
1907 result.task.write().set_spawned();
1908 result
1909 }
1910
1911 pub fn clone_task_for_test(
1914 &self,
1915 flags: u64,
1916 exit_signal: Option<Signal>,
1917 ) -> crate::testing::AutoReleasableTask {
1918 self.clone_task_builder_for_test(flags, exit_signal).into()
1919 }
1920
1921 pub fn check_ptrace_access_mode(
1923 &self,
1924 mode: PtraceAccessMode,
1925 target: &Task,
1926 ) -> Result<(), Errno> {
1927 if self.thread_group().leader == target.thread_group().leader {
1930 return Ok(());
1931 }
1932
1933 let (uid, gid) = if mode.contains(PTRACE_MODE_FSCREDS) {
1945 let fscred = self.current_creds().as_fscred();
1946 (fscred.uid, fscred.gid)
1947 } else if mode.contains(PTRACE_MODE_REALCREDS) {
1948 let creds = self.current_creds();
1949 (creds.uid, creds.gid)
1950 } else {
1951 unreachable!();
1952 };
1953
1954 let target_creds = target.persistent_info.lock_creds();
1964 if !(target_creds.uid == uid
1965 && target_creds.euid == uid
1966 && target_creds.saved_uid == uid
1967 && target_creds.gid == gid
1968 && target_creds.egid == gid
1969 && target_creds.saved_gid == gid)
1970 {
1971 security::check_task_capable(self, CAP_SYS_PTRACE)?;
1972 }
1973
1974 let dumpable = *target.mm()?.dumpable.lock();
1980 match dumpable {
1981 DumpPolicy::User => (),
1982 DumpPolicy::Disable => security::check_task_capable(self, CAP_SYS_PTRACE)?,
1983 }
1984
1985 security::ptrace_access_check(self, target, mode)?;
1988
1989 Ok(())
1992 }
1993
1994 pub fn can_signal(
1995 &self,
1996 target: &Task,
1997 unchecked_signal: UncheckedSignal,
1998 ) -> Result<(), Errno> {
1999 if self.thread_group == target.thread_group {
2002 return Ok(());
2003 }
2004
2005 let self_creds = self.current_creds();
2006 let target_creds = target.real_creds();
2007 if self_creds.euid == target_creds.saved_uid
2017 || self_creds.euid == target_creds.uid
2018 || self_creds.uid == target_creds.uid
2019 || self_creds.uid == target_creds.saved_uid
2020 {
2021 return Ok(());
2022 }
2023
2024 if Signal::try_from(unchecked_signal) == Ok(SIGCONT) {
2025 let target_session = target.thread_group().read().process_group.session.leader;
2026 let self_session = self.thread_group().read().process_group.session.leader;
2027 if target_session == self_session {
2028 return Ok(());
2029 }
2030 }
2031
2032 security::check_task_capable(self, CAP_KILL)
2033 }
2034}
2035
2036impl ArchSpecific for CurrentTask {
2037 fn is_arch32(&self) -> bool {
2038 self.thread_state.is_arch32()
2039 }
2040}
2041
2042impl MemoryAccessor for CurrentTask {
2043 fn read_memory<'a>(
2044 &self,
2045 addr: UserAddress,
2046 bytes: &'a mut [MaybeUninit<u8>],
2047 ) -> Result<&'a mut [u8], Errno> {
2048 self.mm()?.unified_read_memory(self, addr, bytes)
2049 }
2050
2051 fn read_memory_partial_until_null_byte<'a>(
2052 &self,
2053 addr: UserAddress,
2054 bytes: &'a mut [MaybeUninit<u8>],
2055 ) -> Result<&'a mut [u8], Errno> {
2056 self.mm()?.unified_read_memory_partial_until_null_byte(self, addr, bytes)
2057 }
2058
2059 fn read_memory_partial<'a>(
2060 &self,
2061 addr: UserAddress,
2062 bytes: &'a mut [MaybeUninit<u8>],
2063 ) -> Result<&'a mut [u8], Errno> {
2064 self.mm()?.unified_read_memory_partial(self, addr, bytes)
2065 }
2066
2067 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2068 self.mm()?.unified_write_memory(self, addr, bytes)
2069 }
2070
2071 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2072 self.mm()?.unified_write_memory_partial(self, addr, bytes)
2073 }
2074
2075 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
2076 self.mm()?.unified_zero(self, addr, length)
2077 }
2078}
2079
2080impl TaskMemoryAccessor for CurrentTask {
2081 fn maximum_valid_address(&self) -> Option<UserAddress> {
2082 self.mm().ok().map(|mm| mm.maximum_valid_user_address)
2083 }
2084}
2085
2086pub enum ExceptionResult {
2087 Handled,
2089
2090 Signal(SignalInfo),
2092}
2093
2094fn split_path(path: &FsStr) -> LookupVec<&FsStr> {
2095 path.split(|c| *c == b'/').filter(|p| !p.is_empty()).map(<&FsStr>::from).collect()
2096}
2097
2098#[cfg(test)]
2099mod tests {
2100 use crate::testing::spawn_kernel_and_run;
2101 use starnix_uapi::auth::Credentials;
2102
2103 #[::fuchsia::test]
2106 async fn test_override_creds_can_delegate_to_async_version() {
2107 spawn_kernel_and_run(async move |current_task| {
2108 assert_eq!(current_task.override_creds(Credentials::root(), || 0), 0);
2109 })
2110 .await;
2111 }
2112}