1use crate::mm::{MemoryAccessor, MemoryAccessorExt, MemoryManager, TaskMemoryAccessor};
6use crate::mutable_state::{state_accessor, state_implementation};
7use crate::ptrace::{AtomicStopState, PtraceEventData, PtraceState, PtraceStatus, StopState};
8use crate::signals::{KernelSignal, SignalDetail, SignalInfo, SignalState};
9use crate::task::memory_attribution::MemoryAttributionLifecycleEvent;
10use crate::task::run_state::RunState;
11use crate::task::tracing::ZirconIdentity;
12use crate::task::{
13 AbstractUnixSocketNamespace, AbstractVsockSocketNamespace, CurrentCreds, CurrentTask,
14 EventHandler, ExitStatus, Kernel, NormalPriority, Pid, RealtimePriority, SchedulerState,
15 SchedulingPolicy, SeccompFilterContainer, SeccompState, SeccompStateValue, TaskRunningState,
16 ThreadGroup, ThreadState, UtsNamespaceHandle, WaitCanceler, Waiter, ZombieProcess, ZombieState,
17};
18use crate::vfs::{FdTable, FsContext, FsString, SharedFdTable};
19use atomic_bitflags::atomic_bitflags;
20use fuchsia_rcu::{RcuArc, RcuDroppable, RcuDroppableArc, RcuReadGuard, RcuReadScope};
21use macro_rules_attribute::apply;
22use starnix_logging::{log_warn, set_zx_name};
23use starnix_registers::HeapRegs;
24use starnix_sync::{
25 LockDepGuard, LockDepMutex, LockDepReadGuard, LockDepRwLock, LockDepWriteGuard,
26 TaskCommandLevel, TaskCredsLock,
27};
28use starnix_task_command::TaskCommand;
29use starnix_types::arch::ArchWidth;
30use starnix_types::stats::TaskTimeStats;
31use starnix_uapi::auth::{CAP_SYS_PTRACE, Credentials, FsCred};
32use starnix_uapi::errors::Errno;
33use starnix_uapi::signals::{SIGCHLD, SIGKILL, SigSet, Signal, sigaltstack_contains_pointer};
34use starnix_uapi::user_address::{
35 ArchSpecific, MappingMultiArchUserRef, UserAddress, UserCString, UserRef,
36};
37use starnix_uapi::{
38 CLD_TRAPPED, FUTEX_BITSET_MATCH_ANY, errno, error, from_status_like_fdio, pid_t, sigaction_t,
39 sigaltstack, tid_t, uapi,
40};
41use std::collections::VecDeque;
42use std::mem::MaybeUninit;
43use std::ops::Deref;
44use std::sync::atomic::{AtomicBool, Ordering};
45use std::sync::{Arc, Weak};
46use std::{cmp, fmt};
47use zx::{Signals, Task as _};
48
49atomic_bitflags! {
50 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
51 pub struct TaskFlags: u8 {
52 const EXITED = 1 << 0;
53 const SIGNALS_AVAILABLE = 1 << 1;
54 const TEMPORARY_SIGNAL_MASK = 1 << 2;
55 const DUMP_ON_EXIT = 1 << 3;
58 const KERNEL_SIGNALS_AVAILABLE = 1 << 4;
59 const SPAWNED = 1 << 5;
61 }
62}
63
64pub struct CapturedThreadState {
71 pub thread_state: ThreadState<HeapRegs>,
74
75 pub dirty: bool,
78}
79
80impl ArchSpecific for CapturedThreadState {
81 fn is_arch32(&self) -> bool {
82 self.thread_state.is_arch32()
83 }
84}
85
86#[derive(Debug)]
87pub struct RobustList {
88 pub next: RobustListPtr,
89}
90
91pub type RobustListPtr =
92 MappingMultiArchUserRef<RobustList, uapi::robust_list, uapi::arch32::robust_list>;
93
94impl From<uapi::robust_list> for RobustList {
95 fn from(robust_list: uapi::robust_list) -> Self {
96 Self { next: RobustListPtr::from(robust_list.next) }
97 }
98}
99
100#[cfg(target_arch = "aarch64")]
101impl From<uapi::arch32::robust_list> for RobustList {
102 fn from(robust_list: uapi::arch32::robust_list) -> Self {
103 Self { next: RobustListPtr::from(robust_list.next) }
104 }
105}
106
107#[derive(Debug)]
108pub struct RobustListHead {
109 pub list: RobustList,
110 pub futex_offset: isize,
111}
112
113pub type RobustListHeadPtr =
114 MappingMultiArchUserRef<RobustListHead, uapi::robust_list_head, uapi::arch32::robust_list_head>;
115
116impl From<uapi::robust_list_head> for RobustListHead {
117 fn from(robust_list_head: uapi::robust_list_head) -> Self {
118 Self {
119 list: robust_list_head.list.into(),
120 futex_offset: robust_list_head.futex_offset as isize,
121 }
122 }
123}
124
125#[cfg(target_arch = "aarch64")]
126impl From<uapi::arch32::robust_list_head> for RobustListHead {
127 fn from(robust_list_head: uapi::arch32::robust_list_head) -> Self {
128 Self {
129 list: robust_list_head.list.into(),
130 futex_offset: robust_list_head.futex_offset as isize,
131 }
132 }
133}
134
135pub struct TaskMutableState {
136 pub clear_child_tid: UserRef<tid_t>,
138
139 signals: SignalState,
142
143 pub run_state: RunState,
145
146 kernel_signals: VecDeque<KernelSignal>,
154
155 exit_status: Option<ExitStatus>,
157
158 pub scheduler_state: SchedulerState,
161
162 pub uts_ns: UtsNamespaceHandle,
170
171 no_new_privs: bool,
177
178 pub oom_score_adj: i32,
180
181 pub seccomp_filters: SeccompFilterContainer,
183
184 pub robust_list_head: RobustListHeadPtr,
187
188 pub timerslack_ns: u64,
194
195 pub default_timerslack_ns: u64,
201
202 pub ptrace: Option<Box<PtraceState>>,
205
206 pub captured_thread_state: Option<Box<CapturedThreadState>>,
208
209 pub cpuset_path: String,
211}
212
213impl TaskMutableState {
214 pub fn no_new_privs(&self) -> bool {
215 self.no_new_privs
216 }
217
218 pub fn enable_no_new_privs(&mut self) {
221 self.no_new_privs = true;
222 }
223
224 pub fn get_timerslack<T: zx::Timeline>(&self) -> zx::Duration<T> {
225 zx::Duration::from_nanos(self.timerslack_ns as i64)
226 }
227
228 pub fn set_timerslack_ns(&mut self, ns: u64) {
232 if ns == 0 {
233 self.timerslack_ns = self.default_timerslack_ns;
234 } else {
235 self.timerslack_ns = ns;
236 }
237 }
238
239 pub fn is_ptraced(&self) -> bool {
240 self.ptrace.is_some()
241 }
242
243 pub fn is_ptraced_without_cap_sys_ptrace(&self) -> bool {
246 self.ptrace.as_ref().is_some_and(|ptrace| {
247 ptrace.core_state.task.upgrade().is_none_or(|tracer| {
248 !tracer.real_creds().cap_effective.contains(CAP_SYS_PTRACE)
251 })
252 })
253 }
254
255 pub fn is_ptrace_listening(&self) -> bool {
256 self.ptrace.as_ref().is_some_and(|ptrace| ptrace.stop_status == PtraceStatus::Listening)
257 }
258
259 pub fn ptrace_on_signal_consume(&mut self) -> bool {
260 self.ptrace.as_mut().is_some_and(|ptrace: &mut Box<PtraceState>| {
261 if ptrace.stop_status.is_continuing() {
262 ptrace.stop_status = PtraceStatus::Default;
263 false
264 } else {
265 true
266 }
267 })
268 }
269
270 pub fn notify_ptracers(&mut self) {
271 if let Some(ptrace) = &self.ptrace {
272 ptrace.tracer_waiters().notify_all();
273 }
274 }
275
276 pub fn wait_on_ptracer(&self, waiter: &Waiter) {
277 if let Some(ptrace) = &self.ptrace {
278 ptrace.tracee_waiters.wait_async(&waiter);
279 }
280 }
281
282 pub fn notify_ptracees(&mut self) {
283 if let Some(ptrace) = &self.ptrace {
284 ptrace.tracee_waiters.notify_all();
285 }
286 }
287
288 pub fn take_captured_state(&mut self) -> Option<Box<CapturedThreadState>> {
289 self.captured_thread_state.take()
290 }
291
292 fn copy_state_from(&mut self, current_task: &CurrentTask) {
298 if self.captured_thread_state.is_none() {
299 self.captured_thread_state = Some(Box::new(CapturedThreadState {
300 thread_state: current_task.thread_state.extended_snapshot::<HeapRegs>(),
301 dirty: false,
302 }));
303 }
304 }
305
306 pub fn signal_mask(&self) -> SigSet {
308 self.signals.mask()
309 }
310
311 pub fn is_signal_masked(&self, signal: Signal) -> bool {
313 self.signals.mask().has_signal(signal)
314 }
315
316 pub fn is_signal_masked_by_saved_mask(&self, signal: Signal) -> bool {
320 self.signals.saved_mask().is_some_and(|mask| mask.has_signal(signal))
321 }
322
323 pub fn is_blocked(&self) -> bool {
325 self.run_state.is_blocked()
326 }
327
328 pub fn set_run_state(&mut self, run_state: RunState) {
330 self.run_state = run_state;
331 }
332
333 pub fn run_state(&self) -> RunState {
334 self.run_state.clone()
335 }
336
337 pub fn on_signal_stack(&self, stack_pointer_register: u64) -> bool {
338 self.signals
339 .alt_stack
340 .map(|signal_stack| sigaltstack_contains_pointer(&signal_stack, stack_pointer_register))
341 .unwrap_or(false)
342 }
343
344 pub fn set_sigaltstack(&mut self, stack: Option<sigaltstack>) {
345 self.signals.alt_stack = stack;
346 }
347
348 pub fn sigaltstack(&self) -> Option<sigaltstack> {
349 self.signals.alt_stack
350 }
351
352 pub fn wait_on_signal(&mut self, waiter: &Waiter) {
353 self.signals.signal_wait.wait_async(waiter);
354 }
355
356 pub fn signals_mut(&mut self) -> &mut SignalState {
357 &mut self.signals
358 }
359
360 pub fn wait_on_signal_fd_events(
361 &self,
362 waiter: &Waiter,
363 mask: SigSet,
364 handler: EventHandler,
365 ) -> WaitCanceler {
366 self.signals.signal_wait.wait_async_signal_mask(waiter, mask, handler)
367 }
368
369 pub fn notify_signal_waiters(&self, signal: &Signal) {
370 self.signals.signal_wait.notify_signal(signal);
371 }
372
373 pub fn thaw(&mut self) {
375 if let RunState::Frozen(waiter) = self.run_state() {
376 waiter.notify();
377 }
378 }
379
380 pub fn is_frozen(&self) -> bool {
381 matches!(self.run_state(), RunState::Frozen(_))
382 }
383
384 #[cfg(test)]
385 pub fn kernel_signals_for_test(&self) -> &VecDeque<KernelSignal> {
386 &self.kernel_signals
387 }
388}
389
390#[apply(state_implementation!)]
391impl TaskMutableState<Base = Task> {
392 pub fn set_stopped(
393 &mut self,
394 stopped: StopState,
395 siginfo: Option<SignalInfo>,
396 current_task: Option<&CurrentTask>,
397 event: Option<PtraceEventData>,
398 ) {
399 if stopped.ptrace_only() && self.ptrace.is_none() {
400 return;
401 }
402
403 if self.base.load_stopped().is_illegal_transition(stopped) {
404 return;
405 }
406
407 self.store_stopped(stopped);
411 if stopped.is_stopped() {
412 if let Some(ref current_task) = current_task {
413 self.copy_state_from(current_task);
414 }
415 }
416 if let Some(ptrace) = &mut self.ptrace {
417 ptrace.set_last_signal(siginfo);
418 ptrace.set_last_event(event);
419 }
420 if stopped == StopState::Waking || stopped == StopState::ForceWaking {
421 self.notify_ptracees();
422 }
423 if !stopped.is_in_progress() {
424 self.notify_ptracers();
425 }
426 }
427
428 pub fn enqueue_signal(&mut self, signal: SignalInfo) {
430 self.signals.enqueue(signal);
431 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
432 }
433
434 pub fn enqueue_signal_front(&mut self, signal: SignalInfo) {
438 self.signals.jump_queue(signal);
439 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
440 }
441
442 pub fn set_signal_mask(&mut self, mask: SigSet) {
444 self.signals.set_mask(mask);
445 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
446 }
447
448 pub fn set_temporary_signal_mask(&mut self, mask: SigSet) {
452 self.signals.set_temporary_mask(mask);
453 let (signals_clear, signals_set) = if self.signals.is_any_pending() {
454 (TaskFlags::empty(), TaskFlags::SIGNALS_AVAILABLE)
455 } else {
456 (TaskFlags::SIGNALS_AVAILABLE, TaskFlags::empty())
457 };
458 self.update_flags(signals_clear, signals_set | TaskFlags::TEMPORARY_SIGNAL_MASK);
459 }
460
461 pub fn restore_signal_mask(&mut self) {
464 self.signals.restore_mask();
465 let (signals_clear, signals_set) = if self.signals.is_any_pending() {
466 (TaskFlags::empty(), TaskFlags::SIGNALS_AVAILABLE)
467 } else {
468 (TaskFlags::SIGNALS_AVAILABLE, TaskFlags::empty())
469 };
470 self.update_flags(signals_clear | TaskFlags::TEMPORARY_SIGNAL_MASK, signals_set);
471 }
472
473 pub fn pending_signal_count(&self) -> usize {
475 self.signals.num_queued() + self.base.thread_group().num_signals_queued()
476 }
477
478 pub fn has_signal_pending(&self, signal: Signal) -> bool {
480 self.signals.has_queued(signal) || self.base.thread_group().has_signal_queued(signal)
481 }
482
483 pub fn prepare_signal_info(
485 &mut self,
486 stopped: StopState,
487 ) -> Option<(Weak<ThreadGroup>, SignalInfo)> {
488 if !stopped.is_stopped() {
489 return None;
490 }
491
492 if let Some(ptrace) = &self.ptrace {
493 if let Some(last_signal) = ptrace.get_last_signal_ref() {
494 let signal_info = SignalInfo::with_detail(
495 SIGCHLD,
496 CLD_TRAPPED as i32,
497 SignalDetail::SIGCHLD {
498 pid: self.base.tid.clone(),
499 uid: self.base.real_creds().uid,
500 status: last_signal.signal.number() as i32,
501 },
502 );
503
504 return Some((ptrace.core_state.thread_group.clone(), signal_info));
505 }
506 }
507
508 None
509 }
510
511 pub fn set_ptrace(&mut self, tracer: Option<Box<PtraceState>>) -> Result<(), Errno> {
512 if tracer.is_some() && self.ptrace.is_some() {
513 return error!(EPERM);
514 }
515
516 if tracer.is_none() {
517 if let Ok(tg_stop_state) = self.base.thread_group().load_stopped().as_in_progress() {
519 self.set_stopped(tg_stop_state, None, None, None);
520 }
521 }
522 self.ptrace = tracer;
523 Ok(())
524 }
525
526 pub fn can_accept_ptrace_commands(&mut self) -> bool {
527 !self.base.load_stopped().is_waking_or_awake()
528 && self.is_ptraced()
529 && !self.is_ptrace_listening()
530 }
531
532 fn store_stopped(&mut self, state: StopState) {
533 self.base.stop_state.store(state, Ordering::Relaxed)
538 }
539
540 pub fn update_flags(&mut self, clear: TaskFlags, set: TaskFlags) {
541 debug_assert_eq!(clear ^ set, clear | set);
546 let observed = self.base.flags();
547 let swapped = self.base.flags.swap((observed | set) & !clear, Ordering::Relaxed);
548 debug_assert_eq!(swapped, observed);
549 }
550
551 pub fn set_flags(&mut self, flag: TaskFlags, v: bool) {
552 let (clear, set) = if v { (TaskFlags::empty(), flag) } else { (flag, TaskFlags::empty()) };
553
554 self.update_flags(clear, set);
555 }
556
557 pub fn set_spawned(&mut self) {
558 self.set_flags(TaskFlags::SPAWNED, true);
559 }
560
561 pub fn set_exit_status(&mut self, status: ExitStatus) {
562 self.set_flags(TaskFlags::EXITED, true);
563 self.exit_status = Some(status);
564 }
565
566 pub fn set_exit_status_if_not_already(&mut self, status: ExitStatus) {
567 self.set_flags(TaskFlags::EXITED, true);
568 self.exit_status.get_or_insert(status);
569 }
570
571 pub(crate) fn force_wake_for_exit(&mut self) {
574 self.set_stopped(
575 StopState::ForceWaking,
576 None,
577 None,
578 None,
579 );
580 self.notify_signal_waiters(&SIGKILL);
581 self.thaw();
582 }
583
584 pub fn pending_signals(&self) -> SigSet {
587 self.signals.pending() | self.base.thread_group().get_pending_signals()
588 }
589
590 pub fn task_specific_pending_signals(&self) -> SigSet {
593 self.signals.pending()
594 }
595
596 pub fn is_any_signal_allowed_by_mask(&self, mask: SigSet) -> bool {
598 self.signals.is_any_allowed_by_mask(mask)
599 || self.base.thread_group().is_any_signal_allowed_by_mask(mask)
600 }
601
602 pub fn is_any_signal_pending(&self) -> bool {
605 let mask = self.signal_mask();
606 self.signals.is_any_pending()
607 || self.base.thread_group().is_any_signal_allowed_by_mask(mask)
608 }
609
610 pub fn is_interrupt_pending(&self) -> bool {
612 self.is_any_signal_pending()
613 || self.base.load_stopped().is_stopping_or_stopped()
614 || self.base.thread_group().load_stopped().is_stopping_or_stopped()
615 }
616
617 fn take_next_signal_where<F>(&mut self, predicate: F) -> Option<SignalInfo>
619 where
620 F: Fn(&SignalInfo) -> bool,
621 {
622 if let Some(signal) = self.signals.take_next_where(&predicate) {
623 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
624 Some(signal)
625 } else {
626 self.base.thread_group().take_next_signal_where(&predicate)
627 }
628 }
629
630 pub fn take_specific_signal(&mut self, siginfo: SignalInfo) -> Option<SignalInfo> {
634 let signal_mask = self.signal_mask();
635 if signal_mask.has_signal(siginfo.signal) {
636 return None;
637 }
638
639 let predicate = |s: &SignalInfo| s.signal == siginfo.signal;
640 self.take_next_signal_where(predicate)
641 }
642
643 pub fn take_any_signal(&mut self) -> Option<SignalInfo> {
647 let signal_mask = self.signal_mask();
648 let predicate = |s: &SignalInfo| !signal_mask.has_signal(s.signal) || s.force;
649 self.take_next_signal_where(predicate)
650 }
651
652 pub fn take_signal_with_mask(&mut self, signal_mask: SigSet) -> Option<SignalInfo> {
656 let predicate = |s: &SignalInfo| !signal_mask.has_signal(s.signal);
657 self.take_next_signal_where(predicate)
658 }
659
660 pub fn enqueue_kernel_signal(&mut self, signal: KernelSignal) {
662 self.kernel_signals.push_back(signal);
663 self.set_flags(TaskFlags::KERNEL_SIGNALS_AVAILABLE, true);
664 }
665
666 pub fn take_kernel_signal(&mut self) -> Option<KernelSignal> {
670 let signal = self.kernel_signals.pop_front();
671 if self.kernel_signals.is_empty() {
672 self.set_flags(TaskFlags::KERNEL_SIGNALS_AVAILABLE, false);
673 }
674 signal
675 }
676
677 #[cfg(test)]
678 pub fn queued_signal_count(&self, signal: Signal) -> usize {
679 self.signals.queued_count(signal)
680 + self.base.thread_group().pending_signals.lock().queued_count(signal)
681 }
682}
683
684#[derive(Debug, Clone, Copy, PartialEq, Eq)]
685pub enum TaskStateCode {
686 Running,
688
689 Sleeping,
691
692 TracingStop,
694
695 Zombie,
697}
698
699impl TaskStateCode {
700 pub fn code_char(&self) -> char {
701 match self {
702 TaskStateCode::Running => 'R',
703 TaskStateCode::Sleeping => 'S',
704 TaskStateCode::TracingStop => 't',
705 TaskStateCode::Zombie => 'Z',
706 }
707 }
708
709 pub fn name(&self) -> &'static str {
710 match self {
711 TaskStateCode::Running => "running",
712 TaskStateCode::Sleeping => "sleeping",
713 TaskStateCode::TracingStop => "tracing stop",
714 TaskStateCode::Zombie => "zombie",
715 }
716 }
717}
718
719#[derive(Debug, RcuDroppable)]
724pub struct TaskPersistentInfoState {
725 pub tid: Pid,
727 pub pid: Pid,
728
729 command: LockDepMutex<TaskCommand, TaskCommandLevel>,
731
732 creds: RcuDroppableArc<Credentials>,
735
736 creds_lock: LockDepRwLock<(), TaskCredsLock>,
739}
740
741pub struct CredentialsReadGuard<'a> {
743 _lock: LockDepReadGuard<'a, ()>,
744 creds: RcuReadGuard<Credentials>,
745}
746
747impl<'a> Deref for CredentialsReadGuard<'a> {
748 type Target = Credentials;
749
750 fn deref(&self) -> &Self::Target {
751 self.creds.deref()
752 }
753}
754
755pub struct CredentialsWriteGuard<'a> {
758 _lock: LockDepWriteGuard<'a, ()>,
759 creds: &'a RcuDroppableArc<Credentials>,
760}
761
762impl<'a> CredentialsWriteGuard<'a> {
763 pub fn update(&mut self, creds: Arc<Credentials>) {
764 self.creds.update(creds);
765 }
766}
767
768impl TaskPersistentInfoState {
769 fn new(
770 tid: Pid,
771 pid: Pid,
772 command: TaskCommand,
773 creds: Arc<Credentials>,
774 ) -> TaskPersistentInfo {
775 Arc::new(Self {
776 tid,
777 pid,
778 command: command.into(),
779 creds: RcuDroppableArc::new(creds),
780 creds_lock: Default::default(),
781 })
782 }
783
784 pub fn command_guard(&self) -> LockDepGuard<'_, TaskCommand> {
785 self.command.lock()
786 }
787
788 pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
790 self.creds.read()
791 }
792
793 pub fn clone_creds(&self) -> Arc<Credentials> {
796 self.creds.to_arc()
797 }
798
799 pub fn lock_creds(&self) -> CredentialsReadGuard<'_> {
802 let lock = self.creds_lock.read();
803 CredentialsReadGuard { _lock: lock, creds: self.creds.read() }
804 }
805
806 pub(in crate::task) fn write_current_task_creds(
809 self: &Arc<Self>,
810 ) -> CurrentTaskCredentialsWriteGuard {
811 let persistent_info = self.clone();
812 let lock = unsafe {
814 let raw_lock = self.creds_lock.write();
815 std::mem::transmute::<LockDepWriteGuard<'_, ()>, LockDepWriteGuard<'static, ()>>(
816 raw_lock,
817 )
818 };
819 CurrentTaskCredentialsWriteGuard { _lock: lock, persistent_info }
820 }
821}
822
823impl std::borrow::Borrow<Pid> for TaskPersistentInfoState {
824 fn borrow(&self) -> &Pid {
825 &self.tid
826 }
827}
828
829impl PartialEq for TaskPersistentInfoState {
830 fn eq(&self, other: &Self) -> bool {
831 self.tid == other.tid
832 }
833}
834
835impl Eq for TaskPersistentInfoState {}
836
837impl PartialOrd for TaskPersistentInfoState {
838 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
839 Some(self.cmp(other))
840 }
841}
842
843impl Ord for TaskPersistentInfoState {
844 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
845 self.tid.cmp(&other.tid)
846 }
847}
848
849impl std::hash::Hash for TaskPersistentInfoState {
850 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
851 self.tid.hash(state);
852 }
853}
854
855pub type TaskPersistentInfo = Arc<TaskPersistentInfoState>;
856
857pub struct CurrentTaskCredentialsWriteGuard {
858 _lock: LockDepWriteGuard<'static, ()>,
862 pub persistent_info: TaskPersistentInfo,
863}
864
865impl CurrentTaskCredentialsWriteGuard {
866 pub fn update(self, current_task: &CurrentTask, creds: Arc<Credentials>) {
867 self.persistent_info.creds.update(creds.clone());
868 *current_task.current_creds.borrow_mut() = CurrentCreds::Cached(creds);
869
870 let maybe_node = current_task.running_state().proc_pid_directory_cache.get();
873 if let Some(node) = maybe_node {
874 let creds = current_task.real_creds().euid_as_fscred();
875 unsafe {
879 node.force_chown(creds);
880 }
881 }
882 }
883}
884
885pub struct Task {
909 pub weak_self: Weak<Self>,
911
912 pub tid: Pid,
918
919 pub pid: Pid,
921
922 pub kernel: Arc<Kernel>,
924
925 pub thread_group: Arc<ThreadGroup>,
930
931 pub running_state: RcuArc<TaskRunningState>,
935
936 stop_state: AtomicStopState,
940
941 flags: AtomicTaskFlags,
945
946 mutable_state:
948 starnix_sync::LockDepRwLock<TaskMutableState, starnix_sync::TaskMutableStateLock>,
949
950 pub persistent_info: TaskPersistentInfo,
955
956 vfork_event: Option<Arc<zx::Event>>,
960
961 pub seccomp_filter_state: SeccompState,
964
965 pub trace_syscalls: AtomicBool,
967}
968
969#[derive(Debug)]
971pub struct PageFaultExceptionReport {
972 pub faulting_address: u64,
973 pub not_present: bool, pub is_write: bool, pub is_execute: bool, }
977
978impl Task {
979 pub fn kernel(&self) -> &Arc<Kernel> {
980 &self.kernel
981 }
982
983 pub fn thread_group(&self) -> &Arc<ThreadGroup> {
984 &self.thread_group
985 }
986
987 pub fn has_same_address_space(&self, other: Option<&Arc<MemoryManager>>) -> bool {
988 match (self.mm(), other) {
989 (Ok(this), Some(other)) => Arc::ptr_eq(&this, other),
990 (Err(_), None) => true,
991 _ => false,
992 }
993 }
994
995 pub fn flags(&self) -> TaskFlags {
996 self.flags.load(Ordering::Relaxed)
997 }
998
999 pub fn is_spawned(&self) -> bool {
1000 self.flags().contains(TaskFlags::SPAWNED)
1001 }
1002
1003 pub fn set_ptrace_zombie(&self, pids: &mut crate::task::PidTableGuard<'_>) {
1006 if !self.is_spawned() {
1007 return;
1009 }
1010
1011 let (pgid, exit_signal) = {
1012 let tg = self.thread_group().read();
1013 (tg.process_group.clone(), tg.exit_signal.clone())
1014 };
1015 let mut state = self.write();
1016 state.set_stopped(StopState::ForceAwake, None, None, None);
1017 if let Some(ptrace) = &mut state.ptrace {
1018 ptrace.last_signal_waitable = true;
1020 let tracer_tg = ptrace.core_state.thread_group.upgrade();
1021 if let Some(tracer_tg) = tracer_tg {
1022 drop(state);
1023 let mut tracer_state = tracer_tg.write();
1024 if tracer_state.is_exited() {
1025 return;
1028 }
1029
1030 let exit_status = self.exit_status().unwrap_or_else(|| {
1031 starnix_logging::log_error!("Exiting without an exit code.");
1032 ExitStatus::Exit(u8::MAX)
1033 });
1034 let zombie = ZombieProcess {
1035 task: self
1036 .weak_self
1037 .upgrade()
1038 .expect("Task strong reference must exist while &self is held"),
1039 pgid,
1040 state: ZombieState {
1041 exit_status,
1042 time_stats: TaskTimeStats::default(),
1044 },
1045 exit_signal,
1046 is_canonical: false,
1047 };
1048
1049 tracer_state.zombie_ptracees.add(pids, self.tid.clone(), zombie);
1050 };
1051 }
1052 }
1053
1054 pub fn ptrace_disconnect(&self) {
1056 let tracer_tg = self
1059 .read()
1060 .ptrace
1061 .as_ref()
1062 .map(|p| p.core_state.thread_group.clone())
1063 .and_then(|tg| tg.upgrade());
1064 if let Some(tg) = tracer_tg {
1065 tg.ptracees.lock().remove(&self.persistent_info);
1066 }
1067 }
1068
1069 pub fn exit_status(&self) -> Option<ExitStatus> {
1070 self.is_exitted().then(|| self.read().exit_status.clone()).flatten()
1071 }
1072
1073 pub fn is_exitted(&self) -> bool {
1074 self.flags().contains(TaskFlags::EXITED)
1075 }
1076
1077 pub fn load_stopped(&self) -> StopState {
1078 self.stop_state.load(Ordering::Relaxed)
1079 }
1080
1081 pub fn from_weak(weak: &Weak<Task>) -> Result<Arc<Task>, Errno> {
1083 weak.upgrade().ok_or_else(|| errno!(ESRCH))
1084 }
1085
1086 #[allow(clippy::let_and_return)]
1093 pub fn new(
1094 tid: Pid,
1095 command: TaskCommand,
1096 thread_group: Arc<ThreadGroup>,
1097 files: SharedFdTable,
1098 mm: Option<Arc<MemoryManager>>,
1099 fs: Arc<FsContext>,
1102 creds: Arc<Credentials>,
1103 abstract_socket_namespace: Arc<AbstractUnixSocketNamespace>,
1104 abstract_vsock_namespace: Arc<AbstractVsockSocketNamespace>,
1105 signal_mask: SigSet,
1106 kernel_signals: VecDeque<KernelSignal>,
1107 vfork_event: Option<Arc<zx::Event>>,
1108 scheduler_state: SchedulerState,
1109 uts_ns: UtsNamespaceHandle,
1110 no_new_privs: bool,
1111 seccomp_filter_state: SeccompState,
1112 seccomp_filters: SeccompFilterContainer,
1113 robust_list_head: RobustListHeadPtr,
1114 timerslack_ns: u64,
1115 ) -> Arc<Self> {
1116 let pid = thread_group.leader.clone();
1117 Arc::new_cyclic(|weak_self| {
1118 let task = Task {
1119 weak_self: weak_self.clone(),
1120 tid: tid.clone(),
1121 pid: pid.clone(),
1122 kernel: Arc::clone(&thread_group.kernel),
1123 thread_group,
1124 running_state: RcuArc::new(Some(Arc::new(TaskRunningState {
1125 thread: Default::default(),
1126 files: Some(files).into(),
1127 mm: RcuArc::new(mm),
1128 fs: RcuArc::new(Some(fs)),
1129 abstract_socket_namespace,
1130 abstract_vsock_namespace,
1131 proc_pid_directory_cache: Default::default(),
1132 }))),
1133 vfork_event,
1134 stop_state: AtomicStopState::new(StopState::Awake),
1135 flags: AtomicTaskFlags::new(TaskFlags::empty()),
1136 mutable_state: TaskMutableState {
1137 clear_child_tid: UserRef::default(),
1138 signals: SignalState::with_mask(signal_mask),
1139 run_state: RunState::default(),
1140 kernel_signals,
1141 exit_status: None,
1142 scheduler_state,
1143 uts_ns,
1144 no_new_privs,
1145 oom_score_adj: Default::default(),
1146 seccomp_filters,
1147 robust_list_head,
1148 timerslack_ns,
1149 default_timerslack_ns: timerslack_ns,
1151 ptrace: None,
1152 captured_thread_state: None,
1153 cpuset_path: "/".to_string(),
1154 }
1155 .into(),
1156 persistent_info: TaskPersistentInfoState::new(tid, pid, command, creds),
1157 seccomp_filter_state,
1158 trace_syscalls: AtomicBool::new(false),
1159 };
1160
1161 #[cfg(any(test, debug_assertions))]
1162 {
1163 let _l1 = task.persistent_info.lock_creds();
1165 let _l2 = task.read();
1166 let _l3 = task.persistent_info.command_guard();
1167 }
1168 task
1169 })
1170 }
1171
1172 state_accessor!(Task, mutable_state);
1173
1174 pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
1179 self.persistent_info.real_creds()
1180 }
1181
1182 pub fn clone_creds(&self) -> Arc<Credentials> {
1187 self.persistent_info.clone_creds()
1188 }
1189
1190 pub fn ptracer_task(&self) -> Option<Arc<Task>> {
1191 self.read().ptrace.as_ref().and_then(|p| p.core_state.task.upgrade())
1192 }
1193
1194 pub fn is_running(&self) -> bool {
1200 self.running_state.is_some()
1201 }
1202
1203 #[track_caller]
1210 pub fn running_state(&self) -> Result<Arc<TaskRunningState>, Errno> {
1211 self.running_state.upgrade().ok_or_else(|| errno!(ESRCH))
1212 }
1213
1214 #[track_caller]
1222 pub fn files(&self) -> Result<Arc<FdTable>, Errno> {
1223 self.running_state()?.files()
1224 }
1225
1226 #[track_caller]
1234 pub fn fs(&self) -> Result<Arc<FsContext>, Errno> {
1235 self.running_state()?.fs()
1236 }
1237
1238 #[track_caller]
1247 pub fn mm(&self) -> Result<Arc<MemoryManager>, Errno> {
1248 let _scope = RcuReadScope::new();
1251 self.running_state()?.mm.upgrade().ok_or_else(|| errno!(EINVAL))
1252 }
1253
1254 pub(crate) fn set_scheduler_policy_priority_and_reset_on_fork(
1257 &self,
1258 policy: SchedulingPolicy,
1259 priority: RealtimePriority,
1260 reset_on_fork: bool,
1261 ) -> Result<(), Errno> {
1262 self.update_scheduler_state_then_role(|scheduler_state| {
1263 scheduler_state.policy = policy;
1264 scheduler_state.realtime_priority = priority;
1265 scheduler_state.reset_on_fork = reset_on_fork;
1266 })
1267 }
1268
1269 pub(crate) fn set_scheduler_priority(&self, priority: RealtimePriority) -> Result<(), Errno> {
1271 self.update_scheduler_state_then_role(|scheduler_state| {
1272 scheduler_state.realtime_priority = priority
1273 })
1274 }
1275
1276 pub(crate) fn set_scheduler_nice(&self, nice: NormalPriority) -> Result<(), Errno> {
1278 self.update_scheduler_state_then_role(|scheduler_state| {
1279 scheduler_state.normal_priority = nice
1280 })
1281 }
1282
1283 pub fn sync_scheduler_state_to_role(&self) -> Result<(), Errno> {
1288 self.update_scheduler_state_then_role(|_| {})
1289 }
1290
1291 fn update_scheduler_state_then_role(
1292 &self,
1293 updater: impl FnOnce(&mut SchedulerState),
1294 ) -> Result<(), Errno> {
1295 let process_name = self.thread_group().read().leader_command();
1296 let thread_name = self.command();
1297
1298 let (new_scheduler_state, cpuset_path) = {
1299 let mut state = self.write();
1300 updater(&mut state.scheduler_state);
1301 (state.scheduler_state.clone(), state.cpuset_path.clone())
1302 };
1303
1304 let scheduler = &self.thread_group().kernel.scheduler;
1305 let role_name = scheduler.resolve_role_name(
1306 &process_name,
1307 &thread_name,
1308 &cpuset_path,
1309 &new_scheduler_state,
1310 );
1311 if new_scheduler_state.applied_role_name.as_deref() == Some(role_name) {
1312 return Ok(());
1313 }
1314 scheduler.set_thread_role(self, role_name)?;
1315 self.write().scheduler_state.applied_role_name = Some(role_name.to_string());
1320 Ok(())
1321 }
1322
1323 pub fn signal_vfork(&self) {
1325 if let Some(event) = &self.vfork_event {
1326 if let Err(status) = event.signal(Signals::NONE, Signals::USER_0) {
1327 log_warn!("Failed to set vfork signal {status}");
1328 }
1329 };
1330 }
1331
1332 pub fn wait_for_execve(&self, task_to_wait: Weak<Task>) -> Result<(), Errno> {
1335 let event = task_to_wait.upgrade().and_then(|t| t.vfork_event.clone());
1336 if let Some(event) = event {
1337 event
1338 .wait_one(zx::Signals::USER_0, zx::MonotonicInstant::INFINITE)
1339 .map_err(|status| from_status_like_fdio!(status))?;
1340 }
1341 Ok(())
1342 }
1343
1344 pub fn clear_child_tid_if_needed(&self) -> Result<(), Errno> {
1352 let mut state = self.write();
1353 let user_tid = state.clear_child_tid;
1354 if !user_tid.is_null() {
1355 let zero: tid_t = 0;
1356 self.write_object(user_tid, &zero)?;
1357 self.kernel().shared_futexes.wake(
1358 self,
1359 user_tid.addr(),
1360 usize::MAX,
1361 FUTEX_BITSET_MATCH_ANY,
1362 )?;
1363 state.clear_child_tid = UserRef::default();
1364 }
1365 Ok(())
1366 }
1367
1368 pub fn get_task(&self, tid: tid_t) -> Result<Arc<Task>, Errno> {
1369 self.kernel().pids.get(tid)?.get_task()
1370 }
1371
1372 pub fn get_pid(&self) -> pid_t {
1373 self.pid.id
1374 }
1375
1376 pub fn get_tid(&self) -> tid_t {
1377 self.tid.id
1378 }
1379
1380 pub fn is_leader(&self) -> bool {
1381 self.get_pid() == self.get_tid()
1382 }
1383
1384 pub fn read_argv(&self, max_len: usize) -> Result<Vec<FsString>, Errno> {
1385 let Ok(mm) = self.mm() else {
1387 return Ok(vec![]);
1388 };
1389 let (argv_start, argv_end) = {
1390 let mm_state = mm.state.read();
1391 (mm_state.argv_start, mm_state.argv_end)
1392 };
1393
1394 let len_to_read = std::cmp::min(argv_end - argv_start, max_len);
1395 self.read_nul_delimited_c_string_list(argv_start, len_to_read)
1396 }
1397
1398 pub fn read_argv0(&self) -> Result<FsString, Errno> {
1399 let Ok(mm) = self.mm() else {
1401 return Ok(FsString::default());
1402 };
1403 let argv_start = {
1404 let mm_state = mm.state.read();
1405 mm_state.argv_start
1406 };
1407 let argv_start = UserCString::new(&ArchWidth::Arch64, argv_start);
1409 self.read_path(argv_start)
1410 }
1411
1412 pub fn read_env(&self, max_len: usize) -> Result<Vec<FsString>, Errno> {
1413 let Ok(mm) = self.mm() else { return Ok(vec![]) };
1415 let (env_start, env_end) = {
1416 let mm_state = mm.state.read();
1417 (mm_state.environ_start, mm_state.environ_end)
1418 };
1419
1420 let len_to_read = std::cmp::min(env_end - env_start, max_len);
1421 self.read_nul_delimited_c_string_list(env_start, len_to_read)
1422 }
1423
1424 pub fn thread_runtime_info(&self) -> Result<zx::TaskRuntimeInfo, Errno> {
1425 self.running_state()?
1426 .thread
1427 .get()
1428 .ok_or_else(|| errno!(EINVAL))?
1429 .get_runtime_info()
1430 .map_err(|status| from_status_like_fdio!(status))
1431 }
1432
1433 pub fn real_fscred(&self) -> FsCred {
1434 self.real_creds().as_fscred()
1435 }
1436
1437 pub fn interrupt(&self) {
1442 let Ok(running_state) = self.running_state() else {
1443 log_warn!("Cannot interrupt dead task {}", self.get_tid());
1444 return;
1445 };
1446
1447 self.read().run_state.wake();
1448 if let Some(thread) = running_state.thread.get() {
1449 #[allow(
1450 clippy::undocumented_unsafe_blocks,
1451 reason = "Force documented unsafe blocks in Starnix"
1452 )]
1453 let status = unsafe { zx::sys::zx_restricted_kick(thread.raw_handle(), 0) };
1454 if status != zx::sys::ZX_OK {
1455 assert_eq!(status, zx::sys::ZX_ERR_BAD_STATE);
1459 }
1460 }
1461 }
1462
1463 pub fn command(&self) -> TaskCommand {
1464 self.persistent_info.command.lock().clone()
1465 }
1466
1467 pub fn set_command_name(&self, mut new_name: TaskCommand) {
1468 let Ok(running_state) = self.running_state() else {
1469 log_warn!("Cannot set command name for dead task {}", self.get_tid());
1470 return;
1471 };
1472
1473 if let Ok(argv0) = self.read_argv0() {
1477 let argv0 = TaskCommand::from_path_bytes(&argv0);
1478 if let Some(embedded_name) = argv0.try_embed(&new_name) {
1479 new_name = embedded_name;
1480 }
1481 }
1482
1483 let mut command_guard = self.persistent_info.command_guard();
1487
1488 if let Some(thread) = running_state.thread.get() {
1490 set_zx_name(thread.thread.as_ref(), new_name.as_bytes());
1491 }
1492
1493 if self.is_leader() {
1495 set_zx_name(&*self.thread_group().process, new_name.as_bytes());
1496 let _ = zx::Thread::raise_user_exception(
1497 zx::RaiseExceptionOptions::TARGET_JOB_DEBUGGER,
1498 zx::sys::ZX_EXCP_USER_CODE_PROCESS_NAME_CHANGED,
1499 0,
1500 );
1501 }
1502
1503 *command_guard = new_name;
1506 drop(command_guard);
1507
1508 if self.is_leader() {
1509 if let Some(notifier) = &self.thread_group().read().notifier {
1510 let _ = notifier.send(MemoryAttributionLifecycleEvent::name_change(self.tid.id));
1511 }
1512 }
1513
1514 if let Err(err) = self.sync_scheduler_state_to_role() {
1515 log_warn!(err:?; "Failed to update scheduler role after thread name change.");
1516 }
1517 }
1518
1519 pub fn set_seccomp_state(&self, state: SeccompStateValue) -> Result<(), Errno> {
1520 self.seccomp_filter_state.set(&state)
1521 }
1522
1523 pub fn state_code(&self) -> TaskStateCode {
1524 let status = self.read();
1525 if status.exit_status.is_some() {
1526 TaskStateCode::Zombie
1527 } else {
1528 status.run_state.state_code()
1529 }
1530 }
1531
1532 pub fn time_stats(&self) -> TaskTimeStats {
1533 use zx::Task;
1534 let running_state = match self.running_state() {
1536 Ok(running_state) => running_state,
1537 Err(_) => return TaskTimeStats::default(),
1538 };
1539 let info = match running_state.thread.get() {
1540 Some(thread) => thread.get_runtime_info().expect("Failed to get thread stats"),
1541 None => return TaskTimeStats::default(),
1542 };
1543
1544 TaskTimeStats {
1545 user_time: zx::MonotonicDuration::from_nanos(info.cpu_time),
1546 system_time: zx::MonotonicDuration::default(),
1548 }
1549 }
1550
1551 pub fn get_signal_action(&self, signal: Signal) -> sigaction_t {
1552 self.thread_group().signal_actions.get(signal)
1553 }
1554
1555 pub fn should_check_for_pending_signals(&self) -> bool {
1556 self.flags().intersects(
1557 TaskFlags::KERNEL_SIGNALS_AVAILABLE
1558 | TaskFlags::SIGNALS_AVAILABLE
1559 | TaskFlags::TEMPORARY_SIGNAL_MASK,
1560 ) || self.thread_group.has_pending_signals.load(Ordering::Relaxed)
1561 }
1562
1563 pub fn get_zircon_identity(&self) -> Option<ZirconIdentity> {
1568 let process = self.thread_group().get_process_koid().ok()?;
1569 let thread = self.running_state().ok()?.thread.get()?.koid;
1570 Some(ZirconIdentity { process, thread })
1571 }
1572
1573 pub fn record_pid_koid_mapping(&self) {
1575 if !self.kernel().trace_event_manager.is_recording() {
1576 return;
1577 }
1578 if let Some(identity) = self.get_zircon_identity() {
1579 self.kernel().trace_event_manager.record(self.get_pid(), self.get_tid(), identity);
1580 }
1581 }
1582}
1583
1584impl Drop for Task {
1585 fn drop(&mut self) {
1586 debug_assert!(self.running_state.is_none());
1587 }
1588}
1589
1590impl MemoryAccessor for Task {
1591 fn read_memory<'a>(
1592 &self,
1593 addr: UserAddress,
1594 bytes: &'a mut [MaybeUninit<u8>],
1595 ) -> Result<&'a mut [u8], Errno> {
1596 self.mm()?.syscall_read_memory(addr, bytes)
1601 }
1602
1603 fn read_memory_partial_until_null_byte<'a>(
1604 &self,
1605 addr: UserAddress,
1606 bytes: &'a mut [MaybeUninit<u8>],
1607 ) -> Result<&'a mut [u8], Errno> {
1608 self.mm()?.syscall_read_memory_partial_until_null_byte(addr, bytes)
1613 }
1614
1615 fn read_memory_partial<'a>(
1616 &self,
1617 addr: UserAddress,
1618 bytes: &'a mut [MaybeUninit<u8>],
1619 ) -> Result<&'a mut [u8], Errno> {
1620 self.mm()?.syscall_read_memory_partial(addr, bytes)
1625 }
1626
1627 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1628 self.mm()?.syscall_write_memory(addr, bytes)
1633 }
1634
1635 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1636 self.mm()?.syscall_write_memory_partial(addr, bytes)
1641 }
1642
1643 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
1644 self.mm()?.syscall_zero(addr, length)
1649 }
1650}
1651
1652impl TaskMemoryAccessor for Task {
1653 fn maximum_valid_address(&self) -> Option<UserAddress> {
1654 self.mm().map(|mm| mm.maximum_valid_user_address).ok()
1655 }
1656}
1657
1658impl fmt::Debug for Task {
1659 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1660 write!(f, "{}:{}[{}]", self.pid, self.tid, *self.persistent_info.command.lock())
1661 }
1662}
1663
1664impl cmp::PartialEq for Task {
1665 fn eq(&self, other: &Self) -> bool {
1666 let ptr: *const Task = self;
1667 let other_ptr: *const Task = other;
1668 ptr == other_ptr
1669 }
1670}
1671
1672impl cmp::Eq for Task {}
1673
1674#[cfg(test)]
1675mod test {
1676 use super::*;
1677 use crate::security;
1678 use crate::testing::*;
1679 use starnix_uapi::auth::{CAP_SYS_ADMIN, Capabilities};
1680 use starnix_uapi::resource_limits::Resource;
1681 use starnix_uapi::signals::{SIGCHLD, SIGUSR1};
1682 use starnix_uapi::{CLONE_SIGHAND, CLONE_THREAD, CLONE_VM, rlimit};
1683
1684 #[::fuchsia::test]
1685 async fn test_tid_allocation() {
1686 spawn_kernel_and_run(async |current_task| {
1687 let kernel = current_task.kernel();
1688 assert_eq!(current_task.get_tid(), 1);
1689 let another_current = create_task(&kernel, "another-task");
1690 let another_tid = another_current.get_tid();
1691 assert!(another_tid >= 2);
1692
1693 let pids = &kernel.pids;
1694 assert_eq!(pids.get(1).unwrap().get_task().unwrap().get_tid(), 1);
1695 assert_eq!(pids.get(another_tid).unwrap().get_task().unwrap().get_tid(), another_tid);
1696 })
1697 .await;
1698 }
1699
1700 #[::fuchsia::test]
1701 async fn test_clone_pid_and_parent_pid() {
1702 spawn_kernel_and_run(async |current_task| {
1703 let thread = current_task.clone_task_for_test(
1704 (CLONE_THREAD | CLONE_VM | CLONE_SIGHAND) as u64,
1705 Some(SIGCHLD),
1706 );
1707 assert_eq!(current_task.get_pid(), thread.get_pid());
1708 assert_ne!(current_task.get_tid(), thread.get_tid());
1709 assert_eq!(current_task.pid, thread.thread_group().leader);
1710
1711 let child_task = current_task.clone_task_for_test(0, Some(SIGCHLD));
1712 assert_ne!(current_task.get_pid(), child_task.get_pid());
1713 assert_ne!(current_task.get_tid(), child_task.get_tid());
1714 assert_eq!(current_task.get_pid(), child_task.thread_group().read().get_ppid());
1715 })
1716 .await;
1717 }
1718
1719 #[::fuchsia::test]
1720 async fn test_root_capabilities() {
1721 spawn_kernel_and_run(async |current_task| {
1722 assert!(security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN));
1723 assert_eq!(current_task.real_creds().cap_inheritable, Capabilities::empty());
1724
1725 current_task.set_creds(Credentials::with_ids(1, 1));
1726 assert!(!security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN));
1727 })
1728 .await;
1729 }
1730
1731 #[::fuchsia::test]
1732 async fn test_is_spawned() {
1733 spawn_kernel_and_run(async |current_task| {
1734 assert!(current_task.is_spawned());
1736
1737 let child = current_task
1739 .clone_task(
1740 0,
1741 Some(SIGCHLD),
1742 UserRef::default(),
1743 UserRef::default(),
1744 UserRef::default(),
1745 )
1746 .expect("failed to create task in test");
1747 assert!(!child.is_spawned());
1748 child.release(());
1749
1750 let test_child = current_task.clone_task_for_test(0, Some(SIGCHLD));
1753 assert!(test_child.is_spawned());
1754 })
1755 .await;
1756 }
1757
1758 #[::fuchsia::test]
1759 async fn test_clone_rlimit() {
1760 spawn_kernel_and_run(async |current_task| {
1761 let prev_fsize = current_task.thread_group().get_rlimit(Resource::FSIZE);
1762 assert_ne!(prev_fsize, 10);
1763 current_task
1764 .thread_group()
1765 .limits
1766 .lock()
1767 .set(Resource::FSIZE, rlimit { rlim_cur: 10, rlim_max: 100 });
1768 let current_fsize = current_task.thread_group().get_rlimit(Resource::FSIZE);
1769 assert_eq!(current_fsize, 10);
1770
1771 let child_task = current_task.clone_task_for_test(0, Some(SIGCHLD));
1772 let child_fsize = child_task.thread_group().get_rlimit(Resource::FSIZE);
1773 assert_eq!(child_fsize, 10)
1774 })
1775 .await;
1776 }
1777
1778 #[::fuchsia::test]
1779 async fn test_set_command_name_syncs_scheduler_role() {
1780 use crate::task::{RoleOverrides, SchedulerManager};
1781
1782 let mut builder = RoleOverrides::new();
1783 builder.add("renamed-thread", "renamed-thread", None, "test-role");
1784 let overrides = builder.build().unwrap();
1785
1786 let scheduler_manager = SchedulerManager::new_for_tests(None, overrides);
1787
1788 spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
1789 current_task.thread_group().write().did_exec = true;
1791
1792 let scheduler = ¤t_task.thread_group().kernel.scheduler;
1793
1794 let initial_role = scheduler.role_name(current_task).unwrap();
1796 assert_ne!(initial_role, "test-role");
1797
1798 current_task
1800 .set_command_name(starnix_task_command::TaskCommand::new(b"renamed-thread"));
1801
1802 let renamed_role = scheduler.role_name(current_task).unwrap();
1803 assert_eq!(renamed_role, "test-role");
1804 })
1805 .await;
1806 }
1807
1808 #[::fuchsia::test]
1809 async fn test_fork_does_not_inherit_custom_role() {
1810 use crate::task::{RoleOverrides, SchedulerManager};
1811
1812 let mut builder = RoleOverrides::new();
1813 builder.add("renamed-thread", "renamed-thread", None, "test-role");
1814 let overrides = builder.build().unwrap();
1815
1816 let scheduler_manager = SchedulerManager::new_for_tests(None, overrides);
1817
1818 spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
1819 let child = current_task.clone_task_for_test(0, None);
1821
1822 let scheduler = ¤t_task.thread_group().kernel.scheduler;
1823
1824 let initial_role = scheduler.role_name(&child).unwrap();
1826 assert_ne!(initial_role, "test-role");
1827
1828 child.set_command_name(starnix_task_command::TaskCommand::new(b"renamed-thread"));
1831
1832 let renamed_role = scheduler.role_name(&child).unwrap();
1833 assert_ne!(renamed_role, "test-role");
1834 })
1835 .await;
1836 }
1837
1838 #[::fuchsia::test]
1839 async fn test_copy_state_from_preserves_dirty_snapshot() {
1840 spawn_kernel_and_run(async |current_task| {
1841 let mut state = current_task.write();
1842 assert!(state.captured_thread_state.is_none());
1843
1844 state.copy_state_from(current_task);
1845 assert!(state.captured_thread_state.is_some());
1846 assert!(!state.captured_thread_state.as_ref().unwrap().dirty);
1847
1848 state.captured_thread_state.as_mut().unwrap().dirty = true;
1850
1851 state.copy_state_from(current_task);
1853 assert!(state.captured_thread_state.as_ref().unwrap().dirty);
1854 })
1855 .await;
1856 }
1857
1858 #[::fuchsia::test]
1859 async fn test_temporary_signal_mask_without_pending_signals() {
1860 spawn_kernel_and_run(async |current_task| {
1861 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1862 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1863
1864 current_task.write().set_temporary_signal_mask(SigSet::from(SIGUSR1));
1865 assert!(current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1866 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1867
1868 current_task.write().restore_signal_mask();
1869 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1870 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1871 })
1872 .await;
1873 }
1874
1875 #[::fuchsia::test]
1876 async fn test_temporary_signal_mask_masks_pending_signal() {
1877 spawn_kernel_and_run(async |current_task| {
1878 current_task.write().enqueue_signal(SignalInfo::kernel(SIGUSR1));
1879 assert!(current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1880 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1881
1882 current_task.write().set_temporary_signal_mask(SigSet::from(SIGUSR1));
1883 assert!(current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1884 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1885
1886 current_task.write().restore_signal_mask();
1887 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1888 assert!(current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1889 })
1890 .await;
1891 }
1892
1893 #[::fuchsia::test]
1894 async fn test_temporary_signal_mask_unmasks_pending_signal() {
1895 spawn_kernel_and_run(async |current_task| {
1896 current_task.write().set_signal_mask(SigSet::from(SIGUSR1));
1897 current_task.write().enqueue_signal(SignalInfo::kernel(SIGUSR1));
1898 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1899 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1900
1901 current_task.write().set_temporary_signal_mask(SigSet::default());
1902 assert!(current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1903 assert!(current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1904
1905 current_task.write().restore_signal_mask();
1906 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
1907 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
1908 })
1909 .await;
1910 }
1911}