Skip to main content

starnix_core/task/
current_task.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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::{
12    ResolvedProgram, load_executable, resolve_elf_interpreter, resolve_executable,
13};
14use crate::task::{
15    CurrentTaskCredentialsWriteGuard, ExitStatus, PageFaultExceptionReport, RobustListHeadPtr,
16    RunState, SeccompFilter, SeccompFilterContainer, SeccompState, SeccompStateValue, Task,
17    TaskRunningState, ThreadState, Waiter,
18};
19use crate::vfs::{
20    AccessCheck, CreationStatus, DirEntry, DirectoryMode, FdFlags, FdNumber, FdTable, FileHandle,
21    FileMapping, FileWriteGuardMode, FsContext, FsStr, LookupContext, LookupVec,
22    MAX_SYMLINK_FOLLOWS, NamespaceNode, OpenAccessCheck, ResolveBase, SymlinkMode, SymlinkTarget,
23    new_pidfd,
24};
25use futures::FutureExt;
26use linux_uapi::CLONE_PIDFD;
27use starnix_logging::{CATEGORY_STARNIX, log_error, log_warn, track_file_not_found, track_stub};
28use starnix_registers::{HeapRegs, RegisterStorageEnum};
29use starnix_sync::{EventWaitGuard, UninterruptibleLock, WakeReason, assert_lock_level};
30use starnix_syscalls::SyscallResult;
31use starnix_syscalls::decls::Syscall;
32use starnix_task_command::TaskCommand;
33use starnix_types::futex_address::FutexAddress;
34use starnix_types::ownership::{Releasable, release_on_error};
35use starnix_uapi::auth::{
36    CAP_KILL, CAP_SYS_ADMIN, Credentials, FsCred, PTRACE_MODE_FSCREDS, PTRACE_MODE_REALCREDS,
37    PtraceAccessMode,
38};
39use starnix_uapi::device_id::DeviceId;
40use starnix_uapi::errors::Errno;
41use starnix_uapi::file_mode::{Access, FileMode};
42use starnix_uapi::open_flags::OpenFlags;
43use starnix_uapi::signals::{
44    SIGCHLD, SIGCONT, SIGILL, SIGKILL, SIGSEGV, SIGSYS, SIGTRAP, SigSet, Signal, UncheckedSignal,
45};
46use starnix_uapi::user_address::{ArchSpecific, UserAddress, UserRef};
47use starnix_uapi::vfs::ResolveFlags;
48use starnix_uapi::{
49    CLONE_CHILD_CLEARTID, CLONE_CHILD_SETTID, CLONE_CLEAR_SIGHAND, CLONE_FILES, CLONE_FS,
50    CLONE_INTO_CGROUP, CLONE_NEWUTS, CLONE_PARENT, CLONE_PARENT_SETTID, CLONE_PTRACE, CLONE_SETTLS,
51    CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_THREAD, CLONE_VFORK, CLONE_VM, FUTEX_OWNER_DIED,
52    FUTEX_TID_MASK, ROBUST_LIST_LIMIT, SECCOMP_FILTER_FLAG_LOG, SECCOMP_FILTER_FLAG_NEW_LISTENER,
53    SECCOMP_FILTER_FLAG_TSYNC, SECCOMP_FILTER_FLAG_TSYNC_ESRCH, clone_args, errno, error, pid_t,
54    sock_filter, ucred,
55};
56use std::cell::{Ref, RefCell};
57use std::collections::VecDeque;
58use std::ffi::CString;
59use std::fmt;
60use std::marker::PhantomData;
61use std::mem::MaybeUninit;
62use std::sync::{Arc, Weak};
63use zx::sys::zx_restricted_state_t;
64
65use super::ThreadGroupLifecycleWaitValue;
66
67pub struct TaskBuilder {
68    /// The underlying task object.
69    pub task: Arc<Task>,
70
71    pub thread_state: ThreadState<HeapRegs>,
72}
73
74impl TaskBuilder {
75    pub fn new(task: Arc<Task>) -> Self {
76        Self { task, thread_state: Default::default() }
77    }
78
79    #[inline(always)]
80    pub fn release(self, _context: ()) {
81        Releasable::release(self, ());
82    }
83}
84
85impl From<TaskBuilder> for CurrentTask {
86    fn from(builder: TaskBuilder) -> Self {
87        Self::new(builder.task, builder.thread_state.into())
88    }
89}
90
91impl Releasable for TaskBuilder {
92    type Context<'a> = ();
93
94    fn release<'a>(self, _context: Self::Context<'a>) {
95        // Build a temporary CurrentTask to run release actions that require ThreadState.
96        let current_task = CurrentTask::new(self.task, self.thread_state.into());
97        current_task.exit();
98    }
99}
100
101impl std::ops::Deref for TaskBuilder {
102    type Target = Task;
103    fn deref(&self) -> &Self::Target {
104        &self.task
105    }
106}
107
108/// The task object associated with the currently executing thread.
109///
110/// We often pass the `CurrentTask` as the first argument to functions if those functions need to
111/// know contextual information about the thread on which they are running. For example, we often
112/// use the `CurrentTask` to perform access checks, which ensures that the caller is authorized to
113/// perform the requested operation.
114///
115/// The `CurrentTask` also has state that can be referenced only on the currently executing thread,
116/// such as the register state for that thread. Syscalls are given a mutable references to the
117/// `CurrentTask`, which lets them manipulate this state.
118///
119/// See also `Task` for more information about tasks.
120pub struct CurrentTask {
121    /// The underlying task object.
122    pub task: Arc<Task>,
123
124    pub thread_state: ThreadState<RegisterStorageEnum>,
125
126    /// The cached running state of the task.
127    ///
128    /// Extracting `TaskRunningState` from a generic `Task` requires acquiring an RCU read lock.
129    /// While this is a relatively inexpensive operation, it is unnecessary in most cases because
130    /// `CurrentTask` always corresponds to a running `Task`, and every running `Task` has a
131    /// `TaskRunningState`. As such, the `CurrentTask` can safely cache a reference to its
132    /// `TaskRunningState`. This reference will only be invalidated during task exit.
133    pub running_state: Option<Arc<TaskRunningState>>,
134
135    /// The cached file descriptor table of the task.
136    ///
137    /// Extracting `FdTable` from a generic `Task` is a heavy operation with multiple levels of
138    /// synchronization and reference counting. However, because `CurrentTask` always corresponds to
139    /// a running `Task`, and every running `Task` has an `FdTable`, the `CurrentTask` can safely
140    /// cache a reference to its `FdTable`.
141    pub files: RefCell<Option<Arc<FdTable>>>,
142
143    /// The current subjective credentials of the task.
144    // TODO(https://fxbug.dev/433548348): Avoid interior mutability here by passing a
145    // &mut CurrentTask around instead of &CurrentTask.
146    pub current_creds: RefCell<CurrentCreds>,
147
148    pub security_state: security::CurrentTaskState,
149
150    /// Makes CurrentTask neither Sync not Send.
151    _local_marker: PhantomData<*mut u8>,
152}
153
154/// Represents the current state of the task's subjective credentials.
155pub enum CurrentCreds {
156    /// The task does not have overridden credentials, the subjective creds are identical to the
157    /// objective creds stored in the Task. Since credentials are often accessed from the current
158    /// task, we hold a reference here that does not necessitate going through the RCU machinery to
159    /// read.
160    Cached(Arc<Credentials>),
161    /// The task has overridden subjective credentials.
162    Overridden(Arc<Credentials>),
163}
164
165impl CurrentCreds {
166    fn creds(&self) -> &Arc<Credentials> {
167        match self {
168            CurrentCreds::Cached(creds) => creds,
169            CurrentCreds::Overridden(creds) => creds,
170        }
171    }
172}
173
174impl Releasable for CurrentTask {
175    type Context<'a> = ();
176
177    fn release<'a>(self, _context: Self::Context<'a>) {
178        self.exit();
179    }
180}
181
182impl std::ops::Deref for CurrentTask {
183    type Target = Task;
184    fn deref(&self) -> &Self::Target {
185        &self.task
186    }
187}
188
189impl fmt::Debug for CurrentTask {
190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191        self.task.fmt(f)
192    }
193}
194
195impl CurrentTask {
196    pub fn new(task: Arc<Task>, thread_state: ThreadState<RegisterStorageEnum>) -> Self {
197        let current_creds = RefCell::new(CurrentCreds::Cached(task.clone_creds()));
198        let running_state = task.running_state().expect("CurrentTask must have TaskRunningState");
199        let files = running_state.files().expect("CurrentTask must have FdTable");
200        Self {
201            task,
202            thread_state,
203            running_state: Some(running_state),
204            files: RefCell::new(Some(files)),
205            current_creds,
206            security_state: Default::default(),
207            _local_marker: Default::default(),
208        }
209    }
210
211    /// Exit the task by dropping its running state.
212    pub fn exit(mut self) {
213        // When this method returns, the following invariants must be met:
214        // 1. No new references to running `Task` state must be obtainable.
215        // 2. All externally-visible `Task` state must reflect that the `Task` has exited.
216        // 3. All observers of `Task` exit events must be notified.
217
218        self.notify_robust_list();
219        let _ignored = self.clear_child_tid_if_needed();
220
221        self.signal_vfork();
222
223        // Release references to resources specific to the running task before triggering its
224        // delayed releaser for the last time. This schedules any RCU-guarded references retained
225        // solely by this task for RCU reclamation. Triggering the delayed releaser runs RCU
226        // callbacks, ensuring that:
227        //
228        // 1. Any delayed release actions registered by the resource being dropped during
229        //    reclamation are applied during the final delayed releaser trigger.
230        // 2. Any other drop side-effects happen before the thread group sends zombie notifications.
231        //
232        // Specifically, the following resources require explicit release:
233        //
234        // 1. `running_state`: Transitively releases `proc_pid_directory_cache`
235        // 2. `files`: Drops `FileHandle` to close open file descriptors
236        // 3. `mm`: Drops `FsNodeHandle` to remove memory-mapped filesystem nodes and drops
237        //    `FileWriteGuard` for executable mappings
238        // 4. `fs`: Drops `MountClientMarker` to allow unmounting and drops `FsNodeHandle` to remove
239        //    namespace filesystem nodes
240        // 5. `proc_pid_directory_cache`: Drops `FsNodeHandle` to remove /proc/<pid> nodes
241        //
242        // `files`, `mm` and `fs` are released explicitly here rather than by dropping
243        // `running_state`. Other threads may transiently hold a strong reference to
244        // `TaskRunningState` (e.g. `Task::interrupt()`), and if such a thread ends up dropping the
245        // last reference, it runs the destructors of everything still owned by the
246        // `TaskRunningState`, possibly while holding locks. Dropping `fs` in particular may tear
247        // down an entire mount namespace, which acquires `DirEntry` locks, so it must happen here
248        // on the exiting thread, where no locks are held. `proc_pid_directory_cache` only holds an
249        // `FsNodeHandle`, whose release is already deferred to the delayed releaser.
250
251        if let Some(running_state) = self.running_state.take() {
252            *running_state.files.lock() = None;
253            running_state.mm.update(None);
254            running_state.fs.update(None);
255        }
256
257        *self.files.borrow_mut() = None;
258        self.task.running_state.update(None);
259
260        self.trigger_delayed_releaser();
261
262        // We remove from the thread group here because the Weak in the pid
263        // table to this task must be valid until this task is removed from the
264        // thread group, and the code below will invalidate it.
265        // Moreover, this requires an Arc of the task to ensure the tasks of
266        // the thread group are always valid.
267        self.task.thread_group().remove(self.kernel().pids.lock(), &self.task);
268
269        self.ptrace_disconnect();
270    }
271
272    /// Returns the [`TaskRunningState`] for the [`Task`].
273    ///
274    /// # Panics
275    ///
276    /// Calling `running_state()` on a [`CurrentTask`] for which the [`Task`] has no running state
277    /// (i.e. exited tasks) panics. However, such tasks should not have a [`CurrentTask`].
278    ///
279    /// This is primarily a risk in delayed release actions, which receive `&CurrentTask` when its
280    /// delayed releaser is triggered for the final time. At that point the task is mid-exit and its
281    /// [`TaskRunningState`] has been dropped. As such, delayed releases must not use the following
282    /// accessors:
283    ///
284    /// - [`Self::running_state()`]
285    /// - [`Self::files()`]
286    /// - [`Self::fs()`]
287    ///
288    /// If access to [`TaskRunningState`] is required in a delayed release action, use
289    /// [`Task::running_state()`] or an equivalent fallible accessor.
290    #[track_caller]
291    pub fn running_state(&self) -> &Arc<TaskRunningState> {
292        self.running_state.as_ref().expect("CurrentTask must have TaskRunningState")
293    }
294
295    /// Returns the [`FdTable`] for the [`Task`].
296    ///
297    /// # Panics
298    ///
299    /// Calling `files()` on a [`CurrentTask`] for which the [`Task`] has no file descriptor table
300    /// (i.e. exited tasks) panics. However, such tasks should not have a `CurrentTask`.
301    #[track_caller]
302    pub fn files(&self) -> Arc<FdTable> {
303        self.files.borrow().as_ref().expect("CurrentTask must have FdTable").clone()
304    }
305
306    /// Returns the [`FsContext`] for the [`Task`].
307    ///
308    /// # Panics
309    ///
310    /// Calling `fs()` on a [`CurrentTask`] for which the [`Task`] has no file system context
311    /// (i.e. exited tasks) panics. However, such tasks should not have a `CurrentTask`.
312    #[track_caller]
313    pub fn fs(&self) -> Arc<FsContext> {
314        self.running_state().fs().expect("CurrentTask must have FsContext")
315    }
316
317    pub fn has_shared_fs(&self) -> bool {
318        let fs = self.fs();
319        // This check is incorrect because someone else could be holding a temporary Arc to the
320        // FsContext and therefore increasing the strong count.
321        Arc::strong_count(&fs) > 2usize
322    }
323
324    pub fn unshare_fs(&self) {
325        let new_fs = self.fs().fork();
326        self.running_state().fs.update(new_fs);
327    }
328
329    /// Returns the current subjective credentials of the task.
330    ///
331    /// The subjective credentials are the credentials that are used to check permissions for
332    /// actions performed by the task.
333    pub fn current_creds(&self) -> Ref<'_, Arc<Credentials>> {
334        Ref::map(self.current_creds.borrow(), CurrentCreds::creds)
335    }
336
337    pub fn current_fscred(&self) -> FsCred {
338        self.current_creds().as_fscred()
339    }
340
341    pub fn current_ucred(&self) -> ucred {
342        let creds = self.current_creds();
343        ucred { pid: self.get_pid(), uid: creds.uid, gid: creds.gid }
344    }
345
346    /// Save the current creds and security state, alter them by calling `alter_creds`, then call
347    /// `callback`.
348    /// The creds and security state will be restored to their original values at the end of the
349    /// call. Only the "subjective" state of the CurrentTask, accessed with `current_creds()` and
350    ///  used to check permissions for actions performed by the task, is altered. The "objective"
351    ///  state, accessed through `Task::real_creds()` by other tasks and used to check permissions
352    /// for actions performed on the task, is not altered, and changes to the credentials are not
353    /// externally visible.
354    pub async fn override_creds_async<R>(
355        &self,
356        new_creds: Arc<Credentials>,
357        callback: impl AsyncFnOnce() -> R,
358    ) -> R {
359        let saved = self.current_creds.replace(CurrentCreds::Overridden(new_creds));
360        let result = callback().await;
361        self.current_creds.replace(saved);
362        result
363    }
364
365    /// Save the current creds and security state, alter them by calling `alter_creds`, then call
366    /// `callback`.
367    /// The creds and security state will be restored to their original values at the end of the
368    /// call. Only the "subjective" state of the CurrentTask, accessed with `current_creds()` and
369    ///  used to check permissions for actions performed by the task, is altered. The "objective"
370    ///  state, accessed through `Task::real_creds()` by other tasks and used to check permissions
371    /// for actions performed on the task, is not altered, and changes to the credentials are not
372    /// externally visible.
373    pub fn override_creds<R>(
374        &self,
375        new_creds: Arc<Credentials>,
376        callback: impl FnOnce() -> R,
377    ) -> R {
378        self.override_creds_async(new_creds, async move || callback())
379            .now_or_never()
380            .expect("Future should be ready")
381    }
382
383    pub fn has_overridden_creds(&self) -> bool {
384        matches!(*self.current_creds.borrow(), CurrentCreds::Overridden(_))
385    }
386
387    pub fn trigger_delayed_releaser(&self) {
388        self.kernel().delayed_releaser.apply(self);
389    }
390
391    pub fn weak_task(&self) -> Weak<Task> {
392        Arc::downgrade(&self.task)
393    }
394
395    /// Locks the `CurrentTask`'s credentials for writing, allowing readers to coordinate by using
396    /// `Task::lock_creds()` where necessary.  e.g. This is used to avoid ptrace attachment racing
397    /// with critical security checks affecting the task's `Credentials` during `exec()`.
398    pub fn write_creds(&self) -> CurrentTaskCredentialsWriteGuard {
399        assert!(!self.has_overridden_creds());
400        self.persistent_info.write_current_task_creds()
401    }
402
403    /// Change the current and real creds of the task. This is invalid to call while temporary
404    /// credentials are present.
405    pub fn set_creds(&self, creds: Credentials) {
406        // From <https://man7.org/linux/man-pages/man2/PR_SET_PDEATHSIG.2const.html>:
407        //
408        //   The parent-death signal setting is also cleared upon changes
409        //   to any of the following thread credentials: effective user ID,
410        //   effective group ID, filesystem user ID, or filesystem group ID.
411        let prev = self.current_creds();
412        let clear_parent_death_signal = creds.euid != prev.euid
413            || creds.egid != prev.egid
414            || creds.fsuid != prev.fsuid
415            || creds.fsgid != prev.fsgid;
416        std::mem::drop(prev);
417
418        if clear_parent_death_signal {
419            self.thread_group().write().set_parent_death_signal(None);
420        }
421
422        let creds = Arc::new(creds);
423        self.write_creds().update(self, creds);
424    }
425
426    #[inline(always)]
427    pub fn release(self, _context: ()) {
428        Releasable::release(self, ());
429    }
430
431    pub fn set_syscall_restart_func<R: Into<SyscallResult>>(
432        &mut self,
433        f: impl FnOnce(&mut CurrentTask) -> Result<R, Errno> + Send + Sync + 'static,
434    ) {
435        self.thread_state.syscall_restart_func =
436            Some(Box::new(|current_task| Ok(f(current_task)?.into())));
437    }
438
439    pub fn add_file(&self, file: FileHandle, flags: FdFlags) -> Result<FdNumber, Errno> {
440        self.files().add(self, file, flags)
441    }
442
443    /// Sets the task's signal mask to `signal_mask` and runs `wait_function`.
444    ///
445    /// Signals are dequeued prior to the original signal mask being restored. This is done by the
446    /// signal machinery in the syscall dispatch loop.
447    ///
448    /// The returned result is the result returned from the wait function.
449    pub fn wait_with_temporary_mask<F, T>(
450        &mut self,
451        signal_mask: SigSet,
452        wait_function: F,
453    ) -> Result<T, Errno>
454    where
455        F: FnOnce(&CurrentTask) -> Result<T, Errno>,
456    {
457        self.write().set_temporary_signal_mask(signal_mask);
458        wait_function(self)
459    }
460
461    /// If waking, promotes from waking to awake.  If not waking, make waiter async
462    /// wait until woken.  Returns true if woken.
463    pub fn wake_or_wait_until_unstopped_async(&self, waiter: &Waiter) -> bool {
464        let group_state = self.thread_group().read();
465        let mut task_state = self.write();
466
467        // Wake up if
468        //   a) we should wake up, meaning:
469        //      i) we're in group stop, and the thread group has exited group stop, or
470        //      ii) we're waking up,
471        //   b) and ptrace isn't stopping us from waking up, but
472        //   c) always wake up if we got a SIGKILL.
473        let task_stop_state = self.load_stopped();
474        let group_stop_state = self.thread_group().load_stopped();
475        if ((task_stop_state == StopState::GroupStopped && group_stop_state.is_waking_or_awake())
476            || task_stop_state.is_waking_or_awake())
477            && (!task_state.is_ptrace_listening() || task_stop_state.is_force())
478        {
479            let new_state = if task_stop_state.is_waking_or_awake() {
480                task_stop_state.finalize()
481            } else {
482                group_stop_state.finalize()
483            };
484            if let Ok(new_state) = new_state {
485                task_state.set_stopped(new_state, None, Some(self), None);
486                drop(group_state);
487                drop(task_state);
488                // It is possible for the stop state to be changed by another
489                // thread between when it is checked above and the following
490                // invocation, but set_stopped does sufficient checking while
491                // holding the lock to make sure that such a change won't result
492                // in corrupted state.
493                self.thread_group().set_stopped(new_state, None, false);
494                return true;
495            }
496        }
497
498        // We will wait.
499        if self.thread_group().load_stopped().is_stopped() || task_stop_state.is_stopped() {
500            // If we've stopped or PTRACE_LISTEN has been sent, wait for a
501            // signal or instructions from the tracer.
502            group_state
503                .lifecycle_waiters
504                .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::Stopped);
505            task_state.wait_on_ptracer(&waiter);
506        } else if task_state.can_accept_ptrace_commands() {
507            // If we're stopped because a tracer has seen the stop and not taken
508            // further action, wait for further instructions from the tracer.
509            task_state.wait_on_ptracer(&waiter);
510        } else if task_state.is_ptrace_listening() {
511            // A PTRACE_LISTEN is a state where we can get signals and notify a
512            // ptracer, but otherwise remain blocked.
513            if let Some(ptrace) = &mut task_state.ptrace {
514                ptrace.set_last_signal(Some(SignalInfo::kernel(SIGTRAP)));
515                ptrace.set_last_event(Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0)));
516            }
517            task_state.wait_on_ptracer(&waiter);
518            task_state.notify_ptracers();
519        }
520        false
521    }
522
523    /// Returns whether a deliverable signal or a task/thread-group stop is pending for this task.
524    pub fn is_interrupt_pending(&self) -> bool {
525        self.read().is_interrupt_pending()
526    }
527
528    /// Set the RunState for the current task to the given value and then call the given callback.
529    ///
530    /// When the callback is done, the run_state is restored to `RunState::Running`.
531    ///
532    /// This function is typically used just before blocking the current task on some operation.
533    /// The given `run_state` registers the mechanism for interrupting the blocking operation with
534    /// the task and the given `callback` actually blocks the task.
535    ///
536    /// This function can only be called in the `RunState::Running` state and cannot set the
537    /// run state to `RunState::Running`. For this reason, this function cannot be reentered.
538    pub fn run_in_state<F, T>(&self, run_state: RunState, callback: F) -> Result<T, Errno>
539    where
540        F: FnOnce() -> Result<T, Errno>,
541    {
542        assert_ne!(run_state, RunState::Running);
543
544        // Check we do not hold any uninterruptible lock
545        assert_lock_level::<UninterruptibleLock>();
546
547        {
548            let mut state = self.write();
549            assert!(!state.is_blocked());
550
551            // `SIGKILL` and `ThreadGroup::kill` mark tasks `EXITED` synchronously without queueing
552            // a per-task signal, so check `is_exitted()` before blocking.
553            if self.is_exitted() {
554                return error!(EINTR);
555            }
556            if run_state.ignores_signals() {
557                // Tasks frozen or stopped ignore all other signals except SIGKILL.
558                if state.has_signal_pending(SIGKILL) {
559                    return error!(EINTR);
560                }
561            } else if state.is_interrupt_pending() {
562                return error!(EINTR);
563            }
564            state.set_run_state(run_state.clone());
565        }
566
567        let _waiting_guard = crate::task::ThreadLockupDetector::pause_tracking();
568        let result = callback();
569
570        {
571            let mut state = self.write();
572            assert_eq!(
573                state.run_state(),
574                run_state,
575                "SignalState run state changed while waiting!"
576            );
577            state.set_run_state(RunState::Running);
578        };
579
580        result
581    }
582
583    pub fn block_until(
584        &self,
585        guard: EventWaitGuard<'_>,
586        deadline: zx::MonotonicInstant,
587    ) -> Result<(), Errno> {
588        self.block_with_optional_owner_until(guard, None, deadline)
589    }
590
591    pub fn block_with_owner_until(
592        &self,
593        guard: EventWaitGuard<'_>,
594        new_owner: &zx::Thread,
595        deadline: zx::MonotonicInstant,
596    ) -> Result<(), Errno> {
597        self.block_with_optional_owner_until(guard, Some(new_owner), deadline)
598    }
599
600    pub fn block_with_optional_owner_until(
601        &self,
602        guard: EventWaitGuard<'_>,
603        new_owner: Option<&zx::Thread>,
604        deadline: zx::MonotonicInstant,
605    ) -> Result<(), Errno> {
606        self.run_in_state(RunState::Event(guard.event().clone()), move || {
607            guard.block_until(new_owner, deadline).map_err(|e| match e {
608                WakeReason::Interrupted => errno!(EINTR),
609                WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
610            })
611        })
612    }
613
614    /// Determine namespace node indicated by the dir_fd.
615    ///
616    /// Returns the namespace node and the path to use relative to that node.
617    pub fn resolve_dir_fd<'a>(
618        &self,
619        dir_fd: FdNumber,
620        mut path: &'a FsStr,
621        flags: ResolveFlags,
622    ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
623        let path_is_absolute = path.starts_with(b"/");
624        if path_is_absolute {
625            if flags.contains(ResolveFlags::BENEATH) {
626                return error!(EXDEV);
627            }
628            path = &path[1..];
629        }
630
631        let dir = if path_is_absolute && !flags.contains(ResolveFlags::IN_ROOT) {
632            self.fs().root()
633        } else if dir_fd == FdNumber::AT_FDCWD {
634            self.fs().cwd()
635        } else {
636            // O_PATH allowed for:
637            //
638            //   Passing the file descriptor as the dirfd argument of
639            //   openat() and the other "*at()" system calls.  This
640            //   includes linkat(2) with AT_EMPTY_PATH (or via procfs
641            //   using AT_SYMLINK_FOLLOW) even if the file is not a
642            //   directory.
643            //
644            // See https://man7.org/linux/man-pages/man2/open.2.html
645            let file = self.files().get_allowing_opath(dir_fd)?;
646            file.name.to_passive()
647        };
648
649        if !path.is_empty() {
650            if !dir.entry.node.is_dir() {
651                return error!(ENOTDIR);
652            }
653            dir.check_access(self, AccessCheck::for_internal(Access::EXEC))?;
654        }
655        Ok((dir, path.into()))
656    }
657
658    /// A convenient wrapper for opening files relative to FdNumber::AT_FDCWD.
659    ///
660    /// Returns a FileHandle but does not install the FileHandle in the FdTable
661    /// for this task.
662    pub fn open_file(&self, path: &FsStr, flags: OpenFlags) -> Result<FileHandle, Errno> {
663        if flags.contains(OpenFlags::CREAT) {
664            // In order to support OpenFlags::CREAT we would need to take a
665            // FileMode argument.
666            return error!(EINVAL);
667        }
668        self.open_file_at(
669            FdNumber::AT_FDCWD,
670            path,
671            flags,
672            FileMode::default(),
673            ResolveFlags::empty(),
674        )
675    }
676
677    /// Opens an executable or interpreter file for binary execution.
678    ///
679    /// This method is intended for opening initial executables, script interpreters (`#!`),
680    /// and ELF dynamic linkers (`PT_INTERP`).
681    ///
682    /// Resolves the target [`NamespaceNode`] and verifies that it is a regular file before opening
683    /// it, avoiding unintended driver initialization on device nodes or blocking on FIFOs. Returns
684    /// [`EACCES`] if the target is not a regular file, or [`ELOOP`] if [`OpenFlags::NOFOLLOW`] was
685    /// specified and the target is a symbolic link.
686    ///
687    /// Opens the file for execution, verifying DAC execute permissions and filesystem mount
688    /// `MS_NOEXEC`.
689    ///
690    /// Returns an [`Arc<FileMapping>`] with an execution write guard.
691    pub fn open_file_for_exec(
692        &self,
693        dir_fd: FdNumber,
694        path: &FsStr,
695        flags: OpenFlags,
696    ) -> Result<Arc<FileMapping>, Errno> {
697        debug_assert!(
698            (flags & !(OpenFlags::RDONLY | OpenFlags::NOFOLLOW)).is_empty(),
699            "unexpected flags passed to open_file_for_exec: {flags:?}"
700        );
701        if !(flags & !(OpenFlags::RDONLY | OpenFlags::NOFOLLOW)).is_empty() {
702            return error!(EINVAL);
703        }
704
705        let (dir, path) = self.resolve_dir_fd(dir_fd, path, ResolveFlags::empty())?;
706        let nofollow = flags.contains(OpenFlags::NOFOLLOW);
707        let mut context =
708            LookupContext::new(if nofollow { SymlinkMode::NoFollow } else { SymlinkMode::Follow });
709        context.update_for_path(path);
710        let name = self.lookup_path(&mut context, dir, path)?;
711
712        // From <https://man7.org/linux/man-pages/man2/execveat.2.html>:
713        //
714        //   ELOOP  flags includes AT_SYMLINK_NOFOLLOW and the file identified by
715        //          dirfd and pathname is a symbolic link.
716        if nofollow && name.entry.node.info().mode.is_lnk() {
717            return error!(ELOOP);
718        }
719
720        // From <https://man7.org/linux/man-pages/man2/execve.2.html>:
721        //
722        //   EACCES The file or a script interpreter is not a regular file.
723        if !name.entry.node.is_reg() {
724            return error!(EACCES);
725        }
726
727        // From <https://man7.org/linux/man-pages/man2/execve.2.html>:
728        //
729        //   EACCES Execute permission is denied for the file or a script or ELF
730        //          interpreter.
731        //
732        //   EACCES The filesystem is mounted noexec.
733        let file = name.open(self, OpenAccessCheck::for_exec())?;
734        FileMapping::new(file, Some(FileWriteGuardMode::ExecMapping))
735    }
736
737    /// Resolves a path for open.
738    ///
739    /// If the final path component points to a symlink, the symlink is followed (as long as
740    /// the symlink traversal limit has not been reached).
741    ///
742    /// If the final path component (after following any symlinks, if enabled) does not exist,
743    /// and `flags` contains `OpenFlags::CREAT`, a new node is created at the location of the
744    /// final path component.
745    ///
746    /// This returns the resolved node, and a boolean indicating whether the node has been created.
747    fn resolve_open_path(
748        &self,
749        context: &mut LookupContext,
750        dir: &NamespaceNode,
751        path: &FsStr,
752        mode: FileMode,
753        flags: OpenFlags,
754    ) -> Result<(NamespaceNode, bool), Errno> {
755        context.update_for_path(path);
756        let mut parent_content = context.with(SymlinkMode::Follow, context.directory_mode);
757        let (parent, basename) = self.lookup_parent(&mut parent_content, dir, path)?;
758        context.remaining_follows = parent_content.remaining_follows;
759
760        let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
761
762        // Lookup the child, without following a symlink or expecting it to be a directory.
763        let mut child_context = context.with(SymlinkMode::NoFollow, DirectoryMode::AllowAny);
764
765        let child = if flags.contains(OpenFlags::CREAT)
766            && context.directory_mode != DirectoryMode::MustBeDirectory
767            && !DirEntry::is_reserved_name(basename)
768        {
769            // When creating, look up and create the child in a single step under the parent's
770            // children lock, like Linux's lookup_open(). A separate lookup first would just be
771            // repeated under the lock, which costs an extra round trip on remote filesystems.
772            let (child, status) = parent.open_create_node(
773                self,
774                basename,
775                mode.with_type(FileMode::IFREG),
776                DeviceId::NONE,
777            )?;
778            if status == CreationStatus::Created {
779                return Ok((child, true));
780            }
781            // The child already exists. Resolve the node that was found rather than looking it
782            // up again, which would revalidate it a second time. O_EXCL is only checked below,
783            // after mounts have been entered, so that RESOLVE_NO_XDEV takes precedence over
784            // EEXIST, as in Linux.
785            parent.resolve_child(self, &mut child_context, child)
786        } else {
787            parent.lookup_child(self, &mut child_context, basename)
788        };
789
790        match child {
791            Ok(name) => {
792                if name.entry.node.is_lnk() {
793                    if flags.contains(OpenFlags::PATH)
794                        && context.symlink_mode == SymlinkMode::NoFollow
795                    {
796                        // When O_PATH is specified in flags, if pathname is a symbolic link
797                        // and the O_NOFOLLOW flag is also specified, then the call returns
798                        // a file descriptor referring to the symbolic link.
799                        // See https://man7.org/linux/man-pages/man2/openat.2.html
800                        //
801                        // If the trailing component (i.e., basename) of
802                        // pathname is a symbolic link, how.resolve contains
803                        // RESOLVE_NO_SYMLINKS, and how.flags contains both
804                        // O_PATH and O_NOFOLLOW, then an O_PATH file
805                        // descriptor referencing the symbolic link will be
806                        // returned.
807                        // See https://man7.org/linux/man-pages/man2/openat2.2.html
808                        return Ok((name, false));
809                    }
810
811                    if (!flags.contains(OpenFlags::PATH)
812                        && context.symlink_mode == SymlinkMode::NoFollow)
813                        || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
814                        || context.remaining_follows == 0
815                    {
816                        if must_create {
817                            // Since `must_create` is set, and a node was found, this returns EEXIST
818                            // instead of ELOOP.
819                            return error!(EEXIST);
820                        }
821                        // A symlink was found, but one of the following is true:
822                        // * flags specified O_NOFOLLOW but not O_PATH.
823                        // * how.resolve contains RESOLVE_NO_SYMLINKS
824                        // * too many symlink traversals have been attempted
825                        return error!(ELOOP);
826                    }
827
828                    context.remaining_follows -= 1;
829                    match name.readlink(self)? {
830                        SymlinkTarget::Path(path) => {
831                            let dir = if path[0] == b'/' { self.fs().root() } else { parent };
832                            self.resolve_open_path(context, &dir, path.as_ref(), mode, flags)
833                        }
834                        SymlinkTarget::Node(name) => {
835                            if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS)
836                                || name.entry.node.is_lnk()
837                            {
838                                error!(ELOOP)
839                            } else {
840                                Ok((name, false))
841                            }
842                        }
843                    }
844                } else {
845                    if must_create {
846                        return error!(EEXIST);
847                    }
848                    Ok((name, false))
849                }
850            }
851            Err(e)
852                if e == errno!(ENOENT)
853                    && flags.contains(OpenFlags::CREAT)
854                    && context.directory_mode == DirectoryMode::MustBeDirectory =>
855            {
856                // A path that must be a directory is not created. Other children that did not
857                // exist were created above.
858                error!(EISDIR)
859            }
860            Err(e) => Err(e),
861        }
862    }
863
864    /// The primary entry point for opening files relative to a task.
865    ///
866    /// Absolute paths are resolve relative to the root of the FsContext for
867    /// this task. Relative paths are resolve relative to dir_fd. To resolve
868    /// relative to the current working directory, pass FdNumber::AT_FDCWD for
869    /// dir_fd.
870    ///
871    /// Returns a FileHandle but does not install the FileHandle in the FdTable
872    /// for this task.
873    pub fn open_file_at(
874        &self,
875        dir_fd: FdNumber,
876        path: &FsStr,
877        flags: impl Into<OpenAccessCheck>,
878        mode: FileMode,
879        resolve_flags: ResolveFlags,
880    ) -> Result<FileHandle, Errno> {
881        if path.is_empty() {
882            return error!(ENOENT);
883        }
884
885        let (dir, path) = self.resolve_dir_fd(dir_fd, path, resolve_flags)?;
886        self.open_namespace_node_at(dir, path, flags, mode, resolve_flags)
887    }
888
889    pub fn open_namespace_node_at(
890        &self,
891        dir: NamespaceNode,
892        path: &FsStr,
893        open_check: impl Into<OpenAccessCheck>,
894        mode: FileMode,
895        mut resolve_flags: ResolveFlags,
896    ) -> Result<FileHandle, Errno> {
897        let open_check = open_check.into();
898        // 64-bit kernels force the O_LARGEFILE flag to be on.
899        let mut flags = open_check.open_flags() | OpenFlags::LARGEFILE;
900        let opath = flags.contains(OpenFlags::PATH);
901        if opath {
902            // When O_PATH is specified in flags, flag bits other than O_CLOEXEC,
903            // O_DIRECTORY, and O_NOFOLLOW are ignored.
904            const ALLOWED_FLAGS: OpenFlags = OpenFlags::from_bits_truncate(
905                OpenFlags::PATH.bits()
906                    | OpenFlags::CLOEXEC.bits()
907                    | OpenFlags::DIRECTORY.bits()
908                    | OpenFlags::NOFOLLOW.bits(),
909            );
910            flags &= ALLOWED_FLAGS;
911        }
912
913        if flags.contains(OpenFlags::TMPFILE) && !flags.can_write() {
914            return error!(EINVAL);
915        }
916
917        let nofollow = flags.contains(OpenFlags::NOFOLLOW);
918        let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
919
920        let symlink_mode =
921            if nofollow || must_create { SymlinkMode::NoFollow } else { SymlinkMode::Follow };
922
923        let resolve_base = match (
924            resolve_flags.contains(ResolveFlags::BENEATH),
925            resolve_flags.contains(ResolveFlags::IN_ROOT),
926        ) {
927            (false, false) => ResolveBase::None,
928            (true, false) => ResolveBase::Beneath(dir.clone()),
929            (false, true) => ResolveBase::InRoot(dir.clone()),
930            (true, true) => return error!(EINVAL),
931        };
932
933        // `RESOLVE_BENEATH` and `RESOLVE_IN_ROOT` imply `RESOLVE_NO_MAGICLINKS`. This matches
934        // Linux behavior. Strictly speaking it's is not really required, but it's hard to
935        // implement `BENEATH` and `IN_ROOT` flags correctly otherwise.
936        if resolve_base != ResolveBase::None {
937            resolve_flags.insert(ResolveFlags::NO_MAGICLINKS);
938        }
939
940        let mut context = LookupContext {
941            symlink_mode,
942            remaining_follows: MAX_SYMLINK_FOLLOWS,
943            directory_mode: if flags.contains(OpenFlags::DIRECTORY) {
944                DirectoryMode::MustBeDirectory
945            } else {
946                DirectoryMode::AllowAny
947            },
948            resolve_flags,
949            resolve_base,
950        };
951        let (name, created) = match self.resolve_open_path(&mut context, &dir, path, mode, flags) {
952            Ok((n, c)) => (n, c),
953            Err(e) => {
954                let mut abs_path = dir.path(&self.fs());
955                abs_path.extend(&**path);
956                track_file_not_found(abs_path);
957                return Err(e);
958            }
959        };
960
961        let name = if flags.contains(OpenFlags::TMPFILE) {
962            // `O_TMPFILE` is incompatible with `O_CREAT`
963            if flags.contains(OpenFlags::CREAT) {
964                return error!(EINVAL);
965            }
966            name.create_tmpfile(self, mode.with_type(FileMode::IFREG), flags)?
967        } else {
968            let mode = name.entry.node.info().mode;
969
970            // These checks are not needed in the `O_TMPFILE` case because `mode` refers to the
971            // file we are opening. With `O_TMPFILE`, that file is the regular file we just
972            // created rather than the node we found by resolving the path.
973            //
974            // For example, we do not need to produce `ENOTDIR` when `must_be_directory` is set
975            // because `must_be_directory` refers to the node we found by resolving the path.
976            // If that node was not a directory, then `create_tmpfile` will produce an error.
977            //
978            // Similarly, we never need to call `truncate` because `O_TMPFILE` is newly created
979            // and therefor already an empty file.
980
981            if !opath && nofollow && mode.is_lnk() {
982                return error!(ELOOP);
983            }
984
985            if mode.is_dir() {
986                if flags.can_write()
987                    || flags.contains(OpenFlags::CREAT)
988                    || flags.contains(OpenFlags::TRUNC)
989                {
990                    return error!(EISDIR);
991                }
992                if flags.contains(OpenFlags::DIRECT) {
993                    return error!(EINVAL);
994                }
995            } else if context.directory_mode == DirectoryMode::MustBeDirectory {
996                return error!(ENOTDIR);
997            }
998
999            if flags.contains(OpenFlags::TRUNC) && mode.is_reg() && !created {
1000                // You might think we should check file.can_write() at this
1001                // point, which is what the docs suggest, but apparently we
1002                // are supposed to truncate the file if this task can write
1003                // to the underlying node, even if we are opening the file
1004                // as read-only. See OpenTest.CanTruncateReadOnly.
1005                name.truncate(self, 0)?;
1006            }
1007
1008            name
1009        };
1010
1011        // If the node has been created, the open operation should not verify access right:
1012        // From <https://man7.org/linux/man-pages/man2/open.2.html>
1013        //
1014        // > Note that mode applies only to future accesses of the newly created file; the
1015        // > open() call that creates a read-only file may well return a  read/write  file
1016        // > descriptor.
1017        let file = if created {
1018            name.open(self, OpenAccessCheck::skip(flags))?
1019        } else {
1020            name.open(self, OpenAccessCheck::new(flags, open_check.access_check()))?
1021        };
1022
1023        // If the new `FileHandle` represents an open file (rather than a handle to a location in
1024        // the virtual file system, as created with `O_PATH`), then LSM permission checks may be
1025        // required.
1026        if !opath {
1027            security::file_open(self, &file)?;
1028        }
1029
1030        Ok(file)
1031    }
1032
1033    /// A wrapper for FsContext::lookup_parent_at that resolves the given
1034    /// dir_fd to a NamespaceNode.
1035    ///
1036    /// Absolute paths are resolve relative to the root of the FsContext for
1037    /// this task. Relative paths are resolve relative to dir_fd. To resolve
1038    /// relative to the current working directory, pass FdNumber::AT_FDCWD for
1039    /// dir_fd.
1040    pub fn lookup_parent_at<'a>(
1041        &self,
1042        context: &mut LookupContext,
1043        dir_fd: FdNumber,
1044        path: &'a FsStr,
1045    ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
1046        let (dir, path) = self.resolve_dir_fd(dir_fd, path, ResolveFlags::empty())?;
1047        self.lookup_parent(context, &dir, path)
1048    }
1049
1050    /// Lookup the parent of a namespace node.
1051    ///
1052    /// Consider using Task::open_file_at or Task::lookup_parent_at rather than
1053    /// calling this function directly.
1054    ///
1055    /// This function resolves all but the last component of the given path.
1056    /// The function returns the parent directory of the last component as well
1057    /// as the last component.
1058    ///
1059    /// If path is empty, this function returns dir and an empty path.
1060    /// Similarly, if path ends with "." or "..", these components will be
1061    /// returned along with the parent.
1062    ///
1063    /// The returned parent might not be a directory.
1064    pub fn lookup_parent<'a>(
1065        &self,
1066        context: &mut LookupContext,
1067        dir: &NamespaceNode,
1068        path: &'a FsStr,
1069    ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
1070        context.update_for_path(path);
1071
1072        let components = split_path(path);
1073        if components.is_empty() {
1074            return Ok((dir.clone(), Default::default()));
1075        }
1076        let result = dir.lookup_children(self, context, &components[0..components.len() - 1])?;
1077        Ok((result, components.last().unwrap()))
1078    }
1079
1080    /// Lookup a namespace node.
1081    ///
1082    /// Consider using Task::open_file_at or Task::lookup_parent_at rather than
1083    /// calling this function directly.
1084    ///
1085    /// This function resolves the component of the given path.
1086    pub fn lookup_path(
1087        &self,
1088        context: &mut LookupContext,
1089        dir: NamespaceNode,
1090        path: &FsStr,
1091    ) -> Result<NamespaceNode, Errno> {
1092        let components = split_path(path);
1093        dir.lookup_children(self, context, &components)
1094    }
1095
1096    /// Lookup a namespace node starting at the root directory.
1097    ///
1098    /// Resolves symlinks.
1099    pub fn lookup_path_from_root(&self, path: &FsStr) -> Result<NamespaceNode, Errno> {
1100        let mut context = LookupContext::default();
1101        self.lookup_path(&mut context, self.fs().root(), path)
1102    }
1103
1104    pub fn exec(
1105        &mut self,
1106        executable: Arc<FileMapping>,
1107        path: CString,
1108        argv: Vec<CString>,
1109        environ: Vec<CString>,
1110    ) -> Result<(), Errno> {
1111        // Serialize against ptrace_attach by holding the credentials write lock.
1112        let writable_creds = self.write_creds();
1113
1114        // Evaluate LSM access checks and domain transitions (`bprm_creds_for_exec`) against the
1115        // initial executable before resolving `#!` scripts, so that script execution transitions
1116        // to the domain determined by the script file rather than its interpreter. Once `#!`
1117        // scripts are resolved to the target ELF binary, apply SUID/SGID and file capabilities
1118        // (`bprm_creds_from_file`) and validate `PT_INTERP` before committing the exec.
1119        let mut resolved_program = ResolvedProgram::new(self, executable, path, argv, environ);
1120        security::bprm_creds_for_exec(self, &mut resolved_program)?;
1121        resolve_executable(self, &mut resolved_program)?;
1122        security::bprm_creds_from_file(self, &mut resolved_program)?;
1123        resolve_elf_interpreter(self, &mut resolved_program)?;
1124
1125        if self.thread_group().read().tasks_count() > 1 {
1126            track_stub!(TODO("https://fxbug.dev/297434895"), "exec on multithread process");
1127            return error!(EINVAL);
1128        }
1129
1130        // Commit the exec. Failures after this point are unrecoverable.
1131        if let Err(err) = self.finish_exec(resolved_program, writable_creds) {
1132            log_warn!("unrecoverable error in exec: {err:?}");
1133
1134            send_standard_signal(self, SignalInfo::forced(SIGSEGV));
1135            return Err(err);
1136        }
1137
1138        self.ptrace_event(PtraceOptions::TRACEEXEC, self.task.tid.id as u64);
1139        self.signal_vfork();
1140        self.task.thread_group.sync_syscall_log_level();
1141
1142        Ok(())
1143    }
1144
1145    /// After the memory is unmapped, any failure in exec is unrecoverable and results in the
1146    /// process crashing. This function is for that second half; any error returned from this
1147    /// function will be considered unrecoverable.
1148    fn finish_exec(
1149        &mut self,
1150        resolved_program: ResolvedProgram,
1151        writable_creds: CurrentTaskCredentialsWriteGuard,
1152    ) -> Result<(), Errno> {
1153        let elf_arch_width = resolved_program.arch_width().ok_or_else(|| errno!(EINVAL))?;
1154
1155        // Now that the exec will definitely finish (or crash), notify owners of
1156        // locked futexes for the current process, which will be impossible to
1157        // update after process image is replaced.  See get_robust_list(2).
1158        self.notify_robust_list();
1159
1160        // Tear down the old address space and create a new one for the resolved ELF.
1161        let mm = {
1162            let new_mm = MemoryManager::exec(
1163                self.thread_group().root_vmar.unowned(),
1164                self.mm().ok(),
1165                resolved_program.file.name().to_passive(),
1166                elf_arch_width,
1167            )?;
1168            self.running_state().mm.update(Some(new_mm.clone()));
1169            new_mm
1170        };
1171        // From <https://man7.org/linux/man-pages/man2/execve.2.html>:
1172        //
1173        //   All threads other than the calling thread are destroyed during an
1174        //   execve(). Mutual exclusion locks, condition variables, and other
1175        //   pthreads objects are not preserved.
1176        //
1177        // TODO(https://fxbug.dev/42082680): Implement thread destruction.
1178
1179        // Filesystem context sharing (via CLONE_FS with clone(2)) is preserved across
1180        // execve under Linux, as verified by `CloneAndExecTest.ExecDoesNotUnshareCloneFs`.
1181
1182        // From <https://man7.org/linux/man-pages/man2/execve.2.html>:
1183        //
1184        //   If the calling process was sharing its file descriptor table (via
1185        //   the use of CLONE_FILES with clone(2)), then this sharing is undone.
1186        self.running_state().unshare_files(self);
1187        self.files().exec();
1188
1189        // From <https://man7.org/linux/man-pages/man2/PR_SET_PDEATHSIG.2const.html>:
1190        //
1191        //   It is also (since Linux 2.4.36 / 2.6.23) cleared when
1192        //   executing a set-user-ID or set-group-ID binary, or a binary that
1193        //   has associated capabilities (see capabilities(7)); otherwise, this
1194        //   value is preserved across execve(2).
1195        if resolved_program.secure_exec {
1196            self.thread_group().write().set_parent_death_signal(None);
1197        }
1198
1199        {
1200            let mut state = self.write();
1201
1202            // From <https://man7.org/linux/man-pages/man2/execve.2.html>:
1203            //
1204            //   The process's "dumpable" attribute is set to the value 1,
1205            //   unless a set-user-ID program, a set-group-ID program, or a
1206            //   program with capabilities is being executed, in which case the
1207            //   dumpable flag may instead be reset to the value in
1208            //   /proc/sys/fs/suid_dumpable, in the circumstances described
1209            //   under PR_SET_DUMPABLE in prctl(2).
1210            let dumpable =
1211                if resolved_program.secure_exec { DumpPolicy::Disable } else { DumpPolicy::User };
1212            mm.dumpable.store(dumpable);
1213
1214            state.set_sigaltstack(None);
1215            state.robust_list_head = RobustListHeadPtr::null(self);
1216        }
1217
1218        security::bprm_committing_creds(self, &resolved_program)?;
1219
1220        let new_creds = Arc::new(resolved_program.creds.clone());
1221        writable_creds.update(self, new_creds);
1222
1223        // From <https://man7.org/linux/man-pages/man2/execve.2.html>:
1224        //
1225        //   POSIX timers (timer_create(2)) are not preserved.
1226        self.thread_group().timers.reset_for_exec(self);
1227
1228        self.thread_group().signal_actions.reset_for_exec();
1229        security::bprm_committed_creds(self)?;
1230
1231        let command_name = TaskCommand::from_path_bytes(resolved_program.path().to_bytes());
1232        let start_info = load_executable(self, resolved_program)?;
1233
1234        let regs: zx_restricted_state_t = start_info.into();
1235        self.thread_state.registers.load(regs);
1236        self.thread_state.extended_pstate.reset();
1237
1238        // The exit signal (and that of the children) is reset to SIGCHLD.
1239        {
1240            let mut thread_group_state = self.thread_group().write();
1241            thread_group_state.exit_signal = Some(SIGCHLD);
1242            for child in thread_group_state.children() {
1243                // This allow_subclass is safe because locking parent then child strictly
1244                // follows the top-down traversal of the thread group tree, which cannot form
1245                // cycles.
1246                let _token = starnix_sync::allow_subclass();
1247                let mut child_state = child.write();
1248                child_state.exit_signal = Some(SIGCHLD);
1249            }
1250        }
1251
1252        self.thread_group().write().did_exec = true;
1253
1254        self.set_command_name(command_name);
1255
1256        Ok(())
1257    }
1258
1259    pub fn set_command_name(&self, new_name: TaskCommand) {
1260        // set_command_name needs to run before leader_command() in cases where self is the leader.
1261        self.task.set_command_name(new_name.clone());
1262        let leader_command = self.thread_group().read().leader_command();
1263        starnix_logging::set_current_task_info(new_name, leader_command, self.pid.id, self.tid.id);
1264    }
1265
1266    pub fn add_seccomp_filter(
1267        &mut self,
1268        code: Vec<sock_filter>,
1269        flags: u32,
1270    ) -> Result<SyscallResult, Errno> {
1271        let mut notifier = None;
1272        if flags & SECCOMP_FILTER_FLAG_NEW_LISTENER != 0 {
1273            notifier = Some(SeccompFilterContainer::create_notifier());
1274        }
1275
1276        let new_filter = Arc::new(SeccompFilter::from_cbpf(
1277            &code,
1278            self.thread_group().next_seccomp_filter_id.add(1),
1279            flags & SECCOMP_FILTER_FLAG_LOG != 0,
1280            notifier.clone(),
1281        )?);
1282
1283        let mut maybe_fd: Option<FdNumber> = None;
1284        if let Some(notifier) = notifier {
1285            maybe_fd = Some(SeccompFilterContainer::register_listener(self, notifier)?);
1286        }
1287
1288        // We take the process lock here because we can't change any of the threads
1289        // while doing a tsync.  So, you hold the process lock while making any changes.
1290        let state = self.thread_group().write();
1291
1292        if flags & SECCOMP_FILTER_FLAG_TSYNC != 0 {
1293            // TSYNC synchronizes all filters for all threads in the current process to
1294            // the current thread's
1295
1296            // We collect the filters for the current task upfront to save us acquiring
1297            // the task's lock a lot of times below.
1298            let mut filters: SeccompFilterContainer = self.read().seccomp_filters.clone();
1299
1300            // For TSYNC to work, all of the other thread filters in this process have to
1301            // be a prefix of this thread's filters, and none of them can be in
1302            // strict mode.
1303            let tasks = state.tasks();
1304            for task in &tasks {
1305                if task.tid.id == self.tid.id {
1306                    continue;
1307                }
1308                let other_task_state = task.read();
1309
1310                // Target threads cannot be in SECCOMP_MODE_STRICT
1311                if task.seccomp_filter_state.get() == SeccompStateValue::Strict {
1312                    return Self::seccomp_tsync_error(task.tid.id, flags);
1313                }
1314
1315                // Target threads' filters must be a subsequence of this thread's
1316                if !other_task_state.seccomp_filters.can_sync_to(&filters) {
1317                    return Self::seccomp_tsync_error(task.tid.id, flags);
1318                }
1319            }
1320
1321            // Now that we're sure we're allowed to do so, add the filter to all threads.
1322            filters.add_filter(new_filter, code.len() as u16)?;
1323
1324            for task in &tasks {
1325                let mut other_task_state = task.write();
1326
1327                other_task_state.enable_no_new_privs();
1328                other_task_state.seccomp_filters = filters.clone();
1329                task.set_seccomp_state(SeccompStateValue::UserDefined)?;
1330            }
1331        } else {
1332            let mut task_state = self.task.write();
1333
1334            task_state.seccomp_filters.add_filter(new_filter, code.len() as u16)?;
1335            self.set_seccomp_state(SeccompStateValue::UserDefined)?;
1336        }
1337
1338        if let Some(fd) = maybe_fd { Ok(fd.into()) } else { Ok(().into()) }
1339    }
1340
1341    pub fn run_seccomp_filters(
1342        &mut self,
1343        syscall: &Syscall,
1344    ) -> Option<Result<SyscallResult, Errno>> {
1345        // Implementation of SECCOMP_FILTER_STRICT, which has slightly different semantics
1346        // from user-defined seccomp filters.
1347        if self.seccomp_filter_state.get() == SeccompStateValue::Strict {
1348            return SeccompState::do_strict(self, syscall);
1349        }
1350
1351        // Run user-defined seccomp filters
1352        let result = self.task.read().seccomp_filters.run_all(self, syscall);
1353
1354        SeccompState::do_user_defined(result, self, syscall)
1355    }
1356
1357    fn seccomp_tsync_error(id: i32, flags: u32) -> Result<SyscallResult, Errno> {
1358        // By default, TSYNC indicates failure state by returning the first thread
1359        // id not to be able to sync, rather than by returning -1 and setting
1360        // errno.  However, if TSYNC_ESRCH is set, it returns ESRCH.  This
1361        // prevents conflicts with fact that SECCOMP_FILTER_FLAG_NEW_LISTENER
1362        // makes seccomp return an fd.
1363        if flags & SECCOMP_FILTER_FLAG_TSYNC_ESRCH != 0 { error!(ESRCH) } else { Ok(id.into()) }
1364    }
1365
1366    // Notify all futexes in robust list.  The robust list is in user space, so we
1367    // are very careful about walking it, and there are a lot of quiet returns if
1368    // we fail to walk it.
1369    // TODO(https://fxbug.dev/42079081): This only sets the FUTEX_OWNER_DIED bit; it does
1370    // not wake up a waiter.
1371    pub fn notify_robust_list(&self) {
1372        let task_state = self.write();
1373        let robust_list_addr = task_state.robust_list_head.addr();
1374        if robust_list_addr == UserAddress::NULL {
1375            // No one has called set_robust_list.
1376            return;
1377        }
1378        let robust_list_res = self.read_multi_arch_object(task_state.robust_list_head);
1379
1380        let head = if let Ok(head) = robust_list_res {
1381            head
1382        } else {
1383            return;
1384        };
1385
1386        let offset = head.futex_offset;
1387
1388        let mut entries_count = 0;
1389        let mut curr_ptr = head.list.next;
1390        while curr_ptr.addr() != robust_list_addr.into() && entries_count < ROBUST_LIST_LIMIT {
1391            let curr_ref = self.read_multi_arch_object(curr_ptr);
1392
1393            let curr = if let Ok(curr) = curr_ref {
1394                curr
1395            } else {
1396                return;
1397            };
1398
1399            let Some(futex_base) = curr_ptr.addr().checked_add_signed(offset) else {
1400                return;
1401            };
1402
1403            let futex_addr = match FutexAddress::try_from(futex_base) {
1404                Ok(addr) => addr,
1405                Err(_) => {
1406                    return;
1407                }
1408            };
1409
1410            let Ok(mm) = self.mm() else {
1411                log_error!("Asked to notify robust list futexes in system task.");
1412                return;
1413            };
1414            let futex = if let Ok(futex) = mm.atomic_load_u32_relaxed(futex_addr) {
1415                futex
1416            } else {
1417                return;
1418            };
1419
1420            if (futex & FUTEX_TID_MASK) as i32 == self.tid.id {
1421                let owner_died = FUTEX_OWNER_DIED | futex;
1422                if mm.atomic_store_u32_relaxed(futex_addr, owner_died).is_err() {
1423                    return;
1424                }
1425            }
1426            curr_ptr = curr.next;
1427            entries_count += 1;
1428        }
1429    }
1430
1431    pub(crate) fn handle_page_fault(
1432        &self,
1433        decoded: PageFaultExceptionReport,
1434        status: zx::Status,
1435    ) -> ExceptionResult {
1436        if let Ok(mm) = self.mm() {
1437            mm.handle_page_fault(decoded, status)
1438        } else {
1439            panic!(
1440                "system task is handling a major page fault status={:?}, report={:?}",
1441                status, decoded
1442            );
1443        }
1444    }
1445
1446    /// Processes a Zircon exception associated with this task.
1447    pub fn process_exception(&self, report: &zx::ExceptionReport) -> ExceptionResult {
1448        if let Some(result) = handle_hardware_exception(self, report) {
1449            return result;
1450        }
1451
1452        match report.ty {
1453            zx::ExceptionType::General => {
1454                log_error!("Unrecognized general exception: {:?}", report);
1455                ExceptionResult::Signal(SignalInfo::kernel(SIGILL))
1456            }
1457            zx::ExceptionType::ProcessNameChanged => {
1458                log_error!("Received unexpected process name changed exception");
1459                ExceptionResult::Handled
1460            }
1461            zx::ExceptionType::ProcessStarting
1462            | zx::ExceptionType::ThreadStarting
1463            | zx::ExceptionType::ThreadExiting => {
1464                log_error!("Received unexpected task lifecycle exception");
1465                ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1466            }
1467            zx::ExceptionType::PolicyError(policy_code) => {
1468                log_error!(policy_code:?; "Received Zircon policy error exception");
1469                ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1470            }
1471            zx::ExceptionType::UnknownUserGenerated { code, data } => {
1472                log_error!(code:?, data:?; "Received unexpected unknown user generated exception");
1473                ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1474            }
1475            zx::ExceptionType::Unknown { ty, code, data } => {
1476                log_error!(ty:?, code:?, data:?; "Received unexpected exception");
1477                ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1478            }
1479            _ => {
1480                log_error!("Received unknown zircon exception: {:?}", report.ty);
1481                ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1482            }
1483        }
1484    }
1485
1486    /// Clone this task.
1487    ///
1488    /// Creates a new task object that shares some state with this task
1489    /// according to the given flags.
1490    ///
1491    /// Used by the clone() syscall to create both processes and threads.
1492    ///
1493    /// The exit signal is broken out from the flags parameter like clone3() rather than being
1494    /// bitwise-ORed like clone().
1495    pub fn clone_task(
1496        &self,
1497        flags: u64,
1498        child_exit_signal: Option<Signal>,
1499        user_parent_tid: UserRef<pid_t>,
1500        user_child_tid: UserRef<pid_t>,
1501        user_pidfd: UserRef<FdNumber>,
1502    ) -> Result<TaskBuilder, Errno> {
1503        const IMPLEMENTED_FLAGS: u64 = ((CLONE_VM
1504            | CLONE_FS
1505            | CLONE_FILES
1506            | CLONE_SIGHAND
1507            | CLONE_THREAD
1508            | CLONE_SYSVSEM
1509            | CLONE_SETTLS
1510            | CLONE_PARENT
1511            | CLONE_PARENT_SETTID
1512            | CLONE_PIDFD
1513            | CLONE_CHILD_CLEARTID
1514            | CLONE_CHILD_SETTID
1515            | CLONE_VFORK
1516            | CLONE_NEWUTS
1517            | CLONE_PTRACE) as u64)
1518            | CLONE_CLEAR_SIGHAND;
1519
1520        // A mask with all valid flags set, because we want to return a different error code for an
1521        // invalid flag vs an unimplemented flag. Subtracting 1 from the largest valid flag gives a
1522        // mask with all flags below it set. Shift up by one to make sure the largest flag is also
1523        // set.
1524        const VALID_FLAGS: u64 = (CLONE_INTO_CGROUP << 1) - 1;
1525
1526        // CLONE_SETTLS is implemented by sys_clone.
1527
1528        let clone_files = flags & (CLONE_FILES as u64) != 0;
1529        let clone_fs = flags & (CLONE_FS as u64) != 0;
1530        let clone_parent = flags & (CLONE_PARENT as u64) != 0;
1531        let clone_parent_settid = flags & (CLONE_PARENT_SETTID as u64) != 0;
1532        let clone_pidfd = flags & (CLONE_PIDFD as u64) != 0;
1533        let clone_child_cleartid = flags & (CLONE_CHILD_CLEARTID as u64) != 0;
1534        let clone_child_settid = flags & (CLONE_CHILD_SETTID as u64) != 0;
1535        let clone_sysvsem = flags & (CLONE_SYSVSEM as u64) != 0;
1536        let clone_ptrace = flags & (CLONE_PTRACE as u64) != 0;
1537        let clone_thread = flags & (CLONE_THREAD as u64) != 0;
1538        let clone_vm = flags & (CLONE_VM as u64) != 0;
1539        let clone_sighand = flags & (CLONE_SIGHAND as u64) != 0;
1540        let clone_vfork = flags & (CLONE_VFORK as u64) != 0;
1541        let clone_newuts = flags & (CLONE_NEWUTS as u64) != 0;
1542        let clone_into_cgroup = flags & CLONE_INTO_CGROUP != 0;
1543        let clone_clear_sighand = flags & (CLONE_CLEAR_SIGHAND as u64) != 0;
1544
1545        if clone_ptrace {
1546            track_stub!(TODO("https://fxbug.dev/322874630"), "CLONE_PTRACE");
1547        }
1548
1549        if clone_sysvsem {
1550            track_stub!(TODO("https://fxbug.dev/322875185"), "CLONE_SYSVSEM");
1551        }
1552
1553        if clone_into_cgroup {
1554            track_stub!(TODO("https://fxbug.dev/403612570"), "CLONE_INTO_CGROUP");
1555        }
1556
1557        if clone_sighand && !clone_vm {
1558            return error!(EINVAL);
1559        }
1560        if clone_clear_sighand && clone_sighand {
1561            return error!(EINVAL);
1562        }
1563        if clone_thread && !clone_sighand {
1564            return error!(EINVAL);
1565        }
1566
1567        if clone_pidfd && clone_thread {
1568            return error!(EINVAL);
1569        }
1570        if clone_pidfd && clone_parent_settid && user_parent_tid.addr() == user_pidfd.addr() {
1571            // `clone()` uses the same out-argument for these, so error out if they have the same
1572            // user address.
1573            return error!(EINVAL);
1574        }
1575
1576        if flags & !VALID_FLAGS != 0 {
1577            return error!(EINVAL);
1578        }
1579
1580        if clone_vm && !clone_thread {
1581            // TODO(https://fxbug.dev/42066087) Implement CLONE_VM for child processes (not just child
1582            // threads). Currently this executes CLONE_VM (explicitly passed to clone() or as
1583            // used by vfork()) as a fork (the VM in the child is copy-on-write) which is almost
1584            // always OK.
1585            //
1586            // CLONE_VM is primarily as an optimization to avoid making a copy-on-write version of a
1587            // process' VM that will be immediately replaced with a call to exec(). The main users
1588            // (libc and language runtimes) don't actually rely on the memory being shared between
1589            // the two processes. And the vfork() man page explicitly allows vfork() to be
1590            // implemented as fork() which is what we do here.
1591            if !clone_vfork {
1592                track_stub!(
1593                    TODO("https://fxbug.dev/322875227"),
1594                    "CLONE_VM without CLONE_THREAD or CLONE_VFORK"
1595                );
1596            }
1597        } else if clone_thread && !clone_vm {
1598            track_stub!(TODO("https://fxbug.dev/322875167"), "CLONE_THREAD without CLONE_VM");
1599            return error!(ENOSYS);
1600        }
1601
1602        if flags & !IMPLEMENTED_FLAGS != 0 {
1603            track_stub!(
1604                TODO("https://fxbug.dev/322875130"),
1605                "clone unknown flags",
1606                flags & !IMPLEMENTED_FLAGS
1607            );
1608            return error!(ENOSYS);
1609        }
1610
1611        let fs = if clone_fs { self.fs() } else { self.fs().fork() };
1612        let files = if clone_files {
1613            self.running_state().share_files()
1614        } else {
1615            self.running_state().fork_files()
1616        }
1617        .expect("Task must have FdTable");
1618
1619        let kernel = self.kernel();
1620
1621        let mut pids = kernel.pids.lock();
1622
1623        // Lock the cgroup process hierarchy so that the parent process cannot move to a different
1624        // cgroup while a new task or thread_group is created. This may be unnecessary if
1625        // CLONE_INTO_CGROUP is implemented and passed in.
1626        let mut cgroup2_pid_table = kernel.cgroups.lock_cgroup2_pid_table();
1627        // Create a `KernelSignal::Freeze` to put onto the new task, if the cgroup is frozen.
1628        let child_kernel_signals = cgroup2_pid_table
1629            .maybe_create_freeze_signal(&self.pid)
1630            .into_iter()
1631            .collect::<VecDeque<_>>();
1632
1633        let pid;
1634        let command;
1635        let creds;
1636        let scheduler_state;
1637        let no_new_privs;
1638        let seccomp_filters;
1639        let robust_list_head = RobustListHeadPtr::null(self);
1640        let child_signal_mask;
1641        let timerslack_ns;
1642        let uts_ns;
1643
1644        let TaskInfo { thread_group, memory_manager } = {
1645            // These variables hold the original parent in case we need to switch the parent of the
1646            // new task because of CLONE_PARENT.
1647            let weak_original_parent;
1648            let original_parent;
1649
1650            // Make sure to drop these locks ASAP to avoid inversion
1651            let (thread_group_state, creator_task) = {
1652                let thread_group_state = self.thread_group().write();
1653                if clone_parent {
1654                    // With the CLONE_PARENT flag, the parent of the new task is our parent
1655                    // instead of ourselves.
1656                    weak_original_parent =
1657                        thread_group_state.parent.clone().ok_or_else(|| errno!(EINVAL))?;
1658                    let creator_task = weak_original_parent.creator_task().cloned();
1659                    std::mem::drop(thread_group_state);
1660                    original_parent = weak_original_parent.upgrade();
1661                    (original_parent.write(), creator_task)
1662                } else {
1663                    (thread_group_state, Some(self.weak_task()))
1664                }
1665            };
1666
1667            let state = self.read();
1668
1669            no_new_privs = state.no_new_privs();
1670            seccomp_filters = state.seccomp_filters.clone();
1671            child_signal_mask = state.signal_mask();
1672
1673            pid = pids.allocate_pid()?;
1674            command = self.command();
1675            creds = self.current_creds().clone();
1676            scheduler_state = state.scheduler_state.fork();
1677            timerslack_ns = state.timerslack_ns;
1678
1679            uts_ns = if clone_newuts {
1680                security::check_task_capable(self, CAP_SYS_ADMIN)?;
1681                state.uts_ns.read().fork()
1682            } else {
1683                state.uts_ns.clone()
1684            };
1685
1686            if clone_thread {
1687                TaskInfo {
1688                    thread_group: self.thread_group().clone(),
1689                    memory_manager: self.mm().ok(),
1690                }
1691            } else {
1692                // Drop the lock on this task before entering `create_zircon_process`, because it will
1693                // take a lock on the new thread group, and locks on thread groups have a higher
1694                // priority than locks on the task in the thread group.
1695                std::mem::drop(state);
1696                let signal_actions = if clone_sighand {
1697                    self.thread_group().signal_actions.clone()
1698                } else if clone_clear_sighand {
1699                    let actions = self.thread_group().signal_actions.fork();
1700                    actions.reset_for_exec();
1701                    actions
1702                } else {
1703                    self.thread_group().signal_actions.fork()
1704                };
1705                let task_info = {
1706                    fuchsia_trace::duration!(CATEGORY_STARNIX, "create_zircon_process");
1707                    create_zircon_process(
1708                        kernel,
1709                        Some(thread_group_state),
1710                        pid.clone(),
1711                        child_exit_signal,
1712                        signal_actions,
1713                        command.clone(),
1714                    )?
1715                };
1716
1717                if let Some(parent) = &mut task_info.thread_group.write().parent {
1718                    parent.set_creator_task(creator_task);
1719                }
1720
1721                cgroup2_pid_table.inherit_cgroup(self.thread_group(), &task_info.thread_group);
1722
1723                task_info
1724            }
1725        };
1726
1727        // Drop the lock on the cgroup pid_table before creating the TaskBuilder.
1728        // If the TaskBuilder creation fails, the TaskBuilder is dropped, which calls
1729        // ThreadGroup::remove. ThreadGroup::remove takes the cgroup pid_table lock, causing
1730        // a cyclic lock dependency.
1731        std::mem::drop(cgroup2_pid_table);
1732
1733        // Only create the vfork event when the caller requested CLONE_VFORK.
1734        let vfork_event = if clone_vfork { Some(Arc::new(zx::Event::create())) } else { None };
1735
1736        // Clone running state in a nested scope to ensure that the RCU read scope is not held
1737        // across the release_on_error block.
1738        let abstract_socket_namespace;
1739        let abstract_vsock_namespace;
1740        {
1741            let running_state = self.running_state();
1742            abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
1743            abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
1744        }
1745
1746        let (pgid_pid, sid_pid) = {
1747            let tg_state = thread_group.read();
1748            (tg_state.process_group.clone(), tg_state.session.clone())
1749        };
1750
1751        let mut child = TaskBuilder::new(Task::new(
1752            pid,
1753            command,
1754            thread_group,
1755            files,
1756            memory_manager,
1757            fs,
1758            creds,
1759            abstract_socket_namespace,
1760            abstract_vsock_namespace,
1761            child_signal_mask,
1762            child_kernel_signals,
1763            vfork_event,
1764            scheduler_state,
1765            uts_ns,
1766            no_new_privs,
1767            SeccompState::from(&self.seccomp_filter_state),
1768            seccomp_filters,
1769            robust_list_head,
1770            timerslack_ns,
1771        ));
1772        let parent_cpuset_path = self.read().cpuset_path.clone();
1773        child.task.write().cpuset_path = parent_cpuset_path;
1774
1775        release_on_error!(child, {
1776            // Drop the pids lock as soon as possible after creating the child. Destroying the child
1777            // and removing it from the pids table itself requires the pids lock, so an early exit
1778            // would cause a self deadlock.
1779            pids.add_task(Arc::clone(&child.task));
1780
1781            // Child lock must be taken before this lock. Drop the lock on the task, take a writable
1782            // lock on the child and take the current state back.
1783
1784            #[cfg(any(test, debug_assertions))]
1785            {
1786                // Take the lock on the thread group and its child in the correct order to ensure
1787                // any wrong ordering will trigger the tracing-mutex at the right call site.
1788                if !clone_thread {
1789                    let _l1 = self.thread_group().read();
1790                    // This allow_subclass is safe because locking parent then child strictly
1791                    // follows the top-down traversal of the thread group tree, which cannot form
1792                    // cycles.
1793                    let _token = starnix_sync::allow_subclass();
1794                    let _l2 = child.thread_group().read();
1795                }
1796            }
1797
1798            if clone_thread {
1799                self.thread_group().add(Arc::clone(&child.task))?;
1800                std::mem::drop(pids);
1801            } else {
1802                child.thread_group().add(Arc::clone(&child.task))?;
1803                pids.attach_pgid(&pgid_pid, child.thread_group());
1804                pids.attach_sid(&sid_pid, child.thread_group());
1805                std::mem::drop(pids);
1806
1807                // Inherit `controlling_terminal` from the parent now that `child` is attached to
1808                // `sid_pid`. Holding `child.thread_group().write()` across `terminal.read()`
1809                // ensures any concurrent terminal disassociation or steal either already updated
1810                // `terminal.write()` before this check or visits `child` afterward in
1811                // `sid_thread_groups`.
1812                if let Some(ct) = self.thread_group().controlling_terminal() {
1813                    let mut child_state = child.thread_group().write();
1814                    if child_state.session == sid_pid
1815                        && ct.terminal.read().controlling_session() == Some(&sid_pid)
1816                    {
1817                        child_state.controlling_terminal = Some(ct);
1818                    }
1819                }
1820
1821                // These manipulations of the signal handling state appear to be related to
1822                // CLONE_SIGHAND and CLONE_VM rather than CLONE_THREAD. However, Starnix does not
1823                // support all combinations of these flags, so performing these operations here
1824                // might be sufficient unless a test requires moving this logic.
1825                let (sigaltstack, signal_mask) = {
1826                    let state = self.read();
1827                    (state.sigaltstack(), state.signal_mask())
1828                };
1829                let mut child_state = child.write();
1830                child_state.set_sigaltstack(sigaltstack);
1831                child_state.set_signal_mask(signal_mask);
1832            }
1833
1834            if !clone_vm {
1835                // Running threads in the same process with different MemoryManagers is not
1836                // supported.
1837                assert!(!clone_thread);
1838                let child_mm = MemoryManager::snapshot_of(
1839                    &self.mm()?,
1840                    child.thread_group.root_vmar.unowned(),
1841                    self.thread_state.arch_width(),
1842                )?;
1843                child.running_state()?.mm.update(Some(child_mm));
1844            }
1845
1846            if clone_parent_settid {
1847                self.write_object(user_parent_tid, &child.tid.id)?;
1848            }
1849
1850            if clone_child_cleartid {
1851                child.write().clear_child_tid = user_child_tid;
1852            }
1853
1854            if clone_child_settid {
1855                child.write_object(user_child_tid, &child.tid.id)?;
1856            }
1857
1858            if clone_pidfd {
1859                let file = new_pidfd(self, child.pid.clone(), OpenFlags::empty())?;
1860                let pidfd = self.add_file(file, FdFlags::CLOEXEC)?;
1861                self.write_object(user_pidfd, &pidfd)?;
1862            }
1863
1864            // TODO(https://fxbug.dev/42066087): We do not support running different processes with
1865            // the same MemoryManager. Instead, we implement a rough approximation of that behavior
1866            // by making a copy-on-write clone of the memory from the original process.
1867            if clone_vm && !clone_thread {
1868                let child_mm = MemoryManager::snapshot_of(
1869                    &self.mm()?,
1870                    child.thread_group.root_vmar.unowned(),
1871                    self.thread_state.arch_width(),
1872                )?;
1873                child.running_state()?.mm.update(Some(child_mm));
1874            }
1875
1876            child.thread_state = self.thread_state.snapshot::<HeapRegs>();
1877            Ok(())
1878        });
1879
1880        // Take the lock on thread group and task in the correct order to ensure any wrong ordering
1881        // will trigger the tracing-mutex at the right call site.
1882        #[cfg(any(test, debug_assertions))]
1883        {
1884            let _l1 = child.thread_group().read();
1885            let _l2 = child.read();
1886        }
1887
1888        Ok(child)
1889    }
1890
1891    /// Sets the stop state (per set_stopped), and also notifies all listeners,
1892    /// including the parent process and the tracer if appropriate.
1893    pub fn set_stopped_and_notify(&self, stopped: StopState, siginfo: Option<SignalInfo>) {
1894        let maybe_signal_info = {
1895            let mut state = self.write();
1896            state.set_stopped(stopped, siginfo, Some(self), None);
1897            state.prepare_signal_info(stopped)
1898        };
1899
1900        if let Some((tracer, signal_info)) = maybe_signal_info {
1901            if let Some(tracer) = tracer.upgrade() {
1902                tracer.write().send_signal(signal_info);
1903            }
1904        }
1905
1906        if !stopped.is_in_progress() {
1907            let parent = self.thread_group().read().parent.clone();
1908            if let Some(parent) = parent {
1909                parent
1910                    .upgrade()
1911                    .write()
1912                    .lifecycle_waiters
1913                    .notify_value(ThreadGroupLifecycleWaitValue::ChildStatus);
1914            }
1915        }
1916    }
1917
1918    /// Finalizes the stop state of the task, and if the task should be stopped,
1919    /// blocks the execution of `current_task` as long as the task is stopped and
1920    /// not terminated.
1921    ///
1922    /// Returns true if the task was stopped and blocked (and has now woken up),
1923    /// or false if it was not stopped and returned immediately.
1924    pub fn block_if_stopped(&mut self) -> bool {
1925        if !self.finalize_stop_state() {
1926            return false;
1927        }
1928        self.block_while_stopped();
1929
1930        // When coming back from a stop, write modified register state to the ThreadState.
1931        let captured_state = self.write().take_captured_state();
1932        if let Some(captured) = captured_state {
1933            if captured.dirty {
1934                self.thread_state.replace_registers(&captured.thread_state);
1935            }
1936        }
1937        true
1938    }
1939
1940    /// If the task is stopping, set it as stopped. Return whether the caller should stop.
1941    fn finalize_stop_state(&self) -> bool {
1942        let stopped = self.load_stopped();
1943
1944        // Stopping because the thread group is stopping.
1945        // Try to flip to GroupStopped - will fail if we shouldn't.
1946        if self.thread_group().set_stopped(StopState::GroupStopped, None, true)
1947            == StopState::GroupStopped
1948        {
1949            let signal = self.thread_group().read().last_signal.clone();
1950            // stopping because the thread group has stopped
1951            let event = Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0));
1952            self.write().set_stopped(StopState::GroupStopped, signal, Some(self), event);
1953            return true;
1954        }
1955
1956        // Stopping because the task is stopping
1957        if stopped.is_stopping_or_stopped() {
1958            if let Ok(stopped) = stopped.finalize() {
1959                self.set_stopped_and_notify(stopped, None);
1960            }
1961            return true;
1962        }
1963
1964        false
1965    }
1966
1967    /// Block the execution of `current_task` as long as the task is stopped and
1968    /// not terminated.
1969    fn block_while_stopped(&mut self) {
1970        let waiter = Waiter::new();
1971        loop {
1972            // If we've exited, unstop the threads and return without notifying
1973            // waiters.
1974            if self.is_exitted() {
1975                self.thread_group().set_stopped(StopState::ForceAwake, None, false);
1976                self.write().set_stopped(StopState::ForceAwake, None, Some(self), None);
1977                return;
1978            }
1979
1980            if self.wake_or_wait_until_unstopped_async(&waiter) {
1981                return;
1982            }
1983
1984            waiter.stop(self);
1985
1986            // Maybe go from stopping to stopped, if we are currently stopping
1987            // again.
1988            self.finalize_stop_state();
1989        }
1990    }
1991
1992    /// For traced tasks, this will return the data neceessary for a cloned task
1993    /// to attach to the same tracer.
1994    pub fn get_ptrace_core_state_for_clone(
1995        &mut self,
1996        clone_args: &clone_args,
1997    ) -> (PtraceOptions, Option<PtraceCoreState>) {
1998        let state = self.write();
1999        if let Some(ptrace) = &state.ptrace {
2000            ptrace.get_core_state_for_clone(clone_args)
2001        } else {
2002            (PtraceOptions::empty(), None)
2003        }
2004    }
2005
2006    /// If currently being ptraced with the given option, emit the appropriate
2007    /// event.  PTRACE_EVENTMSG will return the given message.  Also emits the
2008    /// appropriate event for execve in the absence of TRACEEXEC.
2009    ///
2010    /// Note that the Linux kernel has a documented bug where, if TRACEEXIT is
2011    /// enabled, SIGKILL will trigger an event.  We do not exhibit this
2012    /// behavior.
2013    pub fn ptrace_event(&mut self, trace_kind: PtraceOptions, msg: u64) {
2014        if !trace_kind.is_empty() {
2015            {
2016                let mut state = self.write();
2017                if let Some(ptrace) = &mut state.ptrace {
2018                    if !ptrace.has_option(trace_kind) {
2019                        // If this would be a TRACEEXEC, but TRACEEXEC is not
2020                        // turned on, then send a SIGTRAP.
2021                        if trace_kind == PtraceOptions::TRACEEXEC && !ptrace.is_seized() {
2022                            // Send a SIGTRAP so that the parent can gain control.
2023                            send_signal_first(self, state, SignalInfo::kernel(SIGTRAP));
2024                        }
2025
2026                        return;
2027                    }
2028                    let ptrace_event = PtraceEvent::from_option(&trace_kind) as u32;
2029                    let siginfo = SignalInfo::with_detail(
2030                        SIGTRAP,
2031                        ((ptrace_event << 8) | SIGTRAP.number()) as i32,
2032                        SignalDetail::None,
2033                    );
2034                    state.set_stopped(
2035                        StopState::PtraceEventStopping,
2036                        Some(siginfo),
2037                        None,
2038                        Some(PtraceEventData::new(trace_kind, msg)),
2039                    );
2040                } else {
2041                    return;
2042                }
2043            }
2044            self.block_if_stopped();
2045        }
2046    }
2047
2048    /// Causes the current thread's thread group to exit, terminating sibling
2049    /// tasks before notifying any ptracer of this task's exit.
2050    pub fn kill_thread_group(&mut self, exit_status: ExitStatus) {
2051        Arc::clone(self.thread_group()).kill(exit_status, Some(self));
2052    }
2053
2054    /// The flags indicates only the flags as in clone3(), and does not use the low 8 bits for the
2055    /// exit signal as in clone().
2056    pub fn clone_task_builder_for_test(
2057        &self,
2058        flags: u64,
2059        exit_signal: Option<Signal>,
2060    ) -> TaskBuilder {
2061        let result = self
2062            .clone_task(
2063                flags,
2064                exit_signal,
2065                UserRef::default(),
2066                UserRef::default(),
2067                UserRef::default(),
2068            )
2069            .expect("failed to create task in test");
2070        result.task.write().set_spawned();
2071        result
2072    }
2073
2074    /// The flags indicates only the flags as in clone3(), and does not use the low 8 bits for the
2075    /// exit signal as in clone().
2076    pub fn clone_task_for_test(
2077        &self,
2078        flags: u64,
2079        exit_signal: Option<Signal>,
2080    ) -> crate::testing::AutoReleasableTask {
2081        self.clone_task_builder_for_test(flags, exit_signal).into()
2082    }
2083
2084    // See "Ptrace access mode checking" in https://man7.org/linux/man-pages/man2/ptrace.2.html
2085    pub fn check_ptrace_access_mode(
2086        &self,
2087        mode: PtraceAccessMode,
2088        target: &Task,
2089    ) -> Result<(), Errno> {
2090        // (1)  If the calling thread and the target thread are in the same
2091        //      thread group, access is always allowed.
2092        if self.pid == target.pid {
2093            return Ok(());
2094        }
2095
2096        // (2)  If the access mode specifies PTRACE_MODE_FSCREDS, then, for
2097        //      the check in the next step, employ the caller's filesystem
2098        //      UID and GID.  (As noted in credentials(7), the filesystem
2099        //      UID and GID almost always have the same values as the
2100        //      corresponding effective IDs.)
2101        //
2102        //      Otherwise, the access mode specifies PTRACE_MODE_REALCREDS,
2103        //      so use the caller's real UID and GID for the checks in the
2104        //      next step.  (Most APIs that check the caller's UID and GID
2105        //      use the effective IDs.  For historical reasons, the
2106        //      PTRACE_MODE_REALCREDS check uses the real IDs instead.)
2107        let (uid, gid) = if mode.contains(PTRACE_MODE_FSCREDS) {
2108            let fscred = self.current_creds().as_fscred();
2109            (fscred.uid, fscred.gid)
2110        } else if mode.contains(PTRACE_MODE_REALCREDS) {
2111            let creds = self.current_creds();
2112            (creds.uid, creds.gid)
2113        } else {
2114            unreachable!();
2115        };
2116
2117        // (3)  Deny access if neither of the following is true:
2118        //
2119        //      -  The real, effective, and saved-set user IDs of the target
2120        //         match the caller's user ID, and the real, effective, and
2121        //         saved-set group IDs of the target match the caller's
2122        //         group ID.
2123        //
2124        //      -  The caller has the CAP_SYS_PTRACE capability in the user
2125        //         namespace of the target.
2126        let creds_match = {
2127            let check = |target_creds: &Credentials| {
2128                target_creds.uid == uid
2129                    && target_creds.euid == uid
2130                    && target_creds.saved_uid == uid
2131                    && target_creds.gid == gid
2132                    && target_creds.egid == gid
2133                    && target_creds.saved_gid == gid
2134            };
2135            if mode.contains(PtraceAccessMode::ATTACH) {
2136                check(&target.persistent_info.lock_creds())
2137            } else {
2138                check(&target.real_creds())
2139            }
2140        };
2141        if !creds_match {
2142            security::check_task_ptrace_capable(self, mode)?;
2143        }
2144
2145        // (4)  Deny access if the target process "dumpable" attribute has a
2146        //      value other than 1 (SUID_DUMP_USER; see the discussion of
2147        //      PR_SET_DUMPABLE in prctl(2)), and the caller does not have
2148        //      the CAP_SYS_PTRACE capability in the user namespace of the
2149        //      target process.
2150        //      Kernel threads and zombies do not have an `mm`, and are treated
2151        //      as dumpable like in Linux's `__ptrace_may_access`.
2152        if let Ok(mm) = target.mm() {
2153            let dumpable = mm.dumpable.load();
2154            match dumpable {
2155                DumpPolicy::User => (),
2156                DumpPolicy::Disable => {
2157                    security::check_task_ptrace_capable(self, mode)?;
2158                }
2159            }
2160        }
2161
2162        // (5)  The kernel LSM security_ptrace_access_check() interface is
2163        //      invoked to see if ptrace access is permitted.
2164        security::ptrace_access_check(self, target, mode)?;
2165
2166        // (6)  If access has not been denied by any of the preceding steps,
2167        //      then access is allowed.
2168        Ok(())
2169    }
2170
2171    pub fn can_signal(
2172        &self,
2173        target: &Task,
2174        unchecked_signal: UncheckedSignal,
2175    ) -> Result<(), Errno> {
2176        // If both the tasks share a thread group the signal can be sent. This is not documented
2177        // in kill(2) because kill does not support task-level granularity in signal sending.
2178        if self.thread_group == target.thread_group {
2179            return Ok(());
2180        }
2181
2182        let self_creds = self.current_creds();
2183        let target_creds = target.real_creds();
2184        // From https://man7.org/linux/man-pages/man2/kill.2.html:
2185        //
2186        // > For a process to have permission to send a signal, it must either be
2187        // > privileged (under Linux: have the CAP_KILL capability in the user
2188        // > namespace of the target process), or the real or effective user ID of
2189        // > the sending process must equal the real or saved set- user-ID of the
2190        // > target process.
2191        //
2192        // Returns true if the credentials are considered to have the same user ID.
2193        if self_creds.euid == target_creds.saved_uid
2194            || self_creds.euid == target_creds.uid
2195            || self_creds.uid == target_creds.uid
2196            || self_creds.uid == target_creds.saved_uid
2197        {
2198            return Ok(());
2199        }
2200
2201        if Signal::try_from(unchecked_signal) == Ok(SIGCONT) {
2202            let target_session = target.thread_group().read().session.clone();
2203            let self_session = self.thread_group().read().session.clone();
2204            if target_session == self_session {
2205                return Ok(());
2206            }
2207        }
2208
2209        security::check_task_capable(self, CAP_KILL)
2210    }
2211}
2212
2213impl ArchSpecific for CurrentTask {
2214    fn is_arch32(&self) -> bool {
2215        self.thread_state.is_arch32()
2216    }
2217}
2218
2219impl MemoryAccessor for CurrentTask {
2220    fn read_memory<'a>(
2221        &self,
2222        addr: UserAddress,
2223        bytes: &'a mut [MaybeUninit<u8>],
2224    ) -> Result<&'a mut [u8], Errno> {
2225        self.mm()?.unified_read_memory(self, addr, bytes)
2226    }
2227
2228    fn read_memory_partial_until_null_byte<'a>(
2229        &self,
2230        addr: UserAddress,
2231        bytes: &'a mut [MaybeUninit<u8>],
2232    ) -> Result<&'a mut [u8], Errno> {
2233        self.mm()?.unified_read_memory_partial_until_null_byte(self, addr, bytes)
2234    }
2235
2236    fn read_memory_partial<'a>(
2237        &self,
2238        addr: UserAddress,
2239        bytes: &'a mut [MaybeUninit<u8>],
2240    ) -> Result<&'a mut [u8], Errno> {
2241        self.mm()?.unified_read_memory_partial(self, addr, bytes)
2242    }
2243
2244    fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2245        self.mm()?.unified_write_memory(self, addr, bytes)
2246    }
2247
2248    fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2249        self.mm()?.unified_write_memory_partial(self, addr, bytes)
2250    }
2251
2252    fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
2253        self.mm()?.unified_zero(self, addr, length)
2254    }
2255}
2256
2257impl TaskMemoryAccessor for CurrentTask {
2258    fn maximum_valid_address(&self) -> Option<UserAddress> {
2259        self.mm().ok().map(|mm| mm.maximum_valid_user_address)
2260    }
2261}
2262
2263pub enum ExceptionResult {
2264    /// The exception was handled and no further action is required.
2265    Handled,
2266
2267    // The exception generated a signal that should be delivered.
2268    Signal(SignalInfo),
2269}
2270
2271fn split_path(path: &FsStr) -> LookupVec<&FsStr> {
2272    path.split(|c| *c == b'/').filter(|p| !p.is_empty()).map(<&FsStr>::from).collect()
2273}
2274
2275#[cfg(test)]
2276mod tests {
2277    use super::*;
2278    use crate::ptrace::{PtraceAttachType, ptrace_attach};
2279    use crate::testing::{create_task, spawn_kernel_and_run};
2280    use starnix_uapi::auth::{Credentials, PTRACE_MODE_READ_FSCREDS};
2281    use std::sync::Arc;
2282
2283    // This test will run `override_creds` and check it doesn't crash. This ensures that the
2284    // delegation to `override_creds_async` is correct.
2285    #[::fuchsia::test]
2286    async fn test_override_creds_can_delegate_to_async_version() {
2287        spawn_kernel_and_run(async move |current_task| {
2288            assert_eq!(current_task.override_creds(Credentials::root(), || 0), 0);
2289        })
2290        .await;
2291    }
2292
2293    // Another thread may hold a transient strong reference to the `TaskRunningState` of a task
2294    // while it exits (e.g. `Task::interrupt()`). The `FsContext` must still be released by
2295    // `exit()` itself rather than by whoever drops the last `TaskRunningState` reference, since
2296    // dropping it can tear down a whole mount namespace and acquire `DirEntry` locks.
2297    #[::fuchsia::test]
2298    async fn test_exit_releases_fs_while_running_state_is_referenced() {
2299        spawn_kernel_and_run(async move |current_task| {
2300            let task = create_task(current_task.kernel(), "task");
2301            let running_state = task.task.running_state().expect("task should be running");
2302            let fs = Arc::downgrade(&task.fs());
2303
2304            // Releasing the `AutoReleasableTask` calls `CurrentTask::exit()`.
2305            std::mem::drop(task);
2306
2307            assert!(running_state.fs().is_err());
2308            assert!(fs.upgrade().is_none(), "FsContext should be dropped by exit()");
2309        })
2310        .await;
2311    }
2312
2313    #[::fuchsia::test]
2314    async fn test_check_ptrace_access_mode() {
2315        spawn_kernel_and_run(async move |current_task| {
2316            let system_tg = current_task.kernel().kthreads.system_thread_group();
2317            let system_task = system_tg.leader.get_task().unwrap();
2318            let mode = PTRACE_MODE_READ_FSCREDS;
2319
2320            // Even root cannot ptrace_attach to the kernel system_task (which has no mm).
2321            assert_eq!(
2322                ptrace_attach(
2323                    current_task,
2324                    &system_tg.leader,
2325                    PtraceAttachType::Attach,
2326                    UserAddress::NULL
2327                ),
2328                error!(EPERM)
2329            );
2330
2331            // Root has CAP_SYS_PTRACE and passes check_ptrace_access_mode on a kernel thread.
2332            assert_eq!(current_task.check_ptrace_access_mode(mode, &system_task), Ok(()));
2333
2334            // Unprivileged caller cannot access a root-owned kernel thread.
2335            let unpriv_creds = Arc::new(Credentials::with_ids(1000, 1000));
2336            let res = current_task.override_creds(unpriv_creds.clone(), || {
2337                current_task.check_ptrace_access_mode(mode, &system_task)
2338            });
2339            assert_eq!(res, error!(EPERM));
2340
2341            // Non-dumpable target requires CAP_SYS_PTRACE even with matching UID/GID.
2342            let target_task = create_task(&current_task.kernel(), "target");
2343            target_task.set_creds(Credentials::with_ids(1000, 1000));
2344            target_task.mm().unwrap().dumpable.store(DumpPolicy::Disable);
2345
2346            let res = current_task.override_creds(unpriv_creds.clone(), || {
2347                current_task.check_ptrace_access_mode(mode, &target_task)
2348            });
2349            assert_eq!(res, error!(EPERM));
2350
2351            assert_eq!(current_task.check_ptrace_access_mode(mode, &target_task), Ok(()));
2352
2353            // Non-running (exited/zombie) task has no `mm` and is treated as dumpable.
2354            let exited_task_ref = Arc::clone(&target_task.task);
2355            std::mem::drop(target_task);
2356            assert!(exited_task_ref.mm().is_err());
2357
2358            let res = current_task.override_creds(unpriv_creds, || {
2359                current_task.check_ptrace_access_mode(mode, &exited_task_ref)
2360            });
2361            assert_eq!(res, Ok(()));
2362
2363            let other_creds = Arc::new(Credentials::with_ids(2000, 2000));
2364            let res = current_task.override_creds(other_creds, || {
2365                current_task.check_ptrace_access_mode(mode, &exited_task_ref)
2366            });
2367            assert_eq!(res, error!(EPERM));
2368
2369            assert_eq!(current_task.check_ptrace_access_mode(mode, &exited_task_ref), Ok(()));
2370        })
2371        .await;
2372    }
2373}