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