Skip to main content

starnix_core/task/
task.rs

1// Copyright 2021 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::mm::{MemoryAccessor, MemoryAccessorExt, MemoryManager, TaskMemoryAccessor};
6use crate::mutable_state::{state_accessor, state_implementation};
7use crate::ptrace::{
8    AtomicStopState, PtraceEvent, PtraceEventData, PtraceState, PtraceStatus, StopState,
9};
10use crate::signals::{KernelSignal, SignalDetail, SignalInfo, SignalState};
11use crate::task::memory_attribution::MemoryAttributionLifecycleEvent;
12use crate::task::run_state::RunState;
13use crate::task::tracing::KoidPair;
14use crate::task::{
15    AbstractUnixSocketNamespace, AbstractVsockSocketNamespace, CurrentCreds, CurrentTask,
16    EventHandler, Kernel, NormalPriority, ProcessExitInfo, RealtimePriority, SchedulerState,
17    SchedulingPolicy, SeccompFilterContainer, SeccompState, SeccompStateValue, TaskRunningState,
18    ThreadGroup, ThreadGroupKey, ThreadState, UtsNamespaceHandle, WaitCanceler, Waiter,
19    ZombieProcess,
20};
21use crate::vfs::{FdTable, FsContext, FsString};
22use atomic_bitflags::atomic_bitflags;
23use fuchsia_rcu::{RcuArc, RcuOptionArc, RcuReadGuard, RcuReadScope};
24use macro_rules_attribute::apply;
25use starnix_logging::{log_warn, set_zx_name};
26use starnix_registers::HeapRegs;
27use starnix_sync::{
28    LockDepGuard, LockDepMutex, LockDepReadGuard, LockDepRwLock, LockDepWriteGuard,
29    TaskCommandLevel, TaskCredsLock,
30};
31use starnix_task_command::TaskCommand;
32use starnix_types::arch::ArchWidth;
33use starnix_types::stats::TaskTimeStats;
34use starnix_uapi::auth::{Credentials, FsCred};
35use starnix_uapi::errors::Errno;
36use starnix_uapi::signals::{SIGCHLD, SigSet, Signal, sigaltstack_contains_pointer};
37use starnix_uapi::user_address::{
38    ArchSpecific, MappingMultiArchUserRef, UserAddress, UserCString, UserRef,
39};
40use starnix_uapi::{
41    CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, CLD_TRAPPED,
42    FUTEX_BITSET_MATCH_ANY, errno, error, from_status_like_fdio, pid_t, sigaction_t, sigaltstack,
43    tid_t, uapi,
44};
45use std::collections::VecDeque;
46use std::mem::MaybeUninit;
47use std::ops::Deref;
48use std::sync::atomic::{AtomicBool, Ordering};
49use std::sync::{Arc, Weak};
50use std::{cmp, fmt};
51use zx::{Signals, Task as _};
52
53#[derive(Clone, Debug, Eq, PartialEq)]
54pub enum ExitStatus {
55    Exit(u8),
56    Kill(SignalInfo),
57    CoreDump(SignalInfo),
58    // The second field for Stop and Continue contains the type of ptrace stop
59    // event that made it stop / continue, if applicable (PTRACE_EVENT_STOP,
60    // PTRACE_EVENT_FORK, etc)
61    Stop(SignalInfo, PtraceEvent),
62    Continue(SignalInfo, PtraceEvent),
63}
64impl ExitStatus {
65    /// Converts the given exit status to a status code suitable for returning from wait syscalls.
66    pub fn wait_status(&self) -> i32 {
67        match self {
68            ExitStatus::Exit(status) => (*status as i32) << 8,
69            ExitStatus::Kill(siginfo) => siginfo.signal.number() as i32,
70            ExitStatus::CoreDump(siginfo) => (siginfo.signal.number() as i32) | 0x80,
71            ExitStatus::Continue(siginfo, trace_event) => {
72                let trace_event_val = *trace_event as u32;
73                if trace_event_val != 0 {
74                    (siginfo.signal.number() as i32) | (trace_event_val << 16) as i32
75                } else {
76                    0xffff
77                }
78            }
79            ExitStatus::Stop(siginfo, trace_event) => {
80                let trace_event_val = *trace_event as u32;
81                (0x7f + ((siginfo.signal.number() as i32) << 8)) | (trace_event_val << 16) as i32
82            }
83        }
84    }
85
86    pub fn signal_info_code(&self) -> i32 {
87        match self {
88            ExitStatus::Exit(_) => CLD_EXITED as i32,
89            ExitStatus::Kill(_) => CLD_KILLED as i32,
90            ExitStatus::CoreDump(_) => CLD_DUMPED as i32,
91            ExitStatus::Stop(_, _) => CLD_STOPPED as i32,
92            ExitStatus::Continue(_, _) => CLD_CONTINUED as i32,
93        }
94    }
95
96    pub fn signal_info_status(&self) -> i32 {
97        match self {
98            ExitStatus::Exit(status) => *status as i32,
99            ExitStatus::Kill(siginfo)
100            | ExitStatus::CoreDump(siginfo)
101            | ExitStatus::Continue(siginfo, _)
102            | ExitStatus::Stop(siginfo, _) => siginfo.signal.number() as i32,
103        }
104    }
105}
106
107atomic_bitflags! {
108    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
109    pub struct TaskFlags: u8 {
110        const EXITED                   = 1 << 0;
111        const SIGNALS_AVAILABLE        = 1 << 1;
112        const TEMPORARY_SIGNAL_MASK    = 1 << 2;
113        /// Whether the executor should dump the stack of this task when it exits.
114        /// Currently used to implement ExitStatus::CoreDump.
115        const DUMP_ON_EXIT             = 1 << 3;
116        const KERNEL_SIGNALS_AVAILABLE = 1 << 4;
117        /// Whether the executor has successfully spawned a thread for this task.
118        const SPAWNED                  = 1 << 5;
119    }
120}
121
122/// This contains thread state that tracers can inspect and modify.  It is
123/// captured when a thread stops, and optionally copied back (if dirty) when a
124/// thread starts again.  An alternative implementation would involve the
125/// tracers acting on thread state directly; however, this would involve sharing
126/// CurrentTask structures across multiple threads, which goes against the
127/// intent of the design of CurrentTask.
128pub struct CapturedThreadState {
129    /// The thread state of the traced task.  This is copied out when the thread
130    /// stops.
131    pub thread_state: ThreadState<HeapRegs>,
132
133    /// Indicates that the last ptrace operation changed the thread state, so it
134    /// should be written back to the original thread.
135    pub dirty: bool,
136}
137
138impl ArchSpecific for CapturedThreadState {
139    fn is_arch32(&self) -> bool {
140        self.thread_state.is_arch32()
141    }
142}
143
144#[derive(Debug)]
145pub struct RobustList {
146    pub next: RobustListPtr,
147}
148
149pub type RobustListPtr =
150    MappingMultiArchUserRef<RobustList, uapi::robust_list, uapi::arch32::robust_list>;
151
152impl From<uapi::robust_list> for RobustList {
153    fn from(robust_list: uapi::robust_list) -> Self {
154        Self { next: RobustListPtr::from(robust_list.next) }
155    }
156}
157
158#[cfg(target_arch = "aarch64")]
159impl From<uapi::arch32::robust_list> for RobustList {
160    fn from(robust_list: uapi::arch32::robust_list) -> Self {
161        Self { next: RobustListPtr::from(robust_list.next) }
162    }
163}
164
165#[derive(Debug)]
166pub struct RobustListHead {
167    pub list: RobustList,
168    pub futex_offset: isize,
169}
170
171pub type RobustListHeadPtr =
172    MappingMultiArchUserRef<RobustListHead, uapi::robust_list_head, uapi::arch32::robust_list_head>;
173
174impl From<uapi::robust_list_head> for RobustListHead {
175    fn from(robust_list_head: uapi::robust_list_head) -> Self {
176        Self {
177            list: robust_list_head.list.into(),
178            futex_offset: robust_list_head.futex_offset as isize,
179        }
180    }
181}
182
183#[cfg(target_arch = "aarch64")]
184impl From<uapi::arch32::robust_list_head> for RobustListHead {
185    fn from(robust_list_head: uapi::arch32::robust_list_head) -> Self {
186        Self {
187            list: robust_list_head.list.into(),
188            futex_offset: robust_list_head.futex_offset as isize,
189        }
190    }
191}
192
193pub struct TaskMutableState {
194    // See https://man7.org/linux/man-pages/man2/set_tid_address.2.html
195    pub clear_child_tid: UserRef<tid_t>,
196
197    /// Signal handler related state. This is grouped together for when atomicity is needed during
198    /// signal sending and delivery.
199    signals: SignalState,
200
201    /// The current run state of the task.
202    pub run_state: RunState,
203
204    /// Internal signals that have a higher priority than a regular signal.
205    ///
206    /// Storing in a separate queue outside of `SignalState` ensures the internal signals will
207    /// never be ignored or masked when dequeuing. Higher priority ensures that no user signals
208    /// will jump the queue, e.g. ptrace, which delays the delivery.
209    ///
210    /// This design is not about observable consequence, but about convenient implementation.
211    kernel_signals: VecDeque<KernelSignal>,
212
213    /// The exit status that this task exited with.
214    exit_status: Option<ExitStatus>,
215
216    /// Desired scheduler state for the task.
217    pub scheduler_state: SchedulerState,
218
219    /// The UTS namespace assigned to this thread.
220    ///
221    /// This field is kept in the mutable state because the UTS namespace of a thread
222    /// can be forked using `clone()` or `unshare()` syscalls.
223    ///
224    /// We use UtsNamespaceHandle because the UTS properties can be modified
225    /// by any other thread that shares this namespace.
226    pub uts_ns: UtsNamespaceHandle,
227
228    /// Bit that determines whether a newly started program can have privileges its parent does
229    /// not have.  See Documentation/prctl/no_new_privs.txt in the Linux kernel for details.
230    /// Note that Starnix does not currently implement the relevant privileges (e.g.,
231    /// setuid/setgid binaries).  So, you can set this, but it does nothing other than get
232    /// propagated to children.
233    ///
234    /// The documentation indicates that this can only ever be set to
235    /// true, and it cannot be reverted to false.  Accessor methods
236    /// for this field ensure this property.
237    no_new_privs: bool,
238
239    /// Userspace hint about how to adjust the OOM score for this process.
240    pub oom_score_adj: i32,
241
242    /// List of currently installed seccomp_filters
243    pub seccomp_filters: SeccompFilterContainer,
244
245    /// A pointer to the head of the robust futex list of this thread in
246    /// userspace. See get_robust_list(2)
247    pub robust_list_head: RobustListHeadPtr,
248
249    /// The timer slack used to group timer expirations for the calling thread.
250    ///
251    /// Timers may expire up to `timerslack_ns` late, but never early.
252    ///
253    /// If this value is 0, the task's default timerslack is used.
254    pub timerslack_ns: u64,
255
256    /// The default value for `timerslack_ns`. This value cannot change during the lifetime of a
257    /// task.
258    ///
259    /// This value is set to the `timerslack_ns` of the creating thread, and thus is not constant
260    /// across tasks.
261    pub default_timerslack_ns: u64,
262
263    /// Information that a tracer needs to communicate with this process, if it
264    /// is being traced.
265    pub ptrace: Option<Box<PtraceState>>,
266
267    /// Information that a tracer needs to inspect this process.
268    pub captured_thread_state: Option<Box<CapturedThreadState>>,
269
270    /// The last applied scheduler role name.
271    last_applied_role: Option<String>,
272
273    /// The cpuset cgroup path of this task.
274    pub cpuset_path: String,
275}
276
277impl TaskMutableState {
278    pub fn no_new_privs(&self) -> bool {
279        self.no_new_privs
280    }
281
282    /// Sets the value of no_new_privs to true.  It is an error to set
283    /// it to anything else.
284    pub fn enable_no_new_privs(&mut self) {
285        self.no_new_privs = true;
286    }
287
288    pub fn get_timerslack<T: zx::Timeline>(&self) -> zx::Duration<T> {
289        zx::Duration::from_nanos(self.timerslack_ns as i64)
290    }
291
292    /// Sets the current timerslack of the task to `ns`.
293    ///
294    /// If `ns` is zero, the current timerslack gets reset to the task's default timerslack.
295    pub fn set_timerslack_ns(&mut self, ns: u64) {
296        if ns == 0 {
297            self.timerslack_ns = self.default_timerslack_ns;
298        } else {
299            self.timerslack_ns = ns;
300        }
301    }
302
303    pub fn is_ptraced(&self) -> bool {
304        self.ptrace.is_some()
305    }
306
307    pub fn is_ptrace_listening(&self) -> bool {
308        self.ptrace.as_ref().is_some_and(|ptrace| ptrace.stop_status == PtraceStatus::Listening)
309    }
310
311    pub fn ptrace_on_signal_consume(&mut self) -> bool {
312        self.ptrace.as_mut().is_some_and(|ptrace: &mut Box<PtraceState>| {
313            if ptrace.stop_status.is_continuing() {
314                ptrace.stop_status = PtraceStatus::Default;
315                false
316            } else {
317                true
318            }
319        })
320    }
321
322    pub fn notify_ptracers(&mut self) {
323        if let Some(ptrace) = &self.ptrace {
324            ptrace.tracer_waiters().notify_all();
325        }
326    }
327
328    pub fn wait_on_ptracer(&self, waiter: &Waiter) {
329        if let Some(ptrace) = &self.ptrace {
330            ptrace.tracee_waiters.wait_async(&waiter);
331        }
332    }
333
334    pub fn notify_ptracees(&mut self) {
335        if let Some(ptrace) = &self.ptrace {
336            ptrace.tracee_waiters.notify_all();
337        }
338    }
339
340    pub fn take_captured_state(&mut self) -> Option<Box<CapturedThreadState>> {
341        if self.captured_thread_state.is_some() {
342            let mut state = None;
343            std::mem::swap(&mut state, &mut self.captured_thread_state);
344            return state;
345        }
346        None
347    }
348
349    pub fn copy_state_from(&mut self, current_task: &CurrentTask) {
350        self.captured_thread_state = Some(Box::new(CapturedThreadState {
351            thread_state: current_task.thread_state.extended_snapshot::<HeapRegs>(),
352            dirty: false,
353        }));
354    }
355
356    /// Returns the task's currently active signal mask.
357    pub fn signal_mask(&self) -> SigSet {
358        self.signals.mask()
359    }
360
361    /// Returns true if `signal` is currently blocked by this task's signal mask.
362    pub fn is_signal_masked(&self, signal: Signal) -> bool {
363        self.signals.mask().has_signal(signal)
364    }
365
366    /// Returns true if `signal` is blocked by the saved signal mask.
367    ///
368    /// Note that the current signal mask may still not be blocking the signal.
369    pub fn is_signal_masked_by_saved_mask(&self, signal: Signal) -> bool {
370        self.signals.saved_mask().is_some_and(|mask| mask.has_signal(signal))
371    }
372
373    /// Removes the currently active, temporary, signal mask and restores the
374    /// previously active signal mask.
375    pub fn restore_signal_mask(&mut self) {
376        self.signals.restore_mask();
377    }
378
379    /// Returns true if the task's current `RunState` is blocked.
380    pub fn is_blocked(&self) -> bool {
381        self.run_state.is_blocked()
382    }
383
384    /// Sets the task's `RunState` to `run_state`.
385    pub fn set_run_state(&mut self, run_state: RunState) {
386        self.run_state = run_state;
387    }
388
389    pub fn run_state(&self) -> RunState {
390        self.run_state.clone()
391    }
392
393    pub fn on_signal_stack(&self, stack_pointer_register: u64) -> bool {
394        self.signals
395            .alt_stack
396            .map(|signal_stack| sigaltstack_contains_pointer(&signal_stack, stack_pointer_register))
397            .unwrap_or(false)
398    }
399
400    pub fn set_sigaltstack(&mut self, stack: Option<sigaltstack>) {
401        self.signals.alt_stack = stack;
402    }
403
404    pub fn sigaltstack(&self) -> Option<sigaltstack> {
405        self.signals.alt_stack
406    }
407
408    pub fn wait_on_signal(&mut self, waiter: &Waiter) {
409        self.signals.signal_wait.wait_async(waiter);
410    }
411
412    pub fn signals_mut(&mut self) -> &mut SignalState {
413        &mut self.signals
414    }
415
416    pub fn wait_on_signal_fd_events(
417        &self,
418        waiter: &Waiter,
419        mask: SigSet,
420        handler: EventHandler,
421    ) -> WaitCanceler {
422        self.signals.signal_wait.wait_async_signal_mask(waiter, mask, handler)
423    }
424
425    pub fn notify_signal_waiters(&self, signal: &Signal) {
426        self.signals.signal_wait.notify_signal(signal);
427    }
428
429    /// Thaw the task if has been frozen
430    pub fn thaw(&mut self) {
431        if let RunState::Frozen(waiter) = self.run_state() {
432            waiter.notify();
433        }
434    }
435
436    pub fn is_frozen(&self) -> bool {
437        matches!(self.run_state(), RunState::Frozen(_))
438    }
439
440    #[cfg(test)]
441    pub fn kernel_signals_for_test(&self) -> &VecDeque<KernelSignal> {
442        &self.kernel_signals
443    }
444}
445
446#[apply(state_implementation!)]
447impl TaskMutableState<Base = Task> {
448    pub fn set_stopped(
449        &mut self,
450        stopped: StopState,
451        siginfo: Option<SignalInfo>,
452        current_task: Option<&CurrentTask>,
453        event: Option<PtraceEventData>,
454    ) {
455        if stopped.ptrace_only() && self.ptrace.is_none() {
456            return;
457        }
458
459        if self.base.load_stopped().is_illegal_transition(stopped) {
460            return;
461        }
462
463        // TODO(https://g-issues.fuchsia.dev/issues/306438676): When task can be
464        // stopped inside user code, task will need to be either restarted or
465        // stopped here.
466        self.store_stopped(stopped);
467        if stopped.is_stopped() {
468            if let Some(ref current_task) = current_task {
469                self.copy_state_from(current_task);
470            }
471        }
472        if let Some(ptrace) = &mut self.ptrace {
473            ptrace.set_last_signal(siginfo);
474            ptrace.set_last_event(event);
475        }
476        if stopped == StopState::Waking || stopped == StopState::ForceWaking {
477            self.notify_ptracees();
478        }
479        if !stopped.is_in_progress() {
480            self.notify_ptracers();
481        }
482    }
483
484    /// Enqueues a signal at the back of the task's signal queue.
485    pub fn enqueue_signal(&mut self, signal: SignalInfo) {
486        self.signals.enqueue(signal);
487        self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
488    }
489
490    /// Enqueues the signal, allowing the signal to skip straight to the front of the task's queue.
491    ///
492    /// `enqueue_signal` is the more common API to use.
493    ///
494    /// Note that this will not guarantee that the signal is dequeued before any process-directed
495    /// signals.
496    pub fn enqueue_signal_front(&mut self, signal: SignalInfo) {
497        self.signals.enqueue(signal);
498        self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
499    }
500
501    /// Sets the current signal mask of the task.
502    pub fn set_signal_mask(&mut self, mask: SigSet) {
503        self.signals.set_mask(mask);
504        self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
505    }
506
507    /// Sets a temporary signal mask for the task.
508    ///
509    /// This mask should be removed by a matching call to `restore_signal_mask`.
510    pub fn set_temporary_signal_mask(&mut self, mask: SigSet) {
511        self.signals.set_temporary_mask(mask);
512        self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
513    }
514
515    /// Returns the number of pending signals for this task, without considering the signal mask.
516    pub fn pending_signal_count(&self) -> usize {
517        self.signals.num_queued() + self.base.thread_group().num_signals_queued()
518    }
519
520    /// Returns `true` if `signal` is pending for this task, without considering the signal mask.
521    pub fn has_signal_pending(&self, signal: Signal) -> bool {
522        self.signals.has_queued(signal) || self.base.thread_group().has_signal_queued(signal)
523    }
524
525    // Prepare a SignalInfo to be sent to the tracer, if any.
526    pub fn prepare_signal_info(
527        &mut self,
528        stopped: StopState,
529    ) -> Option<(Weak<ThreadGroup>, SignalInfo)> {
530        if !stopped.is_stopped() {
531            return None;
532        }
533
534        if let Some(ptrace) = &self.ptrace {
535            if let Some(last_signal) = ptrace.get_last_signal_ref() {
536                let signal_info = SignalInfo::with_detail(
537                    SIGCHLD,
538                    CLD_TRAPPED as i32,
539                    SignalDetail::SIGCHLD {
540                        pid: self.base.tid,
541                        uid: self.base.real_creds().uid,
542                        status: last_signal.signal.number() as i32,
543                    },
544                );
545
546                return Some((ptrace.core_state.thread_group.clone(), signal_info));
547            }
548        }
549
550        None
551    }
552
553    pub fn set_ptrace(&mut self, tracer: Option<Box<PtraceState>>) -> Result<(), Errno> {
554        if tracer.is_some() && self.ptrace.is_some() {
555            return error!(EPERM);
556        }
557
558        if tracer.is_none() {
559            // Handle the case where this is called while the thread group is being released.
560            if let Ok(tg_stop_state) = self.base.thread_group().load_stopped().as_in_progress() {
561                self.set_stopped(tg_stop_state, None, None, None);
562            }
563        }
564        self.ptrace = tracer;
565        Ok(())
566    }
567
568    pub fn can_accept_ptrace_commands(&mut self) -> bool {
569        !self.base.load_stopped().is_waking_or_awake()
570            && self.is_ptraced()
571            && !self.is_ptrace_listening()
572    }
573
574    fn store_stopped(&mut self, state: StopState) {
575        // We don't actually use the guard but we require it to enforce that the
576        // caller holds the thread group's mutable state lock (identified by
577        // mutable access to the thread group's mutable state).
578
579        self.base.stop_state.store(state, Ordering::Relaxed)
580    }
581
582    pub fn update_flags(&mut self, clear: TaskFlags, set: TaskFlags) {
583        // We don't actually use the guard but we require it to enforce that the
584        // caller holds the task's mutable state lock (identified by mutable
585        // access to the task's mutable state).
586
587        debug_assert_eq!(clear ^ set, clear | set);
588        let observed = self.base.flags();
589        let swapped = self.base.flags.swap((observed | set) & !clear, Ordering::Relaxed);
590        debug_assert_eq!(swapped, observed);
591    }
592
593    pub fn set_flags(&mut self, flag: TaskFlags, v: bool) {
594        let (clear, set) = if v { (TaskFlags::empty(), flag) } else { (flag, TaskFlags::empty()) };
595
596        self.update_flags(clear, set);
597    }
598
599    pub fn set_spawned(&mut self) {
600        self.set_flags(TaskFlags::SPAWNED, true);
601    }
602
603    pub fn set_exit_status(&mut self, status: ExitStatus) {
604        self.set_flags(TaskFlags::EXITED, true);
605        self.exit_status = Some(status);
606    }
607
608    pub fn set_exit_status_if_not_already(&mut self, status: ExitStatus) {
609        self.set_flags(TaskFlags::EXITED, true);
610        self.exit_status.get_or_insert(status);
611    }
612
613    /// The set of pending signals for the task, including the signals pending for the thread
614    /// group.
615    pub fn pending_signals(&self) -> SigSet {
616        self.signals.pending() | self.base.thread_group().get_pending_signals()
617    }
618
619    /// The set of pending signals for the task specifically, not including the signals pending
620    /// for the thread group.
621    pub fn task_specific_pending_signals(&self) -> SigSet {
622        self.signals.pending()
623    }
624
625    /// Returns true if any currently pending signal is allowed by `mask`.
626    pub fn is_any_signal_allowed_by_mask(&self, mask: SigSet) -> bool {
627        self.signals.is_any_allowed_by_mask(mask)
628            || self.base.thread_group().is_any_signal_allowed_by_mask(mask)
629    }
630
631    /// Returns whether or not a signal is pending for this task, taking the current
632    /// signal mask into account.
633    pub fn is_any_signal_pending(&self) -> bool {
634        let mask = self.signal_mask();
635        self.signals.is_any_pending()
636            || self.base.thread_group().is_any_signal_allowed_by_mask(mask)
637    }
638
639    /// Returns the next pending signal that passes `predicate`.
640    fn take_next_signal_where<F>(&mut self, predicate: F) -> Option<SignalInfo>
641    where
642        F: Fn(&SignalInfo) -> bool,
643    {
644        if let Some(signal) = self.base.thread_group().take_next_signal_where(&predicate) {
645            Some(signal)
646        } else {
647            let s = self.signals.take_next_where(&predicate);
648            self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
649            s
650        }
651    }
652
653    /// Removes and returns the next pending `signal` for this task.
654    ///
655    /// Returns `None` if `siginfo` is a blocked signal, or no such signal is pending.
656    pub fn take_specific_signal(&mut self, siginfo: SignalInfo) -> Option<SignalInfo> {
657        let signal_mask = self.signal_mask();
658        if signal_mask.has_signal(siginfo.signal) {
659            return None;
660        }
661
662        let predicate = |s: &SignalInfo| s.signal == siginfo.signal;
663        self.take_next_signal_where(predicate)
664    }
665
666    /// Removes and returns a pending signal that is unblocked by the current signal mask.
667    ///
668    /// Returns `None` if there are no unblocked signals pending.
669    pub fn take_any_signal(&mut self) -> Option<SignalInfo> {
670        self.take_signal_with_mask(self.signal_mask())
671    }
672
673    /// Removes and returns a pending signal that is unblocked by `signal_mask`.
674    ///
675    /// Returns `None` if there are no signals pending that are unblocked by `signal_mask`.
676    pub fn take_signal_with_mask(&mut self, signal_mask: SigSet) -> Option<SignalInfo> {
677        let predicate = |s: &SignalInfo| !signal_mask.has_signal(s.signal) || s.force;
678        self.take_next_signal_where(predicate)
679    }
680
681    /// Enqueues an internal signal at the back of the task's kernel signal queue.
682    pub fn enqueue_kernel_signal(&mut self, signal: KernelSignal) {
683        self.kernel_signals.push_back(signal);
684        self.set_flags(TaskFlags::KERNEL_SIGNALS_AVAILABLE, true);
685    }
686
687    /// Removes and returns a pending internal signal.
688    ///
689    /// Returns `None` if there are no signals pending.
690    pub fn take_kernel_signal(&mut self) -> Option<KernelSignal> {
691        let signal = self.kernel_signals.pop_front();
692        if self.kernel_signals.is_empty() {
693            self.set_flags(TaskFlags::KERNEL_SIGNALS_AVAILABLE, false);
694        }
695        signal
696    }
697
698    #[cfg(test)]
699    pub fn queued_signal_count(&self, signal: Signal) -> usize {
700        self.signals.queued_count(signal)
701            + self.base.thread_group().pending_signals.lock().queued_count(signal)
702    }
703}
704
705#[derive(Debug, Clone, Copy, PartialEq, Eq)]
706pub enum TaskStateCode {
707    // Task is being executed.
708    Running,
709
710    // Task is waiting for an event.
711    Sleeping,
712
713    // Tracing stop
714    TracingStop,
715
716    // Task has exited.
717    Zombie,
718}
719
720impl TaskStateCode {
721    pub fn code_char(&self) -> char {
722        match self {
723            TaskStateCode::Running => 'R',
724            TaskStateCode::Sleeping => 'S',
725            TaskStateCode::TracingStop => 't',
726            TaskStateCode::Zombie => 'Z',
727        }
728    }
729
730    pub fn name(&self) -> &'static str {
731        match self {
732            TaskStateCode::Running => "running",
733            TaskStateCode::Sleeping => "sleeping",
734            TaskStateCode::TracingStop => "tracing stop",
735            TaskStateCode::Zombie => "zombie",
736        }
737    }
738}
739
740/// The information of the task that needs to be available to the `ThreadGroup` while computing
741/// which process a wait can target. It is necessary to shared this data with the `ThreadGroup` so
742/// that it is available while the task is being dropped and so is not accessible from a weak
743/// pointer.
744#[derive(Debug)]
745pub struct TaskPersistentInfoState {
746    /// Immutable information about the task
747    tid: tid_t,
748    thread_group_key: ThreadGroupKey,
749
750    /// The command of this task.
751    command: LockDepMutex<TaskCommand, TaskCommandLevel>,
752
753    /// The security credentials for this task. These are only set when the task is the CurrentTask,
754    /// or on task creation.
755    creds: RcuArc<Credentials>,
756
757    // A lock for the security credentials. Writers must take the lock, readers that need to ensure
758    // that the task state does not change may take the lock.
759    creds_lock: LockDepRwLock<(), TaskCredsLock>,
760}
761
762/// Guard for reading locked credentials.
763pub struct CredentialsReadGuard<'a> {
764    _lock: LockDepReadGuard<'a, ()>,
765    creds: RcuReadGuard<Credentials>,
766}
767
768impl<'a> Deref for CredentialsReadGuard<'a> {
769    type Target = Credentials;
770
771    fn deref(&self) -> &Self::Target {
772        self.creds.deref()
773    }
774}
775
776/// Guard for writing credentials. No `CredentialsReadGuard` to the same task can concurrently
777///  exist.
778pub struct CredentialsWriteGuard<'a> {
779    _lock: LockDepWriteGuard<'a, ()>,
780    creds: &'a RcuArc<Credentials>,
781}
782
783impl<'a> CredentialsWriteGuard<'a> {
784    pub fn update(&mut self, creds: Arc<Credentials>) {
785        self.creds.update(creds);
786    }
787}
788
789impl TaskPersistentInfoState {
790    fn new(
791        tid: tid_t,
792        thread_group_key: ThreadGroupKey,
793        command: TaskCommand,
794        creds: Arc<Credentials>,
795    ) -> TaskPersistentInfo {
796        Arc::new(Self {
797            tid,
798            thread_group_key,
799            command: command.into(),
800            creds: RcuArc::new(creds),
801            creds_lock: Default::default(),
802        })
803    }
804
805    pub fn tid(&self) -> tid_t {
806        self.tid
807    }
808
809    pub fn pid(&self) -> pid_t {
810        self.thread_group_key.pid()
811    }
812
813    pub fn command_guard(&self) -> LockDepGuard<'_, TaskCommand> {
814        self.command.lock()
815    }
816
817    /// Snapshots the credentials, returning a short-lived RCU-guarded reference.
818    pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
819        self.creds.read()
820    }
821
822    /// Snapshots the credentials, returning a new reference. Use this if you need to stash the
823    /// credentials somewhere.
824    pub fn clone_creds(&self) -> Arc<Credentials> {
825        self.creds.to_arc()
826    }
827
828    /// Returns a read lock on the credentials. This is appropriate if you need to guarantee that
829    ///  the Task's credentials will not change during a security-sensitive operation.
830    pub fn lock_creds(&self) -> CredentialsReadGuard<'_> {
831        let lock = self.creds_lock.read();
832        CredentialsReadGuard { _lock: lock, creds: self.creds.read() }
833    }
834
835    /// Locks the credentials for writing, returning a guard that the `CurrentTask` can use to
836    /// update both the objective `Task` credentials, and its own subjective cached copy.
837    pub(in crate::task) fn write_current_task_creds(
838        self: &Arc<Self>,
839    ) -> CurrentTaskCredentialsWriteGuard {
840        let persistent_info = self.clone();
841        // SAFETY: `creds_lock` remains live via the `persistent_info` reference to `Self`.
842        let lock = unsafe {
843            let raw_lock = self.creds_lock.write();
844            std::mem::transmute::<LockDepWriteGuard<'_, ()>, LockDepWriteGuard<'static, ()>>(
845                raw_lock,
846            )
847        };
848        CurrentTaskCredentialsWriteGuard { _lock: lock, persistent_info }
849    }
850}
851
852pub type TaskPersistentInfo = Arc<TaskPersistentInfoState>;
853
854pub struct CurrentTaskCredentialsWriteGuard {
855    // Drop order is critical: the lock must be dropped BEFORE the persistent_info Arc.
856    // Rust drops fields in declaration order (top-to-bottom).
857    // So _lock is dropped first, then persistent_info.
858    _lock: LockDepWriteGuard<'static, ()>,
859    pub persistent_info: TaskPersistentInfo,
860}
861
862impl CurrentTaskCredentialsWriteGuard {
863    pub fn update(self, current_task: &CurrentTask, creds: Arc<Credentials>) {
864        self.persistent_info.creds.update(creds.clone());
865        *current_task.current_creds.borrow_mut() = CurrentCreds::Cached(creds);
866
867        // The /proc/pid directory's ownership is updated when the task's euid
868        // or egid changes. See proc(5).
869        let maybe_node = current_task.running_state().proc_pid_directory_cache.cloned();
870        if let Some(node) = maybe_node {
871            let creds = current_task.real_creds().euid_as_fscred();
872            // SAFETY: The /proc/pid directory held by `proc_pid_directory_cache` represents the
873            // current task. It's owner and group are supposed to track the current task's euid and
874            // egid.
875            unsafe {
876                node.force_chown(creds);
877            }
878        }
879    }
880}
881
882/// A unit of execution.
883///
884/// A task is the primary unit of execution in the Starnix kernel. Most tasks are *user* tasks,
885/// which have an associated Zircon thread. The Zircon thread switches between restricted mode,
886/// in which the thread runs userspace code, and normal mode, in which the thread runs Starnix
887/// code.
888///
889/// Tasks track the resources used by userspace by referencing various objects, such as an
890/// `FdTable`, a `MemoryManager`, and an `FsContext`. Many tasks can share references to these
891/// objects. In principle, which objects are shared between which tasks can be largely arbitrary,
892/// but there are common patterns of sharing. For example, tasks created with `pthread_create`
893/// will share the `FdTable`, `MemoryManager`, and `FsContext` and are often called "threads" by
894/// userspace programmers. Tasks created by `posix_spawn` do not share these objects and are often
895/// called "processes" by userspace programmers. However, inside the kernel, there is no clear
896/// definition of a "thread" or a "process".
897///
898/// During boot, the kernel creates the first task, often called `init`. The vast majority of other
899/// tasks are created as transitive clones (e.g., using `clone(2)`) of that task. Sometimes, the
900/// kernel will create new tasks from whole cloth, either with a corresponding userspace component
901/// or to represent some background work inside the kernel.
902///
903/// See also `CurrentTask`, which represents the task corresponding to the thread that is currently
904/// executing.
905pub struct Task {
906    /// Weak reference to this `Task`. This allows us to retrieve an `Arc` from a raw `Task`.
907    pub weak_self: Weak<Self>,
908
909    /// A unique identifier for this task.
910    ///
911    /// This value can be read in userspace using `gettid(2)`. In general, this value
912    /// is different from the value return by `getpid(2)`, which returns the `id` of the leader
913    /// of the `thread_group`.
914    pub tid: tid_t,
915
916    /// The process key of this task.
917    pub thread_group_key: ThreadGroupKey,
918
919    /// The kernel to which this thread group belongs.
920    pub kernel: Arc<Kernel>,
921
922    /// The thread group to which this task belongs.
923    ///
924    /// The group of tasks in a thread group roughly corresponds to the userspace notion of a
925    /// process.
926    pub thread_group: Arc<ThreadGroup>,
927
928    /// The running state of the task.
929    ///
930    /// This is `None` for exited tasks.
931    pub running_state: RcuOptionArc<TaskRunningState>,
932
933    /// The stop state of the task, distinct from the stop state of the thread group.
934    ///
935    /// Must only be set when the `mutable_state` write lock is held.
936    stop_state: AtomicStopState,
937
938    /// The flags for the task.
939    ///
940    /// Must only be set the then `mutable_state` write lock is held.
941    flags: AtomicTaskFlags,
942
943    /// The mutable state of the Task.
944    mutable_state:
945        starnix_sync::LockDepRwLock<TaskMutableState, starnix_sync::TaskMutableStateLock>,
946
947    /// The information of the task that needs to be available to the `ThreadGroup` while computing
948    /// which process a wait can target.
949    /// Contains the command line, the task credentials and the exit signal.
950    /// See `TaskPersistentInfo` for more information.
951    pub persistent_info: TaskPersistentInfo,
952
953    /// For vfork and clone() with CLONE_VFORK, this is set when the task exits or calls execve().
954    /// It allows the calling task to block until the fork has been completed. Only populated
955    /// when created with the CLONE_VFORK flag.
956    vfork_event: Option<Arc<zx::Event>>,
957
958    /// Variable that can tell you whether there are currently seccomp
959    /// filters without holding a lock
960    pub seccomp_filter_state: SeccompState,
961
962    /// Tell you whether you are tracing syscall entry / exit without a lock.
963    pub trace_syscalls: AtomicBool,
964}
965
966/// The decoded cross-platform parts we care about for page fault exception reports.
967#[derive(Debug)]
968pub struct PageFaultExceptionReport {
969    pub faulting_address: u64,
970    pub not_present: bool, // Set when the page fault was due to a not-present page.
971    pub is_write: bool,    // Set when the triggering memory operation was a write.
972    pub is_execute: bool,  // Set when the triggering memory operation was an execute.
973}
974
975impl Task {
976    pub fn kernel(&self) -> &Arc<Kernel> {
977        &self.kernel
978    }
979
980    pub fn thread_group(&self) -> &Arc<ThreadGroup> {
981        &self.thread_group
982    }
983
984    pub fn has_same_address_space(&self, other: Option<&Arc<MemoryManager>>) -> bool {
985        match (self.mm(), other) {
986            (Ok(this), Some(other)) => Arc::ptr_eq(&this, other),
987            (Err(_), None) => true,
988            _ => false,
989        }
990    }
991
992    pub fn flags(&self) -> TaskFlags {
993        self.flags.load(Ordering::Relaxed)
994    }
995
996    pub fn is_spawned(&self) -> bool {
997        self.flags().contains(TaskFlags::SPAWNED)
998    }
999
1000    /// When the task exits, if there is a notification that needs to propagate
1001    /// to a ptracer, make sure it will propagate.
1002    pub fn set_ptrace_zombie(&self, pids: &mut crate::task::PidTable) {
1003        if !self.is_spawned() {
1004            // A task that has not fully spawned cannot become a zombie.
1005            return;
1006        }
1007
1008        let pgid = self.thread_group().read().process_group.leader;
1009        let exit_signal = self.thread_group().read().exit_signal.clone();
1010        let mut state = self.write();
1011        state.set_stopped(StopState::ForceAwake, None, None, None);
1012        if let Some(ptrace) = &mut state.ptrace {
1013            // Add a zombie that the ptracer will notice.
1014            ptrace.last_signal_waitable = true;
1015            let tracer_tg = ptrace.core_state.thread_group.upgrade();
1016            if let Some(tracer_tg) = tracer_tg {
1017                drop(state);
1018                let mut tracer_state = tracer_tg.write();
1019                if !tracer_state.is_running() {
1020                    // An exiting or exited tracer cannot accept new zombies.
1021                    return;
1022                }
1023
1024                let exit_status = self.exit_status().unwrap_or_else(|| {
1025                    starnix_logging::log_error!("Exiting without an exit code.");
1026                    ExitStatus::Exit(u8::MAX)
1027                });
1028                let uid = self.real_creds().uid;
1029                let exit_info = ProcessExitInfo { status: exit_status, exit_signal };
1030                let zombie = ZombieProcess {
1031                    thread_group_key: self.thread_group_key.clone(),
1032                    pgid,
1033                    uid,
1034                    exit_info: exit_info,
1035                    // ptrace doesn't need this.
1036                    time_stats: TaskTimeStats::default(),
1037                    is_canonical: false,
1038                };
1039
1040                tracer_state.zombie_ptracees.add(pids, self.tid, zombie);
1041            };
1042        }
1043    }
1044
1045    /// Disconnects this task from the tracer.
1046    pub fn ptrace_disconnect(&self) {
1047        // Get a reference to the ptracer thread group through the weak reference in PtraceCoreState
1048        // to avoid acquiring a PidTable lock.
1049        let tracer_tg = self
1050            .read()
1051            .ptrace
1052            .as_ref()
1053            .map(|p| p.core_state.thread_group.clone())
1054            .and_then(|tg| tg.upgrade());
1055        if let Some(tg) = tracer_tg {
1056            tg.ptracees.lock().remove(&self.tid);
1057        }
1058    }
1059
1060    pub fn exit_status(&self) -> Option<ExitStatus> {
1061        self.is_exitted().then(|| self.read().exit_status.clone()).flatten()
1062    }
1063
1064    pub fn is_exitted(&self) -> bool {
1065        self.flags().contains(TaskFlags::EXITED)
1066    }
1067
1068    pub fn load_stopped(&self) -> StopState {
1069        self.stop_state.load(Ordering::Relaxed)
1070    }
1071
1072    /// Upgrade a [`Weak<Task>`], returning [`Err(ESRCH)`] if the reference cannot be borrowed.
1073    pub fn from_weak(weak: &Weak<Task>) -> Result<Arc<Task>, Errno> {
1074        weak.upgrade().ok_or_else(|| errno!(ESRCH))
1075    }
1076
1077    /// Internal function for creating a Task object. Useful when you need to specify the value of
1078    /// every field. create_process and create_thread are more likely to be what you want.
1079    ///
1080    /// Any fields that should be initialized fresh for every task, even if the task was created
1081    /// with fork, are initialized to their defaults inside this function. All other fields are
1082    /// passed as parameters.
1083    #[allow(clippy::let_and_return)]
1084    pub fn new(
1085        tid: tid_t,
1086        command: TaskCommand,
1087        thread_group: Arc<ThreadGroup>,
1088        files: FdTable,
1089        mm: Option<Arc<MemoryManager>>,
1090        // The only case where fs should be None if when building the initial task that is the
1091        // used to build the initial FsContext.
1092        fs: Arc<FsContext>,
1093        creds: Arc<Credentials>,
1094        abstract_socket_namespace: Arc<AbstractUnixSocketNamespace>,
1095        abstract_vsock_namespace: Arc<AbstractVsockSocketNamespace>,
1096        signal_mask: SigSet,
1097        kernel_signals: VecDeque<KernelSignal>,
1098        vfork_event: Option<Arc<zx::Event>>,
1099        scheduler_state: SchedulerState,
1100        uts_ns: UtsNamespaceHandle,
1101        no_new_privs: bool,
1102        seccomp_filter_state: SeccompState,
1103        seccomp_filters: SeccompFilterContainer,
1104        robust_list_head: RobustListHeadPtr,
1105        timerslack_ns: u64,
1106    ) -> Arc<Self> {
1107        let thread_group_key = ThreadGroupKey::from(&thread_group);
1108        Arc::new_cyclic(|weak_self| {
1109            let task = Task {
1110                weak_self: weak_self.clone(),
1111                tid,
1112                thread_group_key: thread_group_key.clone(),
1113                kernel: Arc::clone(&thread_group.kernel),
1114                thread_group,
1115                running_state: RcuOptionArc::new(Some(Arc::new(TaskRunningState {
1116                    thread: Default::default(),
1117                    files,
1118                    mm: RcuOptionArc::new(mm),
1119                    fs: RcuArc::new(fs),
1120                    abstract_socket_namespace,
1121                    abstract_vsock_namespace,
1122                    proc_pid_directory_cache: Default::default(),
1123                }))),
1124                vfork_event,
1125                stop_state: AtomicStopState::new(StopState::Awake),
1126                flags: AtomicTaskFlags::new(TaskFlags::empty()),
1127                mutable_state: TaskMutableState {
1128                    clear_child_tid: UserRef::default(),
1129                    signals: SignalState::with_mask(signal_mask),
1130                    run_state: RunState::default(),
1131                    kernel_signals,
1132                    exit_status: None,
1133                    scheduler_state,
1134                    uts_ns,
1135                    no_new_privs,
1136                    oom_score_adj: Default::default(),
1137                    seccomp_filters,
1138                    robust_list_head,
1139                    timerslack_ns,
1140                    // The default timerslack is set to the current timerslack of the creating thread.
1141                    default_timerslack_ns: timerslack_ns,
1142                    ptrace: None,
1143                    captured_thread_state: None,
1144                    last_applied_role: None,
1145                    cpuset_path: "/".to_string(),
1146                }
1147                .into(),
1148                persistent_info: TaskPersistentInfoState::new(
1149                    tid,
1150                    thread_group_key,
1151                    command,
1152                    creds,
1153                ),
1154                seccomp_filter_state,
1155                trace_syscalls: AtomicBool::new(false),
1156            };
1157
1158            #[cfg(any(test, debug_assertions))]
1159            {
1160                // Note that `Kernel::pids` is already locked by the caller of `Task::new()`.
1161                let _l1 = task.persistent_info.lock_creds();
1162                let _l2 = task.read();
1163                let _l3 = task.persistent_info.command_guard();
1164            }
1165            task
1166        })
1167    }
1168
1169    state_accessor!(Task, mutable_state);
1170
1171    /// Returns the real credentials of the task as a short-lived RCU-guarded reference. These
1172    /// credentials are used to check permissions for actions performed on the task. If the task
1173    /// itself is performing an action, use `CurrentTask::current_creds` instead. This does not
1174    /// lock the credentials.
1175    pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
1176        self.persistent_info.real_creds()
1177    }
1178
1179    /// Returns a new long-lived reference to the real credentials of the task.  These credentials
1180    /// are used to check permissions for actions performed on the task. If the task itself is
1181    /// performing an action, use `CurrentTask::current_creds` instead. This does not lock the
1182    /// credentials.
1183    pub fn clone_creds(&self) -> Arc<Credentials> {
1184        self.persistent_info.clone_creds()
1185    }
1186
1187    pub fn ptracer_task(&self) -> Option<Arc<Task>> {
1188        self.read().ptrace.as_ref().and_then(|p| p.core_state.task.upgrade())
1189    }
1190
1191    /// Determine whether the task is running.
1192    ///
1193    /// # Thread Safety
1194    ///
1195    /// The task may exit immediately after `is_running()` returns `true`.
1196    pub fn is_running(&self) -> bool {
1197        self.running_state.read().is_some()
1198    }
1199
1200    /// Returns the running state of the task, if it exists.
1201    ///
1202    /// # Errors
1203    ///
1204    /// Returns [`Err(ESRCH)`] if the task has already transitioned to a zombie state and its running
1205    /// resources have been dropped.
1206    #[track_caller]
1207    pub fn running_state(&self) -> Result<Arc<TaskRunningState>, Errno> {
1208        self.running_state.to_option_arc().ok_or_else(|| errno!(ESRCH))
1209    }
1210
1211    /// Returns the file descriptor table of the task, if it exists.
1212    ///
1213    /// # Errors
1214    ///
1215    /// Returns [`Err(errno)`] where `errno` is:
1216    ///
1217    ///   - `ESRCH`: the task is dead and its live resources have been dropped.
1218    #[track_caller]
1219    pub fn files(&self) -> Result<FdTable, Errno> {
1220        Ok(self.running_state()?.files())
1221    }
1222
1223    /// Returns the memory manager of the task, if it exists.
1224    ///
1225    /// # Errors
1226    ///
1227    /// Returns [`Err(errno)`] where `errno` is:
1228    ///
1229    ///   - `ESRCH`: the task is dead and its live resources have been dropped.
1230    ///   - `EINVAL`: the task does not have a memory manager.
1231    #[track_caller]
1232    pub fn mm(&self) -> Result<Arc<MemoryManager>, Errno> {
1233        // Retain an RCU read scope for the entire operation. This allows self.running_state() and
1234        // mm.to_option_arc() to use cheaper nested RCU read locks.
1235        let _scope = RcuReadScope::new();
1236        self.running_state()?.mm.to_option_arc().ok_or_else(|| errno!(EINVAL))
1237    }
1238
1239    /// Modify the given elements of the scheduler state with new values and update the
1240    /// task's thread's role.
1241    pub(crate) fn set_scheduler_policy_priority_and_reset_on_fork(
1242        &self,
1243        policy: SchedulingPolicy,
1244        priority: RealtimePriority,
1245        reset_on_fork: bool,
1246    ) -> Result<(), Errno> {
1247        self.update_scheduler_state_then_role(|scheduler_state| {
1248            scheduler_state.policy = policy;
1249            scheduler_state.realtime_priority = priority;
1250            scheduler_state.reset_on_fork = reset_on_fork;
1251        })
1252    }
1253
1254    /// Modify the scheduler state's priority and update the task's thread's role.
1255    pub(crate) fn set_scheduler_priority(&self, priority: RealtimePriority) -> Result<(), Errno> {
1256        self.update_scheduler_state_then_role(|scheduler_state| {
1257            scheduler_state.realtime_priority = priority
1258        })
1259    }
1260
1261    /// Modify the scheduler state's nice and update the task's thread's role.
1262    pub(crate) fn set_scheduler_nice(&self, nice: NormalPriority) -> Result<(), Errno> {
1263        self.update_scheduler_state_then_role(|scheduler_state| {
1264            scheduler_state.normal_priority = nice
1265        })
1266    }
1267
1268    /// Overwrite the existing scheduler state with a new one and update the task's thread's role.
1269    pub fn set_scheduler_state(&self, scheduler_state: SchedulerState) -> Result<(), Errno> {
1270        self.update_scheduler_state_then_role(|task_scheduler_state| {
1271            *task_scheduler_state = scheduler_state
1272        })
1273    }
1274
1275    /// Update the task's thread's role based on its current scheduler state without making any
1276    /// changes to the state.
1277    ///
1278    /// This should be called on tasks that have newly created threads, e.g. after cloning.
1279    pub fn sync_scheduler_state_to_role(&self) -> Result<(), Errno> {
1280        self.update_scheduler_state_then_role(|_| {})
1281    }
1282
1283    fn update_scheduler_state_then_role(
1284        &self,
1285        updater: impl FnOnce(&mut SchedulerState),
1286    ) -> Result<(), Errno> {
1287        let process_name = self
1288            .thread_group()
1289            .read()
1290            .get_task(self.thread_group().leader)
1291            .ok_or_else(|| errno!(EINVAL))?
1292            .command();
1293        let thread_name = self.command();
1294
1295        let (new_scheduler_state, cpuset_path, last_applied_role) = {
1296            let mut state = self.write();
1297            updater(&mut state.scheduler_state);
1298            (state.scheduler_state, state.cpuset_path.clone(), state.last_applied_role.clone())
1299        };
1300
1301        let scheduler = &self.thread_group().kernel.scheduler;
1302        let role_name = scheduler.resolve_role_name(
1303            &process_name,
1304            &thread_name,
1305            &cpuset_path,
1306            new_scheduler_state,
1307        );
1308        if last_applied_role.as_deref() == Some(role_name) {
1309            return Ok(());
1310        }
1311        scheduler.set_thread_role(self, role_name)?;
1312        // Note: Re-acquiring the lock here to update `last_applied_role` has a minor race if
1313        // concurrent state updates execute `set_thread_role` out of order relative to cache writes.
1314        // Dropping the lock across `set_thread_role` avoids holding `Task` write lock over FIDL RPCs,
1315        // and any cache mismatch will self-correct on the next scheduler state or cgroup change.
1316        self.write().last_applied_role = Some(role_name.to_string());
1317        Ok(())
1318    }
1319
1320    /// Signals the vfork event, if any, to unblock waiters.
1321    pub fn signal_vfork(&self) {
1322        if let Some(event) = &self.vfork_event {
1323            if let Err(status) = event.signal(Signals::NONE, Signals::USER_0) {
1324                log_warn!("Failed to set vfork signal {status}");
1325            }
1326        };
1327    }
1328
1329    /// Blocks the caller until the task has exited or executed execve(). This is used to implement
1330    /// vfork() and clone(... CLONE_VFORK, ...). The task must have created with CLONE_EXECVE.
1331    pub fn wait_for_execve(&self, task_to_wait: Weak<Task>) -> Result<(), Errno> {
1332        let event = task_to_wait.upgrade().and_then(|t| t.vfork_event.clone());
1333        if let Some(event) = event {
1334            event
1335                .wait_one(zx::Signals::USER_0, zx::MonotonicInstant::INFINITE)
1336                .map_err(|status| from_status_like_fdio!(status))?;
1337        }
1338        Ok(())
1339    }
1340
1341    /// If needed, clear the child tid for this task.
1342    ///
1343    /// Userspace can ask us to clear the child tid and issue a futex wake at
1344    /// the child tid address when we tear down a task. For example, bionic
1345    /// uses this mechanism to implement pthread_join. The thread that calls
1346    /// pthread_join sleeps using FUTEX_WAIT on the child tid address. We wake
1347    /// them up here to let them know the thread is done.
1348    pub fn clear_child_tid_if_needed(&self) -> Result<(), Errno> {
1349        let mut state = self.write();
1350        let user_tid = state.clear_child_tid;
1351        if !user_tid.is_null() {
1352            let zero: tid_t = 0;
1353            self.write_object(user_tid, &zero)?;
1354            self.kernel().shared_futexes.wake(
1355                self,
1356                user_tid.addr(),
1357                usize::MAX,
1358                FUTEX_BITSET_MATCH_ANY,
1359            )?;
1360            state.clear_child_tid = UserRef::default();
1361        }
1362        Ok(())
1363    }
1364
1365    pub fn get_task(&self, tid: tid_t) -> Result<Arc<Task>, Errno> {
1366        self.kernel().pids.read().get_task(tid)
1367    }
1368
1369    pub fn get_pid(&self) -> pid_t {
1370        self.thread_group_key.pid()
1371    }
1372
1373    pub fn get_tid(&self) -> tid_t {
1374        self.tid
1375    }
1376
1377    pub fn is_leader(&self) -> bool {
1378        self.get_pid() == self.get_tid()
1379    }
1380
1381    pub fn read_argv(&self, max_len: usize) -> Result<Vec<FsString>, Errno> {
1382        // argv is empty for kthreads
1383        let Ok(mm) = self.mm() else {
1384            return Ok(vec![]);
1385        };
1386        let (argv_start, argv_end) = {
1387            let mm_state = mm.state.read();
1388            (mm_state.argv_start, mm_state.argv_end)
1389        };
1390
1391        let len_to_read = std::cmp::min(argv_end - argv_start, max_len);
1392        self.read_nul_delimited_c_string_list(argv_start, len_to_read)
1393    }
1394
1395    pub fn read_argv0(&self) -> Result<FsString, Errno> {
1396        // argv is empty for kthreads
1397        let Ok(mm) = self.mm() else {
1398            return Ok(FsString::default());
1399        };
1400        let argv_start = {
1401            let mm_state = mm.state.read();
1402            mm_state.argv_start
1403        };
1404        // Assuming a 64-bit arch width is fine for a type that's just u8's on all arches.
1405        let argv_start = UserCString::new(&ArchWidth::Arch64, argv_start);
1406        self.read_path(argv_start)
1407    }
1408
1409    pub fn read_env(&self, max_len: usize) -> Result<Vec<FsString>, Errno> {
1410        // environment is empty for kthreads
1411        let Ok(mm) = self.mm() else { return Ok(vec![]) };
1412        let (env_start, env_end) = {
1413            let mm_state = mm.state.read();
1414            (mm_state.environ_start, mm_state.environ_end)
1415        };
1416
1417        let len_to_read = std::cmp::min(env_end - env_start, max_len);
1418        self.read_nul_delimited_c_string_list(env_start, len_to_read)
1419    }
1420
1421    pub fn thread_runtime_info(&self) -> Result<zx::TaskRuntimeInfo, Errno> {
1422        self.running_state()?
1423            .thread
1424            .get()
1425            .ok_or_else(|| errno!(EINVAL))?
1426            .get_runtime_info()
1427            .map_err(|status| from_status_like_fdio!(status))
1428    }
1429
1430    pub fn real_fscred(&self) -> FsCred {
1431        self.real_creds().as_fscred()
1432    }
1433
1434    /// Interrupts the current task.
1435    ///
1436    /// This will interrupt any blocking syscalls if the task is blocked on one.
1437    /// The signal_state of the task must not be locked.
1438    pub fn interrupt(&self) {
1439        let Ok(running_state) = self.running_state() else {
1440            log_warn!("Cannot interrupt dead task {}", self.get_tid());
1441            return;
1442        };
1443
1444        self.read().run_state.wake();
1445        if let Some(thread) = running_state.thread.get() {
1446            #[allow(
1447                clippy::undocumented_unsafe_blocks,
1448                reason = "Force documented unsafe blocks in Starnix"
1449            )]
1450            let status = unsafe { zx::sys::zx_restricted_kick(thread.raw_handle(), 0) };
1451            if status != zx::sys::ZX_OK {
1452                // zx_restricted_kick() could return ZX_ERR_BAD_STATE if the target thread is already in the
1453                // DYING or DEAD states. That's fine since it means that the task is in the process of
1454                // tearing down, so allow it.
1455                assert_eq!(status, zx::sys::ZX_ERR_BAD_STATE);
1456            }
1457        }
1458    }
1459
1460    pub fn command(&self) -> TaskCommand {
1461        self.persistent_info.command.lock().clone()
1462    }
1463
1464    pub fn set_command_name(&self, mut new_name: TaskCommand) {
1465        let Ok(running_state) = self.running_state() else {
1466            log_warn!("Cannot set command name for dead task {}", self.get_tid());
1467            return;
1468        };
1469
1470        // If we're going to update the process name, see if we can get a longer one than normally
1471        // provided in the Linux uapi. Only choose the argv0-based name if it's a superset of the
1472        // uapi-provided name to avoid clobbering the name provided by the user.
1473        if let Ok(argv0) = self.read_argv0() {
1474            let argv0 = TaskCommand::from_path_bytes(&argv0);
1475            if let Some(embedded_name) = argv0.try_embed(&new_name) {
1476                new_name = embedded_name;
1477            }
1478        }
1479
1480        // Acquire this before modifying Zircon state to ensure consistency under concurrent access.
1481        // Ideally this would also guard the logic above to read argv[0] but we can't due to lock
1482        // cycles with SELinux checks.
1483        let mut command_guard = self.persistent_info.command_guard();
1484
1485        // Set the name on the Linux thread.
1486        if let Some(thread) = running_state.thread.get() {
1487            set_zx_name(thread.thread.as_ref(), new_name.as_bytes());
1488        }
1489
1490        // If this is the thread group leader, use this name for the process too.
1491        if self.is_leader() {
1492            set_zx_name(&*self.thread_group().process, new_name.as_bytes());
1493            let _ = zx::Thread::raise_user_exception(
1494                zx::RaiseExceptionOptions::TARGET_JOB_DEBUGGER,
1495                zx::sys::ZX_EXCP_USER_CODE_PROCESS_NAME_CHANGED,
1496                0,
1497            );
1498        }
1499
1500        // Avoid a lock cycle by dropping the guard before notifying memory attribution of the
1501        // change.
1502        *command_guard = new_name;
1503        drop(command_guard);
1504
1505        if self.is_leader() {
1506            if let Some(notifier) = &self.thread_group().read().notifier {
1507                let _ = notifier.send(MemoryAttributionLifecycleEvent::name_change(self.tid));
1508            }
1509        }
1510
1511        if let Err(err) = self.sync_scheduler_state_to_role() {
1512            log_warn!(err:?; "Failed to update scheduler role after thread name change.");
1513        }
1514    }
1515
1516    pub fn set_seccomp_state(&self, state: SeccompStateValue) -> Result<(), Errno> {
1517        self.seccomp_filter_state.set(&state)
1518    }
1519
1520    pub fn state_code(&self) -> TaskStateCode {
1521        let status = self.read();
1522        if status.exit_status.is_some() {
1523            TaskStateCode::Zombie
1524        } else if status.run_state.is_blocked() {
1525            let stop_state = self.load_stopped();
1526            if stop_state.ptrace_only() && stop_state.is_stopped() {
1527                TaskStateCode::TracingStop
1528            } else {
1529                TaskStateCode::Sleeping
1530            }
1531        } else {
1532            TaskStateCode::Running
1533        }
1534    }
1535
1536    pub fn time_stats(&self) -> TaskTimeStats {
1537        use zx::Task;
1538        // TODO(https://fxbug.dev/297440106): Return time stats for zombie tasks.
1539        let running_state = match self.running_state() {
1540            Ok(running_state) => running_state,
1541            Err(_) => return TaskTimeStats::default(),
1542        };
1543        let info = match running_state.thread.get() {
1544            Some(thread) => thread.get_runtime_info().expect("Failed to get thread stats"),
1545            None => return TaskTimeStats::default(),
1546        };
1547
1548        TaskTimeStats {
1549            user_time: zx::MonotonicDuration::from_nanos(info.cpu_time),
1550            // TODO(https://fxbug.dev/42078242): How can we calculate system time?
1551            system_time: zx::MonotonicDuration::default(),
1552        }
1553    }
1554
1555    pub fn get_signal_action(&self, signal: Signal) -> sigaction_t {
1556        self.thread_group().signal_actions.get(signal)
1557    }
1558
1559    pub fn should_check_for_pending_signals(&self) -> bool {
1560        self.flags().intersects(
1561            TaskFlags::KERNEL_SIGNALS_AVAILABLE
1562                | TaskFlags::SIGNALS_AVAILABLE
1563                | TaskFlags::TEMPORARY_SIGNAL_MASK,
1564        ) || self.thread_group.has_pending_signals.load(Ordering::Relaxed)
1565    }
1566
1567    pub fn record_pid_koid_mapping(&self) {
1568        let Ok(running_state) = self.running_state() else {
1569            log_warn!("Cannot record pid/koid mapping for dead task {}", self.get_tid());
1570            return;
1571        };
1572
1573        let Some(ref mapping_table) = *self.kernel().pid_to_koid_mapping.read() else { return };
1574
1575        let pkoid = self.thread_group().get_process_koid().ok();
1576        let tkoid = running_state.thread.get().map(|t| t.koid);
1577        mapping_table.write().insert(self.tid, KoidPair { process: pkoid, thread: tkoid });
1578    }
1579}
1580
1581impl Drop for Task {
1582    fn drop(&mut self) {
1583        debug_assert!(self.running_state.read().is_none());
1584    }
1585}
1586
1587impl MemoryAccessor for Task {
1588    fn read_memory<'a>(
1589        &self,
1590        addr: UserAddress,
1591        bytes: &'a mut [MaybeUninit<u8>],
1592    ) -> Result<&'a mut [u8], Errno> {
1593        // Using a `Task` to read memory generally indicates that the memory
1594        // is being read from a task different than the `CurrentTask`. When
1595        // this `Task` is not current, its address space is not mapped
1596        // so we need to go through the VMO.
1597        self.mm()?.syscall_read_memory(addr, bytes)
1598    }
1599
1600    fn read_memory_partial_until_null_byte<'a>(
1601        &self,
1602        addr: UserAddress,
1603        bytes: &'a mut [MaybeUninit<u8>],
1604    ) -> Result<&'a mut [u8], Errno> {
1605        // Using a `Task` to read memory generally indicates that the memory
1606        // is being read from a task different than the `CurrentTask`. When
1607        // this `Task` is not current, its address space is not mapped
1608        // so we need to go through the VMO.
1609        self.mm()?.syscall_read_memory_partial_until_null_byte(addr, bytes)
1610    }
1611
1612    fn read_memory_partial<'a>(
1613        &self,
1614        addr: UserAddress,
1615        bytes: &'a mut [MaybeUninit<u8>],
1616    ) -> Result<&'a mut [u8], Errno> {
1617        // Using a `Task` to read memory generally indicates that the memory
1618        // is being read from a task different than the `CurrentTask`. When
1619        // this `Task` is not current, its address space is not mapped
1620        // so we need to go through the VMO.
1621        self.mm()?.syscall_read_memory_partial(addr, bytes)
1622    }
1623
1624    fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1625        // Using a `Task` to write memory generally indicates that the memory
1626        // is being written to a task different than the `CurrentTask`. When
1627        // this `Task` is not current, its address space is not mapped
1628        // so we need to go through the VMO.
1629        self.mm()?.syscall_write_memory(addr, bytes)
1630    }
1631
1632    fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1633        // Using a `Task` to write memory generally indicates that the memory
1634        // is being written to a task different than the `CurrentTask`. When
1635        // this `Task` is not current, its address space is not mapped
1636        // so we need to go through the VMO.
1637        self.mm()?.syscall_write_memory_partial(addr, bytes)
1638    }
1639
1640    fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
1641        // Using a `Task` to zero memory generally indicates that the memory
1642        // is being zeroed from a task different than the `CurrentTask`. When
1643        // this `Task` is not current, its address space is not mapped
1644        // so we need to go through the VMO.
1645        self.mm()?.syscall_zero(addr, length)
1646    }
1647}
1648
1649impl TaskMemoryAccessor for Task {
1650    fn maximum_valid_address(&self) -> Option<UserAddress> {
1651        self.mm().map(|mm| mm.maximum_valid_user_address).ok()
1652    }
1653}
1654
1655impl fmt::Debug for Task {
1656    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1657        write!(
1658            f,
1659            "{}:{}[{}]",
1660            self.thread_group().leader,
1661            self.tid,
1662            *self.persistent_info.command.lock()
1663        )
1664    }
1665}
1666
1667impl cmp::PartialEq for Task {
1668    fn eq(&self, other: &Self) -> bool {
1669        let ptr: *const Task = self;
1670        let other_ptr: *const Task = other;
1671        ptr == other_ptr
1672    }
1673}
1674
1675impl cmp::Eq for Task {}
1676
1677#[cfg(test)]
1678mod test {
1679    use super::*;
1680    use crate::security;
1681    use crate::testing::*;
1682    use starnix_uapi::auth::{CAP_SYS_ADMIN, Capabilities};
1683    use starnix_uapi::resource_limits::Resource;
1684    use starnix_uapi::signals::SIGCHLD;
1685    use starnix_uapi::{CLONE_SIGHAND, CLONE_THREAD, CLONE_VM, rlimit};
1686
1687    #[::fuchsia::test]
1688    async fn test_tid_allocation() {
1689        spawn_kernel_and_run(async |current_task| {
1690            let kernel = current_task.kernel();
1691            assert_eq!(current_task.get_tid(), 1);
1692            let another_current = create_task(&kernel, "another-task");
1693            let another_tid = another_current.get_tid();
1694            assert!(another_tid >= 2);
1695
1696            let pids = kernel.pids.read();
1697            assert_eq!(pids.get_task(1).unwrap().get_tid(), 1);
1698            assert_eq!(pids.get_task(another_tid).unwrap().get_tid(), another_tid);
1699        })
1700        .await;
1701    }
1702
1703    #[::fuchsia::test]
1704    async fn test_clone_pid_and_parent_pid() {
1705        spawn_kernel_and_run(async |current_task| {
1706            let thread = current_task.clone_task_for_test(
1707                (CLONE_THREAD | CLONE_VM | CLONE_SIGHAND) as u64,
1708                Some(SIGCHLD),
1709            );
1710            assert_eq!(current_task.get_pid(), thread.get_pid());
1711            assert_ne!(current_task.get_tid(), thread.get_tid());
1712            assert_eq!(current_task.thread_group().leader, thread.thread_group().leader);
1713
1714            let child_task = current_task.clone_task_for_test(0, Some(SIGCHLD));
1715            assert_ne!(current_task.get_pid(), child_task.get_pid());
1716            assert_ne!(current_task.get_tid(), child_task.get_tid());
1717            assert_eq!(current_task.get_pid(), child_task.thread_group().read().get_ppid());
1718        })
1719        .await;
1720    }
1721
1722    #[::fuchsia::test]
1723    async fn test_root_capabilities() {
1724        spawn_kernel_and_run(async |current_task| {
1725            assert!(security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN));
1726            assert_eq!(current_task.real_creds().cap_inheritable, Capabilities::empty());
1727
1728            current_task.set_creds(Credentials::with_ids(1, 1));
1729            assert!(!security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN));
1730        })
1731        .await;
1732    }
1733
1734    #[::fuchsia::test]
1735    async fn test_is_spawned() {
1736        spawn_kernel_and_run(async |current_task| {
1737            // The init task should be marked as spawned, because it is executing.
1738            assert!(current_task.is_spawned());
1739
1740            // A cloned task should not be marked as spawned, because it has not yet been executed.
1741            let child = current_task
1742                .clone_task(
1743                    0,
1744                    Some(SIGCHLD),
1745                    UserRef::default(),
1746                    UserRef::default(),
1747                    UserRef::default(),
1748                )
1749                .expect("failed to create task in test");
1750            assert!(!child.is_spawned());
1751            child.release(());
1752
1753            // A cloned task for a test should be marked as spawned, because we intentionally avoid
1754            // spawning threads for test tasks but want them to behave as normal tasks.
1755            let test_child = current_task.clone_task_for_test(0, Some(SIGCHLD));
1756            assert!(test_child.is_spawned());
1757        })
1758        .await;
1759    }
1760
1761    #[::fuchsia::test]
1762    async fn test_clone_rlimit() {
1763        spawn_kernel_and_run(async |current_task| {
1764            let prev_fsize = current_task.thread_group().get_rlimit(Resource::FSIZE);
1765            assert_ne!(prev_fsize, 10);
1766            current_task
1767                .thread_group()
1768                .limits
1769                .lock()
1770                .set(Resource::FSIZE, rlimit { rlim_cur: 10, rlim_max: 100 });
1771            let current_fsize = current_task.thread_group().get_rlimit(Resource::FSIZE);
1772            assert_eq!(current_fsize, 10);
1773
1774            let child_task = current_task.clone_task_for_test(0, Some(SIGCHLD));
1775            let child_fsize = child_task.thread_group().get_rlimit(Resource::FSIZE);
1776            assert_eq!(child_fsize, 10)
1777        })
1778        .await;
1779    }
1780
1781    #[::fuchsia::test]
1782    async fn test_set_command_name_syncs_scheduler_role() {
1783        use crate::task::{RoleOverrides, SchedulerManager};
1784
1785        let mut builder = RoleOverrides::new();
1786        builder.add("renamed-thread", "renamed-thread", None, "test-role");
1787        let overrides = builder.build().unwrap();
1788
1789        let scheduler_manager = SchedulerManager::new_for_tests(None, overrides);
1790
1791        spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
1792            // Set did_exec = true so custom role overrides are applied.
1793            current_task.thread_group().write().did_exec = true;
1794
1795            let scheduler = &current_task.thread_group().kernel.scheduler;
1796
1797            // Before rename, check task's role name.
1798            let initial_role = scheduler.role_name(current_task).unwrap();
1799            assert_ne!(initial_role, "test-role");
1800
1801            // Rename the task's thread to renamed-thread.
1802            current_task
1803                .set_command_name(starnix_task_command::TaskCommand::new(b"renamed-thread"));
1804
1805            let renamed_role = scheduler.role_name(current_task).unwrap();
1806            assert_eq!(renamed_role, "test-role");
1807        })
1808        .await;
1809    }
1810
1811    #[::fuchsia::test]
1812    async fn test_fork_does_not_inherit_custom_role() {
1813        use crate::task::{RoleOverrides, SchedulerManager};
1814
1815        let mut builder = RoleOverrides::new();
1816        builder.add("renamed-thread", "renamed-thread", None, "test-role");
1817        let overrides = builder.build().unwrap();
1818
1819        let scheduler_manager = SchedulerManager::new_for_tests(None, overrides);
1820
1821        spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
1822            // Fork a child process (which sets did_exec = false on the child's thread group)
1823            let child = current_task.clone_task_for_test(0, None);
1824
1825            let scheduler = &current_task.thread_group().kernel.scheduler;
1826
1827            // Before rename, check child's role name.
1828            let initial_role = scheduler.role_name(&child).unwrap();
1829            assert_ne!(initial_role, "test-role");
1830
1831            // Rename the child's thread to renamed-thread. Since did_exec is false on the child,
1832            // this should NOT map to "test-role" from the overrides.
1833            child.set_command_name(starnix_task_command::TaskCommand::new(b"renamed-thread"));
1834
1835            let renamed_role = scheduler.role_name(&child).unwrap();
1836            assert_ne!(renamed_role, "test-role");
1837        })
1838        .await;
1839    }
1840}