1use crate::mm::{
6 MappingAccess, MemoryAccessor, MemoryAccessorExt, MemoryManager, TaskMemoryAccessor,
7};
8use crate::mutable_state::{state_accessor, state_implementation};
9use crate::ptrace::{AtomicStopState, PtraceEventData, PtraceState, PtraceStatus, StopState};
10use crate::signals::{KernelSignal, SignalDetail, SignalInfo, SignalState};
11use crate::task::memory_attribution::MemoryAttributionLifecycleEvent;
12use crate::task::run_state::RunState;
13use crate::task::tracing::ZirconIdentity;
14use crate::task::{
15 AbstractUnixSocketNamespace, AbstractVsockSocketNamespace, CurrentCreds, CurrentTask,
16 EventHandler, ExitStatus, Kernel, NormalPriority, Pid, RealtimePriority, SchedulerState,
17 SchedulingPolicy, SeccompFilterContainer, SeccompState, SeccompStateValue, TaskRunningState,
18 ThreadGroup, ThreadState, UtsNamespaceHandle, WaitCanceler, Waiter, ZombieProcess, ZombieState,
19};
20use crate::vfs::{FdTable, FsContext, FsString, SharedFdTable, SharedFsContext};
21use atomic_bitflags::atomic_bitflags;
22use fuchsia_rcu::{RcuArc, RcuDroppable, RcuDroppableArc, RcuReadGuard, RcuReadScope};
23use macro_rules_attribute::apply;
24use starnix_logging::{log_warn, set_zx_name};
25use starnix_registers::HeapRegs;
26use starnix_sync::{
27 LockDepGuard, LockDepMutex, LockDepReadGuard, LockDepRwLock, LockDepWriteGuard,
28 TaskCommandLevel, TaskCredsLock,
29};
30use starnix_task_command::TaskCommand;
31use starnix_types::arch::ArchWidth;
32use starnix_types::stats::TaskTimeStats;
33use starnix_types::user_buffer::UserBuffer;
34use starnix_uapi::auth::{CAP_SYS_PTRACE, Credentials, FsCred};
35use starnix_uapi::errors::Errno;
36use starnix_uapi::signals::{SIGCHLD, SIGKILL, SigSet, Signal, sigaltstack_contains_pointer};
37use starnix_uapi::user_address::{
38 ArchSpecific, MappingMultiArchUserRef, UserAddress, UserCString, UserRef,
39};
40use starnix_uapi::{
41 CLD_TRAPPED, FUTEX_BITSET_MATCH_ANY, errno, error, from_status_like_fdio, pid_t, sigaction_t,
42 sigaltstack, tid_t, uapi,
43};
44use std::collections::VecDeque;
45use std::mem::MaybeUninit;
46use std::ops::Deref;
47use std::sync::atomic::{AtomicBool, Ordering};
48use std::sync::{Arc, Weak};
49use std::{cmp, fmt};
50use zx::{Signals, Task as _};
51
52atomic_bitflags! {
53 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
54 pub struct TaskFlags: u8 {
55 const EXITED = 1 << 0;
56 const SIGNALS_AVAILABLE = 1 << 1;
57 const TEMPORARY_SIGNAL_MASK = 1 << 2;
58 const DUMP_ON_EXIT = 1 << 3;
61 const KERNEL_SIGNALS_AVAILABLE = 1 << 4;
62 const SPAWNED = 1 << 5;
64 const WORK_CANCELLED = 1 << 6;
69 const IN_CORE_DUMP_SIGNAL_HANDLER = 1 << 7;
78 }
79}
80
81pub struct CapturedThreadState {
88 pub thread_state: ThreadState<HeapRegs>,
91
92 pub dirty: bool,
95}
96
97impl ArchSpecific for CapturedThreadState {
98 fn is_arch32(&self) -> bool {
99 self.thread_state.is_arch32()
100 }
101}
102
103#[derive(Debug)]
104pub struct RobustList {
105 pub next: RobustListPtr,
106}
107
108pub type RobustListPtr =
109 MappingMultiArchUserRef<RobustList, uapi::robust_list, uapi::arch32::robust_list>;
110
111impl From<uapi::robust_list> for RobustList {
112 fn from(robust_list: uapi::robust_list) -> Self {
113 Self { next: RobustListPtr::from(robust_list.next) }
114 }
115}
116
117#[cfg(target_arch = "aarch64")]
118impl From<uapi::arch32::robust_list> for RobustList {
119 fn from(robust_list: uapi::arch32::robust_list) -> Self {
120 Self { next: RobustListPtr::from(robust_list.next) }
121 }
122}
123
124#[derive(Debug)]
125pub struct RobustListHead {
126 pub list: RobustList,
127 pub futex_offset: isize,
128}
129
130pub type RobustListHeadPtr =
131 MappingMultiArchUserRef<RobustListHead, uapi::robust_list_head, uapi::arch32::robust_list_head>;
132
133impl From<uapi::robust_list_head> for RobustListHead {
134 fn from(robust_list_head: uapi::robust_list_head) -> Self {
135 Self {
136 list: robust_list_head.list.into(),
137 futex_offset: robust_list_head.futex_offset as isize,
138 }
139 }
140}
141
142#[cfg(target_arch = "aarch64")]
143impl From<uapi::arch32::robust_list_head> for RobustListHead {
144 fn from(robust_list_head: uapi::arch32::robust_list_head) -> Self {
145 Self {
146 list: robust_list_head.list.into(),
147 futex_offset: robust_list_head.futex_offset as isize,
148 }
149 }
150}
151
152pub struct TaskMutableState {
153 pub clear_child_tid: UserRef<tid_t>,
155
156 signals: SignalState,
159
160 run_state: RunState,
162
163 kernel_signals: VecDeque<KernelSignal>,
171
172 exit_status: Option<ExitStatus>,
174
175 pub uts_ns: UtsNamespaceHandle,
183
184 no_new_privs: bool,
190
191 pub oom_score_adj: i32,
193
194 pub seccomp_filters: SeccompFilterContainer,
196
197 pub robust_list_head: RobustListHeadPtr,
200
201 pub timerslack_ns: u64,
207
208 pub default_timerslack_ns: u64,
214
215 pub ptrace: Option<Box<PtraceState>>,
218
219 pub captured_thread_state: Option<Box<CapturedThreadState>>,
221
222 pub cpuset_path: String,
224}
225
226impl TaskMutableState {
227 pub fn no_new_privs(&self) -> bool {
228 self.no_new_privs
229 }
230
231 pub fn enable_no_new_privs(&mut self) {
234 self.no_new_privs = true;
235 }
236
237 pub fn get_timerslack<T: zx::Timeline>(&self) -> zx::Duration<T> {
238 zx::Duration::from_nanos(self.timerslack_ns as i64)
239 }
240
241 pub fn set_timerslack_ns(&mut self, ns: u64) {
245 if ns == 0 {
246 self.timerslack_ns = self.default_timerslack_ns;
247 } else {
248 self.timerslack_ns = ns;
249 }
250 }
251
252 pub fn is_ptraced(&self) -> bool {
253 self.ptrace.is_some()
254 }
255
256 pub fn is_ptraced_without_cap_sys_ptrace(&self) -> bool {
259 self.ptrace.as_ref().is_some_and(|ptrace| {
260 ptrace.core_state.task.upgrade().is_none_or(|tracer| {
261 !tracer.real_creds().cap_effective.contains(CAP_SYS_PTRACE)
264 })
265 })
266 }
267
268 pub fn is_ptrace_listening(&self) -> bool {
269 self.ptrace.as_ref().is_some_and(|ptrace| ptrace.stop_status == PtraceStatus::Listening)
270 }
271
272 pub fn ptrace_on_signal_consume(&mut self) -> bool {
273 self.ptrace.as_mut().is_some_and(|ptrace: &mut Box<PtraceState>| {
274 if ptrace.stop_status.is_continuing() {
275 ptrace.stop_status = PtraceStatus::Default;
276 false
277 } else {
278 true
279 }
280 })
281 }
282
283 pub fn notify_ptracers(&mut self) {
284 if let Some(ptrace) = &self.ptrace {
285 ptrace.tracer_waiters().notify_all();
286 }
287 }
288
289 pub fn wait_on_ptracer(&self, waiter: &Waiter) {
290 if let Some(ptrace) = &self.ptrace {
291 ptrace.tracee_waiters.wait_async(&waiter);
292 }
293 }
294
295 pub fn notify_ptracees(&mut self) {
296 if let Some(ptrace) = &self.ptrace {
297 ptrace.tracee_waiters.notify_all();
298 }
299 }
300
301 pub fn take_captured_state(&mut self) -> Option<Box<CapturedThreadState>> {
302 self.captured_thread_state.take()
303 }
304
305 fn copy_state_from(&mut self, current_task: &CurrentTask) {
311 if self.captured_thread_state.is_none() {
312 self.captured_thread_state = Some(Box::new(CapturedThreadState {
313 thread_state: current_task.thread_state.extended_snapshot::<HeapRegs>(),
314 dirty: false,
315 }));
316 }
317 }
318
319 pub fn signal_mask(&self) -> SigSet {
321 self.signals.mask()
322 }
323
324 pub fn is_signal_masked(&self, signal: Signal) -> bool {
326 self.signals.mask().has_signal(signal)
327 }
328
329 pub fn is_signal_masked_by_saved_mask(&self, signal: Signal) -> bool {
333 self.signals.saved_mask().is_some_and(|mask| mask.has_signal(signal))
334 }
335
336 pub fn is_blocked(&self) -> bool {
338 self.run_state.is_blocked()
339 }
340
341 pub(super) unsafe fn set_run_state(&mut self, run_state: RunState) -> RunState {
348 std::mem::replace(&mut self.run_state, run_state)
349 }
350
351 pub fn run_state(&self) -> RunState {
352 self.run_state.clone()
353 }
354
355 pub fn wake(&self) {
357 unsafe { self.run_state.wake() };
361 }
362
363 pub fn on_signal_stack(&self, stack_pointer_register: u64) -> bool {
364 self.signals
365 .alt_stack
366 .map(|signal_stack| sigaltstack_contains_pointer(&signal_stack, stack_pointer_register))
367 .unwrap_or(false)
368 }
369
370 pub fn set_sigaltstack(&mut self, stack: Option<sigaltstack>) {
371 self.signals.alt_stack = stack;
372 }
373
374 pub fn sigaltstack(&self) -> Option<sigaltstack> {
375 self.signals.alt_stack
376 }
377
378 pub fn wait_on_signal(&mut self, waiter: &Waiter) {
379 self.signals.signal_wait.wait_async(waiter);
380 }
381
382 pub fn signals_mut(&mut self) -> &mut SignalState {
383 &mut self.signals
384 }
385
386 pub fn wait_on_signal_fd_events(
387 &self,
388 waiter: &Waiter,
389 mask: SigSet,
390 handler: EventHandler,
391 ) -> WaitCanceler {
392 self.signals.signal_wait.wait_async_signal_mask(waiter, mask, handler)
393 }
394
395 pub fn notify_signal_waiters(&self, signal: &Signal) {
396 self.signals.signal_wait.notify_signal(signal);
397 }
398
399 pub fn thaw(&mut self) {
401 if let RunState::Frozen(waiter) = &self.run_state {
402 waiter.notify();
403 }
404 }
405
406 pub fn is_frozen(&self) -> bool {
407 matches!(self.run_state, RunState::Frozen(_))
408 }
409
410 #[cfg(test)]
411 pub fn kernel_signals_for_test(&self) -> &VecDeque<KernelSignal> {
412 &self.kernel_signals
413 }
414}
415
416#[apply(state_implementation!)]
417impl TaskMutableState<Base = Task> {
418 pub fn set_stopped(
419 &mut self,
420 stopped: StopState,
421 siginfo: Option<SignalInfo>,
422 current_task: Option<&CurrentTask>,
423 event: Option<PtraceEventData>,
424 ) {
425 if stopped.ptrace_only() && self.ptrace.is_none() {
426 return;
427 }
428
429 if self.base.load_stopped().is_illegal_transition(stopped) {
430 return;
431 }
432
433 self.store_stopped(stopped);
437 if stopped.is_stopped() {
438 if let Some(ref current_task) = current_task {
439 self.copy_state_from(current_task);
440 }
441 }
442 if let Some(ptrace) = &mut self.ptrace {
443 ptrace.set_last_signal(siginfo);
444 ptrace.set_last_event(event);
445 }
446 if stopped == StopState::Waking || stopped == StopState::ForceWaking {
447 self.notify_ptracees();
448 }
449 if !stopped.is_in_progress() {
450 self.notify_ptracers();
451 }
452 }
453
454 pub fn enqueue_signal(&mut self, signal: SignalInfo) {
456 self.signals.enqueue(signal);
457 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
458 }
459
460 pub fn enqueue_signal_front(&mut self, signal: SignalInfo) {
464 self.signals.jump_queue(signal);
465 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
466 }
467
468 pub fn set_signal_mask(&mut self, mask: SigSet) {
470 self.signals.set_mask(mask);
471 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
472 }
473
474 pub fn set_temporary_signal_mask(&mut self, mask: SigSet) {
478 self.signals.set_temporary_mask(mask);
479 let (signals_clear, signals_set) = if self.signals.is_any_pending() {
480 (TaskFlags::empty(), TaskFlags::SIGNALS_AVAILABLE)
481 } else {
482 (TaskFlags::SIGNALS_AVAILABLE, TaskFlags::empty())
483 };
484 self.update_flags(signals_clear, signals_set | TaskFlags::TEMPORARY_SIGNAL_MASK);
485 }
486
487 pub fn restore_signal_mask(&mut self) {
490 self.signals.restore_mask();
491 let (signals_clear, signals_set) = if self.signals.is_any_pending() {
492 (TaskFlags::empty(), TaskFlags::SIGNALS_AVAILABLE)
493 } else {
494 (TaskFlags::SIGNALS_AVAILABLE, TaskFlags::empty())
495 };
496 self.update_flags(signals_clear | TaskFlags::TEMPORARY_SIGNAL_MASK, signals_set);
497 }
498
499 pub fn pending_signal_count(&self) -> usize {
501 self.signals.num_queued() + self.base.thread_group().num_signals_queued()
502 }
503
504 pub fn has_signal_pending(&self, signal: Signal) -> bool {
506 self.signals.has_queued(signal) || self.base.thread_group().has_signal_queued(signal)
507 }
508
509 pub fn prepare_signal_info(
511 &mut self,
512 stopped: StopState,
513 ) -> Option<(Weak<ThreadGroup>, SignalInfo)> {
514 if !stopped.is_stopped() {
515 return None;
516 }
517
518 if let Some(ptrace) = &self.ptrace {
519 if let Some(last_signal) = ptrace.get_last_signal_ref() {
520 let signal_info = SignalInfo::with_detail(
521 SIGCHLD,
522 CLD_TRAPPED as i32,
523 SignalDetail::SIGCHLD {
524 pid: self.base.tid.clone(),
525 uid: self.base.real_creds().uid,
526 status: last_signal.signal.number() as i32,
527 },
528 );
529
530 return Some((ptrace.core_state.thread_group.clone(), signal_info));
531 }
532 }
533
534 None
535 }
536
537 pub fn set_ptrace(&mut self, tracer: Option<Box<PtraceState>>) -> Result<(), Errno> {
538 if tracer.is_some() && self.ptrace.is_some() {
539 return error!(EPERM);
540 }
541
542 if tracer.is_none() {
543 if let Ok(tg_stop_state) = self.base.thread_group().load_stopped().as_in_progress() {
545 self.set_stopped(tg_stop_state, None, None, None);
546 }
547 }
548 self.ptrace = tracer;
549 Ok(())
550 }
551
552 pub fn can_accept_ptrace_commands(&mut self) -> bool {
553 !self.base.load_stopped().is_waking_or_awake()
554 && self.is_ptraced()
555 && !self.is_ptrace_listening()
556 }
557
558 fn store_stopped(&mut self, state: StopState) {
559 self.base.stop_state.store(state, Ordering::Relaxed)
564 }
565
566 pub fn update_flags(&mut self, clear: TaskFlags, set: TaskFlags) {
567 debug_assert_eq!(clear ^ set, clear | set);
572 let observed = self.base.flags();
573 let swapped = self.base.flags.swap((observed | set) & !clear, Ordering::Relaxed);
574 debug_assert_eq!(swapped, observed);
575 }
576
577 pub fn set_flags(&mut self, flag: TaskFlags, v: bool) {
578 let (clear, set) = if v { (TaskFlags::empty(), flag) } else { (flag, TaskFlags::empty()) };
579
580 self.update_flags(clear, set);
581 }
582
583 pub fn set_spawned(&mut self) {
584 self.set_flags(TaskFlags::SPAWNED, true);
585 }
586
587 pub fn set_exit_status(&mut self, status: ExitStatus) {
588 self.set_flags(TaskFlags::EXITED, true);
589 self.exit_status = Some(status);
590 }
591
592 pub fn set_exit_status_if_not_already(&mut self, status: ExitStatus) {
593 self.set_flags(TaskFlags::EXITED, true);
594 self.exit_status.get_or_insert(status);
595 }
596
597 pub(crate) fn force_wake_for_exit(&mut self) {
600 self.set_stopped(
601 StopState::ForceWaking,
602 None,
603 None,
604 None,
605 );
606 self.notify_signal_waiters(&SIGKILL);
607 self.thaw();
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 pub fn is_interrupt_pending(&self) -> bool {
638 self.is_any_signal_pending()
639 || self.base.load_stopped().is_stopping_or_stopped()
640 || self.base.thread_group().load_stopped().is_stopping_or_stopped()
641 }
642
643 fn take_next_signal_where<F>(&mut self, predicate: F) -> Option<SignalInfo>
645 where
646 F: Fn(&SignalInfo) -> bool,
647 {
648 if let Some(signal) = self.signals.take_next_where(&predicate) {
649 self.set_flags(TaskFlags::SIGNALS_AVAILABLE, self.signals.is_any_pending());
650 Some(signal)
651 } else {
652 self.base.thread_group().take_next_signal_where(&predicate)
653 }
654 }
655
656 pub fn take_specific_signal(&mut self, siginfo: SignalInfo) -> Option<SignalInfo> {
660 let signal_mask = self.signal_mask();
661 if signal_mask.has_signal(siginfo.signal) {
662 return None;
663 }
664
665 let predicate = |s: &SignalInfo| s.signal == siginfo.signal;
666 self.take_next_signal_where(predicate)
667 }
668
669 pub fn take_any_signal(&mut self) -> Option<SignalInfo> {
673 let signal_mask = self.signal_mask();
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 take_signal_with_mask(&mut self, signal_mask: SigSet) -> Option<SignalInfo> {
682 let predicate = |s: &SignalInfo| !signal_mask.has_signal(s.signal);
683 self.take_next_signal_where(predicate)
684 }
685
686 pub fn enqueue_kernel_signal(&mut self, signal: KernelSignal) {
688 self.kernel_signals.push_back(signal);
689 self.set_flags(TaskFlags::KERNEL_SIGNALS_AVAILABLE, true);
690 }
691
692 pub fn take_kernel_signal(&mut self) -> Option<KernelSignal> {
696 let signal = self.kernel_signals.pop_front();
697 if self.kernel_signals.is_empty() {
698 self.set_flags(TaskFlags::KERNEL_SIGNALS_AVAILABLE, false);
699 }
700 signal
701 }
702
703 #[cfg(test)]
704 pub fn queued_signal_count(&self, signal: Signal) -> usize {
705 self.signals.queued_count(signal)
706 + self.base.thread_group().pending_signals.lock().queued_count(signal)
707 }
708}
709
710#[derive(Debug, Clone, Copy, PartialEq, Eq)]
711pub enum TaskStateCode {
712 Running,
714
715 Sleeping,
717
718 TracingStop,
720
721 Zombie,
723}
724
725impl TaskStateCode {
726 pub fn code_char(&self) -> char {
727 match self {
728 TaskStateCode::Running => 'R',
729 TaskStateCode::Sleeping => 'S',
730 TaskStateCode::TracingStop => 't',
731 TaskStateCode::Zombie => 'Z',
732 }
733 }
734
735 pub fn name(&self) -> &'static str {
736 match self {
737 TaskStateCode::Running => "running",
738 TaskStateCode::Sleeping => "sleeping",
739 TaskStateCode::TracingStop => "tracing stop",
740 TaskStateCode::Zombie => "zombie",
741 }
742 }
743}
744
745#[derive(Debug, RcuDroppable)]
750pub struct TaskPersistentInfoState {
751 pub tid: Pid,
753 pub pid: Pid,
754
755 command: LockDepMutex<TaskCommand, TaskCommandLevel>,
757
758 creds: RcuDroppableArc<Credentials>,
761
762 creds_lock: LockDepRwLock<(), TaskCredsLock>,
765}
766
767pub struct CredentialsReadGuard<'a> {
769 _lock: LockDepReadGuard<'a, ()>,
770 creds: RcuReadGuard<Credentials>,
771}
772
773impl<'a> Deref for CredentialsReadGuard<'a> {
774 type Target = Credentials;
775
776 fn deref(&self) -> &Self::Target {
777 self.creds.deref()
778 }
779}
780
781pub struct CredentialsWriteGuard<'a> {
784 _lock: LockDepWriteGuard<'a, ()>,
785 creds: &'a RcuDroppableArc<Credentials>,
786}
787
788impl<'a> CredentialsWriteGuard<'a> {
789 pub fn update(&mut self, creds: Arc<Credentials>) {
790 self.creds.update(creds);
791 }
792}
793
794impl TaskPersistentInfoState {
795 fn new(
796 tid: Pid,
797 pid: Pid,
798 command: TaskCommand,
799 creds: Arc<Credentials>,
800 ) -> TaskPersistentInfo {
801 Arc::new(Self {
802 tid,
803 pid,
804 command: command.into(),
805 creds: RcuDroppableArc::new(creds),
806 creds_lock: Default::default(),
807 })
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
849impl std::borrow::Borrow<Pid> for TaskPersistentInfoState {
850 fn borrow(&self) -> &Pid {
851 &self.tid
852 }
853}
854
855impl PartialEq for TaskPersistentInfoState {
856 fn eq(&self, other: &Self) -> bool {
857 self.tid == other.tid
858 }
859}
860
861impl Eq for TaskPersistentInfoState {}
862
863impl PartialOrd for TaskPersistentInfoState {
864 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
865 Some(self.cmp(other))
866 }
867}
868
869impl Ord for TaskPersistentInfoState {
870 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
871 self.tid.cmp(&other.tid)
872 }
873}
874
875impl std::hash::Hash for TaskPersistentInfoState {
876 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
877 self.tid.hash(state);
878 }
879}
880
881pub type TaskPersistentInfo = Arc<TaskPersistentInfoState>;
882
883pub struct CurrentTaskCredentialsWriteGuard {
884 _lock: LockDepWriteGuard<'static, ()>,
888 pub persistent_info: TaskPersistentInfo,
889}
890
891impl CurrentTaskCredentialsWriteGuard {
892 pub fn update(self, current_task: &CurrentTask, creds: Arc<Credentials>) {
893 self.persistent_info.creds.update(creds.clone());
894 *current_task.current_creds.borrow_mut() = CurrentCreds::Cached(creds);
895
896 let maybe_node = current_task.running_state().proc_pid_directory_cache.get();
899 if let Some(node) = maybe_node {
900 let creds = current_task.real_creds().euid_as_fscred();
901 unsafe {
905 node.force_chown(creds);
906 }
907 }
908 }
909}
910
911pub struct Task {
935 pub weak_self: Weak<Self>,
937
938 pub tid: Pid,
944
945 pub pid: Pid,
947
948 pub kernel: Arc<Kernel>,
950
951 pub thread_group: Arc<ThreadGroup>,
956
957 pub running_state: RcuArc<TaskRunningState>,
961
962 stop_state: AtomicStopState,
966
967 flags: AtomicTaskFlags,
971
972 mutable_state:
974 starnix_sync::LockDepRwLock<TaskMutableState, starnix_sync::TaskMutableStateLock>,
975
976 pub scheduler_state:
979 starnix_sync::LockDepMutex<SchedulerState, starnix_sync::TaskSchedulerStateLock>,
980
981 pub persistent_info: TaskPersistentInfo,
986
987 vfork_event: Option<Arc<zx::Event>>,
991
992 pub seccomp_filter_state: SeccompState,
995
996 pub trace_syscalls: AtomicBool,
998}
999
1000#[derive(Debug)]
1002pub struct PageFaultExceptionReport {
1003 pub faulting_address: u64,
1004 pub not_present: bool, pub is_write: bool, pub is_execute: bool, }
1008
1009impl Task {
1010 pub fn kernel(&self) -> &Arc<Kernel> {
1011 &self.kernel
1012 }
1013
1014 pub fn thread_group(&self) -> &Arc<ThreadGroup> {
1015 &self.thread_group
1016 }
1017
1018 pub fn has_same_address_space(&self, other: Option<&Arc<MemoryManager>>) -> bool {
1019 match (self.mm(), other) {
1020 (Ok(this), Some(other)) => Arc::ptr_eq(&this, other),
1021 (Err(_), None) => true,
1022 _ => false,
1023 }
1024 }
1025
1026 pub fn flags(&self) -> TaskFlags {
1027 self.flags.load(Ordering::Relaxed)
1028 }
1029
1030 pub fn is_spawned(&self) -> bool {
1031 self.flags().contains(TaskFlags::SPAWNED)
1032 }
1033
1034 pub fn set_ptrace_zombie(&self, pids: &mut crate::task::PidTableGuard<'_>) {
1037 if !self.is_spawned() {
1038 return;
1040 }
1041
1042 let exit_signal = self.thread_group().read().exit_signal.clone();
1043 let mut state = self.write();
1044 state.set_stopped(StopState::ForceAwake, None, None, None);
1045 if let Some(ptrace) = &mut state.ptrace {
1046 ptrace.last_signal_waitable = true;
1048 let tracer_tg = ptrace.core_state.thread_group.upgrade();
1049 if let Some(tracer_tg) = tracer_tg {
1050 drop(state);
1051 let mut tracer_state = tracer_tg.write();
1052 if tracer_state.is_exited() {
1053 return;
1056 }
1057
1058 let exit_status = self.exit_status().unwrap_or_else(|| {
1059 starnix_logging::log_error!("Exiting without an exit code.");
1060 ExitStatus::Exit(u8::MAX)
1061 });
1062 let zombie = ZombieProcess {
1063 task: self
1064 .weak_self
1065 .upgrade()
1066 .expect("Task strong reference must exist while &self is held"),
1067 state: ZombieState {
1068 exit_status,
1069 time_stats: TaskTimeStats::default(),
1071 },
1072 exit_signal,
1073 is_canonical: false,
1074 };
1075
1076 tracer_state.zombie_ptracees.add(pids, self.tid.clone(), zombie);
1077 };
1078 }
1079 }
1080
1081 pub fn ptrace_disconnect(&self) {
1083 let tracer_tg = self
1086 .read()
1087 .ptrace
1088 .as_ref()
1089 .map(|p| p.core_state.thread_group.clone())
1090 .and_then(|tg| tg.upgrade());
1091 if let Some(tg) = tracer_tg {
1092 tg.ptracees.lock().remove(&self.persistent_info);
1093 }
1094 }
1095
1096 pub fn exit_status(&self) -> Option<ExitStatus> {
1097 self.is_exitted().then(|| self.read().exit_status.clone()).flatten()
1098 }
1099
1100 pub fn is_exitted(&self) -> bool {
1101 self.flags().contains(TaskFlags::EXITED)
1102 }
1103
1104 pub fn load_stopped(&self) -> StopState {
1105 self.stop_state.load(Ordering::Relaxed)
1106 }
1107
1108 pub fn from_weak(weak: &Weak<Task>) -> Result<Arc<Task>, Errno> {
1110 weak.upgrade().ok_or_else(|| errno!(ESRCH))
1111 }
1112
1113 #[allow(clippy::let_and_return)]
1120 pub fn new(
1121 tid: Pid,
1122 command: TaskCommand,
1123 thread_group: Arc<ThreadGroup>,
1124 files: SharedFdTable,
1125 mm: Option<Arc<MemoryManager>>,
1126 fs: Arc<FsContext>,
1129 creds: Arc<Credentials>,
1130 abstract_socket_namespace: Arc<AbstractUnixSocketNamespace>,
1131 abstract_vsock_namespace: Arc<AbstractVsockSocketNamespace>,
1132 signal_mask: SigSet,
1133 kernel_signals: VecDeque<KernelSignal>,
1134 vfork_event: Option<Arc<zx::Event>>,
1135 scheduler_state: SchedulerState,
1136 uts_ns: UtsNamespaceHandle,
1137 no_new_privs: bool,
1138 seccomp_filter_state: SeccompState,
1139 seccomp_filters: SeccompFilterContainer,
1140 robust_list_head: RobustListHeadPtr,
1141 timerslack_ns: u64,
1142 ) -> Arc<Self> {
1143 let pid = thread_group.leader.clone();
1144 Arc::new_cyclic(|weak_self| {
1145 let task = Task {
1146 weak_self: weak_self.clone(),
1147 tid: tid.clone(),
1148 pid: pid.clone(),
1149 kernel: Arc::clone(&thread_group.kernel),
1150 thread_group,
1151 running_state: RcuArc::new(Some(Arc::new(TaskRunningState {
1152 thread: Default::default(),
1153 files: Some(files).into(),
1154 mm: RcuArc::new(mm),
1155 fs: SharedFsContext::new(fs),
1156 abstract_socket_namespace,
1157 abstract_vsock_namespace,
1158 proc_pid_directory_cache: Default::default(),
1159 }))),
1160 vfork_event,
1161 stop_state: AtomicStopState::new(StopState::Awake),
1162 flags: AtomicTaskFlags::new(TaskFlags::empty()),
1163 mutable_state: TaskMutableState {
1164 clear_child_tid: UserRef::default(),
1165 signals: SignalState::with_mask(signal_mask),
1166 run_state: RunState::default(),
1167 kernel_signals,
1168 exit_status: None,
1169 uts_ns,
1170 no_new_privs,
1171 oom_score_adj: Default::default(),
1172 seccomp_filters,
1173 robust_list_head,
1174 timerslack_ns,
1175 default_timerslack_ns: timerslack_ns,
1177 ptrace: None,
1178 captured_thread_state: None,
1179 cpuset_path: "/".to_string(),
1180 }
1181 .into(),
1182 scheduler_state: LockDepMutex::new(scheduler_state),
1183 persistent_info: TaskPersistentInfoState::new(tid, pid, command, creds),
1184 seccomp_filter_state,
1185 trace_syscalls: AtomicBool::new(false),
1186 };
1187
1188 #[cfg(any(test, debug_assertions))]
1189 {
1190 let _l1 = task.persistent_info.lock_creds();
1192 let _l2 = task.scheduler_state.lock();
1193 let _l3 = task.read();
1194 let _l4 = task.persistent_info.command_guard();
1195 }
1196 task
1197 })
1198 }
1199
1200 state_accessor!(Task, mutable_state);
1201
1202 pub fn real_creds(&self) -> RcuReadGuard<Credentials> {
1207 self.persistent_info.real_creds()
1208 }
1209
1210 pub fn clone_creds(&self) -> Arc<Credentials> {
1215 self.persistent_info.clone_creds()
1216 }
1217
1218 pub fn ptracer_task(&self) -> Option<Arc<Task>> {
1219 self.read().ptrace.as_ref().and_then(|p| p.core_state.task.upgrade())
1220 }
1221
1222 pub fn is_running(&self) -> bool {
1228 self.running_state.is_some()
1229 }
1230
1231 #[track_caller]
1238 pub fn running_state(&self) -> Result<Arc<TaskRunningState>, Errno> {
1239 self.running_state.upgrade().ok_or_else(|| errno!(ESRCH))
1240 }
1241
1242 #[track_caller]
1250 pub fn files(&self) -> Result<Arc<FdTable>, Errno> {
1251 self.running_state()?.files()
1252 }
1253
1254 #[track_caller]
1262 pub fn fs(&self) -> Result<Arc<FsContext>, Errno> {
1263 self.running_state()?.fs()
1264 }
1265
1266 #[track_caller]
1275 pub fn mm(&self) -> Result<Arc<MemoryManager>, Errno> {
1276 let _scope = RcuReadScope::new();
1279 self.running_state()?.mm.upgrade().ok_or_else(|| errno!(EINVAL))
1280 }
1281
1282 pub(crate) fn set_scheduler_policy_priority_and_reset_on_fork(
1285 &self,
1286 policy: SchedulingPolicy,
1287 priority: RealtimePriority,
1288 reset_on_fork: bool,
1289 ) -> Result<(), Errno> {
1290 self.update_scheduler_state_then_role(|scheduler_state| {
1291 scheduler_state.policy = policy;
1292 scheduler_state.realtime_priority = priority;
1293 scheduler_state.reset_on_fork = reset_on_fork;
1294 })
1295 }
1296
1297 pub(crate) fn set_scheduler_priority(&self, priority: RealtimePriority) -> Result<(), Errno> {
1299 self.update_scheduler_state_then_role(|scheduler_state| {
1300 scheduler_state.realtime_priority = priority;
1301 })
1302 }
1303
1304 pub(crate) fn set_scheduler_nice(&self, nice: NormalPriority) -> Result<(), Errno> {
1306 self.update_scheduler_state_then_role(|scheduler_state| {
1307 scheduler_state.normal_priority = nice;
1308 })
1309 }
1310
1311 pub fn sync_scheduler_state_to_role(&self) -> Result<(), Errno> {
1316 self.update_scheduler_state_then_role(|_| {})
1317 }
1318
1319 fn update_scheduler_state_then_role(
1320 &self,
1321 updater: impl FnOnce(&mut SchedulerState),
1322 ) -> Result<(), Errno> {
1323 let mut scheduler_state = self.scheduler_state.lock();
1324 let prev = (
1325 scheduler_state.policy,
1326 scheduler_state.normal_priority,
1327 scheduler_state.realtime_priority,
1328 scheduler_state.reset_on_fork,
1329 );
1330 updater(&mut scheduler_state);
1331 let result = if !scheduler_state.policy.is_valid_priority(scheduler_state.realtime_priority)
1332 {
1333 error!(EINVAL)
1334 } else {
1335 self.thread_group().kernel.scheduler.commit_thread_role(self, &mut scheduler_state)
1336 };
1337 result.inspect_err(|_| {
1338 (
1339 scheduler_state.policy,
1340 scheduler_state.normal_priority,
1341 scheduler_state.realtime_priority,
1342 scheduler_state.reset_on_fork,
1343 ) = prev;
1344 })
1345 }
1346
1347 pub fn signal_vfork(&self) {
1349 if let Some(event) = &self.vfork_event {
1350 if let Err(status) = event.signal(Signals::NONE, Signals::USER_0) {
1351 log_warn!("Failed to set vfork signal {status}");
1352 }
1353 };
1354 }
1355
1356 pub fn wait_for_execve(&self, task_to_wait: Weak<Task>) -> Result<(), Errno> {
1359 let event = task_to_wait.upgrade().and_then(|t| t.vfork_event.clone());
1360 if let Some(event) = event {
1361 event
1362 .wait_one(zx::Signals::USER_0, zx::MonotonicInstant::INFINITE)
1363 .map_err(|status| from_status_like_fdio!(status))?;
1364 }
1365 Ok(())
1366 }
1367
1368 pub fn clear_child_tid_if_needed(&self) -> Result<(), Errno> {
1376 let mut state = self.write();
1377 let user_tid = state.clear_child_tid;
1378 if !user_tid.is_null() {
1379 let zero: tid_t = 0;
1380 self.write_object(user_tid, &zero)?;
1381 self.kernel().shared_futexes.wake::<crate::mm::SharedFutexKey>(
1382 self,
1383 user_tid.addr(),
1384 usize::MAX,
1385 FUTEX_BITSET_MATCH_ANY,
1386 )?;
1387 state.clear_child_tid = UserRef::default();
1388 }
1389 Ok(())
1390 }
1391
1392 pub fn get_task(&self, tid: tid_t) -> Result<Arc<Task>, Errno> {
1393 self.kernel().pids.get(tid)?.get_task()
1394 }
1395
1396 pub fn get_pid(&self) -> pid_t {
1397 self.pid.id
1398 }
1399
1400 pub fn get_tid(&self) -> tid_t {
1401 self.tid.id
1402 }
1403
1404 pub fn is_leader(&self) -> bool {
1405 self.get_pid() == self.get_tid()
1406 }
1407
1408 pub fn read_argv(&self, max_len: usize) -> Result<Vec<FsString>, Errno> {
1409 let Ok(mm) = self.mm() else {
1411 return Ok(vec![]);
1412 };
1413 let (argv_start, argv_end) = {
1414 let mm_state = mm.state.read();
1415 (mm_state.argv_start, mm_state.argv_end)
1416 };
1417
1418 let len_to_read = std::cmp::min(argv_end - argv_start, max_len);
1419 self.read_nul_delimited_c_string_list(argv_start, len_to_read)
1420 }
1421
1422 pub fn read_argv0(&self) -> Result<FsString, Errno> {
1423 let Ok(mm) = self.mm() else {
1425 return Ok(FsString::default());
1426 };
1427 let argv_start = {
1428 let mm_state = mm.state.read();
1429 mm_state.argv_start
1430 };
1431 let argv_start = UserCString::new(&ArchWidth::Arch64, argv_start);
1433 self.read_path(argv_start)
1434 }
1435
1436 pub fn read_env(&self, max_len: usize) -> Result<Vec<FsString>, Errno> {
1437 let Ok(mm) = self.mm() else { return Ok(vec![]) };
1439 let (env_start, env_end) = {
1440 let mm_state = mm.state.read();
1441 (mm_state.environ_start, mm_state.environ_end)
1442 };
1443
1444 let len_to_read = std::cmp::min(env_end - env_start, max_len);
1445 self.read_nul_delimited_c_string_list(env_start, len_to_read)
1446 }
1447
1448 pub fn thread_runtime_info(&self) -> Result<zx::TaskRuntimeInfo, Errno> {
1449 self.running_state()?
1450 .thread
1451 .get()
1452 .ok_or_else(|| errno!(EINVAL))?
1453 .get_runtime_info()
1454 .map_err(|status| from_status_like_fdio!(status))
1455 }
1456
1457 pub fn real_fscred(&self) -> FsCred {
1458 self.real_creds().as_fscred()
1459 }
1460
1461 pub fn interrupt(&self) {
1466 let Ok(running_state) = self.running_state() else {
1467 log_warn!("Cannot interrupt dead task {}", self.get_tid());
1468 return;
1469 };
1470
1471 self.read().wake();
1472 if let Some(thread) = running_state.thread.get() {
1473 #[allow(
1474 clippy::undocumented_unsafe_blocks,
1475 reason = "Force documented unsafe blocks in Starnix"
1476 )]
1477 let status = unsafe { zx::sys::zx_restricted_kick(thread.raw_handle(), 0) };
1478 if status != zx::sys::ZX_OK {
1479 assert_eq!(status, zx::sys::ZX_ERR_BAD_STATE);
1483 }
1484 }
1485 }
1486
1487 pub fn command(&self) -> TaskCommand {
1488 self.persistent_info.command.lock().clone()
1489 }
1490
1491 pub fn set_command_name(&self, mut new_name: TaskCommand) {
1492 let Ok(running_state) = self.running_state() else {
1493 log_warn!("Cannot set command name for dead task {}", self.get_tid());
1494 return;
1495 };
1496
1497 let is_leader = self.is_leader();
1498
1499 if is_leader {
1503 if let Ok(argv0) = self.read_argv0() {
1504 let argv0 = TaskCommand::from_path_bytes(&argv0);
1505 if let Some(embedded_name) = argv0.try_embed(&new_name) {
1506 new_name = embedded_name;
1507 }
1508 }
1509 }
1510
1511 let mut command_guard = self.persistent_info.command_guard();
1515
1516 if let Some(thread) = running_state.thread.get() {
1519 set_zx_name(thread.thread.as_ref(), new_name.as_bytes());
1520 }
1521
1522 if is_leader {
1524 set_zx_name(&*self.thread_group().process, new_name.as_bytes());
1525 let _ = zx::Thread::raise_user_exception(
1526 zx::RaiseExceptionOptions::TARGET_JOB_DEBUGGER,
1527 zx::sys::ZX_EXCP_USER_CODE_PROCESS_NAME_CHANGED,
1528 0,
1529 );
1530 }
1531
1532 *command_guard = new_name;
1535 drop(command_guard);
1536
1537 if is_leader {
1538 let tasks = {
1539 let thread_group = self.thread_group().read();
1540 if let Some(notifier) = &thread_group.notifier {
1541 let _ =
1542 notifier.send(MemoryAttributionLifecycleEvent::name_change(self.tid.id));
1543 }
1544 thread_group.tasks()
1545 };
1546 for task in tasks {
1547 if let Err(err) = task.sync_scheduler_state_to_role() {
1548 log_warn!(err:?; "Failed to update scheduler role after process name change.");
1549 }
1550 }
1551 } else if let Err(err) = self.sync_scheduler_state_to_role() {
1552 log_warn!(err:?; "Failed to update scheduler role after thread name change.");
1553 }
1554 }
1555
1556 pub fn set_seccomp_state(&self, state: SeccompStateValue) -> Result<(), Errno> {
1557 self.seccomp_filter_state.set(&state)
1558 }
1559
1560 pub fn state_code(&self) -> TaskStateCode {
1561 let status = self.read();
1562 if status.exit_status.is_some() {
1563 TaskStateCode::Zombie
1564 } else {
1565 status.run_state.state_code()
1566 }
1567 }
1568
1569 pub fn time_stats(&self) -> TaskTimeStats {
1570 use zx::Task;
1571 let running_state = match self.running_state() {
1573 Ok(running_state) => running_state,
1574 Err(_) => return TaskTimeStats::default(),
1575 };
1576 let info = match running_state.thread.get() {
1577 Some(thread) => thread.get_runtime_info().expect("Failed to get thread stats"),
1578 None => return TaskTimeStats::default(),
1579 };
1580
1581 TaskTimeStats {
1582 user_time: zx::MonotonicDuration::from_nanos(info.cpu_time),
1583 system_time: zx::MonotonicDuration::default(),
1585 }
1586 }
1587
1588 pub fn get_signal_action(&self, signal: Signal) -> sigaction_t {
1589 self.thread_group().signal_actions.get(signal)
1590 }
1591
1592 pub fn should_check_for_pending_signals(&self) -> bool {
1593 self.flags().intersects(
1594 TaskFlags::KERNEL_SIGNALS_AVAILABLE
1595 | TaskFlags::SIGNALS_AVAILABLE
1596 | TaskFlags::TEMPORARY_SIGNAL_MASK,
1597 ) || self.thread_group.has_pending_signals.load(Ordering::Relaxed)
1598 }
1599
1600 pub fn get_zircon_identity(&self) -> Option<ZirconIdentity> {
1605 let process = self.thread_group().get_process_koid().ok()?;
1606 let thread = self.running_state().ok()?.thread.get()?.koid;
1607 Some(ZirconIdentity { process, thread })
1608 }
1609
1610 pub fn record_pid_koid_mapping(&self) {
1612 if !self.kernel().trace_event_manager.is_recording() {
1613 return;
1614 }
1615 if let Some(identity) = self.get_zircon_identity() {
1616 self.kernel().trace_event_manager.record(self.get_pid(), self.get_tid(), identity);
1617 }
1618 }
1619}
1620
1621impl Drop for Task {
1622 fn drop(&mut self) {
1623 debug_assert!(self.running_state.is_none());
1624 }
1625}
1626
1627impl MemoryAccessor for Task {
1628 fn read_memory<'a>(
1629 &self,
1630 addr: UserAddress,
1631 bytes: &'a mut [MaybeUninit<u8>],
1632 ) -> Result<&'a mut [u8], Errno> {
1633 self.mm()?.syscall_read_memory(addr, bytes)
1638 }
1639
1640 fn read_memory_partial_until_null_byte<'a>(
1641 &self,
1642 addr: UserAddress,
1643 bytes: &'a mut [MaybeUninit<u8>],
1644 ) -> Result<&'a mut [u8], Errno> {
1645 self.mm()?.syscall_read_memory_partial_until_null_byte(addr, bytes)
1650 }
1651
1652 fn read_memory_partial<'a>(
1653 &self,
1654 addr: UserAddress,
1655 bytes: &'a mut [MaybeUninit<u8>],
1656 ) -> Result<&'a mut [u8], Errno> {
1657 self.mm()?.syscall_read_memory_partial(addr, bytes)
1662 }
1663
1664 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1665 self.mm()?.syscall_write_memory(addr, bytes)
1670 }
1671
1672 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
1673 self.mm()?.syscall_write_memory_partial(addr, bytes)
1678 }
1679
1680 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
1681 self.mm()?.syscall_zero(addr, length)
1686 }
1687}
1688
1689impl TaskMemoryAccessor for Task {
1690 fn maximum_valid_address(&self) -> Option<UserAddress> {
1691 self.mm().map(|mm| mm.maximum_valid_user_address).ok()
1692 }
1693
1694 fn ensure_buffers_mapped_in_user_vmar(
1695 &self,
1696 _buffers: &[UserBuffer],
1697 _access: MappingAccess,
1698 ) -> Result<(), Errno> {
1699 error!(ENOTSUP)
1704 }
1705}
1706
1707impl fmt::Debug for Task {
1708 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1709 write!(f, "{}:{}[{}]", self.pid, self.tid, *self.persistent_info.command.lock())
1710 }
1711}
1712
1713impl cmp::PartialEq for Task {
1714 fn eq(&self, other: &Self) -> bool {
1715 let ptr: *const Task = self;
1716 let other_ptr: *const Task = other;
1717 ptr == other_ptr
1718 }
1719}
1720
1721impl cmp::Eq for Task {}
1722
1723#[cfg(test)]
1724mod test {
1725 use super::*;
1726 use crate::mm::PAGE_SIZE;
1727 use crate::security;
1728 use crate::testing::*;
1729 use starnix_uapi::auth::{CAP_SYS_ADMIN, Capabilities};
1730 use starnix_uapi::resource_limits::Resource;
1731 use starnix_uapi::signals::{SIGCHLD, SIGUSR1};
1732 use starnix_uapi::{CLONE_SIGHAND, CLONE_THREAD, CLONE_VM, rlimit};
1733
1734 #[::fuchsia::test]
1735 async fn test_tid_allocation() {
1736 spawn_kernel_and_run(async |current_task| {
1737 let kernel = current_task.kernel();
1738 assert_eq!(current_task.get_tid(), 1);
1739 let another_current = create_task(&kernel, "another-task");
1740 let another_tid = another_current.get_tid();
1741 assert!(another_tid >= 2);
1742
1743 let pids = &kernel.pids;
1744 assert_eq!(pids.get(1).unwrap().get_task().unwrap().get_tid(), 1);
1745 assert_eq!(pids.get(another_tid).unwrap().get_task().unwrap().get_tid(), another_tid);
1746 })
1747 .await;
1748 }
1749
1750 #[::fuchsia::test]
1751 async fn test_clone_pid_and_parent_pid() {
1752 spawn_kernel_and_run(async |current_task| {
1753 let thread = current_task.clone_task_for_test(
1754 (CLONE_THREAD | CLONE_VM | CLONE_SIGHAND) as u64,
1755 Some(SIGCHLD),
1756 );
1757 assert_eq!(current_task.get_pid(), thread.get_pid());
1758 assert_ne!(current_task.get_tid(), thread.get_tid());
1759 assert_eq!(current_task.pid, thread.thread_group().leader);
1760
1761 let child_task = current_task.clone_task_for_test(0, Some(SIGCHLD));
1762 assert_ne!(current_task.get_pid(), child_task.get_pid());
1763 assert_ne!(current_task.get_tid(), child_task.get_tid());
1764 assert_eq!(current_task.get_pid(), child_task.thread_group().read().get_ppid());
1765 })
1766 .await;
1767 }
1768
1769 #[::fuchsia::test]
1770 async fn test_root_capabilities() {
1771 spawn_kernel_and_run(async |current_task| {
1772 assert!(security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN));
1773 assert_eq!(current_task.real_creds().cap_inheritable, Capabilities::empty());
1774
1775 current_task.set_creds(Credentials::with_ids(1, 1));
1776 assert!(!security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN));
1777 })
1778 .await;
1779 }
1780
1781 #[::fuchsia::test]
1782 async fn test_is_spawned() {
1783 spawn_kernel_and_run(async |current_task| {
1784 assert!(current_task.is_spawned());
1786
1787 let child = current_task
1789 .clone_task(
1790 0,
1791 Some(SIGCHLD),
1792 UserRef::default(),
1793 UserRef::default(),
1794 UserRef::default(),
1795 )
1796 .expect("failed to create task in test");
1797 assert!(!child.is_spawned());
1798 child.release(());
1799
1800 let test_child = current_task.clone_task_for_test(0, Some(SIGCHLD));
1803 assert!(test_child.is_spawned());
1804 })
1805 .await;
1806 }
1807
1808 #[::fuchsia::test]
1809 async fn test_clone_rlimit() {
1810 spawn_kernel_and_run(async |current_task| {
1811 let prev_fsize = current_task.thread_group().get_rlimit(Resource::FSIZE);
1812 assert_ne!(prev_fsize, 10);
1813 current_task
1814 .thread_group()
1815 .limits
1816 .lock()
1817 .set(Resource::FSIZE, rlimit { rlim_cur: 10, rlim_max: 100 });
1818 let current_fsize = current_task.thread_group().get_rlimit(Resource::FSIZE);
1819 assert_eq!(current_fsize, 10);
1820
1821 let child_task = current_task.clone_task_for_test(0, Some(SIGCHLD));
1822 let child_fsize = child_task.thread_group().get_rlimit(Resource::FSIZE);
1823 assert_eq!(child_fsize, 10)
1824 })
1825 .await;
1826 }
1827
1828 #[::fuchsia::test]
1829 async fn test_set_command_name_syncs_scheduler_role() {
1830 use crate::task::{RoleOverrides, SchedulerManager};
1831
1832 let mut builder = RoleOverrides::new();
1833 builder.add("renamed-thread", "renamed-thread", None, "test-role");
1834 let overrides = builder.build().unwrap();
1835
1836 let scheduler_manager = SchedulerManager::new_for_tests(None, overrides);
1837
1838 spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
1839 current_task.thread_group().write().did_exec = true;
1841
1842 let scheduler = ¤t_task.thread_group().kernel.scheduler;
1843
1844 let initial_state = current_task.scheduler_state.lock().clone();
1846 let initial_role = scheduler.role_name(current_task, &initial_state).unwrap();
1847 assert_ne!(initial_role, "test-role");
1848
1849 current_task
1851 .set_command_name(starnix_task_command::TaskCommand::new(b"renamed-thread"));
1852
1853 let renamed_state = current_task.scheduler_state.lock().clone();
1854 let renamed_role = scheduler.role_name(current_task, &renamed_state).unwrap();
1855 assert_eq!(renamed_role, "test-role");
1856 })
1857 .await;
1858 }
1859
1860 #[::fuchsia::test]
1861 async fn test_set_command_name_on_leader_syncs_sibling_scheduler_roles() {
1862 use crate::task::{RoleOverrides, SchedulerManager};
1863 use fidl_fuchsia_scheduler::{
1864 RoleManagerMarker, RoleManagerRequest, RoleManagerSetRoleResponse,
1865 };
1866 use futures::StreamExt as _;
1867 use starnix_sync::Mutex;
1868
1869 let (role_manager, server_end) = fidl::endpoints::create_sync_proxy::<RoleManagerMarker>();
1870 let committed_roles = Arc::new(Mutex::new(Vec::<String>::new()));
1871 let committed_roles_server = committed_roles.clone();
1872 std::thread::spawn(move || {
1873 let mut executor = fuchsia_async::LocalExecutor::default();
1874 executor.run_singlethreaded(async move {
1875 let mut stream = server_end.into_stream();
1876 while let Some(Ok(request)) = stream.next().await {
1877 match request {
1878 RoleManagerRequest::GetProfileForRole { responder, .. } => {
1879 let _ = responder.send(Err(zx::Status::NOT_SUPPORTED.into_raw()));
1880 }
1881 RoleManagerRequest::SetRole { payload, responder } => {
1882 committed_roles_server.lock().push(payload.role.unwrap().role);
1883 let _ = responder.send(Ok(RoleManagerSetRoleResponse::default()));
1884 }
1885 _ => unreachable!(),
1886 }
1887 }
1888 });
1889 });
1890
1891 let mut builder = RoleOverrides::new();
1892 builder.add("my-app", "my-app", None, "leader-role");
1893 builder.add("my-app", "RenderThread", None, "render-role");
1894 let overrides = builder.build().unwrap();
1895 let scheduler_manager = SchedulerManager::new_for_tests(Some(role_manager), overrides);
1896
1897 spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, move |current_task| {
1898 let sibling = current_task.clone_task_for_test(
1899 (CLONE_THREAD | CLONE_VM | CLONE_SIGHAND) as u64,
1900 Some(SIGCHLD),
1901 );
1902 assert!(!sibling.is_leader());
1903 let leader_thread = current_task.running_state().thread.get().unwrap().clone();
1904 sibling.running_state().thread.set(leader_thread).unwrap();
1905
1906 sibling.set_command_name(TaskCommand::new(b"RenderThread"));
1909 assert!(!committed_roles.lock().contains(&"render-role".to_string()));
1910
1911 committed_roles.lock().clear();
1912
1913 current_task.set_command_name(TaskCommand::new(b"my-app"));
1916 let roles = committed_roles.lock().clone();
1917 assert!(roles.contains(&"leader-role".to_string()), "roles: {roles:?}");
1918 assert!(roles.contains(&"render-role".to_string()), "roles: {roles:?}");
1919 })
1920 .await;
1921 }
1922
1923 #[::fuchsia::test]
1924 async fn test_fork_does_not_inherit_custom_role() {
1925 use crate::task::{RoleOverrides, SchedulerManager};
1926
1927 let mut builder = RoleOverrides::new();
1928 builder.add("renamed-thread", "renamed-thread", None, "test-role");
1929 let overrides = builder.build().unwrap();
1930
1931 let scheduler_manager = SchedulerManager::new_for_tests(None, overrides);
1932
1933 spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
1934 let child = current_task.clone_task_for_test(0, None);
1936
1937 let scheduler = ¤t_task.thread_group().kernel.scheduler;
1938
1939 let initial_state = child.scheduler_state.lock().clone();
1941 let initial_role = scheduler.role_name(&child, &initial_state).unwrap();
1942 assert_ne!(initial_role, "test-role");
1943
1944 child.set_command_name(starnix_task_command::TaskCommand::new(b"renamed-thread"));
1947
1948 let renamed_state = child.scheduler_state.lock().clone();
1949 let renamed_role = scheduler.role_name(&child, &renamed_state).unwrap();
1950 assert_ne!(renamed_role, "test-role");
1951 })
1952 .await;
1953 }
1954
1955 #[::fuchsia::test]
1956 async fn test_set_command_name_only_embeds_argv0_on_leader() {
1957 spawn_kernel_and_run(async |current_task| {
1958 let argv0_bytes = b"/bin/my_long_command_name\0";
1959 let addr = map_memory(current_task, UserAddress::default(), *PAGE_SIZE);
1960 current_task.write_memory(addr, argv0_bytes).expect("write argv0");
1961 {
1962 let mm = current_task.mm().expect("mm");
1963 let mut mm_state = mm.state.write();
1964 mm_state.argv_start = addr;
1965 mm_state.argv_end = (addr + argv0_bytes.len()).expect("argv_end");
1966 }
1967
1968 current_task.set_command_name(TaskCommand::new(b"my_long_command"));
1971 let cmd = current_task.command();
1972 assert_eq!(cmd.as_bytes(), b"my_long_command_name");
1973 assert_eq!(cmd.comm_name(), b"my_long_command");
1974
1975 let thread = current_task.clone_task_for_test(
1977 (CLONE_THREAD | CLONE_VM | CLONE_SIGHAND) as u64,
1978 Some(SIGCHLD),
1979 );
1980 assert!(!thread.is_leader());
1981 thread.set_command_name(TaskCommand::new(b"my_long_command"));
1982 let cmd = thread.command();
1983 assert_eq!(cmd.as_bytes(), b"my_long_command");
1984 assert_eq!(cmd.comm_name(), b"my_long_command");
1985 })
1986 .await;
1987 }
1988
1989 #[::fuchsia::test]
1990 async fn test_set_scheduler_priority_validates_policy() {
1991 spawn_kernel_and_run(async |current_task| {
1992 let non_realtime = SchedulingPolicy::Normal.realtime_priority_from(0).unwrap();
1993 let realtime_10 = SchedulingPolicy::Fifo.realtime_priority_from(10).unwrap();
1994 let realtime_20 = SchedulingPolicy::Fifo.realtime_priority_from(20).unwrap();
1995
1996 assert!(SchedulingPolicy::Normal.is_valid_priority(non_realtime));
1997 assert!(!SchedulingPolicy::Normal.is_valid_priority(realtime_10));
1998 assert!(SchedulingPolicy::Fifo.is_valid_priority(realtime_10));
1999 assert!(!SchedulingPolicy::Fifo.is_valid_priority(non_realtime));
2000
2001 assert_eq!(current_task.scheduler_state.lock().policy, SchedulingPolicy::Normal);
2002 assert_eq!(current_task.scheduler_state.lock().realtime_priority, non_realtime);
2003
2004 assert_eq!(current_task.set_scheduler_priority(realtime_10), error!(EINVAL));
2007 assert_eq!(current_task.scheduler_state.lock().realtime_priority, non_realtime);
2008
2009 current_task
2010 .set_scheduler_policy_priority_and_reset_on_fork(
2011 SchedulingPolicy::Fifo,
2012 realtime_10,
2013 false,
2014 )
2015 .expect("set_scheduler_policy_priority_and_reset_on_fork");
2016 assert_eq!(current_task.scheduler_state.lock().policy, SchedulingPolicy::Fifo);
2017 assert_eq!(current_task.scheduler_state.lock().realtime_priority, realtime_10);
2018
2019 current_task.set_scheduler_priority(realtime_20).expect("set_scheduler_priority");
2020 assert_eq!(current_task.scheduler_state.lock().realtime_priority, realtime_20);
2021
2022 assert_eq!(current_task.set_scheduler_priority(non_realtime), error!(EINVAL));
2025 assert_eq!(current_task.scheduler_state.lock().realtime_priority, realtime_20);
2026
2027 assert_eq!(
2030 current_task.set_scheduler_policy_priority_and_reset_on_fork(
2031 SchedulingPolicy::Normal,
2032 realtime_10,
2033 true,
2034 ),
2035 error!(EINVAL)
2036 );
2037 assert_eq!(current_task.scheduler_state.lock().policy, SchedulingPolicy::Fifo);
2038 assert_eq!(current_task.scheduler_state.lock().realtime_priority, realtime_20);
2039 assert!(!current_task.scheduler_state.lock().reset_on_fork);
2040 })
2041 .await;
2042 }
2043
2044 #[::fuchsia::test]
2045 async fn test_update_scheduler_state_rolls_back_on_commit_error() {
2046 use crate::task::{RoleOverrides, SchedulerManager};
2047 use fidl_fuchsia_scheduler::RoleManagerMarker;
2048
2049 let (role_manager, server_end) = fidl::endpoints::create_sync_proxy::<RoleManagerMarker>();
2050 drop(server_end);
2053
2054 let overrides = RoleOverrides::new().build().unwrap();
2055 let scheduler_manager = SchedulerManager::new_for_tests(Some(role_manager), overrides);
2056
2057 spawn_kernel_with_scheduler_and_run_sync(scheduler_manager, |current_task| {
2058 let initial_state = current_task.scheduler_state.lock().clone();
2059 let realtime_10 = SchedulingPolicy::Fifo.realtime_priority_from(10).unwrap();
2060
2061 assert_eq!(
2062 current_task.set_scheduler_policy_priority_and_reset_on_fork(
2063 SchedulingPolicy::Fifo,
2064 realtime_10,
2065 true,
2066 ),
2067 error!(EINVAL)
2068 );
2069 assert_eq!(*current_task.scheduler_state.lock(), initial_state);
2070
2071 let nicer = NormalPriority::from_setpriority_syscall(-5);
2072 assert_eq!(current_task.set_scheduler_nice(nicer), error!(EINVAL));
2073 assert_eq!(*current_task.scheduler_state.lock(), initial_state);
2074 })
2075 .await;
2076 }
2077
2078 #[::fuchsia::test]
2079 async fn test_copy_state_from_preserves_dirty_snapshot() {
2080 spawn_kernel_and_run(async |current_task| {
2081 let mut state = current_task.write();
2082 assert!(state.captured_thread_state.is_none());
2083
2084 state.copy_state_from(current_task);
2085 assert!(state.captured_thread_state.is_some());
2086 assert!(!state.captured_thread_state.as_ref().unwrap().dirty);
2087
2088 state.captured_thread_state.as_mut().unwrap().dirty = true;
2090
2091 state.copy_state_from(current_task);
2093 assert!(state.captured_thread_state.as_ref().unwrap().dirty);
2094 })
2095 .await;
2096 }
2097
2098 #[::fuchsia::test]
2099 async fn test_temporary_signal_mask_without_pending_signals() {
2100 spawn_kernel_and_run(async |current_task| {
2101 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2102 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2103
2104 current_task.write().set_temporary_signal_mask(SigSet::from(SIGUSR1));
2105 assert!(current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2106 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2107
2108 current_task.write().restore_signal_mask();
2109 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2110 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2111 })
2112 .await;
2113 }
2114
2115 #[::fuchsia::test]
2116 async fn test_temporary_signal_mask_masks_pending_signal() {
2117 spawn_kernel_and_run(async |current_task| {
2118 current_task.write().enqueue_signal(SignalInfo::kernel(SIGUSR1));
2119 assert!(current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2120 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2121
2122 current_task.write().set_temporary_signal_mask(SigSet::from(SIGUSR1));
2123 assert!(current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2124 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2125
2126 current_task.write().restore_signal_mask();
2127 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2128 assert!(current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2129 })
2130 .await;
2131 }
2132
2133 #[::fuchsia::test]
2134 async fn test_temporary_signal_mask_unmasks_pending_signal() {
2135 spawn_kernel_and_run(async |current_task| {
2136 current_task.write().set_signal_mask(SigSet::from(SIGUSR1));
2137 current_task.write().enqueue_signal(SignalInfo::kernel(SIGUSR1));
2138 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2139 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2140
2141 current_task.write().set_temporary_signal_mask(SigSet::default());
2142 assert!(current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2143 assert!(current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2144
2145 current_task.write().restore_signal_mask();
2146 assert!(!current_task.flags().contains(TaskFlags::TEMPORARY_SIGNAL_MASK));
2147 assert!(!current_task.flags().contains(TaskFlags::SIGNALS_AVAILABLE));
2148 })
2149 .await;
2150 }
2151}