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, RcuReadGuard, RcuReadScope};
24use macro_rules_attribute::apply;
25use starnix_logging::{log_warn, set_zx_name};
26use starnix_registers::HeapRegs;
27use starnix_sync::{
28 LockDepGuard, LockDepMutex, LockDepReadGuard, LockDepRwLock, LockDepWriteGuard,
29 TaskCommandLevel, TaskCredsLock,
30};
31use starnix_task_command::TaskCommand;
32use starnix_types::arch::ArchWidth;
33use starnix_types::stats::TaskTimeStats;
34use starnix_uapi::auth::{Credentials, FsCred};
35use starnix_uapi::errors::Errno;
36use starnix_uapi::signals::{SIGCHLD, SigSet, Signal, sigaltstack_contains_pointer};
37use starnix_uapi::user_address::{
38 ArchSpecific, MappingMultiArchUserRef, UserAddress, UserCString, UserRef,
39};
40use starnix_uapi::{
41 CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, CLD_TRAPPED,
42 FUTEX_BITSET_MATCH_ANY, errno, error, from_status_like_fdio, pid_t, sigaction_t, sigaltstack,
43 tid_t, uapi,
44};
45use std::collections::VecDeque;
46use std::mem::MaybeUninit;
47use std::ops::Deref;
48use std::sync::atomic::{AtomicBool, Ordering};
49use std::sync::{Arc, Weak};
50use std::{cmp, fmt};
51use zx::{Signals, Task as _};
52
53#[derive(Clone, Debug, Eq, PartialEq)]
54pub enum ExitStatus {
55 Exit(u8),
56 Kill(SignalInfo),
57 CoreDump(SignalInfo),
58 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 pub cpuset_path: String,
275}
276
277impl TaskMutableState {
278 pub fn no_new_privs(&self) -> bool {
279 self.no_new_privs
280 }
281
282 pub fn enable_no_new_privs(&mut self) {
285 self.no_new_privs = true;
286 }
287
288 pub fn get_timerslack<T: zx::Timeline>(&self) -> zx::Duration<T> {
289 zx::Duration::from_nanos(self.timerslack_ns as i64)
290 }
291
292 pub fn set_timerslack_ns(&mut self, ns: u64) {
296 if ns == 0 {
297 self.timerslack_ns = self.default_timerslack_ns;
298 } else {
299 self.timerslack_ns = ns;
300 }
301 }
302
303 pub fn is_ptraced(&self) -> bool {
304 self.ptrace.is_some()
305 }
306
307 pub fn is_ptrace_listening(&self) -> bool {
308 self.ptrace.as_ref().is_some_and(|ptrace| ptrace.stop_status == PtraceStatus::Listening)
309 }
310
311 pub fn ptrace_on_signal_consume(&mut self) -> bool {
312 self.ptrace.as_mut().is_some_and(|ptrace: &mut Box<PtraceState>| {
313 if ptrace.stop_status.is_continuing() {
314 ptrace.stop_status = PtraceStatus::Default;
315 false
316 } else {
317 true
318 }
319 })
320 }
321
322 pub fn notify_ptracers(&mut self) {
323 if let Some(ptrace) = &self.ptrace {
324 ptrace.tracer_waiters().notify_all();
325 }
326 }
327
328 pub fn wait_on_ptracer(&self, waiter: &Waiter) {
329 if let Some(ptrace) = &self.ptrace {
330 ptrace.tracee_waiters.wait_async(&waiter);
331 }
332 }
333
334 pub fn notify_ptracees(&mut self) {
335 if let Some(ptrace) = &self.ptrace {
336 ptrace.tracee_waiters.notify_all();
337 }
338 }
339
340 pub fn take_captured_state(&mut self) -> Option<Box<CapturedThreadState>> {
341 if self.captured_thread_state.is_some() {
342 let mut state = None;
343 std::mem::swap(&mut state, &mut self.captured_thread_state);
344 return state;
345 }
346 None
347 }
348
349 pub fn copy_state_from(&mut self, current_task: &CurrentTask) {
350 self.captured_thread_state = Some(Box::new(CapturedThreadState {
351 thread_state: current_task.thread_state.extended_snapshot::<HeapRegs>(),
352 dirty: false,
353 }));
354 }
355
356 pub fn signal_mask(&self) -> SigSet {
358 self.signals.mask()
359 }
360
361 pub fn is_signal_masked(&self, signal: Signal) -> bool {
363 self.signals.mask().has_signal(signal)
364 }
365
366 pub fn is_signal_masked_by_saved_mask(&self, signal: Signal) -> bool {
370 self.signals.saved_mask().is_some_and(|mask| mask.has_signal(signal))
371 }
372
373 pub fn restore_signal_mask(&mut self) {
376 self.signals.restore_mask();
377 }
378
379 pub fn is_blocked(&self) -> bool {
381 self.run_state.is_blocked()
382 }
383
384 pub fn set_run_state(&mut self, run_state: RunState) {
386 self.run_state = run_state;
387 }
388
389 pub fn run_state(&self) -> RunState {
390 self.run_state.clone()
391 }
392
393 pub fn on_signal_stack(&self, stack_pointer_register: u64) -> bool {
394 self.signals
395 .alt_stack
396 .map(|signal_stack| sigaltstack_contains_pointer(&signal_stack, stack_pointer_register))
397 .unwrap_or(false)
398 }
399
400 pub fn set_sigaltstack(&mut self, stack: Option<sigaltstack>) {
401 self.signals.alt_stack = stack;
402 }
403
404 pub fn sigaltstack(&self) -> Option<sigaltstack> {
405 self.signals.alt_stack
406 }
407
408 pub fn wait_on_signal(&mut self, waiter: &Waiter) {
409 self.signals.signal_wait.wait_async(waiter);
410 }
411
412 pub fn signals_mut(&mut self) -> &mut SignalState {
413 &mut self.signals
414 }
415
416 pub fn wait_on_signal_fd_events(
417 &self,
418 waiter: &Waiter,
419 mask: SigSet,
420 handler: EventHandler,
421 ) -> WaitCanceler {
422 self.signals.signal_wait.wait_async_signal_mask(waiter, mask, handler)
423 }
424
425 pub fn notify_signal_waiters(&self, signal: &Signal) {
426 self.signals.signal_wait.notify_signal(signal);
427 }
428
429 pub fn thaw(&mut self) {
431 if let RunState::Frozen(waiter) = self.run_state() {
432 waiter.notify();
433 }
434 }
435
436 pub fn is_frozen(&self) -> bool {
437 matches!(self.run_state(), RunState::Frozen(_))
438 }
439
440 #[cfg(test)]
441 pub fn kernel_signals_for_test(&self) -> &VecDeque<KernelSignal> {
442 &self.kernel_signals
443 }
444}
445
446#[apply(state_implementation!)]
447impl TaskMutableState<Base = Task> {
448 pub fn set_stopped(
449 &mut self,
450 stopped: StopState,
451 siginfo: Option<SignalInfo>,
452 current_task: Option<&CurrentTask>,
453 event: Option<PtraceEventData>,
454 ) {
455 if stopped.ptrace_only() && self.ptrace.is_none() {
456 return;
457 }
458
459 if self.base.load_stopped().is_illegal_transition(stopped) {
460 return;
461 }
462
463 self.store_stopped(stopped);
467 if stopped.is_stopped() {
468 if let Some(ref current_task) = current_task {
469 self.copy_state_from(current_task);
470 }
471 }
472 if let Some(ptrace) = &mut self.ptrace {
473 ptrace.set_last_signal(siginfo);
474 ptrace.set_last_event(event);
475 }
476 if stopped == StopState::Waking || stopped == StopState::ForceWaking {
477 self.notify_ptracees();
478 }
479 if !stopped.is_in_progress() {
480 self.notify_ptracers();
481 }
482 }
483
484 pub fn enqueue_signal(&mut self, signal: SignalInfo) {
486 self.signals.enqueue(signal);
487 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
488 }
489
490 pub fn enqueue_signal_front(&mut self, signal: SignalInfo) {
497 self.signals.enqueue(signal);
498 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
499 }
500
501 pub fn set_signal_mask(&mut self, mask: SigSet) {
503 self.signals.set_mask(mask);
504 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
505 }
506
507 pub fn set_temporary_signal_mask(&mut self, mask: SigSet) {
511 self.signals.set_temporary_mask(mask);
512 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
513 }
514
515 pub fn pending_signal_count(&self) -> usize {
517 self.signals.num_queued() + self.base.thread_group().num_signals_queued()
518 }
519
520 pub fn has_signal_pending(&self, signal: Signal) -> bool {
522 self.signals.has_queued(signal) || self.base.thread_group().has_signal_queued(signal)
523 }
524
525 pub fn prepare_signal_info(
527 &mut self,
528 stopped: StopState,
529 ) -> Option<(Weak<ThreadGroup>, SignalInfo)> {
530 if !stopped.is_stopped() {
531 return None;
532 }
533
534 if let Some(ptrace) = &self.ptrace {
535 if let Some(last_signal) = ptrace.get_last_signal_ref() {
536 let signal_info = SignalInfo::with_detail(
537 SIGCHLD,
538 CLD_TRAPPED as i32,
539 SignalDetail::SIGCHLD {
540 pid: self.base.tid,
541 uid: self.base.real_creds().uid,
542 status: last_signal.signal.number() as i32,
543 },
544 );
545
546 return Some((ptrace.core_state.thread_group.clone(), signal_info));
547 }
548 }
549
550 None
551 }
552
553 pub fn set_ptrace(&mut self, tracer: Option<Box<PtraceState>>) -> Result<(), Errno> {
554 if tracer.is_some() && self.ptrace.is_some() {
555 return error!(EPERM);
556 }
557
558 if tracer.is_none() {
559 if let Ok(tg_stop_state) = self.base.thread_group().load_stopped().as_in_progress() {
561 self.set_stopped(tg_stop_state, None, None, None);
562 }
563 }
564 self.ptrace = tracer;
565 Ok(())
566 }
567
568 pub fn can_accept_ptrace_commands(&mut self) -> bool {
569 !self.base.load_stopped().is_waking_or_awake()
570 && self.is_ptraced()
571 && !self.is_ptrace_listening()
572 }
573
574 fn store_stopped(&mut self, state: StopState) {
575 self.base.stop_state.store(state, Ordering::Relaxed)
580 }
581
582 pub fn update_flags(&mut self, clear: TaskFlags, set: TaskFlags) {
583 debug_assert_eq!(clear ^ set, clear | set);
588 let observed = self.base.flags();
589 let swapped = self.base.flags.swap((observed | set) & !clear, Ordering::Relaxed);
590 debug_assert_eq!(swapped, observed);
591 }
592
593 pub fn set_flags(&mut self, flag: TaskFlags, v: bool) {
594 let (clear, set) = if v { (TaskFlags::empty(), flag) } else { (flag, TaskFlags::empty()) };
595
596 self.update_flags(clear, set);
597 }
598
599 pub fn set_spawned(&mut self) {
600 self.set_flags(TaskFlags::SPAWNED, true);
601 }
602
603 pub fn set_exit_status(&mut self, status: ExitStatus) {
604 self.set_flags(TaskFlags::EXITED, true);
605 self.exit_status = Some(status);
606 }
607
608 pub fn set_exit_status_if_not_already(&mut self, status: ExitStatus) {
609 self.set_flags(TaskFlags::EXITED, true);
610 self.exit_status.get_or_insert(status);
611 }
612
613 pub fn pending_signals(&self) -> SigSet {
616 self.signals.pending() | self.base.thread_group().get_pending_signals()
617 }
618
619 pub fn task_specific_pending_signals(&self) -> SigSet {
622 self.signals.pending()
623 }
624
625 pub fn is_any_signal_allowed_by_mask(&self, mask: SigSet) -> bool {
627 self.signals.is_any_allowed_by_mask(mask)
628 || self.base.thread_group().is_any_signal_allowed_by_mask(mask)
629 }
630
631 pub fn is_any_signal_pending(&self) -> bool {
634 let mask = self.signal_mask();
635 self.signals.is_any_pending()
636 || self.base.thread_group().is_any_signal_allowed_by_mask(mask)
637 }
638
639 fn take_next_signal_where<F>(&mut self, predicate: F) -> Option<SignalInfo>
641 where
642 F: Fn(&SignalInfo) -> bool,
643 {
644 if let Some(signal) = self.base.thread_group().take_next_signal_where(&predicate) {
645 Some(signal)
646 } else {
647 let s = self.signals.take_next_where(&predicate);
648 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
649 s
650 }
651 }
652
653 pub fn take_specific_signal(&mut self, siginfo: SignalInfo) -> Option<SignalInfo> {
657 let signal_mask = self.signal_mask();
658 if signal_mask.has_signal(siginfo.signal) {
659 return None;
660 }
661
662 let predicate = |s: &SignalInfo| s.signal == siginfo.signal;
663 self.take_next_signal_where(predicate)
664 }
665
666 pub fn take_any_signal(&mut self) -> Option<SignalInfo> {
670 self.take_signal_with_mask(self.signal_mask())
671 }
672
673 pub fn take_signal_with_mask(&mut self, signal_mask: SigSet) -> Option<SignalInfo> {
677 let predicate = |s: &SignalInfo| !signal_mask.has_signal(s.signal) || s.force;
678 self.take_next_signal_where(predicate)
679 }
680
681 pub fn enqueue_kernel_signal(&mut self, signal: KernelSignal) {
683 self.kernel_signals.push_back(signal);
684 self.set_flags(TaskFlags::KERNEL_SIGNALS_AVAILABLE, true);
685 }
686
687 pub fn take_kernel_signal(&mut self) -> Option<KernelSignal> {
691 let signal = self.kernel_signals.pop_front();
692 if self.kernel_signals.is_empty() {
693 self.set_flags(TaskFlags::KERNEL_SIGNALS_AVAILABLE, false);
694 }
695 signal
696 }
697
698 #[cfg(test)]
699 pub fn queued_signal_count(&self, signal: Signal) -> usize {
700 self.signals.queued_count(signal)
701 + self.base.thread_group().pending_signals.lock().queued_count(signal)
702 }
703}
704
705#[derive(Debug, Clone, Copy, PartialEq, Eq)]
706pub enum TaskStateCode {
707 Running,
709
710 Sleeping,
712
713 TracingStop,
715
716 Zombie,
718}
719
720impl TaskStateCode {
721 pub fn code_char(&self) -> char {
722 match self {
723 TaskStateCode::Running => 'R',
724 TaskStateCode::Sleeping => 'S',
725 TaskStateCode::TracingStop => 't',
726 TaskStateCode::Zombie => 'Z',
727 }
728 }
729
730 pub fn name(&self) -> &'static str {
731 match self {
732 TaskStateCode::Running => "running",
733 TaskStateCode::Sleeping => "sleeping",
734 TaskStateCode::TracingStop => "tracing stop",
735 TaskStateCode::Zombie => "zombie",
736 }
737 }
738}
739
740#[derive(Debug)]
745pub struct TaskPersistentInfoState {
746 tid: tid_t,
748 thread_group_key: ThreadGroupKey,
749
750 command: LockDepMutex<TaskCommand, TaskCommandLevel>,
752
753 creds: RcuArc<Credentials>,
756
757 creds_lock: LockDepRwLock<(), TaskCredsLock>,
760}
761
762pub struct CredentialsReadGuard<'a> {
764 _lock: LockDepReadGuard<'a, ()>,
765 creds: RcuReadGuard<Credentials>,
766}
767
768impl<'a> Deref for CredentialsReadGuard<'a> {
769 type Target = Credentials;
770
771 fn deref(&self) -> &Self::Target {
772 self.creds.deref()
773 }
774}
775
776pub struct CredentialsWriteGuard<'a> {
779 _lock: LockDepWriteGuard<'a, ()>,
780 creds: &'a RcuArc<Credentials>,
781}
782
783impl<'a> CredentialsWriteGuard<'a> {
784 pub fn update(&mut self, creds: Arc<Credentials>) {
785 self.creds.update(creds);
786 }
787}
788
789impl TaskPersistentInfoState {
790 fn new(
791 tid: tid_t,
792 thread_group_key: ThreadGroupKey,
793 command: TaskCommand,
794 creds: Arc<Credentials>,
795 ) -> TaskPersistentInfo {
796 Arc::new(Self {
797 tid,
798 thread_group_key,
799 command: command.into(),
800 creds: RcuArc::new(creds),
801 creds_lock: Default::default(),
802 })
803 }
804
805 pub fn tid(&self) -> tid_t {
806 self.tid
807 }
808
809 pub fn pid(&self) -> pid_t {
810 self.thread_group_key.pid()
811 }
812
813 pub fn command_guard(&self) -> LockDepGuard<'_, TaskCommand> {
814 self.command.lock()
815 }
816
817 pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
819 self.creds.read()
820 }
821
822 pub fn clone_creds(&self) -> Arc<Credentials> {
825 self.creds.to_arc()
826 }
827
828 pub fn lock_creds(&self) -> CredentialsReadGuard<'_> {
831 let lock = self.creds_lock.read();
832 CredentialsReadGuard { _lock: lock, creds: self.creds.read() }
833 }
834
835 pub(in crate::task) fn write_current_task_creds(
838 self: &Arc<Self>,
839 ) -> CurrentTaskCredentialsWriteGuard {
840 let persistent_info = self.clone();
841 let lock = unsafe {
843 let raw_lock = self.creds_lock.write();
844 std::mem::transmute::<LockDepWriteGuard<'_, ()>, LockDepWriteGuard<'static, ()>>(
845 raw_lock,
846 )
847 };
848 CurrentTaskCredentialsWriteGuard { _lock: lock, persistent_info }
849 }
850}
851
852pub type TaskPersistentInfo = Arc<TaskPersistentInfoState>;
853
854pub struct CurrentTaskCredentialsWriteGuard {
855 _lock: LockDepWriteGuard<'static, ()>,
859 pub persistent_info: TaskPersistentInfo,
860}
861
862impl CurrentTaskCredentialsWriteGuard {
863 pub fn update(self, current_task: &CurrentTask, creds: Arc<Credentials>) {
864 self.persistent_info.creds.update(creds.clone());
865 *current_task.current_creds.borrow_mut() = CurrentCreds::Cached(creds);
866
867 let maybe_node = current_task.running_state().proc_pid_directory_cache.cloned();
870 if let Some(node) = maybe_node {
871 let creds = current_task.real_creds().euid_as_fscred();
872 unsafe {
876 node.force_chown(creds);
877 }
878 }
879 }
880}
881
882pub struct Task {
906 pub weak_self: Weak<Self>,
908
909 pub tid: tid_t,
915
916 pub thread_group_key: ThreadGroupKey,
918
919 pub kernel: Arc<Kernel>,
921
922 pub thread_group: Arc<ThreadGroup>,
927
928 pub running_state: RcuOptionArc<TaskRunningState>,
932
933 stop_state: AtomicStopState,
937
938 flags: AtomicTaskFlags,
942
943 mutable_state:
945 starnix_sync::LockDepRwLock<TaskMutableState, starnix_sync::TaskMutableStateLock>,
946
947 pub persistent_info: TaskPersistentInfo,
952
953 vfork_event: Option<Arc<zx::Event>>,
957
958 pub seccomp_filter_state: SeccompState,
961
962 pub trace_syscalls: AtomicBool,
964}
965
966#[derive(Debug)]
968pub struct PageFaultExceptionReport {
969 pub faulting_address: u64,
970 pub not_present: bool, pub is_write: bool, pub is_execute: bool, }
974
975impl Task {
976 pub fn kernel(&self) -> &Arc<Kernel> {
977 &self.kernel
978 }
979
980 pub fn thread_group(&self) -> &Arc<ThreadGroup> {
981 &self.thread_group
982 }
983
984 pub fn has_same_address_space(&self, other: Option<&Arc<MemoryManager>>) -> bool {
985 match (self.mm(), other) {
986 (Ok(this), Some(other)) => Arc::ptr_eq(&this, other),
987 (Err(_), None) => true,
988 _ => false,
989 }
990 }
991
992 pub fn flags(&self) -> TaskFlags {
993 self.flags.load(Ordering::Relaxed)
994 }
995
996 pub fn is_spawned(&self) -> bool {
997 self.flags().contains(TaskFlags::SPAWNED)
998 }
999
1000 pub fn set_ptrace_zombie(&self, pids: &mut crate::task::PidTable) {
1003 if !self.is_spawned() {
1004 return;
1006 }
1007
1008 let pgid = self.thread_group().read().process_group.leader;
1009 let exit_signal = self.thread_group().read().exit_signal.clone();
1010 let mut state = self.write();
1011 state.set_stopped(StopState::ForceAwake, None, None, None);
1012 if let Some(ptrace) = &mut state.ptrace {
1013 ptrace.last_signal_waitable = true;
1015 let tracer_tg = ptrace.core_state.thread_group.upgrade();
1016 if let Some(tracer_tg) = tracer_tg {
1017 drop(state);
1018 let mut tracer_state = tracer_tg.write();
1019 if !tracer_state.is_running() {
1020 return;
1022 }
1023
1024 let exit_status = self.exit_status().unwrap_or_else(|| {
1025 starnix_logging::log_error!("Exiting without an exit code.");
1026 ExitStatus::Exit(u8::MAX)
1027 });
1028 let uid = self.real_creds().uid;
1029 let exit_info = ProcessExitInfo { status: exit_status, exit_signal };
1030 let zombie = ZombieProcess {
1031 thread_group_key: self.thread_group_key.clone(),
1032 pgid,
1033 uid,
1034 exit_info: exit_info,
1035 time_stats: TaskTimeStats::default(),
1037 is_canonical: false,
1038 };
1039
1040 tracer_state.zombie_ptracees.add(pids, self.tid, zombie);
1041 };
1042 }
1043 }
1044
1045 pub fn ptrace_disconnect(&self) {
1047 let tracer_tg = self
1050 .read()
1051 .ptrace
1052 .as_ref()
1053 .map(|p| p.core_state.thread_group.clone())
1054 .and_then(|tg| tg.upgrade());
1055 if let Some(tg) = tracer_tg {
1056 tg.ptracees.lock().remove(&self.tid);
1057 }
1058 }
1059
1060 pub fn exit_status(&self) -> Option<ExitStatus> {
1061 self.is_exitted().then(|| self.read().exit_status.clone()).flatten()
1062 }
1063
1064 pub fn is_exitted(&self) -> bool {
1065 self.flags().contains(TaskFlags::EXITED)
1066 }
1067
1068 pub fn load_stopped(&self) -> StopState {
1069 self.stop_state.load(Ordering::Relaxed)
1070 }
1071
1072 pub fn from_weak(weak: &Weak<Task>) -> Result<Arc<Task>, Errno> {
1074 weak.upgrade().ok_or_else(|| errno!(ESRCH))
1075 }
1076
1077 #[allow(clippy::let_and_return)]
1084 pub fn new(
1085 tid: tid_t,
1086 command: TaskCommand,
1087 thread_group: Arc<ThreadGroup>,
1088 files: FdTable,
1089 mm: Option<Arc<MemoryManager>>,
1090 fs: Arc<FsContext>,
1093 creds: Arc<Credentials>,
1094 abstract_socket_namespace: Arc<AbstractUnixSocketNamespace>,
1095 abstract_vsock_namespace: Arc<AbstractVsockSocketNamespace>,
1096 signal_mask: SigSet,
1097 kernel_signals: VecDeque<KernelSignal>,
1098 vfork_event: Option<Arc<zx::Event>>,
1099 scheduler_state: SchedulerState,
1100 uts_ns: UtsNamespaceHandle,
1101 no_new_privs: bool,
1102 seccomp_filter_state: SeccompState,
1103 seccomp_filters: SeccompFilterContainer,
1104 robust_list_head: RobustListHeadPtr,
1105 timerslack_ns: u64,
1106 ) -> Arc<Self> {
1107 let thread_group_key = ThreadGroupKey::from(&thread_group);
1108 Arc::new_cyclic(|weak_self| {
1109 let task = Task {
1110 weak_self: weak_self.clone(),
1111 tid,
1112 thread_group_key: thread_group_key.clone(),
1113 kernel: Arc::clone(&thread_group.kernel),
1114 thread_group,
1115 running_state: RcuOptionArc::new(Some(Arc::new(TaskRunningState {
1116 thread: Default::default(),
1117 files,
1118 mm: RcuOptionArc::new(mm),
1119 fs: RcuArc::new(fs),
1120 abstract_socket_namespace,
1121 abstract_vsock_namespace,
1122 proc_pid_directory_cache: Default::default(),
1123 }))),
1124 vfork_event,
1125 stop_state: AtomicStopState::new(StopState::Awake),
1126 flags: AtomicTaskFlags::new(TaskFlags::empty()),
1127 mutable_state: TaskMutableState {
1128 clear_child_tid: UserRef::default(),
1129 signals: SignalState::with_mask(signal_mask),
1130 run_state: RunState::default(),
1131 kernel_signals,
1132 exit_status: None,
1133 scheduler_state,
1134 uts_ns,
1135 no_new_privs,
1136 oom_score_adj: Default::default(),
1137 seccomp_filters,
1138 robust_list_head,
1139 timerslack_ns,
1140 default_timerslack_ns: timerslack_ns,
1142 ptrace: None,
1143 captured_thread_state: None,
1144 last_applied_role: None,
1145 cpuset_path: "/".to_string(),
1146 }
1147 .into(),
1148 persistent_info: TaskPersistentInfoState::new(
1149 tid,
1150 thread_group_key,
1151 command,
1152 creds,
1153 ),
1154 seccomp_filter_state,
1155 trace_syscalls: AtomicBool::new(false),
1156 };
1157
1158 #[cfg(any(test, debug_assertions))]
1159 {
1160 let _l1 = task.persistent_info.lock_creds();
1162 let _l2 = task.read();
1163 let _l3 = task.persistent_info.command_guard();
1164 }
1165 task
1166 })
1167 }
1168
1169 state_accessor!(Task, mutable_state);
1170
1171 pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
1176 self.persistent_info.real_creds()
1177 }
1178
1179 pub fn clone_creds(&self) -> Arc<Credentials> {
1184 self.persistent_info.clone_creds()
1185 }
1186
1187 pub fn ptracer_task(&self) -> Option<Arc<Task>> {
1188 self.read().ptrace.as_ref().and_then(|p| p.core_state.task.upgrade())
1189 }
1190
1191 pub fn is_running(&self) -> bool {
1197 self.running_state.read().is_some()
1198 }
1199
1200 #[track_caller]
1207 pub fn running_state(&self) -> Result<Arc<TaskRunningState>, Errno> {
1208 self.running_state.to_option_arc().ok_or_else(|| errno!(ESRCH))
1209 }
1210
1211 #[track_caller]
1219 pub fn files(&self) -> Result<FdTable, Errno> {
1220 Ok(self.running_state()?.files())
1221 }
1222
1223 #[track_caller]
1232 pub fn mm(&self) -> Result<Arc<MemoryManager>, Errno> {
1233 let _scope = RcuReadScope::new();
1236 self.running_state()?.mm.to_option_arc().ok_or_else(|| errno!(EINVAL))
1237 }
1238
1239 pub(crate) fn set_scheduler_policy_priority_and_reset_on_fork(
1242 &self,
1243 policy: SchedulingPolicy,
1244 priority: RealtimePriority,
1245 reset_on_fork: bool,
1246 ) -> Result<(), Errno> {
1247 self.update_scheduler_state_then_role(|scheduler_state| {
1248 scheduler_state.policy = policy;
1249 scheduler_state.realtime_priority = priority;
1250 scheduler_state.reset_on_fork = reset_on_fork;
1251 })
1252 }
1253
1254 pub(crate) fn set_scheduler_priority(&self, priority: RealtimePriority) -> Result<(), Errno> {
1256 self.update_scheduler_state_then_role(|scheduler_state| {
1257 scheduler_state.realtime_priority = priority
1258 })
1259 }
1260
1261 pub(crate) fn set_scheduler_nice(&self, nice: NormalPriority) -> Result<(), Errno> {
1263 self.update_scheduler_state_then_role(|scheduler_state| {
1264 scheduler_state.normal_priority = nice
1265 })
1266 }
1267
1268 pub fn set_scheduler_state(&self, scheduler_state: SchedulerState) -> Result<(), Errno> {
1270 self.update_scheduler_state_then_role(|task_scheduler_state| {
1271 *task_scheduler_state = scheduler_state
1272 })
1273 }
1274
1275 pub fn sync_scheduler_state_to_role(&self) -> Result<(), Errno> {
1280 self.update_scheduler_state_then_role(|_| {})
1281 }
1282
1283 fn update_scheduler_state_then_role(
1284 &self,
1285 updater: impl FnOnce(&mut SchedulerState),
1286 ) -> Result<(), Errno> {
1287 let process_name = self
1288 .thread_group()
1289 .read()
1290 .get_task(self.thread_group().leader)
1291 .ok_or_else(|| errno!(EINVAL))?
1292 .command();
1293 let thread_name = self.command();
1294
1295 let (new_scheduler_state, cpuset_path, last_applied_role) = {
1296 let mut state = self.write();
1297 updater(&mut state.scheduler_state);
1298 (state.scheduler_state, state.cpuset_path.clone(), state.last_applied_role.clone())
1299 };
1300
1301 let scheduler = &self.thread_group().kernel.scheduler;
1302 let role_name = scheduler.resolve_role_name(
1303 &process_name,
1304 &thread_name,
1305 &cpuset_path,
1306 new_scheduler_state,
1307 );
1308 if last_applied_role.as_deref() == Some(role_name) {
1309 return Ok(());
1310 }
1311 scheduler.set_thread_role(self, role_name)?;
1312 self.write().last_applied_role = Some(role_name.to_string());
1317 Ok(())
1318 }
1319
1320 pub fn signal_vfork(&self) {
1322 if let Some(event) = &self.vfork_event {
1323 if let Err(status) = event.signal(Signals::NONE, Signals::USER_0) {
1324 log_warn!("Failed to set vfork signal {status}");
1325 }
1326 };
1327 }
1328
1329 pub fn wait_for_execve(&self, task_to_wait: Weak<Task>) -> Result<(), Errno> {
1332 let event = task_to_wait.upgrade().and_then(|t| t.vfork_event.clone());
1333 if let Some(event) = event {
1334 event
1335 .wait_one(zx::Signals::USER_0, zx::MonotonicInstant::INFINITE)
1336 .map_err(|status| from_status_like_fdio!(status))?;
1337 }
1338 Ok(())
1339 }
1340
1341 pub fn clear_child_tid_if_needed(&self) -> Result<(), Errno> {
1349 let mut state = self.write();
1350 let user_tid = state.clear_child_tid;
1351 if !user_tid.is_null() {
1352 let zero: tid_t = 0;
1353 self.write_object(user_tid, &zero)?;
1354 self.kernel().shared_futexes.wake(
1355 self,
1356 user_tid.addr(),
1357 usize::MAX,
1358 FUTEX_BITSET_MATCH_ANY,
1359 )?;
1360 state.clear_child_tid = UserRef::default();
1361 }
1362 Ok(())
1363 }
1364
1365 pub fn get_task(&self, tid: tid_t) -> Result<Arc<Task>, Errno> {
1366 self.kernel().pids.read().get_task(tid)
1367 }
1368
1369 pub fn get_pid(&self) -> pid_t {
1370 self.thread_group_key.pid()
1371 }
1372
1373 pub fn get_tid(&self) -> tid_t {
1374 self.tid
1375 }
1376
1377 pub fn is_leader(&self) -> bool {
1378 self.get_pid() == self.get_tid()
1379 }
1380
1381 pub fn read_argv(&self, max_len: usize) -> Result<Vec<FsString>, Errno> {
1382 let Ok(mm) = self.mm() else {
1384 return Ok(vec![]);
1385 };
1386 let (argv_start, argv_end) = {
1387 let mm_state = mm.state.read();
1388 (mm_state.argv_start, mm_state.argv_end)
1389 };
1390
1391 let len_to_read = std::cmp::min(argv_end - argv_start, max_len);
1392 self.read_nul_delimited_c_string_list(argv_start, len_to_read)
1393 }
1394
1395 pub fn read_argv0(&self) -> Result<FsString, Errno> {
1396 let Ok(mm) = self.mm() else {
1398 return Ok(FsString::default());
1399 };
1400 let argv_start = {
1401 let mm_state = mm.state.read();
1402 mm_state.argv_start
1403 };
1404 let argv_start = UserCString::new(&ArchWidth::Arch64, argv_start);
1406 self.read_path(argv_start)
1407 }
1408
1409 pub fn read_env(&self, max_len: usize) -> Result<Vec<FsString>, Errno> {
1410 let Ok(mm) = self.mm() else { return Ok(vec![]) };
1412 let (env_start, env_end) = {
1413 let mm_state = mm.state.read();
1414 (mm_state.environ_start, mm_state.environ_end)
1415 };
1416
1417 let len_to_read = std::cmp::min(env_end - env_start, max_len);
1418 self.read_nul_delimited_c_string_list(env_start, len_to_read)
1419 }
1420
1421 pub fn thread_runtime_info(&self) -> Result<zx::TaskRuntimeInfo, Errno> {
1422 self.running_state()?
1423 .thread
1424 .get()
1425 .ok_or_else(|| errno!(EINVAL))?
1426 .get_runtime_info()
1427 .map_err(|status| from_status_like_fdio!(status))
1428 }
1429
1430 pub fn real_fscred(&self) -> FsCred {
1431 self.real_creds().as_fscred()
1432 }
1433
1434 pub fn interrupt(&self) {
1439 let Ok(running_state) = self.running_state() else {
1440 log_warn!("Cannot interrupt dead task {}", self.get_tid());
1441 return;
1442 };
1443
1444 self.read().run_state.wake();
1445 if let Some(thread) = running_state.thread.get() {
1446 #[allow(
1447 clippy::undocumented_unsafe_blocks,
1448 reason = "Force documented unsafe blocks in Starnix"
1449 )]
1450 let status = unsafe { zx::sys::zx_restricted_kick(thread.raw_handle(), 0) };
1451 if status != zx::sys::ZX_OK {
1452 assert_eq!(status, zx::sys::ZX_ERR_BAD_STATE);
1456 }
1457 }
1458 }
1459
1460 pub fn command(&self) -> TaskCommand {
1461 self.persistent_info.command.lock().clone()
1462 }
1463
1464 pub fn set_command_name(&self, mut new_name: TaskCommand) {
1465 let Ok(running_state) = self.running_state() else {
1466 log_warn!("Cannot set command name for dead task {}", self.get_tid());
1467 return;
1468 };
1469
1470 if let Ok(argv0) = self.read_argv0() {
1474 let argv0 = TaskCommand::from_path_bytes(&argv0);
1475 if let Some(embedded_name) = argv0.try_embed(&new_name) {
1476 new_name = embedded_name;
1477 }
1478 }
1479
1480 let mut command_guard = self.persistent_info.command_guard();
1484
1485 if let Some(thread) = running_state.thread.get() {
1487 set_zx_name(thread.thread.as_ref(), new_name.as_bytes());
1488 }
1489
1490 if self.is_leader() {
1492 set_zx_name(&*self.thread_group().process, new_name.as_bytes());
1493 let _ = zx::Thread::raise_user_exception(
1494 zx::RaiseExceptionOptions::TARGET_JOB_DEBUGGER,
1495 zx::sys::ZX_EXCP_USER_CODE_PROCESS_NAME_CHANGED,
1496 0,
1497 );
1498 }
1499
1500 *command_guard = new_name;
1503 drop(command_guard);
1504
1505 if self.is_leader() {
1506 if let Some(notifier) = &self.thread_group().read().notifier {
1507 let _ = notifier.send(MemoryAttributionLifecycleEvent::name_change(self.tid));
1508 }
1509 }
1510
1511 if let Err(err) = self.sync_scheduler_state_to_role() {
1512 log_warn!(err:?; "Failed to update scheduler role after thread name change.");
1513 }
1514 }
1515
1516 pub fn set_seccomp_state(&self, state: SeccompStateValue) -> Result<(), Errno> {
1517 self.seccomp_filter_state.set(&state)
1518 }
1519
1520 pub fn state_code(&self) -> TaskStateCode {
1521 let status = self.read();
1522 if status.exit_status.is_some() {
1523 TaskStateCode::Zombie
1524 } else if status.run_state.is_blocked() {
1525 let stop_state = self.load_stopped();
1526 if stop_state.ptrace_only() && stop_state.is_stopped() {
1527 TaskStateCode::TracingStop
1528 } else {
1529 TaskStateCode::Sleeping
1530 }
1531 } else {
1532 TaskStateCode::Running
1533 }
1534 }
1535
1536 pub fn time_stats(&self) -> TaskTimeStats {
1537 use zx::Task;
1538 let running_state = match self.running_state() {
1540 Ok(running_state) => running_state,
1541 Err(_) => return TaskTimeStats::default(),
1542 };
1543 let info = match running_state.thread.get() {
1544 Some(thread) => thread.get_runtime_info().expect("Failed to get thread stats"),
1545 None => return TaskTimeStats::default(),
1546 };
1547
1548 TaskTimeStats {
1549 user_time: zx::MonotonicDuration::from_nanos(info.cpu_time),
1550 system_time: zx::MonotonicDuration::default(),
1552 }
1553 }
1554
1555 pub fn get_signal_action(&self, signal: Signal) -> sigaction_t {
1556 self.thread_group().signal_actions.get(signal)
1557 }
1558
1559 pub fn should_check_for_pending_signals(&self) -> bool {
1560 self.flags().intersects(
1561 TaskFlags::KERNEL_SIGNALS_AVAILABLE
1562 | TaskFlags::SIGNALS_AVAILABLE
1563 | TaskFlags::TEMPORARY_SIGNAL_MASK,
1564 ) || self.thread_group.has_pending_signals.load(Ordering::Relaxed)
1565 }
1566
1567 pub fn record_pid_koid_mapping(&self) {
1568 let Ok(running_state) = self.running_state() else {
1569 log_warn!("Cannot record pid/koid mapping for dead task {}", self.get_tid());
1570 return;
1571 };
1572
1573 let Some(ref mapping_table) = *self.kernel().pid_to_koid_mapping.read() else { return };
1574
1575 let pkoid = self.thread_group().get_process_koid().ok();
1576 let tkoid = running_state.thread.get().map(|t| t.koid);
1577 mapping_table.write().insert(self.tid, KoidPair { process: pkoid, thread: tkoid });
1578 }
1579}
1580
1581impl Drop for Task {
1582 fn drop(&mut self) {
1583 debug_assert!(self.running_state.read().is_none());
1584 }
1585}
1586
1587impl MemoryAccessor for Task {
1588 fn read_memory<'a>(
1589 &self,
1590 addr: UserAddress,
1591 bytes: &'a mut [MaybeUninit<u8>],
1592 ) -> Result<&'a mut [u8], Errno> {
1593 self.mm()?.syscall_read_memory(addr, bytes)
1598 }
1599
1600 fn read_memory_partial_until_null_byte<'a>(
1601 &self,
1602 addr: UserAddress,
1603 bytes: &'a mut [MaybeUninit<u8>],
1604 ) -> Result<&'a mut [u8], Errno> {
1605 self.mm()?.syscall_read_memory_partial_until_null_byte(addr, bytes)
1610 }
1611
1612 fn read_memory_partial<'a>(
1613 &self,
1614 addr: UserAddress,
1615 bytes: &'a mut [MaybeUninit<u8>],
1616 ) -> Result<&'a mut [u8], Errno> {
1617 self.mm()?.syscall_read_memory_partial(addr, bytes)
1622 }
1623
1624 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1625 self.mm()?.syscall_write_memory(addr, bytes)
1630 }
1631
1632 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1633 self.mm()?.syscall_write_memory_partial(addr, bytes)
1638 }
1639
1640 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
1641 self.mm()?.syscall_zero(addr, length)
1646 }
1647}
1648
1649impl TaskMemoryAccessor for Task {
1650 fn maximum_valid_address(&self) -> Option<UserAddress> {
1651 self.mm().map(|mm| mm.maximum_valid_user_address).ok()
1652 }
1653}
1654
1655impl fmt::Debug for Task {
1656 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1657 write!(
1658 f,
1659 "{}:{}[{}]",
1660 self.thread_group().leader,
1661 self.tid,
1662 *self.persistent_info.command.lock()
1663 )
1664 }
1665}
1666
1667impl cmp::PartialEq for Task {
1668 fn eq(&self, other: &Self) -> bool {
1669 let ptr: *const Task = self;
1670 let other_ptr: *const Task = other;
1671 ptr == other_ptr
1672 }
1673}
1674
1675impl cmp::Eq for Task {}
1676
1677#[cfg(test)]
1678mod test {
1679 use super::*;
1680 use crate::security;
1681 use crate::testing::*;
1682 use starnix_uapi::auth::{CAP_SYS_ADMIN, Capabilities};
1683 use starnix_uapi::resource_limits::Resource;
1684 use starnix_uapi::signals::SIGCHLD;
1685 use starnix_uapi::{CLONE_SIGHAND, CLONE_THREAD, CLONE_VM, rlimit};
1686
1687 #[::fuchsia::test]
1688 async fn test_tid_allocation() {
1689 spawn_kernel_and_run(async |current_task| {
1690 let kernel = current_task.kernel();
1691 assert_eq!(current_task.get_tid(), 1);
1692 let another_current = create_task(&kernel, "another-task");
1693 let another_tid = another_current.get_tid();
1694 assert!(another_tid >= 2);
1695
1696 let pids = kernel.pids.read();
1697 assert_eq!(pids.get_task(1).unwrap().get_tid(), 1);
1698 assert_eq!(pids.get_task(another_tid).unwrap().get_tid(), another_tid);
1699 })
1700 .await;
1701 }
1702
1703 #[::fuchsia::test]
1704 async fn test_clone_pid_and_parent_pid() {
1705 spawn_kernel_and_run(async |current_task| {
1706 let thread = current_task.clone_task_for_test(
1707 (CLONE_THREAD | CLONE_VM | CLONE_SIGHAND) as u64,
1708 Some(SIGCHLD),
1709 );
1710 assert_eq!(current_task.get_pid(), thread.get_pid());
1711 assert_ne!(current_task.get_tid(), thread.get_tid());
1712 assert_eq!(current_task.thread_group().leader, thread.thread_group().leader);
1713
1714 let child_task = current_task.clone_task_for_test(0, Some(SIGCHLD));
1715 assert_ne!(current_task.get_pid(), child_task.get_pid());
1716 assert_ne!(current_task.get_tid(), child_task.get_tid());
1717 assert_eq!(current_task.get_pid(), child_task.thread_group().read().get_ppid());
1718 })
1719 .await;
1720 }
1721
1722 #[::fuchsia::test]
1723 async fn test_root_capabilities() {
1724 spawn_kernel_and_run(async |current_task| {
1725 assert!(security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN));
1726 assert_eq!(current_task.real_creds().cap_inheritable, Capabilities::empty());
1727
1728 current_task.set_creds(Credentials::with_ids(1, 1));
1729 assert!(!security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN));
1730 })
1731 .await;
1732 }
1733
1734 #[::fuchsia::test]
1735 async fn test_is_spawned() {
1736 spawn_kernel_and_run(async |current_task| {
1737 assert!(current_task.is_spawned());
1739
1740 let child = current_task
1742 .clone_task(
1743 0,
1744 Some(SIGCHLD),
1745 UserRef::default(),
1746 UserRef::default(),
1747 UserRef::default(),
1748 )
1749 .expect("failed to create task in test");
1750 assert!(!child.is_spawned());
1751 child.release(());
1752
1753 let test_child = current_task.clone_task_for_test(0, Some(SIGCHLD));
1756 assert!(test_child.is_spawned());
1757 })
1758 .await;
1759 }
1760
1761 #[::fuchsia::test]
1762 async fn test_clone_rlimit() {
1763 spawn_kernel_and_run(async |current_task| {
1764 let prev_fsize = current_task.thread_group().get_rlimit(Resource::FSIZE);
1765 assert_ne!(prev_fsize, 10);
1766 current_task
1767 .thread_group()
1768 .limits
1769 .lock()
1770 .set(Resource::FSIZE, rlimit { rlim_cur: 10, rlim_max: 100 });
1771 let current_fsize = current_task.thread_group().get_rlimit(Resource::FSIZE);
1772 assert_eq!(current_fsize, 10);
1773
1774 let child_task = current_task.clone_task_for_test(0, Some(SIGCHLD));
1775 let child_fsize = child_task.thread_group().get_rlimit(Resource::FSIZE);
1776 assert_eq!(child_fsize, 10)
1777 })
1778 .await;
1779 }
1780
1781 #[::fuchsia::test]
1782 async fn test_set_command_name_syncs_scheduler_role() {
1783 use crate::task::{RoleOverrides, SchedulerManager};
1784
1785 let mut builder = RoleOverrides::new();
1786 builder.add("renamed-thread", "renamed-thread", None, "test-role");
1787 let overrides = builder.build().unwrap();
1788
1789 let scheduler_manager = SchedulerManager::new_for_tests(None, overrides);
1790
1791 spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
1792 current_task.thread_group().write().did_exec = true;
1794
1795 let scheduler = ¤t_task.thread_group().kernel.scheduler;
1796
1797 let initial_role = scheduler.role_name(current_task).unwrap();
1799 assert_ne!(initial_role, "test-role");
1800
1801 current_task
1803 .set_command_name(starnix_task_command::TaskCommand::new(b"renamed-thread"));
1804
1805 let renamed_role = scheduler.role_name(current_task).unwrap();
1806 assert_eq!(renamed_role, "test-role");
1807 })
1808 .await;
1809 }
1810
1811 #[::fuchsia::test]
1812 async fn test_fork_does_not_inherit_custom_role() {
1813 use crate::task::{RoleOverrides, SchedulerManager};
1814
1815 let mut builder = RoleOverrides::new();
1816 builder.add("renamed-thread", "renamed-thread", None, "test-role");
1817 let overrides = builder.build().unwrap();
1818
1819 let scheduler_manager = SchedulerManager::new_for_tests(None, overrides);
1820
1821 spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
1822 let child = current_task.clone_task_for_test(0, None);
1824
1825 let scheduler = ¤t_task.thread_group().kernel.scheduler;
1826
1827 let initial_role = scheduler.role_name(&child).unwrap();
1829 assert_ne!(initial_role, "test-role");
1830
1831 child.set_command_name(starnix_task_command::TaskCommand::new(b"renamed-thread"));
1834
1835 let renamed_role = scheduler.role_name(&child).unwrap();
1836 assert_ne!(renamed_role, "test-role");
1837 })
1838 .await;
1839 }
1840}