1use 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 Stop(SignalInfo, PtraceEvent),
62 Continue(SignalInfo, PtraceEvent),
63}
64impl ExitStatus {
65 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 const DUMP_ON_EXIT = 1 << 3;
116 const KERNEL_SIGNALS_AVAILABLE = 1 << 4;
117 const SPAWNED = 1 << 5;
119 }
120}
121
122pub struct CapturedThreadState {
129 pub thread_state: ThreadState<HeapRegs>,
132
133 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 pub clear_child_tid: UserRef<tid_t>,
196
197 signals: SignalState,
200
201 pub run_state: RunState,
203
204 kernel_signals: VecDeque<KernelSignal>,
212
213 exit_status: Option<ExitStatus>,
215
216 pub scheduler_state: SchedulerState,
218
219 pub uts_ns: UtsNamespaceHandle,
227
228 no_new_privs: bool,
238
239 pub oom_score_adj: i32,
241
242 pub seccomp_filters: SeccompFilterContainer,
244
245 pub robust_list_head: RobustListHeadPtr,
248
249 pub timerslack_ns: u64,
255
256 pub default_timerslack_ns: u64,
262
263 pub ptrace: Option<Box<PtraceState>>,
266
267 pub captured_thread_state: Option<Box<CapturedThreadState>>,
269
270 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 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 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 pub fn signal_mask(&self) -> SigSet {
355 self.signals.mask()
356 }
357
358 pub fn is_signal_masked(&self, signal: Signal) -> bool {
360 self.signals.mask().has_signal(signal)
361 }
362
363 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 pub fn restore_signal_mask(&mut self) {
373 self.signals.restore_mask();
374 }
375
376 pub fn is_blocked(&self) -> bool {
378 self.run_state.is_blocked()
379 }
380
381 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 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 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 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 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 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 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 pub fn pending_signal_count(&self) -> usize {
514 self.signals.num_queued() + self.base.thread_group().num_signals_queued()
515 }
516
517 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 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 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 self.base.stop_state.store(state, Ordering::Relaxed)
577 }
578
579 pub fn update_flags(&mut self, clear: TaskFlags, set: TaskFlags) {
580 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 pub fn pending_signals(&self) -> SigSet {
613 self.signals.pending() | self.base.thread_group().get_pending_signals()
614 }
615
616 pub fn task_specific_pending_signals(&self) -> SigSet {
619 self.signals.pending()
620 }
621
622 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 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 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 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 pub fn take_any_signal(&mut self) -> Option<SignalInfo> {
667 self.take_signal_with_mask(self.signal_mask())
668 }
669
670 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 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 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 Running,
706
707 Sleeping,
709
710 TracingStop,
712
713 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#[derive(Debug)]
742pub struct TaskPersistentInfoState {
743 tid: tid_t,
745 thread_group_key: ThreadGroupKey,
746
747 command: LockDepMutex<TaskCommand, TaskCommandLevel>,
749
750 creds: RcuArc<Credentials>,
753
754 creds_lock: LockDepRwLock<(), TaskCredsLock>,
757}
758
759pub 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
773pub 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 pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
816 self.creds.read()
817 }
818
819 pub fn clone_creds(&self) -> Arc<Credentials> {
822 self.creds.to_arc()
823 }
824
825 pub fn lock_creds(&self) -> CredentialsReadGuard<'_> {
828 let lock = self.creds_lock.read();
829 CredentialsReadGuard { _lock: lock, creds: self.creds.read() }
830 }
831
832 pub(in crate::task) fn write_current_task_creds(
835 self: &Arc<Self>,
836 ) -> CurrentTaskCredentialsWriteGuard {
837 let persistent_info = self.clone();
838 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 _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 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 unsafe {
873 node.force_chown(creds);
874 }
875 }
876 }
877}
878
879pub struct Task {
903 pub weak_self: Weak<Self>,
905
906 pub tid: tid_t,
912
913 pub thread_group_key: ThreadGroupKey,
915
916 pub kernel: Arc<Kernel>,
918
919 pub thread_group: Arc<ThreadGroup>,
924
925 pub running_state: RcuOptionBox<TaskRunningState>,
929
930 stop_state: AtomicStopState,
934
935 flags: AtomicTaskFlags,
939
940 mutable_state:
942 starnix_sync::LockDepRwLock<TaskMutableState, starnix_sync::TaskMutableStateLock>,
943
944 pub persistent_info: TaskPersistentInfo,
949
950 vfork_event: Option<Arc<zx::Event>>,
954
955 pub seccomp_filter_state: SeccompState,
958
959 pub trace_syscalls: AtomicBool,
961}
962
963#[derive(Debug)]
965pub struct PageFaultExceptionReport {
966 pub faulting_address: u64,
967 pub not_present: bool, pub is_write: bool, pub is_execute: bool, }
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 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 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 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 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 pub fn ptrace_disconnect(&self) {
1039 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 pub fn from_weak(weak: &Weak<Task>) -> Result<Arc<Task>, Errno> {
1066 weak.upgrade().ok_or_else(|| errno!(ESRCH))
1067 }
1068
1069 #[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 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 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 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 pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
1167 self.persistent_info.real_creds()
1168 }
1169
1170 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 pub fn is_running(&self) -> bool {
1188 self.running_state.read().is_some()
1189 }
1190
1191 #[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 #[track_caller]
1210 pub fn files(&self) -> Result<FdTable, Errno> {
1211 Ok(self.running_state()?.files())
1212 }
1213
1214 #[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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 let mut command_guard = self.persistent_info.command_guard();
1466
1467 if let Some(thread) = running_state.thread.get() {
1469 set_zx_name(thread.thread.as_ref(), new_name.as_bytes());
1470 }
1471
1472 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 *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 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 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 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 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 self.mm()?.syscall_read_memory_partial(addr, bytes)
1604 }
1605
1606 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1607 self.mm()?.syscall_write_memory(addr, bytes)
1612 }
1613
1614 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1615 self.mm()?.syscall_write_memory_partial(addr, bytes)
1620 }
1621
1622 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
1623 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 assert!(current_task.is_spawned());
1722
1723 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 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 current_task.thread_group().write().did_exec = true;
1778
1779 let scheduler = ¤t_task.thread_group().kernel.scheduler;
1780
1781 let initial_role = scheduler.role_name(current_task).unwrap();
1783 assert_ne!(initial_role, "test-role");
1784
1785 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 let child = current_task.clone_task_for_test(locked, 0, None);
1808
1809 let scheduler = ¤t_task.thread_group().kernel.scheduler;
1810
1811 let initial_role = scheduler.role_name(&child).unwrap();
1813 assert_ne!(initial_role, "test-role");
1814
1815 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}