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, SeccompNotifierHandle, SeccompState,
16 SeccompStateValue, Task, 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 fuchsia_rcu::RcuReadGuard;
24use futures::FutureExt;
25use linux_uapi::CLONE_PIDFD;
26use starnix_logging::{CATEGORY_STARNIX, log_error, log_warn, track_file_not_found, track_stub};
27use starnix_registers::{HeapRegs, RegisterStorageEnum};
28use starnix_stack::clean_stack;
29use starnix_sync::{
30 EventWaitGuard, FileOpsCore, LockBefore, LockEqualOrBefore, Locked, MmDumpable,
31 ProcessGroupState, TaskRelease, UninterruptibleLock, Unlocked, WakeReason, assert_lock_level,
32};
33use starnix_syscalls::SyscallResult;
34use starnix_syscalls::decls::Syscall;
35use starnix_task_command::TaskCommand;
36use starnix_types::futex_address::FutexAddress;
37use starnix_types::ownership::{Releasable, release_on_error};
38use starnix_uapi::auth::{
39 CAP_KILL, CAP_SYS_ADMIN, CAP_SYS_PTRACE, Credentials, FsCred, PTRACE_MODE_FSCREDS,
40 PTRACE_MODE_REALCREDS, PtraceAccessMode,
41};
42use starnix_uapi::device_id::DeviceId;
43use starnix_uapi::errors::Errno;
44use starnix_uapi::file_mode::{Access, AccessCheck, FileMode};
45use starnix_uapi::open_flags::OpenFlags;
46use starnix_uapi::signals::{
47 SIGCHLD, SIGCONT, SIGILL, SIGKILL, SIGSEGV, SIGSYS, SIGTRAP, SigSet, Signal, UncheckedSignal,
48};
49use starnix_uapi::user_address::{ArchSpecific, UserAddress, UserRef};
50use starnix_uapi::vfs::ResolveFlags;
51use starnix_uapi::{
52 CLONE_CHILD_CLEARTID, CLONE_CHILD_SETTID, CLONE_CLEAR_SIGHAND, CLONE_FILES, CLONE_FS,
53 CLONE_INTO_CGROUP, CLONE_NEWUTS, CLONE_PARENT, CLONE_PARENT_SETTID, CLONE_PTRACE, CLONE_SETTLS,
54 CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_THREAD, CLONE_VFORK, CLONE_VM, FUTEX_OWNER_DIED,
55 FUTEX_TID_MASK, ROBUST_LIST_LIMIT, SECCOMP_FILTER_FLAG_LOG, SECCOMP_FILTER_FLAG_NEW_LISTENER,
56 SECCOMP_FILTER_FLAG_TSYNC, SECCOMP_FILTER_FLAG_TSYNC_ESRCH, clone_args, errno, error, pid_t,
57 sock_filter, ucred,
58};
59use std::cell::{Ref, RefCell};
60use std::collections::VecDeque;
61use std::ffi::CString;
62use std::fmt;
63use std::marker::PhantomData;
64use std::mem::MaybeUninit;
65use std::sync::{Arc, Weak};
66use zx::sys::zx_restricted_state_t;
67
68use super::ThreadGroupLifecycleWaitValue;
69
70pub struct TaskBuilder {
71 pub task: Arc<Task>,
73
74 pub thread_state: ThreadState<HeapRegs>,
75}
76
77impl TaskBuilder {
78 pub fn new(task: Arc<Task>) -> Self {
79 Self { task, thread_state: Default::default() }
80 }
81
82 #[inline(always)]
83 pub fn release<L>(self, locked: &mut Locked<L>)
84 where
85 L: LockBefore<TaskRelease>,
86 {
87 let locked = locked.cast_locked::<TaskRelease>();
88 Releasable::release(self, locked);
89 }
90}
91
92impl From<TaskBuilder> for CurrentTask {
93 fn from(builder: TaskBuilder) -> Self {
94 Self::new(builder.task, builder.thread_state.into())
95 }
96}
97
98impl Releasable for TaskBuilder {
99 type Context<'a> = &'a mut Locked<TaskRelease>;
100
101 fn release<'a>(self, locked: Self::Context<'a>) {
102 let current_task = CurrentTask::new(self.task, self.thread_state.into());
104 current_task.exit(locked);
105 }
106}
107
108impl std::ops::Deref for TaskBuilder {
109 type Target = Task;
110 fn deref(&self) -> &Self::Target {
111 &self.task
112 }
113}
114
115pub struct CurrentTask {
128 pub task: Arc<Task>,
130
131 pub thread_state: ThreadState<RegisterStorageEnum>,
132
133 pub current_creds: RefCell<CurrentCreds>,
137
138 pub security_state: security::CurrentTaskState,
139
140 _local_marker: PhantomData<*mut u8>,
142}
143
144pub enum CurrentCreds {
146 Cached(Arc<Credentials>),
151 Overridden(Arc<Credentials>),
153}
154
155impl CurrentCreds {
156 fn creds(&self) -> &Arc<Credentials> {
157 match self {
158 CurrentCreds::Cached(creds) => creds,
159 CurrentCreds::Overridden(creds) => creds,
160 }
161 }
162}
163
164impl Releasable for CurrentTask {
165 type Context<'a> = &'a mut Locked<TaskRelease>;
166
167 fn release<'a>(self, locked: Self::Context<'a>) {
168 self.exit(locked);
169 }
170}
171
172impl std::ops::Deref for CurrentTask {
173 type Target = Task;
174 fn deref(&self) -> &Self::Target {
175 &self.task
176 }
177}
178
179impl fmt::Debug for CurrentTask {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 self.task.fmt(f)
182 }
183}
184
185impl CurrentTask {
186 pub fn new(task: Arc<Task>, thread_state: ThreadState<RegisterStorageEnum>) -> Self {
187 let current_creds = RefCell::new(CurrentCreds::Cached(task.clone_creds()));
188 Self {
189 task,
190 thread_state,
191 current_creds,
192 security_state: Default::default(),
193 _local_marker: Default::default(),
194 }
195 }
196
197 pub fn exit(&self, locked: &mut Locked<TaskRelease>) {
199 self.notify_robust_list();
205 let _ignored = self.clear_child_tid_if_needed(locked);
206
207 self.signal_vfork();
208
209 if let Ok(running_state) = self.task.running_state() {
211 running_state.files.release();
212 running_state.mm.update(None);
213 }
214 self.running_state.update(None);
215
216 self.trigger_delayed_releaser(locked);
217
218 self.task.thread_group().remove(locked, self.kernel().pids.write(), &self.task);
224
225 self.ptrace_disconnect();
226 }
227
228 #[track_caller]
235 pub fn running_state(&self) -> RcuReadGuard<TaskRunningState> {
236 self.task.running_state().expect("CurrentTask must have TaskRunningState")
237 }
238
239 #[track_caller]
246 pub fn files(&self) -> FdTable {
247 self.task.files().expect("CurrentTask must have FdTable")
248 }
249
250 pub fn fs(&self) -> Arc<FsContext> {
251 self.running_state().fs()
252 }
253
254 pub fn has_shared_fs(&self) -> bool {
255 let fs = self.fs();
256 Arc::strong_count(&fs) > 2usize
259 }
260
261 pub fn unshare_fs(&self) {
262 let new_fs = self.fs().fork();
263 self.running_state().fs.update(new_fs);
264 }
265
266 pub fn current_creds(&self) -> Ref<'_, Arc<Credentials>> {
271 Ref::map(self.current_creds.borrow(), CurrentCreds::creds)
272 }
273
274 pub fn current_fscred(&self) -> FsCred {
275 self.current_creds().as_fscred()
276 }
277
278 pub fn current_ucred(&self) -> ucred {
279 let creds = self.current_creds();
280 ucred { pid: self.get_pid(), uid: creds.uid, gid: creds.gid }
281 }
282
283 pub async fn override_creds_async<R>(
292 &self,
293 new_creds: Arc<Credentials>,
294 callback: impl AsyncFnOnce() -> R,
295 ) -> R {
296 let saved = self.current_creds.replace(CurrentCreds::Overridden(new_creds));
297 let result = callback().await;
298 self.current_creds.replace(saved);
299 result
300 }
301
302 pub fn override_creds<R>(
311 &self,
312 new_creds: Arc<Credentials>,
313 callback: impl FnOnce() -> R,
314 ) -> R {
315 self.override_creds_async(new_creds, async move || callback())
316 .now_or_never()
317 .expect("Future should be ready")
318 }
319
320 pub fn has_overridden_creds(&self) -> bool {
321 matches!(*self.current_creds.borrow(), CurrentCreds::Overridden(_))
322 }
323
324 pub fn trigger_delayed_releaser<L>(&self, locked: &mut Locked<L>)
325 where
326 L: LockEqualOrBefore<FileOpsCore>,
327 {
328 let locked = locked.cast_locked::<FileOpsCore>();
329 self.kernel().delayed_releaser.apply(locked, self);
330 }
331
332 pub fn weak_task(&self) -> Weak<Task> {
333 Arc::downgrade(&self.task)
334 }
335
336 pub fn write_creds(&self) -> CurrentTaskCredentialsWriteGuard {
340 assert!(!self.has_overridden_creds());
341 self.persistent_info.write_current_task_creds()
342 }
343
344 pub fn set_creds(&self, creds: Credentials) {
347 let creds = Arc::new(creds);
348 self.write_creds().update(self, creds);
349 }
350
351 #[inline(always)]
352 pub fn release<L>(self, locked: &mut Locked<L>)
353 where
354 L: LockBefore<TaskRelease>,
355 {
356 let locked = locked.cast_locked::<TaskRelease>();
357 Releasable::release(self, locked);
358 }
359
360 pub fn set_syscall_restart_func<R: Into<SyscallResult>>(
361 &mut self,
362 f: impl FnOnce(&mut Locked<Unlocked>, &mut CurrentTask) -> Result<R, Errno>
363 + Send
364 + Sync
365 + 'static,
366 ) {
367 self.thread_state.syscall_restart_func =
368 Some(Box::new(|locked, current_task| Ok(f(locked, current_task)?.into())));
369 }
370
371 pub fn add_file<L>(
372 &self,
373 locked: &mut Locked<L>,
374 file: FileHandle,
375 flags: FdFlags,
376 ) -> Result<FdNumber, Errno>
377 where
378 L: LockEqualOrBefore<FileOpsCore>,
379 {
380 self.files().add(locked, self, file, flags)
381 }
382
383 pub fn wait_with_temporary_mask<F, T, L>(
390 &mut self,
391 locked: &mut Locked<L>,
392 signal_mask: SigSet,
393 wait_function: F,
394 ) -> Result<T, Errno>
395 where
396 L: LockEqualOrBefore<FileOpsCore>,
397 F: FnOnce(&mut Locked<L>, &CurrentTask) -> Result<T, Errno>,
398 {
399 {
400 let mut state = self.write();
401 state.set_flags(TaskFlags::TEMPORARY_SIGNAL_MASK, true);
402 state.set_temporary_signal_mask(signal_mask);
403 }
404 wait_function(locked, self)
405 }
406
407 pub fn wake_or_wait_until_unstopped_async(&self, waiter: &Waiter) -> bool {
410 let group_state = self.thread_group().read();
411 let mut task_state = self.write();
412
413 let task_stop_state = self.load_stopped();
420 let group_stop_state = self.thread_group().load_stopped();
421 if ((task_stop_state == StopState::GroupStopped && group_stop_state.is_waking_or_awake())
422 || task_stop_state.is_waking_or_awake())
423 && (!task_state.is_ptrace_listening() || task_stop_state.is_force())
424 {
425 let new_state = if task_stop_state.is_waking_or_awake() {
426 task_stop_state.finalize()
427 } else {
428 group_stop_state.finalize()
429 };
430 if let Ok(new_state) = new_state {
431 task_state.set_stopped(new_state, None, Some(self), None);
432 drop(group_state);
433 drop(task_state);
434 self.thread_group().set_stopped(new_state, None, false);
440 return true;
441 }
442 }
443
444 if self.thread_group().load_stopped().is_stopped() || task_stop_state.is_stopped() {
446 group_state
449 .lifecycle_waiters
450 .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::Stopped);
451 task_state.wait_on_ptracer(&waiter);
452 } else if task_state.can_accept_ptrace_commands() {
453 task_state.wait_on_ptracer(&waiter);
456 } else if task_state.is_ptrace_listening() {
457 if let Some(ptrace) = &mut task_state.ptrace {
460 ptrace.set_last_signal(Some(SignalInfo::kernel(SIGTRAP)));
461 ptrace.set_last_event(Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0)));
462 }
463 task_state.wait_on_ptracer(&waiter);
464 task_state.notify_ptracers();
465 }
466 false
467 }
468
469 pub fn run_in_state<F, T>(&self, run_state: RunState, callback: F) -> Result<T, Errno>
480 where
481 F: FnOnce() -> Result<T, Errno>,
482 {
483 assert_ne!(run_state, RunState::Running);
484
485 assert_lock_level::<UninterruptibleLock>();
487 clean_stack();
490
491 {
492 let mut state = self.write();
493 assert!(!state.is_blocked());
494
495 if matches!(run_state, RunState::Frozen(_)) {
496 if state.has_signal_pending(SIGKILL) {
499 return error!(EINTR);
500 }
501 } else if state.is_any_signal_pending() && !state.is_ptrace_listening() {
502 return error!(EINTR);
505 }
506 state.set_run_state(run_state.clone());
507 }
508
509 let _waiting_guard = crate::task::ThreadLockupDetector::pause_tracking();
510 let result = callback();
511
512 {
513 let mut state = self.write();
514 assert_eq!(
515 state.run_state(),
516 run_state,
517 "SignalState run state changed while waiting!"
518 );
519 state.set_run_state(RunState::Running);
520 };
521
522 result
523 }
524
525 pub fn block_until(
526 &self,
527 guard: EventWaitGuard<'_>,
528 deadline: zx::MonotonicInstant,
529 ) -> Result<(), Errno> {
530 self.run_in_state(RunState::Event(guard.event().clone()), move || {
531 guard.block_until(None, deadline).map_err(|e| match e {
532 WakeReason::Interrupted => errno!(EINTR),
533 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
534 })
535 })
536 }
537
538 pub fn block_with_owner_until(
539 &self,
540 guard: EventWaitGuard<'_>,
541 new_owner: &zx::Thread,
542 deadline: zx::MonotonicInstant,
543 ) -> Result<(), Errno> {
544 self.run_in_state(RunState::Event(guard.event().clone()), move || {
545 guard.block_until(Some(new_owner), deadline).map_err(|e| match e {
546 WakeReason::Interrupted => errno!(EINTR),
547 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
548 })
549 })
550 }
551
552 pub fn resolve_dir_fd<'a, L>(
556 &self,
557 locked: &mut Locked<L>,
558 dir_fd: FdNumber,
559 mut path: &'a FsStr,
560 flags: ResolveFlags,
561 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
562 where
563 L: LockEqualOrBefore<FileOpsCore>,
564 {
565 let path_is_absolute = path.starts_with(b"/");
566 if path_is_absolute {
567 if flags.contains(ResolveFlags::BENEATH) {
568 return error!(EXDEV);
569 }
570 path = &path[1..];
571 }
572
573 let dir = if path_is_absolute && !flags.contains(ResolveFlags::IN_ROOT) {
574 self.fs().root()
575 } else if dir_fd == FdNumber::AT_FDCWD {
576 self.fs().cwd()
577 } else {
578 let file = self.files().get_allowing_opath(dir_fd)?;
588 file.name.to_passive()
589 };
590
591 if !path.is_empty() {
592 if !dir.entry.node.is_dir() {
593 return error!(ENOTDIR);
594 }
595 dir.check_access(
596 locked,
597 self,
598 Access::EXEC,
599 CheckAccessReason::InternalPermissionChecks,
600 )?;
601 }
602 Ok((dir, path.into()))
603 }
604
605 pub fn open_file(
610 &self,
611 locked: &mut Locked<Unlocked>,
612 path: &FsStr,
613 flags: OpenFlags,
614 ) -> Result<FileHandle, Errno> {
615 if flags.contains(OpenFlags::CREAT) {
616 return error!(EINVAL);
619 }
620 self.open_file_at(
621 locked,
622 FdNumber::AT_FDCWD,
623 path,
624 flags,
625 FileMode::default(),
626 ResolveFlags::empty(),
627 AccessCheck::default(),
628 )
629 }
630
631 fn resolve_open_path<L>(
642 &self,
643 locked: &mut Locked<L>,
644 context: &mut LookupContext,
645 dir: &NamespaceNode,
646 path: &FsStr,
647 mode: FileMode,
648 flags: OpenFlags,
649 ) -> Result<(NamespaceNode, bool), Errno>
650 where
651 L: LockEqualOrBefore<FileOpsCore>,
652 {
653 context.update_for_path(path);
654 let mut parent_content = context.with(SymlinkMode::Follow);
655 let (parent, basename) = self.lookup_parent(locked, &mut parent_content, dir, path)?;
656 context.remaining_follows = parent_content.remaining_follows;
657
658 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
659
660 let mut child_context = context.with(SymlinkMode::NoFollow);
662 child_context.must_be_directory = false;
663
664 match parent.lookup_child(locked, self, &mut child_context, basename) {
665 Ok(name) => {
666 if name.entry.node.is_lnk() {
667 if flags.contains(OpenFlags::PATH)
668 && context.symlink_mode == SymlinkMode::NoFollow
669 {
670 return Ok((name, false));
683 }
684
685 if (!flags.contains(OpenFlags::PATH)
686 && context.symlink_mode == SymlinkMode::NoFollow)
687 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
688 || context.remaining_follows == 0
689 {
690 if must_create {
691 return error!(EEXIST);
694 }
695 return error!(ELOOP);
700 }
701
702 context.remaining_follows -= 1;
703 match name.readlink(locked, self)? {
704 SymlinkTarget::Path(path) => {
705 let dir = if path[0] == b'/' { self.fs().root() } else { parent };
706 self.resolve_open_path(
707 locked,
708 context,
709 &dir,
710 path.as_ref(),
711 mode,
712 flags,
713 )
714 }
715 SymlinkTarget::Node(name) => {
716 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS)
717 || name.entry.node.is_lnk()
718 {
719 error!(ELOOP)
720 } else {
721 Ok((name, false))
722 }
723 }
724 }
725 } else {
726 if must_create {
727 return error!(EEXIST);
728 }
729 Ok((name, false))
730 }
731 }
732 Err(e) if e == errno!(ENOENT) && flags.contains(OpenFlags::CREAT) => {
733 if context.must_be_directory {
734 return error!(EISDIR);
735 }
736 Ok((
737 parent.open_create_node(
738 locked,
739 self,
740 basename,
741 mode.with_type(FileMode::IFREG),
742 DeviceId::NONE,
743 flags,
744 )?,
745 true,
746 ))
747 }
748 Err(e) => Err(e),
749 }
750 }
751
752 pub fn open_file_at(
762 &self,
763 locked: &mut Locked<Unlocked>,
764 dir_fd: FdNumber,
765 path: &FsStr,
766 flags: OpenFlags,
767 mode: FileMode,
768 resolve_flags: ResolveFlags,
769 access_check: AccessCheck,
770 ) -> Result<FileHandle, Errno> {
771 if path.is_empty() {
772 return error!(ENOENT);
773 }
774
775 let (dir, path) = self.resolve_dir_fd(locked, dir_fd, path, resolve_flags)?;
776 self.open_namespace_node_at(locked, dir, path, flags, mode, resolve_flags, access_check)
777 }
778
779 pub fn open_namespace_node_at(
780 &self,
781 locked: &mut Locked<Unlocked>,
782 dir: NamespaceNode,
783 path: &FsStr,
784 flags: OpenFlags,
785 mode: FileMode,
786 mut resolve_flags: ResolveFlags,
787 access_check: AccessCheck,
788 ) -> Result<FileHandle, Errno> {
789 let mut flags = flags | OpenFlags::LARGEFILE;
791 let opath = flags.contains(OpenFlags::PATH);
792 if opath {
793 const ALLOWED_FLAGS: OpenFlags = OpenFlags::from_bits_truncate(
796 OpenFlags::PATH.bits()
797 | OpenFlags::CLOEXEC.bits()
798 | OpenFlags::DIRECTORY.bits()
799 | OpenFlags::NOFOLLOW.bits(),
800 );
801 flags &= ALLOWED_FLAGS;
802 }
803
804 if flags.contains(OpenFlags::TMPFILE) && !flags.can_write() {
805 return error!(EINVAL);
806 }
807
808 let nofollow = flags.contains(OpenFlags::NOFOLLOW);
809 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
810
811 let symlink_mode =
812 if nofollow || must_create { SymlinkMode::NoFollow } else { SymlinkMode::Follow };
813
814 let resolve_base = match (
815 resolve_flags.contains(ResolveFlags::BENEATH),
816 resolve_flags.contains(ResolveFlags::IN_ROOT),
817 ) {
818 (false, false) => ResolveBase::None,
819 (true, false) => ResolveBase::Beneath(dir.clone()),
820 (false, true) => ResolveBase::InRoot(dir.clone()),
821 (true, true) => return error!(EINVAL),
822 };
823
824 if resolve_base != ResolveBase::None {
828 resolve_flags.insert(ResolveFlags::NO_MAGICLINKS);
829 }
830
831 let mut context = LookupContext {
832 symlink_mode,
833 remaining_follows: MAX_SYMLINK_FOLLOWS,
834 must_be_directory: flags.contains(OpenFlags::DIRECTORY),
835 resolve_flags,
836 resolve_base,
837 };
838 let (name, created) =
839 match self.resolve_open_path(locked, &mut context, &dir, path, mode, flags) {
840 Ok((n, c)) => (n, c),
841 Err(e) => {
842 let mut abs_path = dir.path(&self.fs());
843 abs_path.extend(&**path);
844 track_file_not_found(abs_path);
845 return Err(e);
846 }
847 };
848
849 let name = if flags.contains(OpenFlags::TMPFILE) {
850 if flags.contains(OpenFlags::CREAT) {
852 return error!(EINVAL);
853 }
854 name.create_tmpfile(locked, self, mode.with_type(FileMode::IFREG), flags)?
855 } else {
856 let mode = name.entry.node.info().mode;
857
858 if !opath && nofollow && mode.is_lnk() {
870 return error!(ELOOP);
871 }
872
873 if mode.is_dir() {
874 if flags.can_write()
875 || flags.contains(OpenFlags::CREAT)
876 || flags.contains(OpenFlags::TRUNC)
877 {
878 return error!(EISDIR);
879 }
880 if flags.contains(OpenFlags::DIRECT) {
881 return error!(EINVAL);
882 }
883 } else if context.must_be_directory {
884 return error!(ENOTDIR);
885 }
886
887 if flags.contains(OpenFlags::TRUNC) && mode.is_reg() && !created {
888 name.truncate(locked, self, 0)?;
894 }
895
896 name
897 };
898
899 let access_check = if created { AccessCheck::skip() } else { access_check };
906 let file = name.open(locked, self, flags, access_check)?;
907
908 if !opath {
912 security::file_open(self, &file)?;
913 }
914
915 Ok(file)
916 }
917
918 pub fn lookup_parent_at<'a, L>(
926 &self,
927 locked: &mut Locked<L>,
928 context: &mut LookupContext,
929 dir_fd: FdNumber,
930 path: &'a FsStr,
931 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
932 where
933 L: LockEqualOrBefore<FileOpsCore>,
934 {
935 let (dir, path) = self.resolve_dir_fd(locked, dir_fd, path, ResolveFlags::empty())?;
936 self.lookup_parent(locked, context, &dir, path)
937 }
938
939 pub fn lookup_parent<'a, L>(
954 &self,
955 locked: &mut Locked<L>,
956 context: &mut LookupContext,
957 dir: &NamespaceNode,
958 path: &'a FsStr,
959 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
960 where
961 L: LockEqualOrBefore<FileOpsCore>,
962 {
963 context.update_for_path(path);
964
965 let components = split_path(path);
966 if components.is_empty() {
967 return Ok((dir.clone(), Default::default()));
968 }
969 let result =
970 dir.lookup_children(locked, self, context, &components[0..components.len() - 1])?;
971 Ok((result, components.last().unwrap()))
972 }
973
974 pub fn lookup_path<L>(
981 &self,
982 locked: &mut Locked<L>,
983 context: &mut LookupContext,
984 dir: NamespaceNode,
985 path: &FsStr,
986 ) -> Result<NamespaceNode, Errno>
987 where
988 L: LockEqualOrBefore<FileOpsCore>,
989 {
990 let components = split_path(path);
991 dir.lookup_children(locked, self, context, &components)
992 }
993
994 pub fn lookup_path_from_root<L>(
998 &self,
999 locked: &mut Locked<L>,
1000 path: &FsStr,
1001 ) -> Result<NamespaceNode, Errno>
1002 where
1003 L: LockEqualOrBefore<FileOpsCore>,
1004 {
1005 let mut context = LookupContext::default();
1006 self.lookup_path(locked, &mut context, self.fs().root(), path)
1007 }
1008
1009 pub fn exec(
1010 &mut self,
1011 locked: &mut Locked<Unlocked>,
1012 executable: FileHandle,
1013 path: CString,
1014 argv: Vec<CString>,
1015 environ: Vec<CString>,
1016 ) -> Result<(), Errno> {
1017 if !executable.name.entry.node.is_reg() {
1021 return error!(EACCES);
1022 }
1023
1024 executable.name.check_access(locked, self, Access::EXEC, CheckAccessReason::Exec)?;
1029
1030 let mut resolved_elf =
1033 resolve_executable(locked, self, executable.clone(), path.clone(), argv, environ)?;
1034
1035 let writable_creds = self.write_creds();
1037
1038 security::bprm_creds_from_file(self, &mut resolved_elf)?;
1051
1052 security::bprm_creds_for_exec(self, &executable.name, &mut resolved_elf)?;
1054
1055 if self.thread_group().read().tasks_count() > 1 {
1056 track_stub!(TODO("https://fxbug.dev/297434895"), "exec on multithread process");
1057 return error!(EINVAL);
1058 }
1059
1060 if let Err(err) = self.finish_exec(locked, path, resolved_elf, writable_creds) {
1062 log_warn!("unrecoverable error in exec: {err:?}");
1063
1064 send_standard_signal(locked, self, SignalInfo::forced(SIGSEGV));
1065 return Err(err);
1066 }
1067
1068 self.ptrace_event(locked, PtraceOptions::TRACEEXEC, self.task.tid as u64);
1069 self.signal_vfork();
1070 self.task.thread_group.sync_syscall_log_level();
1071
1072 Ok(())
1073 }
1074
1075 fn finish_exec(
1079 &mut self,
1080 locked: &mut Locked<Unlocked>,
1081 path: CString,
1082 resolved_elf: ResolvedElf,
1083 writable_creds: CurrentTaskCredentialsWriteGuard,
1084 ) -> Result<(), Errno> {
1085 self.notify_robust_list();
1089
1090 let mm = {
1092 let new_mm = MemoryManager::exec(
1093 self.thread_group().root_vmar.unowned(),
1094 self.mm().ok(),
1095 resolved_elf.file.name.to_passive(),
1096 resolved_elf.arch_width,
1097 )?;
1098 self.running_state().mm.update(Some(new_mm.clone()));
1099 new_mm
1100 };
1101 self.running_state().files.unshare();
1122 self.files().exec(locked, self);
1123
1124 {
1125 let mut state = self.write();
1126
1127 let dumpable =
1136 if resolved_elf.secure_exec { DumpPolicy::Disable } else { DumpPolicy::User };
1137 *mm.dumpable.lock(locked) = dumpable;
1138
1139 state.set_sigaltstack(None);
1140 state.robust_list_head = RobustListHeadPtr::null(self);
1141 }
1150
1151 security::bprm_committing_creds(locked, self, &resolved_elf)?;
1152
1153 let new_creds = Arc::new(resolved_elf.creds.clone());
1154 writable_creds.update(self, new_creds);
1155
1156 let start_info = load_executable(self, resolved_elf, &path)?;
1157
1158 let regs: zx_restricted_state_t = start_info.into();
1159 self.thread_state.registers.load(regs);
1160 self.thread_state.extended_pstate.reset();
1161 self.thread_group().signal_actions.reset_for_exec();
1162
1163 {
1165 let mut thread_group_state = self.thread_group().write();
1166 thread_group_state.exit_signal = Some(SIGCHLD);
1167 for (_, weak_child) in &mut thread_group_state.children {
1168 if let Some(child) = weak_child.upgrade() {
1169 let _token = starnix_sync::allow_subclass();
1173 let mut child_state = child.write();
1174 child_state.exit_signal = Some(SIGCHLD);
1175 }
1176 }
1177 }
1178
1179 security::bprm_committed_creds(locked, self)?;
1180
1181 self.thread_group().write().did_exec = true;
1182
1183 self.set_command_name(TaskCommand::from_path_bytes(path.to_bytes()));
1184
1185 Ok(())
1186 }
1187
1188 pub fn set_command_name(&self, new_name: TaskCommand) {
1189 self.task.set_command_name(new_name.clone());
1191 let leader_command = self.thread_group().read().leader_command();
1192 starnix_logging::set_current_task_info(
1193 new_name,
1194 leader_command,
1195 self.thread_group().leader,
1196 self.tid,
1197 );
1198 }
1199
1200 pub fn add_seccomp_filter(
1201 &mut self,
1202 locked: &mut Locked<Unlocked>,
1203 code: Vec<sock_filter>,
1204 flags: u32,
1205 ) -> Result<SyscallResult, Errno> {
1206 let new_filter = Arc::new(SeccompFilter::from_cbpf(
1207 &code,
1208 self.thread_group().next_seccomp_filter_id.add(1),
1209 flags & SECCOMP_FILTER_FLAG_LOG != 0,
1210 )?);
1211
1212 let mut maybe_fd: Option<FdNumber> = None;
1213
1214 if flags & SECCOMP_FILTER_FLAG_NEW_LISTENER != 0 {
1215 maybe_fd = Some(SeccompFilterContainer::create_listener(locked, self)?);
1216 }
1217
1218 let state = self.thread_group().write();
1221
1222 if flags & SECCOMP_FILTER_FLAG_TSYNC != 0 {
1223 let mut filters: SeccompFilterContainer = self.read().seccomp_filters.clone();
1229
1230 let tasks = state.tasks();
1234 for task in &tasks {
1235 if task.tid == self.tid {
1236 continue;
1237 }
1238 let other_task_state = task.read();
1239
1240 if task.seccomp_filter_state.get() == SeccompStateValue::Strict {
1242 return Self::seccomp_tsync_error(task.tid, flags);
1243 }
1244
1245 if !other_task_state.seccomp_filters.can_sync_to(&filters) {
1247 return Self::seccomp_tsync_error(task.tid, flags);
1248 }
1249 }
1250
1251 filters.add_filter(new_filter, code.len() as u16)?;
1253
1254 for task in &tasks {
1255 let mut other_task_state = task.write();
1256
1257 other_task_state.enable_no_new_privs();
1258 other_task_state.seccomp_filters = filters.clone();
1259 task.set_seccomp_state(SeccompStateValue::UserDefined)?;
1260 }
1261 } else {
1262 let mut task_state = self.task.write();
1263
1264 task_state.seccomp_filters.add_filter(new_filter, code.len() as u16)?;
1265 self.set_seccomp_state(SeccompStateValue::UserDefined)?;
1266 }
1267
1268 if let Some(fd) = maybe_fd { Ok(fd.into()) } else { Ok(().into()) }
1269 }
1270
1271 pub fn run_seccomp_filters(
1272 &mut self,
1273 locked: &mut Locked<Unlocked>,
1274 syscall: &Syscall,
1275 ) -> Option<Result<SyscallResult, Errno>> {
1276 if self.seccomp_filter_state.get() == SeccompStateValue::Strict {
1279 return SeccompState::do_strict(locked, self, syscall);
1280 }
1281
1282 let result = self.task.read().seccomp_filters.run_all(self, syscall);
1284
1285 SeccompState::do_user_defined(locked, result, self, syscall)
1286 }
1287
1288 fn seccomp_tsync_error(id: i32, flags: u32) -> Result<SyscallResult, Errno> {
1289 if flags & SECCOMP_FILTER_FLAG_TSYNC_ESRCH != 0 { error!(ESRCH) } else { Ok(id.into()) }
1295 }
1296
1297 pub fn notify_robust_list(&self) {
1303 let task_state = self.write();
1304 let robust_list_addr = task_state.robust_list_head.addr();
1305 if robust_list_addr == UserAddress::NULL {
1306 return;
1308 }
1309 let robust_list_res = self.read_multi_arch_object(task_state.robust_list_head);
1310
1311 let head = if let Ok(head) = robust_list_res {
1312 head
1313 } else {
1314 return;
1315 };
1316
1317 let offset = head.futex_offset;
1318
1319 let mut entries_count = 0;
1320 let mut curr_ptr = head.list.next;
1321 while curr_ptr.addr() != robust_list_addr.into() && entries_count < ROBUST_LIST_LIMIT {
1322 let curr_ref = self.read_multi_arch_object(curr_ptr);
1323
1324 let curr = if let Ok(curr) = curr_ref {
1325 curr
1326 } else {
1327 return;
1328 };
1329
1330 let Some(futex_base) = curr_ptr.addr().checked_add_signed(offset) else {
1331 return;
1332 };
1333
1334 let futex_addr = match FutexAddress::try_from(futex_base) {
1335 Ok(addr) => addr,
1336 Err(_) => {
1337 return;
1338 }
1339 };
1340
1341 let Ok(mm) = self.mm() else {
1342 log_error!("Asked to notify robust list futexes in system task.");
1343 return;
1344 };
1345 let futex = if let Ok(futex) = mm.atomic_load_u32_relaxed(futex_addr) {
1346 futex
1347 } else {
1348 return;
1349 };
1350
1351 if (futex & FUTEX_TID_MASK) as i32 == self.tid {
1352 let owner_died = FUTEX_OWNER_DIED | futex;
1353 if mm.atomic_store_u32_relaxed(futex_addr, owner_died).is_err() {
1354 return;
1355 }
1356 }
1357 curr_ptr = curr.next;
1358 entries_count += 1;
1359 }
1360 }
1361
1362 pub fn get_seccomp_notifier(&mut self) -> Option<SeccompNotifierHandle> {
1364 self.task.write().seccomp_filters.notifier.clone()
1365 }
1366
1367 pub fn set_seccomp_notifier(&mut self, notifier: Option<SeccompNotifierHandle>) {
1368 self.task.write().seccomp_filters.notifier = notifier;
1369 }
1370
1371 pub(crate) fn handle_page_fault(
1372 &self,
1373 locked: &mut Locked<Unlocked>,
1374 decoded: PageFaultExceptionReport,
1375 status: zx::Status,
1376 ) -> ExceptionResult {
1377 if let Ok(mm) = self.mm() {
1378 mm.handle_page_fault(locked, decoded, status)
1379 } else {
1380 panic!(
1381 "system task is handling a major page fault status={:?}, report={:?}",
1382 status, decoded
1383 );
1384 }
1385 }
1386
1387 pub fn process_exception(
1389 &self,
1390 locked: &mut Locked<Unlocked>,
1391 report: &zx::ExceptionReport,
1392 ) -> ExceptionResult {
1393 if let Some(result) = handle_hardware_exception(locked, self, report) {
1394 return result;
1395 }
1396
1397 match report.ty {
1398 zx::ExceptionType::General => {
1399 log_error!("Unrecognized general exception: {:?}", report);
1400 ExceptionResult::Signal(SignalInfo::kernel(SIGILL))
1401 }
1402 zx::ExceptionType::ProcessNameChanged => {
1403 log_error!("Received unexpected process name changed exception");
1404 ExceptionResult::Handled
1405 }
1406 zx::ExceptionType::ProcessStarting
1407 | zx::ExceptionType::ThreadStarting
1408 | zx::ExceptionType::ThreadExiting => {
1409 log_error!("Received unexpected task lifecycle exception");
1410 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1411 }
1412 zx::ExceptionType::PolicyError(policy_code) => {
1413 log_error!(policy_code:?; "Received Zircon policy error exception");
1414 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1415 }
1416 zx::ExceptionType::UnknownUserGenerated { code, data } => {
1417 log_error!(code:?, data:?; "Received unexpected unknown user generated exception");
1418 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1419 }
1420 zx::ExceptionType::Unknown { ty, code, data } => {
1421 log_error!(ty:?, code:?, data:?; "Received unexpected exception");
1422 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1423 }
1424 _ => {
1425 log_error!("Received unknown zircon exception: {:?}", report.ty);
1426 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1427 }
1428 }
1429 }
1430
1431 pub fn clone_task<L>(
1441 &self,
1442 locked: &mut Locked<L>,
1443 flags: u64,
1444 child_exit_signal: Option<Signal>,
1445 user_parent_tid: UserRef<pid_t>,
1446 user_child_tid: UserRef<pid_t>,
1447 user_pidfd: UserRef<FdNumber>,
1448 ) -> Result<TaskBuilder, Errno>
1449 where
1450 L: LockBefore<MmDumpable>,
1451 L: LockBefore<TaskRelease>,
1452 L: LockBefore<ProcessGroupState>,
1453 {
1454 const IMPLEMENTED_FLAGS: u64 = ((CLONE_VM
1455 | CLONE_FS
1456 | CLONE_FILES
1457 | CLONE_SIGHAND
1458 | CLONE_THREAD
1459 | CLONE_SYSVSEM
1460 | CLONE_SETTLS
1461 | CLONE_PARENT
1462 | CLONE_PARENT_SETTID
1463 | CLONE_PIDFD
1464 | CLONE_CHILD_CLEARTID
1465 | CLONE_CHILD_SETTID
1466 | CLONE_VFORK
1467 | CLONE_NEWUTS
1468 | CLONE_PTRACE) as u64)
1469 | CLONE_CLEAR_SIGHAND;
1470
1471 const VALID_FLAGS: u64 = (CLONE_INTO_CGROUP << 1) - 1;
1476
1477 let clone_files = flags & (CLONE_FILES as u64) != 0;
1480 let clone_fs = flags & (CLONE_FS as u64) != 0;
1481 let clone_parent = flags & (CLONE_PARENT as u64) != 0;
1482 let clone_parent_settid = flags & (CLONE_PARENT_SETTID as u64) != 0;
1483 let clone_pidfd = flags & (CLONE_PIDFD as u64) != 0;
1484 let clone_child_cleartid = flags & (CLONE_CHILD_CLEARTID as u64) != 0;
1485 let clone_child_settid = flags & (CLONE_CHILD_SETTID as u64) != 0;
1486 let clone_sysvsem = flags & (CLONE_SYSVSEM as u64) != 0;
1487 let clone_ptrace = flags & (CLONE_PTRACE as u64) != 0;
1488 let clone_thread = flags & (CLONE_THREAD as u64) != 0;
1489 let clone_vm = flags & (CLONE_VM as u64) != 0;
1490 let clone_sighand = flags & (CLONE_SIGHAND as u64) != 0;
1491 let clone_vfork = flags & (CLONE_VFORK as u64) != 0;
1492 let clone_newuts = flags & (CLONE_NEWUTS as u64) != 0;
1493 let clone_into_cgroup = flags & CLONE_INTO_CGROUP != 0;
1494 let clone_clear_sighand = flags & (CLONE_CLEAR_SIGHAND as u64) != 0;
1495
1496 if clone_ptrace {
1497 track_stub!(TODO("https://fxbug.dev/322874630"), "CLONE_PTRACE");
1498 }
1499
1500 if clone_sysvsem {
1501 track_stub!(TODO("https://fxbug.dev/322875185"), "CLONE_SYSVSEM");
1502 }
1503
1504 if clone_into_cgroup {
1505 track_stub!(TODO("https://fxbug.dev/403612570"), "CLONE_INTO_CGROUP");
1506 }
1507
1508 if clone_sighand && !clone_vm {
1509 return error!(EINVAL);
1510 }
1511 if clone_clear_sighand && clone_sighand {
1512 return error!(EINVAL);
1513 }
1514 if clone_thread && !clone_sighand {
1515 return error!(EINVAL);
1516 }
1517
1518 if clone_pidfd && clone_thread {
1519 return error!(EINVAL);
1520 }
1521 if clone_pidfd && clone_parent_settid && user_parent_tid.addr() == user_pidfd.addr() {
1522 return error!(EINVAL);
1525 }
1526
1527 if flags & !VALID_FLAGS != 0 {
1528 return error!(EINVAL);
1529 }
1530
1531 if clone_vm && !clone_thread {
1532 if !clone_vfork {
1543 track_stub!(
1544 TODO("https://fxbug.dev/322875227"),
1545 "CLONE_VM without CLONE_THREAD or CLONE_VFORK"
1546 );
1547 }
1548 } else if clone_thread && !clone_vm {
1549 track_stub!(TODO("https://fxbug.dev/322875167"), "CLONE_THREAD without CLONE_VM");
1550 return error!(ENOSYS);
1551 }
1552
1553 if flags & !IMPLEMENTED_FLAGS != 0 {
1554 track_stub!(
1555 TODO("https://fxbug.dev/322875130"),
1556 "clone unknown flags",
1557 flags & !IMPLEMENTED_FLAGS
1558 );
1559 return error!(ENOSYS);
1560 }
1561
1562 let fs = if clone_fs { self.fs() } else { self.fs().fork() };
1563 let files = if clone_files {
1564 self.running_state().files.clone()
1565 } else {
1566 self.running_state().files.fork()
1567 };
1568
1569 let kernel = self.kernel();
1570
1571 let mut pids = kernel.pids.write();
1572
1573 let mut cgroup2_pid_table = kernel.cgroups.lock_cgroup2_pid_table();
1577 let child_kernel_signals = cgroup2_pid_table
1579 .maybe_create_freeze_signal(self.thread_group())
1580 .into_iter()
1581 .collect::<VecDeque<_>>();
1582
1583 let pid;
1584 let command;
1585 let creds;
1586 let scheduler_state;
1587 let no_new_privs;
1588 let seccomp_filters;
1589 let robust_list_head = RobustListHeadPtr::null(self);
1590 let child_signal_mask;
1591 let timerslack_ns;
1592 let uts_ns;
1593
1594 let TaskInfo { thread_group, memory_manager } = {
1595 let weak_original_parent;
1598 let original_parent;
1599
1600 let thread_group_state = {
1602 let thread_group_state = self.thread_group().write();
1603 if clone_parent {
1604 weak_original_parent =
1607 thread_group_state.parent.clone().ok_or_else(|| errno!(EINVAL))?;
1608 std::mem::drop(thread_group_state);
1609 original_parent = weak_original_parent.upgrade();
1610 original_parent.write()
1611 } else {
1612 thread_group_state
1613 }
1614 };
1615
1616 let state = self.read();
1617
1618 no_new_privs = state.no_new_privs();
1619 seccomp_filters = state.seccomp_filters.clone();
1620 child_signal_mask = state.signal_mask();
1621
1622 pid = pids.allocate_pid();
1623 command = self.command();
1624 creds = self.current_creds().clone();
1625 scheduler_state = state.scheduler_state.fork();
1626 timerslack_ns = state.timerslack_ns;
1627
1628 uts_ns = if clone_newuts {
1629 security::check_task_capable(self, CAP_SYS_ADMIN)?;
1630 state.uts_ns.read().fork()
1631 } else {
1632 state.uts_ns.clone()
1633 };
1634
1635 if clone_thread {
1636 TaskInfo {
1637 thread_group: self.thread_group().clone(),
1638 memory_manager: self.mm().ok(),
1639 }
1640 } else {
1641 std::mem::drop(state);
1645 let signal_actions = if clone_sighand {
1646 self.thread_group().signal_actions.clone()
1647 } else if clone_clear_sighand {
1648 let actions = self.thread_group().signal_actions.fork();
1649 actions.reset_for_exec();
1650 actions
1651 } else {
1652 self.thread_group().signal_actions.fork()
1653 };
1654 let process_group = thread_group_state.process_group.clone();
1655
1656 let task_info = {
1657 fuchsia_trace::duration!(CATEGORY_STARNIX, "create_zircon_process");
1658 create_zircon_process(
1659 locked,
1660 kernel,
1661 Some(thread_group_state),
1662 pid,
1663 child_exit_signal,
1664 process_group,
1665 signal_actions,
1666 command.clone(),
1667 )?
1668 };
1669
1670 cgroup2_pid_table.inherit_cgroup(self.thread_group(), &task_info.thread_group);
1671
1672 task_info
1673 }
1674 };
1675
1676 std::mem::drop(cgroup2_pid_table);
1681
1682 let vfork_event = if clone_vfork { Some(Arc::new(zx::Event::create())) } else { None };
1684
1685 let abstract_socket_namespace;
1688 let abstract_vsock_namespace;
1689 {
1690 let running_state = self.running_state();
1691 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
1692 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
1693 }
1694
1695 let mut child = TaskBuilder::new(Task::new(
1696 pid,
1697 command,
1698 thread_group,
1699 files,
1700 memory_manager,
1701 fs,
1702 creds,
1703 abstract_socket_namespace,
1704 abstract_vsock_namespace,
1705 child_signal_mask,
1706 child_kernel_signals,
1707 vfork_event,
1708 scheduler_state,
1709 uts_ns,
1710 no_new_privs,
1711 SeccompState::from(&self.seccomp_filter_state),
1712 seccomp_filters,
1713 robust_list_head,
1714 timerslack_ns,
1715 ));
1716
1717 release_on_error!(child, locked, {
1718 pids.add_task(Arc::clone(&child.task));
1722 std::mem::drop(pids);
1723
1724 #[cfg(any(test, debug_assertions))]
1728 {
1729 if !clone_thread {
1732 let _l1 = self.thread_group().read();
1733 let _token = starnix_sync::allow_subclass();
1737 let _l2 = child.thread_group().read();
1738 }
1739 }
1740
1741 if clone_thread {
1742 self.thread_group().add(Arc::clone(&child.task))?;
1743 } else {
1744 child.thread_group().add(Arc::clone(&child.task))?;
1745
1746 let (sigaltstack, signal_mask) = {
1752 let state = self.read();
1753 (state.sigaltstack(), state.signal_mask())
1754 };
1755 let mut child_state = child.write();
1756 child_state.set_sigaltstack(sigaltstack);
1757 child_state.set_signal_mask(signal_mask);
1758 }
1759
1760 if !clone_vm {
1761 assert!(!clone_thread);
1764 let child_mm = MemoryManager::snapshot_of(
1765 locked,
1766 &self.mm()?,
1767 child.thread_group.root_vmar.unowned(),
1768 self.thread_state.arch_width(),
1769 )?;
1770 child.running_state()?.mm.update(Some(child_mm));
1771 }
1772
1773 if clone_parent_settid {
1774 self.write_object(user_parent_tid, &child.tid)?;
1775 }
1776
1777 if clone_child_cleartid {
1778 child.write().clear_child_tid = user_child_tid;
1779 }
1780
1781 if clone_child_settid {
1782 child.write_object(user_child_tid, &child.tid)?;
1783 }
1784
1785 if clone_pidfd {
1786 let locked = locked.cast_locked::<TaskRelease>();
1787 let file = new_pidfd(
1788 locked,
1789 self,
1790 child.thread_group(),
1791 &*child.mm()?,
1792 OpenFlags::empty(),
1793 );
1794 let pidfd = self.add_file(locked, file, FdFlags::CLOEXEC)?;
1795 self.write_object(user_pidfd, &pidfd)?;
1796 }
1797
1798 if clone_vm && !clone_thread {
1802 let child_mm = MemoryManager::snapshot_of(
1803 locked,
1804 &self.mm()?,
1805 child.thread_group.root_vmar.unowned(),
1806 self.thread_state.arch_width(),
1807 )?;
1808 child.running_state()?.mm.update(Some(child_mm));
1809 }
1810
1811 child.thread_state = self.thread_state.snapshot::<HeapRegs>();
1812 Ok(())
1813 });
1814
1815 #[cfg(any(test, debug_assertions))]
1818 {
1819 let _l1 = child.thread_group().read();
1820 let _l2 = child.read();
1821 }
1822
1823 Ok(child)
1824 }
1825
1826 pub fn set_stopped_and_notify(&self, stopped: StopState, siginfo: Option<SignalInfo>) {
1829 let maybe_signal_info = {
1830 let mut state = self.write();
1831 state.copy_state_from(self);
1832 state.set_stopped(stopped, siginfo, Some(self), None);
1833 state.prepare_signal_info(stopped)
1834 };
1835
1836 if let Some((tracer, signal_info)) = maybe_signal_info {
1837 if let Some(tracer) = tracer.upgrade() {
1838 tracer.write().send_signal(signal_info);
1839 }
1840 }
1841
1842 if !stopped.is_in_progress() {
1843 let parent = self.thread_group().read().parent.clone();
1844 if let Some(parent) = parent {
1845 parent
1846 .upgrade()
1847 .write()
1848 .lifecycle_waiters
1849 .notify_value(ThreadGroupLifecycleWaitValue::ChildStatus);
1850 }
1851 }
1852 }
1853
1854 pub fn block_if_stopped(&mut self, locked: &mut Locked<Unlocked>) -> bool {
1861 if self.finalize_stop_state() {
1862 self.block_while_stopped(locked);
1863 true
1864 } else {
1865 false
1866 }
1867 }
1868
1869 fn finalize_stop_state(&mut self) -> bool {
1872 let stopped = self.load_stopped();
1873
1874 if !stopped.is_stopping_or_stopped() {
1875 let captured_state = self.write().take_captured_state();
1877 if let Some(captured) = captured_state {
1878 if captured.dirty {
1879 self.thread_state.replace_registers(&captured.thread_state);
1880 }
1881 }
1882 }
1883
1884 if self.thread_group().set_stopped(StopState::GroupStopped, None, true)
1887 == StopState::GroupStopped
1888 {
1889 let signal = self.thread_group().read().last_signal.clone();
1890 let event = Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0));
1892 self.write().set_stopped(StopState::GroupStopped, signal, Some(self), event);
1893 return true;
1894 }
1895
1896 if stopped.is_stopping_or_stopped() {
1898 if let Ok(stopped) = stopped.finalize() {
1899 self.set_stopped_and_notify(stopped, None);
1900 }
1901 return true;
1902 }
1903
1904 false
1905 }
1906
1907 fn block_while_stopped(&mut self, locked: &mut Locked<Unlocked>) {
1910 let waiter = Waiter::with_options(WaiterOptions::IGNORE_SIGNALS);
1911 loop {
1912 if self.is_exitted() {
1915 self.thread_group().set_stopped(StopState::ForceAwake, None, false);
1916 self.write().set_stopped(StopState::ForceAwake, None, Some(self), None);
1917 return;
1918 }
1919
1920 if self.wake_or_wait_until_unstopped_async(&waiter) {
1921 return;
1922 }
1923
1924 let _: Result<(), Errno> = waiter.wait(locked, self);
1926
1927 self.finalize_stop_state();
1930 }
1931 }
1932
1933 pub fn get_ptrace_core_state_for_clone(
1936 &mut self,
1937 clone_args: &clone_args,
1938 ) -> (PtraceOptions, Option<PtraceCoreState>) {
1939 let state = self.write();
1940 if let Some(ptrace) = &state.ptrace {
1941 ptrace.get_core_state_for_clone(clone_args)
1942 } else {
1943 (PtraceOptions::empty(), None)
1944 }
1945 }
1946
1947 pub fn ptrace_event(
1955 &mut self,
1956 locked: &mut Locked<Unlocked>,
1957 trace_kind: PtraceOptions,
1958 msg: u64,
1959 ) {
1960 if !trace_kind.is_empty() {
1961 {
1962 let mut state = self.write();
1963 if let Some(ptrace) = &mut state.ptrace {
1964 if !ptrace.has_option(trace_kind) {
1965 if trace_kind == PtraceOptions::TRACEEXEC && !ptrace.is_seized() {
1968 send_signal_first(locked, self, state, SignalInfo::kernel(SIGTRAP));
1970 }
1971
1972 return;
1973 }
1974 let ptrace_event = PtraceEvent::from_option(&trace_kind) as u32;
1975 let siginfo = SignalInfo::with_detail(
1976 SIGTRAP,
1977 ((ptrace_event << 8) | SIGTRAP.number()) as i32,
1978 SignalDetail::None,
1979 );
1980 state.set_stopped(
1981 StopState::PtraceEventStopping,
1982 Some(siginfo),
1983 None,
1984 Some(PtraceEventData::new(trace_kind, msg)),
1985 );
1986 } else {
1987 return;
1988 }
1989 }
1990 self.block_if_stopped(locked);
1991 }
1992 }
1993
1994 pub fn kill_thread_group(&mut self, locked: &mut Locked<Unlocked>, exit_status: ExitStatus) {
1997 self.ptrace_event(
1998 locked,
1999 PtraceOptions::TRACEEXIT,
2000 exit_status.signal_info_status() as u64,
2001 );
2002 self.thread_group().kill(locked, exit_status, None);
2003 }
2004
2005 pub fn clone_task_builder_for_test<L>(
2008 &self,
2009 locked: &mut Locked<L>,
2010 flags: u64,
2011 exit_signal: Option<Signal>,
2012 ) -> TaskBuilder
2013 where
2014 L: LockBefore<MmDumpable>,
2015 L: LockBefore<TaskRelease>,
2016 L: LockBefore<ProcessGroupState>,
2017 {
2018 let result = self
2019 .clone_task(
2020 locked,
2021 flags,
2022 exit_signal,
2023 UserRef::default(),
2024 UserRef::default(),
2025 UserRef::default(),
2026 )
2027 .expect("failed to create task in test");
2028 result.task.write().set_spawned();
2029 result
2030 }
2031
2032 pub fn clone_task_for_test<L>(
2035 &self,
2036 locked: &mut Locked<L>,
2037 flags: u64,
2038 exit_signal: Option<Signal>,
2039 ) -> crate::testing::AutoReleasableTask
2040 where
2041 L: LockBefore<MmDumpable>,
2042 L: LockBefore<TaskRelease>,
2043 L: LockBefore<ProcessGroupState>,
2044 {
2045 self.clone_task_builder_for_test(locked, flags, exit_signal).into()
2046 }
2047
2048 pub fn check_ptrace_access_mode<L>(
2050 &self,
2051 locked: &mut Locked<L>,
2052 mode: PtraceAccessMode,
2053 target: &Task,
2054 ) -> Result<(), Errno>
2055 where
2056 L: LockBefore<MmDumpable>,
2057 {
2058 if self.thread_group().leader == target.thread_group().leader {
2061 return Ok(());
2062 }
2063
2064 let (uid, gid) = if mode.contains(PTRACE_MODE_FSCREDS) {
2076 let fscred = self.current_creds().as_fscred();
2077 (fscred.uid, fscred.gid)
2078 } else if mode.contains(PTRACE_MODE_REALCREDS) {
2079 let creds = self.current_creds();
2080 (creds.uid, creds.gid)
2081 } else {
2082 unreachable!();
2083 };
2084
2085 let target_creds = target.persistent_info.lock_creds();
2095 if !(target_creds.uid == uid
2096 && target_creds.euid == uid
2097 && target_creds.saved_uid == uid
2098 && target_creds.gid == gid
2099 && target_creds.egid == gid
2100 && target_creds.saved_gid == gid)
2101 {
2102 security::check_task_capable(self, CAP_SYS_PTRACE)?;
2103 }
2104
2105 let dumpable = *target.mm()?.dumpable.lock(locked);
2111 match dumpable {
2112 DumpPolicy::User => (),
2113 DumpPolicy::Disable => security::check_task_capable(self, CAP_SYS_PTRACE)?,
2114 }
2115
2116 security::ptrace_access_check(self, target, mode)?;
2119
2120 Ok(())
2123 }
2124
2125 pub fn can_signal(
2126 &self,
2127 target: &Task,
2128 unchecked_signal: UncheckedSignal,
2129 ) -> Result<(), Errno> {
2130 if self.thread_group == target.thread_group {
2133 return Ok(());
2134 }
2135
2136 let self_creds = self.current_creds();
2137 let target_creds = target.real_creds();
2138 if self_creds.euid == target_creds.saved_uid
2148 || self_creds.euid == target_creds.uid
2149 || self_creds.uid == target_creds.uid
2150 || self_creds.uid == target_creds.saved_uid
2151 {
2152 return Ok(());
2153 }
2154
2155 if Signal::try_from(unchecked_signal) == Ok(SIGCONT) {
2156 let target_session = target.thread_group().read().process_group.session.leader;
2157 let self_session = self.thread_group().read().process_group.session.leader;
2158 if target_session == self_session {
2159 return Ok(());
2160 }
2161 }
2162
2163 security::check_task_capable(self, CAP_KILL)
2164 }
2165}
2166
2167impl ArchSpecific for CurrentTask {
2168 fn is_arch32(&self) -> bool {
2169 self.thread_state.is_arch32()
2170 }
2171}
2172
2173impl MemoryAccessor for CurrentTask {
2174 fn read_memory<'a>(
2175 &self,
2176 addr: UserAddress,
2177 bytes: &'a mut [MaybeUninit<u8>],
2178 ) -> Result<&'a mut [u8], Errno> {
2179 self.mm()?.unified_read_memory(self, addr, bytes)
2180 }
2181
2182 fn read_memory_partial_until_null_byte<'a>(
2183 &self,
2184 addr: UserAddress,
2185 bytes: &'a mut [MaybeUninit<u8>],
2186 ) -> Result<&'a mut [u8], Errno> {
2187 self.mm()?.unified_read_memory_partial_until_null_byte(self, addr, bytes)
2188 }
2189
2190 fn read_memory_partial<'a>(
2191 &self,
2192 addr: UserAddress,
2193 bytes: &'a mut [MaybeUninit<u8>],
2194 ) -> Result<&'a mut [u8], Errno> {
2195 self.mm()?.unified_read_memory_partial(self, addr, bytes)
2196 }
2197
2198 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2199 self.mm()?.unified_write_memory(self, addr, bytes)
2200 }
2201
2202 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2203 self.mm()?.unified_write_memory_partial(self, addr, bytes)
2204 }
2205
2206 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
2207 self.mm()?.unified_zero(self, addr, length)
2208 }
2209}
2210
2211impl TaskMemoryAccessor for CurrentTask {
2212 fn maximum_valid_address(&self) -> Option<UserAddress> {
2213 self.mm().ok().map(|mm| mm.maximum_valid_user_address)
2214 }
2215}
2216
2217pub enum ExceptionResult {
2218 Handled,
2220
2221 Signal(SignalInfo),
2223}
2224
2225fn split_path(path: &FsStr) -> LookupVec<&FsStr> {
2226 path.split(|c| *c == b'/').filter(|p| !p.is_empty()).map(<&FsStr>::from).collect()
2227}
2228
2229#[cfg(test)]
2230mod tests {
2231 use crate::testing::spawn_kernel_and_run;
2232 use starnix_uapi::auth::Credentials;
2233
2234 #[::fuchsia::test]
2237 async fn test_override_creds_can_delegate_to_async_version() {
2238 spawn_kernel_and_run(async move |_, current_task| {
2239 assert_eq!(current_task.override_creds(Credentials::root(), || 0), 0);
2240 })
2241 .await;
2242 }
2243}