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