1use crate::arch::task::{decode_page_fault_exception_report, get_signal_for_general_exception};
6use crate::execution::{TaskInfo, create_zircon_process};
7use crate::mm::{DumpPolicy, MemoryAccessor, MemoryAccessorExt, TaskMemoryAccessor};
8use crate::ptrace::{PtraceCoreState, PtraceEvent, PtraceEventData, PtraceOptions, StopState};
9use crate::security;
10use crate::signals::{RunState, SignalInfo, send_signal_first, send_standard_signal};
11use crate::task::loader::{ResolvedElf, load_executable, resolve_executable};
12use crate::task::waiter::WaiterOptions;
13use crate::task::{
14 ExitStatus, RobustListHeadPtr, SeccompFilter, SeccompFilterContainer, SeccompNotifierHandle,
15 SeccompState, SeccompStateValue, Task, TaskFlags, Waiter,
16};
17use crate::vfs::{
18 CheckAccessReason, FdFlags, FdNumber, FileHandle, FsStr, LookupContext, MAX_SYMLINK_FOLLOWS,
19 NamespaceNode, ResolveBase, SymlinkMode, SymlinkTarget, new_pidfd,
20};
21use extended_pstate::ExtendedPstateState;
22use futures::FutureExt;
23use linux_uapi::CLONE_PIDFD;
24use starnix_logging::{log_error, log_warn, track_file_not_found, track_stub};
25use starnix_registers::{HeapRegs, RegisterState, RegisterStorage, RegisterStorageEnum};
26use starnix_stack::clean_stack;
27use starnix_sync::{
28 EventWaitGuard, FileOpsCore, LockBefore, LockEqualOrBefore, Locked, MmDumpable,
29 ProcessGroupState, TaskRelease, Unlocked, WakeReason,
30};
31use starnix_syscalls::SyscallResult;
32use starnix_syscalls::decls::Syscall;
33use starnix_task_command::TaskCommand;
34use starnix_types::arch::ArchWidth;
35use starnix_types::futex_address::FutexAddress;
36use starnix_types::ownership::{OwnedRef, Releasable, TempRef, WeakRef, release_on_error};
37use starnix_uapi::auth::{
38 CAP_KILL, CAP_SYS_ADMIN, CAP_SYS_PTRACE, Credentials, FsCred, PTRACE_MODE_FSCREDS,
39 PTRACE_MODE_REALCREDS, PtraceAccessMode, UserAndOrGroupId,
40};
41use starnix_uapi::device_type::DeviceType;
42use starnix_uapi::errors::{Errno, ErrnoCode};
43use starnix_uapi::file_mode::{Access, AccessCheck, FileMode};
44use starnix_uapi::open_flags::OpenFlags;
45use starnix_uapi::signals::{
46 SIGBUS, SIGCHLD, SIGCONT, SIGILL, SIGKILL, SIGSEGV, SIGSYS, SIGTRAP, SigSet, Signal,
47 UncheckedSignal,
48};
49use starnix_uapi::user_address::{ArchSpecific, UserAddress, UserRef};
50use starnix_uapi::vfs::ResolveFlags;
51use starnix_uapi::{
52 CLONE_CHILD_CLEARTID, CLONE_CHILD_SETTID, CLONE_FILES, CLONE_FS, CLONE_INTO_CGROUP,
53 CLONE_NEWUTS, CLONE_PARENT, CLONE_PARENT_SETTID, CLONE_PTRACE, CLONE_SETTLS, CLONE_SIGHAND,
54 CLONE_SYSVSEM, CLONE_THREAD, CLONE_VFORK, CLONE_VM, FUTEX_OWNER_DIED, FUTEX_TID_MASK,
55 ROBUST_LIST_LIMIT, SECCOMP_FILTER_FLAG_LOG, SECCOMP_FILTER_FLAG_NEW_LISTENER,
56 SECCOMP_FILTER_FLAG_TSYNC, SECCOMP_FILTER_FLAG_TSYNC_ESRCH, SI_KERNEL, clone_args, errno,
57 error, from_status_like_fdio, pid_t, sock_filter, ucred,
58};
59use std::cell::{Ref, RefCell};
60use std::collections::VecDeque;
61use std::ffi::CString;
62use std::fmt;
63use std::marker::PhantomData;
64use std::mem::MaybeUninit;
65use std::sync::Arc;
66use zx::sys::zx_restricted_state_t;
67
68use super::ThreadGroupLifecycleWaitValue;
69
70pub struct TaskBuilder {
71 pub task: OwnedRef<Task>,
73
74 pub thread_state: ThreadState<HeapRegs>,
75}
76
77impl TaskBuilder {
78 pub fn new(task: OwnedRef<Task>) -> Self {
79 Self { task, thread_state: Default::default() }
80 }
81
82 #[inline(always)]
83 pub fn release<L>(self, locked: &mut Locked<L>)
84 where
85 L: LockBefore<TaskRelease>,
86 {
87 let locked = locked.cast_locked::<TaskRelease>();
88 Releasable::release(self, locked);
89 }
90}
91
92impl From<TaskBuilder> for CurrentTask {
93 fn from(builder: TaskBuilder) -> Self {
94 Self::new(builder.task, builder.thread_state.into())
95 }
96}
97
98impl Releasable for TaskBuilder {
99 type Context<'a> = &'a mut Locked<TaskRelease>;
100
101 fn release<'a>(self, locked: Self::Context<'a>) {
102 let kernel = Arc::clone(self.kernel());
103 let mut pids = kernel.pids.write();
104
105 self.task.thread_group().remove(locked, &mut pids, &self.task);
111
112 let context = (self.thread_state.into(), locked, pids);
113 self.task.release(context);
114 }
115}
116
117impl std::ops::Deref for TaskBuilder {
118 type Target = Task;
119 fn deref(&self) -> &Self::Target {
120 &self.task
121 }
122}
123
124#[derive(Debug, Clone)]
127pub struct FullCredentials {
128 pub creds: Arc<Credentials>,
129 pub security_state: security::TaskState,
130}
131
132impl FullCredentials {
133 pub fn for_kernel() -> Self {
134 Self { creds: Credentials::root(), security_state: security::task_alloc_for_kernel() }
135 }
136}
137
138pub struct CurrentTask {
151 pub task: OwnedRef<Task>,
153
154 pub thread_state: ThreadState<RegisterStorageEnum>,
155
156 pub current_creds: RefCell<CurrentCreds>,
160
161 _local_marker: PhantomData<*mut u8>,
163}
164
165pub enum CurrentCreds {
167 Cached(Arc<Credentials>),
172 Overridden(Arc<Credentials>, security::TaskState),
175}
176
177impl CurrentCreds {
178 fn creds(&self) -> &Arc<Credentials> {
179 match self {
180 CurrentCreds::Cached(creds) => creds,
181 CurrentCreds::Overridden(creds, _) => creds,
182 }
183 }
184}
185
186#[derive(Default)]
189pub struct ThreadState<T: RegisterStorage> {
190 pub registers: RegisterState<T>,
194
195 pub extended_pstate: ExtendedPstateState,
197
198 pub restart_code: Option<ErrnoCode>,
200
201 pub syscall_restart_func: Option<Box<SyscallRestartFunc>>,
205
206 pub arch_width: ArchWidth,
209}
210
211impl<T: RegisterStorage> ThreadState<T> {
212 fn snapshot<R: RegisterStorage>(&self) -> ThreadState<R>
214 where
215 RegisterState<R>: From<RegisterState<T>>,
216 {
217 ThreadState::<R> {
218 registers: self.registers.clone().into(),
219 extended_pstate: Default::default(),
220 restart_code: self.restart_code,
221 syscall_restart_func: None,
222 arch_width: self.arch_width,
223 }
224 }
225
226 pub fn extended_snapshot<R: RegisterStorage>(&self) -> ThreadState<R>
227 where
228 RegisterState<R>: From<RegisterState<T>>,
229 {
230 ThreadState::<R> {
231 registers: self.registers.clone().into(),
232 extended_pstate: self.extended_pstate.clone(),
233 restart_code: self.restart_code,
234 syscall_restart_func: None,
235 arch_width: self.arch_width,
236 }
237 }
238
239 pub fn replace_registers<O: RegisterStorage>(&mut self, other: &ThreadState<O>) {
240 self.registers.load(*other.registers);
241 self.extended_pstate = other.extended_pstate;
242 self.arch_width = other.arch_width;
243 }
244
245 pub fn get_user_register(&mut self, offset: usize) -> Result<usize, Errno> {
246 let mut result: usize = 0;
247 self.registers.apply_user_register(offset, &mut |register| result = *register as usize)?;
248 Ok(result)
249 }
250
251 pub fn set_user_register(&mut self, offset: usize, value: usize) -> Result<(), Errno> {
252 self.registers.apply_user_register(offset, &mut |register| *register = value as u64)
253 }
254}
255
256impl From<ThreadState<HeapRegs>> for ThreadState<RegisterStorageEnum> {
257 fn from(value: ThreadState<HeapRegs>) -> Self {
258 ThreadState {
259 registers: value.registers.into(),
260 extended_pstate: value.extended_pstate,
261 restart_code: value.restart_code,
262 syscall_restart_func: value.syscall_restart_func,
263 arch_width: value.arch_width,
264 }
265 }
266}
267
268impl<T: RegisterStorage> ArchSpecific for ThreadState<T> {
269 fn is_arch32(&self) -> bool {
270 self.arch_width.is_arch32()
271 }
272}
273
274type SyscallRestartFunc = dyn FnOnce(&mut Locked<Unlocked>, &mut CurrentTask) -> Result<SyscallResult, Errno>
275 + Send
276 + Sync;
277
278impl Releasable for CurrentTask {
279 type Context<'a> = &'a mut Locked<TaskRelease>;
280
281 fn release<'a>(self, locked: Self::Context<'a>) {
282 self.notify_robust_list();
283 let _ignored = self.clear_child_tid_if_needed(locked);
284
285 let kernel = Arc::clone(self.kernel());
286 let mut pids = kernel.pids.write();
287
288 self.task.thread_group().remove(locked, &mut pids, &self.task);
294
295 let context = (self.thread_state, locked, pids);
296 self.task.release(context);
297 }
298}
299
300impl std::ops::Deref for CurrentTask {
301 type Target = Task;
302 fn deref(&self) -> &Self::Target {
303 &self.task
304 }
305}
306
307impl fmt::Debug for CurrentTask {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 self.task.fmt(f)
310 }
311}
312
313impl CurrentTask {
314 pub fn new(task: OwnedRef<Task>, thread_state: ThreadState<RegisterStorageEnum>) -> Self {
315 let current_creds = RefCell::new(CurrentCreds::Cached(task.clone_creds()));
316 Self { task, thread_state, current_creds, _local_marker: Default::default() }
317 }
318
319 pub fn current_creds(&self) -> Ref<'_, Arc<Credentials>> {
324 Ref::map(self.current_creds.borrow(), CurrentCreds::creds)
325 }
326
327 pub fn full_current_creds(&self) -> FullCredentials {
329 match *self.current_creds.borrow() {
330 CurrentCreds::Cached(ref creds) => FullCredentials {
331 creds: creds.clone(),
332 security_state: self.security_state.clone(),
333 },
334 CurrentCreds::Overridden(ref creds, ref security_state) => {
335 FullCredentials { creds: creds.clone(), security_state: security_state.clone() }
336 }
337 }
338 }
339
340 pub fn current_fscred(&self) -> FsCred {
341 self.current_creds().as_fscred()
342 }
343
344 pub fn current_ucred(&self) -> ucred {
345 let creds = self.current_creds();
346 ucred { pid: self.get_pid(), uid: creds.uid, gid: creds.gid }
347 }
348
349 pub async fn override_creds_async<R>(
358 &self,
359 new_creds: FullCredentials,
360 callback: impl AsyncFnOnce() -> R,
361 ) -> R {
362 let saved = self
363 .current_creds
364 .replace(CurrentCreds::Overridden(new_creds.creds, new_creds.security_state));
365 let result = callback().await;
366 self.current_creds.replace(saved);
367 result
368 }
369
370 pub fn override_creds<R>(&self, new_creds: FullCredentials, callback: impl FnOnce() -> R) -> R {
379 self.override_creds_async(new_creds, async move || callback())
380 .now_or_never()
381 .expect("Future should be ready")
382 }
383
384 pub fn has_overridden_creds(&self) -> bool {
385 matches!(*self.current_creds.borrow(), CurrentCreds::Overridden(_, _))
386 }
387
388 pub fn trigger_delayed_releaser<L>(&self, locked: &mut Locked<L>)
389 where
390 L: LockEqualOrBefore<FileOpsCore>,
391 {
392 let locked = locked.cast_locked::<FileOpsCore>();
393 self.kernel().delayed_releaser.apply(locked, self);
394 }
395
396 pub fn weak_task(&self) -> WeakRef<Task> {
397 WeakRef::from(&self.task)
398 }
399
400 pub fn temp_task(&self) -> TempRef<'_, Task> {
401 TempRef::from(&self.task)
402 }
403
404 pub fn set_creds(&self, creds: Credentials) {
407 assert!(!self.has_overridden_creds());
408
409 let creds = Arc::new(creds);
410 let mut current_creds = self.current_creds.borrow_mut();
411 *current_creds = CurrentCreds::Cached(creds.clone());
412
413 unsafe {
415 self.persistent_info.write_creds().update(creds);
416 }
417 let maybe_node = self.proc_pid_directory_cache.lock();
420 if let Some(node) = &*maybe_node {
421 let creds = self.real_creds().euid_as_fscred();
422 unsafe {
426 node.force_chown(creds);
427 }
428 }
429 }
430
431 #[inline(always)]
432 pub fn release<L>(self, locked: &mut Locked<L>)
433 where
434 L: LockBefore<TaskRelease>,
435 {
436 let locked = locked.cast_locked::<TaskRelease>();
437 Releasable::release(self, locked);
438 }
439
440 pub fn set_syscall_restart_func<R: Into<SyscallResult>>(
441 &mut self,
442 f: impl FnOnce(&mut Locked<Unlocked>, &mut CurrentTask) -> Result<R, Errno>
443 + Send
444 + Sync
445 + 'static,
446 ) {
447 self.thread_state.syscall_restart_func =
448 Some(Box::new(|locked, current_task| Ok(f(locked, current_task)?.into())));
449 }
450
451 pub fn add_file<L>(
452 &self,
453 locked: &mut Locked<L>,
454 file: FileHandle,
455 flags: FdFlags,
456 ) -> Result<FdNumber, Errno>
457 where
458 L: LockEqualOrBefore<FileOpsCore>,
459 {
460 self.files.add(locked, self, file, flags)
461 }
462
463 pub fn wait_with_temporary_mask<F, T, L>(
470 &mut self,
471 locked: &mut Locked<L>,
472 signal_mask: SigSet,
473 wait_function: F,
474 ) -> Result<T, Errno>
475 where
476 L: LockEqualOrBefore<FileOpsCore>,
477 F: FnOnce(&mut Locked<L>, &CurrentTask) -> Result<T, Errno>,
478 {
479 {
480 let mut state = self.write();
481 state.set_flags(TaskFlags::TEMPORARY_SIGNAL_MASK, true);
482 state.set_temporary_signal_mask(signal_mask);
483 }
484 wait_function(locked, self)
485 }
486
487 pub fn wake_or_wait_until_unstopped_async(&self, waiter: &Waiter) -> bool {
490 let group_state = self.thread_group().read();
491 let mut task_state = self.write();
492
493 let task_stop_state = self.load_stopped();
500 let group_stop_state = self.thread_group().load_stopped();
501 if ((task_stop_state == StopState::GroupStopped && group_stop_state.is_waking_or_awake())
502 || task_stop_state.is_waking_or_awake())
503 && (!task_state.is_ptrace_listening() || task_stop_state.is_force())
504 {
505 let new_state = if task_stop_state.is_waking_or_awake() {
506 task_stop_state.finalize()
507 } else {
508 group_stop_state.finalize()
509 };
510 if let Ok(new_state) = new_state {
511 task_state.set_stopped(new_state, None, Some(self), None);
512 drop(group_state);
513 drop(task_state);
514 self.thread_group().set_stopped(new_state, None, false);
520 return true;
521 }
522 }
523
524 if self.thread_group().load_stopped().is_stopped() || task_stop_state.is_stopped() {
526 group_state
529 .lifecycle_waiters
530 .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::Stopped);
531 task_state.wait_on_ptracer(&waiter);
532 } else if task_state.can_accept_ptrace_commands() {
533 task_state.wait_on_ptracer(&waiter);
536 } else if task_state.is_ptrace_listening() {
537 if let Some(ptrace) = &mut task_state.ptrace {
540 ptrace.set_last_signal(Some(SignalInfo::default(SIGTRAP)));
541 ptrace.set_last_event(Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0)));
542 }
543 task_state.wait_on_ptracer(&waiter);
544 task_state.notify_ptracers();
545 }
546 false
547 }
548
549 pub fn run_in_state<F, T>(&self, run_state: RunState, callback: F) -> Result<T, Errno>
560 where
561 F: FnOnce() -> Result<T, Errno>,
562 {
563 assert_ne!(run_state, RunState::Running);
564
565 clean_stack();
568
569 {
570 let mut state = self.write();
571 assert!(!state.is_blocked());
572
573 if matches!(run_state, RunState::Frozen(_)) {
574 if state.has_signal_pending(SIGKILL) {
577 return error!(EINTR);
578 }
579 } else if state.is_any_signal_pending() && !state.is_ptrace_listening() {
580 return error!(EINTR);
583 }
584 state.set_run_state(run_state.clone());
585 }
586
587 let result = callback();
588
589 {
590 let mut state = self.write();
591 assert_eq!(
592 state.run_state(),
593 run_state,
594 "SignalState run state changed while waiting!"
595 );
596 state.set_run_state(RunState::Running);
597 };
598
599 result
600 }
601
602 pub fn block_until(
603 &self,
604 guard: EventWaitGuard<'_>,
605 deadline: zx::MonotonicInstant,
606 ) -> Result<(), Errno> {
607 self.run_in_state(RunState::Event(guard.event().clone()), move || {
608 guard.block_until(None, deadline).map_err(|e| match e {
609 WakeReason::Interrupted => errno!(EINTR),
610 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
611 })
612 })
613 }
614
615 pub fn block_with_owner_until(
616 &self,
617 guard: EventWaitGuard<'_>,
618 new_owner: &zx::Thread,
619 deadline: zx::MonotonicInstant,
620 ) -> Result<(), Errno> {
621 self.run_in_state(RunState::Event(guard.event().clone()), move || {
622 guard.block_until(Some(new_owner), deadline).map_err(|e| match e {
623 WakeReason::Interrupted => errno!(EINTR),
624 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
625 })
626 })
627 }
628
629 pub fn resolve_dir_fd<'a, L>(
633 &self,
634 locked: &mut Locked<L>,
635 dir_fd: FdNumber,
636 mut path: &'a FsStr,
637 flags: ResolveFlags,
638 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
639 where
640 L: LockEqualOrBefore<FileOpsCore>,
641 {
642 let path_is_absolute = path.starts_with(b"/");
643 if path_is_absolute {
644 if flags.contains(ResolveFlags::BENEATH) {
645 return error!(EXDEV);
646 }
647 path = &path[1..];
648 }
649
650 let dir = if path_is_absolute && !flags.contains(ResolveFlags::IN_ROOT) {
651 self.fs().root()
652 } else if dir_fd == FdNumber::AT_FDCWD {
653 self.fs().cwd()
654 } else {
655 let file = self.files.get_allowing_opath(dir_fd)?;
665 file.name.to_passive()
666 };
667
668 if !path.is_empty() {
669 if !dir.entry.node.is_dir() {
670 return error!(ENOTDIR);
671 }
672 dir.check_access(
673 locked,
674 self,
675 Access::EXEC,
676 CheckAccessReason::InternalPermissionChecks,
677 )?;
678 }
679 Ok((dir, path.into()))
680 }
681
682 pub fn open_file(
687 &self,
688 locked: &mut Locked<Unlocked>,
689 path: &FsStr,
690 flags: OpenFlags,
691 ) -> Result<FileHandle, Errno> {
692 if flags.contains(OpenFlags::CREAT) {
693 return error!(EINVAL);
696 }
697 self.open_file_at(
698 locked,
699 FdNumber::AT_FDCWD,
700 path,
701 flags,
702 FileMode::default(),
703 ResolveFlags::empty(),
704 AccessCheck::default(),
705 )
706 }
707
708 fn resolve_open_path<L>(
719 &self,
720 locked: &mut Locked<L>,
721 context: &mut LookupContext,
722 dir: &NamespaceNode,
723 path: &FsStr,
724 mode: FileMode,
725 flags: OpenFlags,
726 ) -> Result<(NamespaceNode, bool), Errno>
727 where
728 L: LockEqualOrBefore<FileOpsCore>,
729 {
730 context.update_for_path(path);
731 let mut parent_content = context.with(SymlinkMode::Follow);
732 let (parent, basename) = self.lookup_parent(locked, &mut parent_content, dir, path)?;
733 context.remaining_follows = parent_content.remaining_follows;
734
735 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
736
737 let mut child_context = context.with(SymlinkMode::NoFollow);
739 child_context.must_be_directory = false;
740
741 match parent.lookup_child(locked, self, &mut child_context, basename) {
742 Ok(name) => {
743 if name.entry.node.is_lnk() {
744 if flags.contains(OpenFlags::PATH)
745 && context.symlink_mode == SymlinkMode::NoFollow
746 {
747 return Ok((name, false));
760 }
761
762 if (!flags.contains(OpenFlags::PATH)
763 && context.symlink_mode == SymlinkMode::NoFollow)
764 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
765 || context.remaining_follows == 0
766 {
767 if must_create {
768 return error!(EEXIST);
771 }
772 return error!(ELOOP);
777 }
778
779 context.remaining_follows -= 1;
780 match name.readlink(locked, self)? {
781 SymlinkTarget::Path(path) => {
782 let dir = if path[0] == b'/' { self.fs().root() } else { parent };
783 self.resolve_open_path(
784 locked,
785 context,
786 &dir,
787 path.as_ref(),
788 mode,
789 flags,
790 )
791 }
792 SymlinkTarget::Node(name) => {
793 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS)
794 || name.entry.node.is_lnk()
795 {
796 error!(ELOOP)
797 } else {
798 Ok((name, false))
799 }
800 }
801 }
802 } else {
803 if must_create {
804 return error!(EEXIST);
805 }
806 Ok((name, false))
807 }
808 }
809 Err(e) if e == errno!(ENOENT) && flags.contains(OpenFlags::CREAT) => {
810 if context.must_be_directory {
811 return error!(EISDIR);
812 }
813 Ok((
814 parent.open_create_node(
815 locked,
816 self,
817 basename,
818 mode.with_type(FileMode::IFREG),
819 DeviceType::NONE,
820 flags,
821 )?,
822 true,
823 ))
824 }
825 Err(e) => Err(e),
826 }
827 }
828
829 pub fn open_file_at(
839 &self,
840 locked: &mut Locked<Unlocked>,
841 dir_fd: FdNumber,
842 path: &FsStr,
843 flags: OpenFlags,
844 mode: FileMode,
845 resolve_flags: ResolveFlags,
846 access_check: AccessCheck,
847 ) -> Result<FileHandle, Errno> {
848 if path.is_empty() {
849 return error!(ENOENT);
850 }
851
852 let (dir, path) = self.resolve_dir_fd(locked, dir_fd, path, resolve_flags)?;
853 self.open_namespace_node_at(locked, dir, path, flags, mode, resolve_flags, access_check)
854 }
855
856 pub fn open_namespace_node_at(
857 &self,
858 locked: &mut Locked<Unlocked>,
859 dir: NamespaceNode,
860 path: &FsStr,
861 flags: OpenFlags,
862 mode: FileMode,
863 mut resolve_flags: ResolveFlags,
864 access_check: AccessCheck,
865 ) -> Result<FileHandle, Errno> {
866 let mut flags = flags | OpenFlags::LARGEFILE;
868 let opath = flags.contains(OpenFlags::PATH);
869 if opath {
870 const ALLOWED_FLAGS: OpenFlags = OpenFlags::from_bits_truncate(
873 OpenFlags::PATH.bits()
874 | OpenFlags::CLOEXEC.bits()
875 | OpenFlags::DIRECTORY.bits()
876 | OpenFlags::NOFOLLOW.bits(),
877 );
878 flags &= ALLOWED_FLAGS;
879 }
880
881 if flags.contains(OpenFlags::TMPFILE) && !flags.can_write() {
882 return error!(EINVAL);
883 }
884
885 let nofollow = flags.contains(OpenFlags::NOFOLLOW);
886 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
887
888 let symlink_mode =
889 if nofollow || must_create { SymlinkMode::NoFollow } else { SymlinkMode::Follow };
890
891 let resolve_base = match (
892 resolve_flags.contains(ResolveFlags::BENEATH),
893 resolve_flags.contains(ResolveFlags::IN_ROOT),
894 ) {
895 (false, false) => ResolveBase::None,
896 (true, false) => ResolveBase::Beneath(dir.clone()),
897 (false, true) => ResolveBase::InRoot(dir.clone()),
898 (true, true) => return error!(EINVAL),
899 };
900
901 if resolve_base != ResolveBase::None {
905 resolve_flags.insert(ResolveFlags::NO_MAGICLINKS);
906 }
907
908 let mut context = LookupContext {
909 symlink_mode,
910 remaining_follows: MAX_SYMLINK_FOLLOWS,
911 must_be_directory: flags.contains(OpenFlags::DIRECTORY),
912 resolve_flags,
913 resolve_base,
914 };
915 let (name, created) =
916 match self.resolve_open_path(locked, &mut context, &dir, path, mode, flags) {
917 Ok((n, c)) => (n, c),
918 Err(e) => {
919 let mut abs_path = dir.path(&self.task);
920 abs_path.extend(&**path);
921 track_file_not_found(abs_path);
922 return Err(e);
923 }
924 };
925
926 let name = if flags.contains(OpenFlags::TMPFILE) {
927 if flags.contains(OpenFlags::CREAT) {
929 return error!(EINVAL);
930 }
931 name.create_tmpfile(locked, self, mode.with_type(FileMode::IFREG), flags)?
932 } else {
933 let mode = name.entry.node.info().mode;
934
935 if !opath && nofollow && mode.is_lnk() {
947 return error!(ELOOP);
948 }
949
950 if mode.is_dir() {
951 if flags.can_write()
952 || flags.contains(OpenFlags::CREAT)
953 || flags.contains(OpenFlags::TRUNC)
954 {
955 return error!(EISDIR);
956 }
957 if flags.contains(OpenFlags::DIRECT) {
958 return error!(EINVAL);
959 }
960 } else if context.must_be_directory {
961 return error!(ENOTDIR);
962 }
963
964 if flags.contains(OpenFlags::TRUNC) && mode.is_reg() && !created {
965 name.truncate(locked, self, 0)?;
971 }
972
973 name
974 };
975
976 let access_check = if created { AccessCheck::skip() } else { access_check };
984 name.open(locked, self, flags, access_check)
985 }
986
987 pub fn lookup_parent_at<'a, L>(
995 &self,
996 locked: &mut Locked<L>,
997 context: &mut LookupContext,
998 dir_fd: FdNumber,
999 path: &'a FsStr,
1000 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
1001 where
1002 L: LockEqualOrBefore<FileOpsCore>,
1003 {
1004 let (dir, path) = self.resolve_dir_fd(locked, dir_fd, path, ResolveFlags::empty())?;
1005 self.lookup_parent(locked, context, &dir, path)
1006 }
1007
1008 pub fn lookup_parent<'a, L>(
1023 &self,
1024 locked: &mut Locked<L>,
1025 context: &mut LookupContext,
1026 dir: &NamespaceNode,
1027 path: &'a FsStr,
1028 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
1029 where
1030 L: LockEqualOrBefore<FileOpsCore>,
1031 {
1032 context.update_for_path(path);
1033
1034 let mut current_node = dir.clone();
1035 let mut it = path.split(|c| *c == b'/').filter(|p| !p.is_empty()).map(<&FsStr>::from);
1036 let mut current_path_component = it.next().unwrap_or_default();
1037 for next_path_component in it {
1038 current_node =
1039 current_node.lookup_child(locked, self, context, current_path_component)?;
1040 current_path_component = next_path_component;
1041 }
1042 Ok((current_node, current_path_component))
1043 }
1044
1045 pub fn lookup_path<L>(
1052 &self,
1053 locked: &mut Locked<L>,
1054 context: &mut LookupContext,
1055 dir: NamespaceNode,
1056 path: &FsStr,
1057 ) -> Result<NamespaceNode, Errno>
1058 where
1059 L: LockEqualOrBefore<FileOpsCore>,
1060 {
1061 let (parent, basename) = self.lookup_parent(locked, context, &dir, path)?;
1062 parent.lookup_child(locked, self, context, basename)
1063 }
1064
1065 pub fn lookup_path_from_root<L>(
1069 &self,
1070 locked: &mut Locked<L>,
1071 path: &FsStr,
1072 ) -> Result<NamespaceNode, Errno>
1073 where
1074 L: LockEqualOrBefore<FileOpsCore>,
1075 {
1076 let mut context = LookupContext::default();
1077 self.lookup_path(locked, &mut context, self.fs().root(), path)
1078 }
1079
1080 pub fn exec(
1081 &mut self,
1082 locked: &mut Locked<Unlocked>,
1083 executable: FileHandle,
1084 path: CString,
1085 argv: Vec<CString>,
1086 environ: Vec<CString>,
1087 ) -> Result<(), Errno> {
1088 if !executable.name.entry.node.is_reg() {
1090 return error!(EACCES);
1091 }
1092
1093 executable.name.check_access(locked, self, Access::EXEC, CheckAccessReason::Exec)?;
1097
1098 let elf_security_state = security::bprm_creds_for_exec(self, &executable.name)?;
1099
1100 let resolved_elf = resolve_executable(
1101 locked,
1102 self,
1103 executable,
1104 path.clone(),
1105 argv,
1106 environ,
1107 elf_security_state,
1108 )?;
1109
1110 let maybe_set_id = if self.kernel().features.enable_suid {
1111 resolved_elf.file.name.suid_and_sgid(&self)?
1112 } else {
1113 Default::default()
1114 };
1115
1116 if self.thread_group().read().tasks_count() > 1 {
1117 track_stub!(TODO("https://fxbug.dev/297434895"), "exec on multithread process");
1118 return error!(EINVAL);
1119 }
1120
1121 if let Err(err) = self.finish_exec(locked, path, resolved_elf, maybe_set_id) {
1122 log_warn!("unrecoverable error in exec: {err:?}");
1123
1124 send_standard_signal(
1125 locked,
1126 self,
1127 SignalInfo { code: SI_KERNEL as i32, force: true, ..SignalInfo::default(SIGSEGV) },
1128 );
1129 return Err(err);
1130 }
1131
1132 self.ptrace_event(locked, PtraceOptions::TRACEEXEC, self.task.tid as u64);
1133 self.signal_vfork();
1134
1135 Ok(())
1136 }
1137
1138 fn finish_exec(
1142 &mut self,
1143 locked: &mut Locked<Unlocked>,
1144 path: CString,
1145 resolved_elf: ResolvedElf,
1146 mut maybe_set_id: UserAndOrGroupId,
1147 ) -> Result<(), Errno> {
1148 self.notify_robust_list();
1152
1153 let mm = {
1156 let mm = self.mm()?;
1157 let new_mm = mm
1158 .exec(resolved_elf.file.name.to_passive(), resolved_elf.arch_width)
1159 .map_err(|status| from_status_like_fdio!(status))?;
1160 self.mm.update(Some(new_mm.clone()));
1161 new_mm
1162 };
1163
1164 {
1165 let mut state = self.write();
1166
1167 if state.no_new_privs() || state.is_ptraced() {
1183 maybe_set_id.clear();
1184 }
1185
1186 let dumpable =
1195 if maybe_set_id.is_none() { DumpPolicy::User } else { DumpPolicy::Disable };
1196 *mm.dumpable.lock(locked) = dumpable;
1197
1198 let mut writable_creds = unsafe { self.persistent_info.write_creds() };
1202 state.set_sigaltstack(None);
1203 state.robust_list_head = RobustListHeadPtr::null(self);
1204
1205 let mut new_creds = Credentials::clone(&self.current_creds());
1217 new_creds.exec(maybe_set_id);
1218 let new_creds = Arc::new(new_creds);
1219 writable_creds.update(new_creds.clone());
1220 *self.current_creds.borrow_mut() = CurrentCreds::Cached(new_creds);
1221 }
1222
1223 let security_state = resolved_elf.security_state.clone();
1224
1225 let start_info = load_executable(self, resolved_elf, &path)?;
1226 self.thread_state.arch_width = start_info.arch_width;
1228
1229 let regs: zx_restricted_state_t = start_info.into();
1230 self.thread_state.registers.load(regs);
1231 self.thread_state.extended_pstate.reset();
1232 self.thread_group().signal_actions.reset_for_exec();
1233
1234 let mut thread_group_state = self.thread_group().write();
1236 thread_group_state.exit_signal = Some(SIGCHLD);
1237 for (_, weak_child) in &mut thread_group_state.children {
1238 if let Some(child) = weak_child.upgrade() {
1239 let mut child_state = child.write();
1240 child_state.exit_signal = Some(SIGCHLD);
1241 }
1242 }
1243
1244 std::mem::drop(thread_group_state);
1245
1246 self.files.unshare();
1255 self.files.exec(locked, self);
1256
1257 security::exec_binprm(locked, self, &security_state);
1265
1266 self.thread_group().write().did_exec = true;
1267
1268 self.set_command_name(TaskCommand::from_path_bytes(path.to_bytes()));
1269
1270 Ok(())
1271 }
1272
1273 pub fn set_command_name(&self, new_name: TaskCommand) {
1274 self.task.set_command_name(new_name.clone());
1276 let leader_command = self.thread_group().read().leader_command();
1277 starnix_logging::set_current_task_info(
1278 new_name,
1279 leader_command,
1280 self.thread_group().leader,
1281 self.tid,
1282 );
1283 }
1284
1285 pub fn add_seccomp_filter(
1286 &mut self,
1287 locked: &mut Locked<Unlocked>,
1288 code: Vec<sock_filter>,
1289 flags: u32,
1290 ) -> Result<SyscallResult, Errno> {
1291 let new_filter = Arc::new(SeccompFilter::from_cbpf(
1292 &code,
1293 self.thread_group().next_seccomp_filter_id.add(1),
1294 flags & SECCOMP_FILTER_FLAG_LOG != 0,
1295 )?);
1296
1297 let mut maybe_fd: Option<FdNumber> = None;
1298
1299 if flags & SECCOMP_FILTER_FLAG_NEW_LISTENER != 0 {
1300 maybe_fd = Some(SeccompFilterContainer::create_listener(locked, self)?);
1301 }
1302
1303 let state = self.thread_group().write();
1306
1307 if flags & SECCOMP_FILTER_FLAG_TSYNC != 0 {
1308 let mut filters: SeccompFilterContainer = self.read().seccomp_filters.clone();
1314
1315 let tasks = state.tasks().collect::<Vec<_>>();
1319 for task in &tasks {
1320 if task.tid == self.tid {
1321 continue;
1322 }
1323 let other_task_state = task.read();
1324
1325 if task.seccomp_filter_state.get() == SeccompStateValue::Strict {
1327 return Self::seccomp_tsync_error(task.tid, flags);
1328 }
1329
1330 if !other_task_state.seccomp_filters.can_sync_to(&filters) {
1332 return Self::seccomp_tsync_error(task.tid, flags);
1333 }
1334 }
1335
1336 filters.add_filter(new_filter, code.len() as u16)?;
1338
1339 for task in &tasks {
1340 let mut other_task_state = task.write();
1341
1342 other_task_state.enable_no_new_privs();
1343 other_task_state.seccomp_filters = filters.clone();
1344 task.set_seccomp_state(SeccompStateValue::UserDefined)?;
1345 }
1346 } else {
1347 let mut task_state = self.task.write();
1348
1349 task_state.seccomp_filters.add_filter(new_filter, code.len() as u16)?;
1350 self.set_seccomp_state(SeccompStateValue::UserDefined)?;
1351 }
1352
1353 if let Some(fd) = maybe_fd { Ok(fd.into()) } else { Ok(().into()) }
1354 }
1355
1356 pub fn run_seccomp_filters(
1357 &mut self,
1358 locked: &mut Locked<Unlocked>,
1359 syscall: &Syscall,
1360 ) -> Option<Result<SyscallResult, Errno>> {
1361 if self.seccomp_filter_state.get() == SeccompStateValue::Strict {
1364 return SeccompState::do_strict(locked, self, syscall);
1365 }
1366
1367 let result = self.task.read().seccomp_filters.run_all(self, syscall);
1369
1370 SeccompState::do_user_defined(locked, result, self, syscall)
1371 }
1372
1373 fn seccomp_tsync_error(id: i32, flags: u32) -> Result<SyscallResult, Errno> {
1374 if flags & SECCOMP_FILTER_FLAG_TSYNC_ESRCH != 0 { error!(ESRCH) } else { Ok(id.into()) }
1380 }
1381
1382 pub fn notify_robust_list(&self) {
1388 let task_state = self.write();
1389 let robust_list_addr = task_state.robust_list_head.addr();
1390 if robust_list_addr == UserAddress::NULL {
1391 return;
1393 }
1394 let robust_list_res = self.read_multi_arch_object(task_state.robust_list_head);
1395
1396 let head = if let Ok(head) = robust_list_res {
1397 head
1398 } else {
1399 return;
1400 };
1401
1402 let offset = head.futex_offset;
1403
1404 let mut entries_count = 0;
1405 let mut curr_ptr = head.list.next;
1406 while curr_ptr.addr() != robust_list_addr.into() && entries_count < ROBUST_LIST_LIMIT {
1407 let curr_ref = self.read_multi_arch_object(curr_ptr);
1408
1409 let curr = if let Ok(curr) = curr_ref {
1410 curr
1411 } else {
1412 return;
1413 };
1414
1415 let Some(futex_base) = curr_ptr.addr().checked_add_signed(offset) else {
1416 return;
1417 };
1418
1419 let futex_addr = match FutexAddress::try_from(futex_base) {
1420 Ok(addr) => addr,
1421 Err(_) => {
1422 return;
1423 }
1424 };
1425
1426 let Ok(mm) = self.mm() else {
1427 log_error!("Asked to notify robust list futexes in system task.");
1428 return;
1429 };
1430 let futex = if let Ok(futex) = mm.atomic_load_u32_relaxed(futex_addr) {
1431 futex
1432 } else {
1433 return;
1434 };
1435
1436 if (futex & FUTEX_TID_MASK) as i32 == self.tid {
1437 let owner_died = FUTEX_OWNER_DIED | futex;
1438 if mm.atomic_store_u32_relaxed(futex_addr, owner_died).is_err() {
1439 return;
1440 }
1441 }
1442 curr_ptr = curr.next;
1443 entries_count += 1;
1444 }
1445 }
1446
1447 pub fn get_seccomp_notifier(&mut self) -> Option<SeccompNotifierHandle> {
1449 self.task.write().seccomp_filters.notifier.clone()
1450 }
1451
1452 pub fn set_seccomp_notifier(&mut self, notifier: Option<SeccompNotifierHandle>) {
1453 self.task.write().seccomp_filters.notifier = notifier;
1454 }
1455
1456 pub fn process_exception(
1458 &self,
1459 locked: &mut Locked<Unlocked>,
1460 report: &zx::ExceptionReport,
1461 ) -> ExceptionResult {
1462 match report.ty {
1463 zx::ExceptionType::General => match get_signal_for_general_exception(&report.arch) {
1464 Some(sig) => ExceptionResult::Signal(SignalInfo::default(sig)),
1465 None => {
1466 log_error!("Unrecognized general exception: {:?}", report);
1467 ExceptionResult::Signal(SignalInfo::default(SIGILL))
1468 }
1469 },
1470 zx::ExceptionType::FatalPageFault { status } => {
1471 let report = decode_page_fault_exception_report(&report.arch);
1472 if let Ok(mm) = self.mm() {
1473 mm.handle_page_fault(locked, report, status)
1474 } else {
1475 panic!(
1476 "system task is handling a major page fault status={:?}, report={:?}",
1477 status, report
1478 );
1479 }
1480 }
1481 zx::ExceptionType::UndefinedInstruction => {
1482 ExceptionResult::Signal(SignalInfo::default(SIGILL))
1483 }
1484 zx::ExceptionType::UnalignedAccess => {
1485 ExceptionResult::Signal(SignalInfo::default(SIGBUS))
1486 }
1487 zx::ExceptionType::SoftwareBreakpoint | zx::ExceptionType::HardwareBreakpoint => {
1488 ExceptionResult::Signal(SignalInfo::default(SIGTRAP))
1489 }
1490 zx::ExceptionType::ProcessNameChanged => {
1491 log_error!("Received unexpected process name changed exception");
1492 ExceptionResult::Handled
1493 }
1494 zx::ExceptionType::ProcessStarting
1495 | zx::ExceptionType::ThreadStarting
1496 | zx::ExceptionType::ThreadExiting => {
1497 log_error!("Received unexpected task lifecycle exception");
1498 ExceptionResult::Signal(SignalInfo::default(SIGSYS))
1499 }
1500 zx::ExceptionType::PolicyError(policy_code) => {
1501 log_error!(policy_code:?; "Received Zircon policy error exception");
1502 ExceptionResult::Signal(SignalInfo::default(SIGSYS))
1503 }
1504 zx::ExceptionType::UnknownUserGenerated { code, data } => {
1505 log_error!(code:?, data:?; "Received unexpected unknown user generated exception");
1506 ExceptionResult::Signal(SignalInfo::default(SIGSYS))
1507 }
1508 zx::ExceptionType::Unknown { ty, code, data } => {
1509 log_error!(ty:?, code:?, data:?; "Received unexpected exception");
1510 ExceptionResult::Signal(SignalInfo::default(SIGSYS))
1511 }
1512 }
1513 }
1514
1515 pub fn clone_task<L>(
1525 &self,
1526 locked: &mut Locked<L>,
1527 flags: u64,
1528 child_exit_signal: Option<Signal>,
1529 user_parent_tid: UserRef<pid_t>,
1530 user_child_tid: UserRef<pid_t>,
1531 user_pidfd: UserRef<FdNumber>,
1532 ) -> Result<TaskBuilder, Errno>
1533 where
1534 L: LockBefore<MmDumpable>,
1535 L: LockBefore<TaskRelease>,
1536 L: LockBefore<ProcessGroupState>,
1537 {
1538 const IMPLEMENTED_FLAGS: u64 = (CLONE_VM
1539 | CLONE_FS
1540 | CLONE_FILES
1541 | CLONE_SIGHAND
1542 | CLONE_THREAD
1543 | CLONE_SYSVSEM
1544 | CLONE_SETTLS
1545 | CLONE_PARENT
1546 | CLONE_PARENT_SETTID
1547 | CLONE_PIDFD
1548 | CLONE_CHILD_CLEARTID
1549 | CLONE_CHILD_SETTID
1550 | CLONE_VFORK
1551 | CLONE_NEWUTS
1552 | CLONE_PTRACE) as u64;
1553
1554 const VALID_FLAGS: u64 = (CLONE_INTO_CGROUP << 1) - 1;
1559
1560 let clone_files = flags & (CLONE_FILES as u64) != 0;
1563 let clone_fs = flags & (CLONE_FS as u64) != 0;
1564 let clone_parent = flags & (CLONE_PARENT as u64) != 0;
1565 let clone_parent_settid = flags & (CLONE_PARENT_SETTID as u64) != 0;
1566 let clone_pidfd = flags & (CLONE_PIDFD as u64) != 0;
1567 let clone_child_cleartid = flags & (CLONE_CHILD_CLEARTID as u64) != 0;
1568 let clone_child_settid = flags & (CLONE_CHILD_SETTID as u64) != 0;
1569 let clone_sysvsem = flags & (CLONE_SYSVSEM as u64) != 0;
1570 let clone_ptrace = flags & (CLONE_PTRACE as u64) != 0;
1571 let clone_thread = flags & (CLONE_THREAD as u64) != 0;
1572 let clone_vm = flags & (CLONE_VM as u64) != 0;
1573 let clone_sighand = flags & (CLONE_SIGHAND as u64) != 0;
1574 let clone_vfork = flags & (CLONE_VFORK as u64) != 0;
1575 let clone_newuts = flags & (CLONE_NEWUTS as u64) != 0;
1576 let clone_into_cgroup = flags & CLONE_INTO_CGROUP != 0;
1577
1578 if clone_ptrace {
1579 track_stub!(TODO("https://fxbug.dev/322874630"), "CLONE_PTRACE");
1580 }
1581
1582 if clone_sysvsem {
1583 track_stub!(TODO("https://fxbug.dev/322875185"), "CLONE_SYSVSEM");
1584 }
1585
1586 if clone_into_cgroup {
1587 track_stub!(TODO("https://fxbug.dev/403612570"), "CLONE_INTO_CGROUP");
1588 }
1589
1590 if clone_sighand && !clone_vm {
1591 return error!(EINVAL);
1592 }
1593 if clone_thread && !clone_sighand {
1594 return error!(EINVAL);
1595 }
1596
1597 if clone_pidfd && clone_thread {
1598 return error!(EINVAL);
1599 }
1600 if clone_pidfd && clone_parent_settid && user_parent_tid.addr() == user_pidfd.addr() {
1601 return error!(EINVAL);
1604 }
1605
1606 if flags & !VALID_FLAGS != 0 {
1607 return error!(EINVAL);
1608 }
1609
1610 if clone_vm && !clone_thread {
1611 if !clone_vfork {
1622 track_stub!(
1623 TODO("https://fxbug.dev/322875227"),
1624 "CLONE_VM without CLONE_THREAD or CLONE_VFORK"
1625 );
1626 }
1627 } else if clone_thread && !clone_vm {
1628 track_stub!(TODO("https://fxbug.dev/322875167"), "CLONE_THREAD without CLONE_VM");
1629 return error!(ENOSYS);
1630 }
1631
1632 if flags & !IMPLEMENTED_FLAGS != 0 {
1633 track_stub!(
1634 TODO("https://fxbug.dev/322875130"),
1635 "clone unknown flags",
1636 flags & !IMPLEMENTED_FLAGS
1637 );
1638 return error!(ENOSYS);
1639 }
1640
1641 let fs = if clone_fs { self.fs() } else { self.fs().fork() };
1642 let files = if clone_files { self.files.clone() } else { self.files.fork() };
1643
1644 let kernel = self.kernel();
1645
1646 let mut pids = kernel.pids.write();
1647
1648 let mut cgroup2_pid_table = kernel.cgroups.lock_cgroup2_pid_table();
1652 let child_kernel_signals = cgroup2_pid_table
1654 .maybe_create_freeze_signal(self.thread_group())
1655 .into_iter()
1656 .collect::<VecDeque<_>>();
1657
1658 let pid;
1659 let command;
1660 let creds;
1661 let scheduler_state;
1662 let no_new_privs;
1663 let seccomp_filters;
1664 let robust_list_head = RobustListHeadPtr::null(self);
1665 let child_signal_mask;
1666 let timerslack_ns;
1667 let uts_ns;
1668 let security_state = security::task_alloc(&self, flags);
1669
1670 let TaskInfo { thread, thread_group, memory_manager } = {
1671 let weak_original_parent;
1674 let original_parent;
1675
1676 let thread_group_state = {
1678 let thread_group_state = self.thread_group().write();
1679 if clone_parent {
1680 weak_original_parent =
1683 thread_group_state.parent.clone().ok_or_else(|| errno!(EINVAL))?;
1684 std::mem::drop(thread_group_state);
1685 original_parent = weak_original_parent.upgrade();
1686 original_parent.write()
1687 } else {
1688 thread_group_state
1689 }
1690 };
1691
1692 let state = self.read();
1693
1694 no_new_privs = state.no_new_privs();
1695 seccomp_filters = state.seccomp_filters.clone();
1696 child_signal_mask = state.signal_mask();
1697
1698 pid = pids.allocate_pid();
1699 command = self.command();
1700 creds = self.current_creds().clone();
1701 scheduler_state = state.scheduler_state.fork();
1702 timerslack_ns = state.timerslack_ns;
1703
1704 uts_ns = if clone_newuts {
1705 security::check_task_capable(self, CAP_SYS_ADMIN)?;
1706 state.uts_ns.read().fork()
1707 } else {
1708 state.uts_ns.clone()
1709 };
1710
1711 if clone_thread {
1712 TaskInfo {
1713 thread: None,
1714 thread_group: self.thread_group().clone(),
1715 memory_manager: self.mm().ok(),
1716 }
1717 } else {
1718 std::mem::drop(state);
1722 let signal_actions = if clone_sighand {
1723 self.thread_group().signal_actions.clone()
1724 } else {
1725 self.thread_group().signal_actions.fork()
1726 };
1727 let process_group = thread_group_state.process_group.clone();
1728
1729 let task_info = create_zircon_process(
1730 locked,
1731 kernel,
1732 Some(thread_group_state),
1733 pid,
1734 child_exit_signal,
1735 process_group,
1736 signal_actions,
1737 command.clone(),
1738 )?;
1739
1740 cgroup2_pid_table.inherit_cgroup(self.thread_group(), &task_info.thread_group);
1741
1742 task_info
1743 }
1744 };
1745
1746 std::mem::drop(cgroup2_pid_table);
1751
1752 let vfork_event = if clone_vfork { Some(Arc::new(zx::Event::create())) } else { None };
1754
1755 let mut child = TaskBuilder::new(Task::new(
1756 pid,
1757 command,
1758 thread_group,
1759 thread,
1760 files,
1761 memory_manager,
1762 fs,
1763 creds,
1764 self.abstract_socket_namespace.clone(),
1765 self.abstract_vsock_namespace.clone(),
1766 child_signal_mask,
1767 child_kernel_signals,
1768 vfork_event,
1769 scheduler_state,
1770 uts_ns,
1771 no_new_privs,
1772 SeccompState::from(&self.seccomp_filter_state),
1773 seccomp_filters,
1774 robust_list_head,
1775 timerslack_ns,
1776 security_state,
1777 ));
1778
1779 release_on_error!(child, locked, {
1780 let child_task = TempRef::from(&child.task);
1781 pids.add_task(&child_task);
1785 std::mem::drop(pids);
1786
1787 #[cfg(any(test, debug_assertions))]
1791 {
1792 if !clone_thread {
1795 let _l1 = self.thread_group().read();
1796 let _l2 = child.thread_group().read();
1797 }
1798 }
1799
1800 if clone_thread {
1801 self.thread_group().add(&child_task)?;
1802 } else {
1803 child.thread_group().add(&child_task)?;
1804
1805 let mut child_state = child.write();
1811 let state = self.read();
1812 child_state.set_sigaltstack(state.sigaltstack());
1813 child_state.set_signal_mask(state.signal_mask());
1814 }
1815
1816 if !clone_vm {
1817 assert!(!clone_thread);
1820 self.mm()?.snapshot_to(locked, &child.mm()?)?;
1821 }
1822
1823 if clone_parent_settid {
1824 self.write_object(user_parent_tid, &child.tid)?;
1825 }
1826
1827 if clone_child_cleartid {
1828 child.write().clear_child_tid = user_child_tid;
1829 }
1830
1831 if clone_child_settid {
1832 child.write_object(user_child_tid, &child.tid)?;
1833 }
1834
1835 if clone_pidfd {
1836 let locked = locked.cast_locked::<TaskRelease>();
1837 let file = new_pidfd(
1838 locked,
1839 self,
1840 child.thread_group(),
1841 &*child.mm()?,
1842 OpenFlags::empty(),
1843 );
1844 let pidfd = self.add_file(locked, file, FdFlags::CLOEXEC)?;
1845 self.write_object(user_pidfd, &pidfd)?;
1846 }
1847
1848 if clone_vm && !clone_thread {
1852 self.mm()?.snapshot_to(locked, &child.mm()?)?;
1853 }
1854
1855 child.thread_state = self.thread_state.snapshot::<HeapRegs>();
1856 Ok(())
1857 });
1858
1859 #[cfg(any(test, debug_assertions))]
1862 {
1863 let _l1 = child.thread_group().read();
1864 let _l2 = child.read();
1865 }
1866
1867 Ok(child)
1868 }
1869
1870 pub fn set_stopped_and_notify(&self, stopped: StopState, siginfo: Option<SignalInfo>) {
1873 let maybe_signal_info = {
1874 let mut state = self.write();
1875 state.copy_state_from(self);
1876 state.set_stopped(stopped, siginfo, Some(self), None);
1877 state.prepare_signal_info(stopped)
1878 };
1879
1880 if let Some((tracer, signal_info)) = maybe_signal_info {
1881 if let Some(tracer) = tracer.upgrade() {
1882 tracer.write().send_signal(signal_info);
1883 }
1884 }
1885
1886 if !stopped.is_in_progress() {
1887 let parent = self.thread_group().read().parent.clone();
1888 if let Some(parent) = parent {
1889 parent
1890 .upgrade()
1891 .write()
1892 .lifecycle_waiters
1893 .notify_value(ThreadGroupLifecycleWaitValue::ChildStatus);
1894 }
1895 }
1896 }
1897
1898 pub fn finalize_stop_state(&mut self) -> bool {
1901 let stopped = self.load_stopped();
1902
1903 if !stopped.is_stopping_or_stopped() {
1904 let captured_state = self.write().take_captured_state();
1906 if let Some(captured) = captured_state {
1907 if captured.dirty {
1908 self.thread_state.replace_registers(&captured.thread_state);
1909 }
1910 }
1911 }
1912
1913 if self.thread_group().set_stopped(StopState::GroupStopped, None, true)
1916 == StopState::GroupStopped
1917 {
1918 let signal = self.thread_group().read().last_signal.clone();
1919 let event = Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0));
1921 self.write().set_stopped(StopState::GroupStopped, signal, Some(self), event);
1922 return true;
1923 }
1924
1925 if stopped.is_stopping_or_stopped() {
1927 if let Ok(stopped) = stopped.finalize() {
1928 self.set_stopped_and_notify(stopped, None);
1929 }
1930 return true;
1931 }
1932
1933 false
1934 }
1935
1936 pub fn block_while_stopped(&mut self, locked: &mut Locked<Unlocked>) {
1939 if !self.finalize_stop_state() {
1942 return;
1943 }
1944
1945 let waiter = Waiter::with_options(WaiterOptions::IGNORE_SIGNALS);
1946 loop {
1947 if self.is_exitted() {
1950 self.thread_group().set_stopped(StopState::ForceAwake, None, false);
1951 self.write().set_stopped(StopState::ForceAwake, None, Some(self), None);
1952 return;
1953 }
1954
1955 if self.wake_or_wait_until_unstopped_async(&waiter) {
1956 return;
1957 }
1958
1959 let _: Result<(), Errno> = waiter.wait(locked, self);
1961
1962 self.finalize_stop_state();
1965 }
1966 }
1967
1968 pub fn get_ptrace_core_state_for_clone(
1971 &mut self,
1972 clone_args: &clone_args,
1973 ) -> (PtraceOptions, Option<PtraceCoreState>) {
1974 let state = self.write();
1975 if let Some(ptrace) = &state.ptrace {
1976 ptrace.get_core_state_for_clone(clone_args)
1977 } else {
1978 (PtraceOptions::empty(), None)
1979 }
1980 }
1981
1982 pub fn ptrace_event(
1990 &mut self,
1991 locked: &mut Locked<Unlocked>,
1992 trace_kind: PtraceOptions,
1993 msg: u64,
1994 ) {
1995 if !trace_kind.is_empty() {
1996 {
1997 let mut state = self.write();
1998 if let Some(ptrace) = &mut state.ptrace {
1999 if !ptrace.has_option(trace_kind) {
2000 if trace_kind == PtraceOptions::TRACEEXEC && !ptrace.is_seized() {
2003 send_signal_first(locked, self, state, SignalInfo::default(SIGTRAP));
2005 }
2006
2007 return;
2008 }
2009 let mut siginfo = SignalInfo::default(starnix_uapi::signals::SIGTRAP);
2010 siginfo.code = (((PtraceEvent::from_option(&trace_kind) as u32) << 8)
2011 | linux_uapi::SIGTRAP) as i32;
2012 state.set_stopped(
2013 StopState::PtraceEventStopping,
2014 Some(siginfo),
2015 None,
2016 Some(PtraceEventData::new(trace_kind, msg)),
2017 );
2018 } else {
2019 return;
2020 }
2021 }
2022 self.block_while_stopped(locked);
2023 }
2024 }
2025
2026 pub fn thread_group_exit(&mut self, locked: &mut Locked<Unlocked>, exit_status: ExitStatus) {
2029 self.ptrace_event(
2030 locked,
2031 PtraceOptions::TRACEEXIT,
2032 exit_status.signal_info_status() as u64,
2033 );
2034 self.thread_group().exit(locked, exit_status, None);
2035 }
2036
2037 pub fn clone_task_for_test<L>(
2040 &self,
2041 locked: &mut Locked<L>,
2042 flags: u64,
2043 exit_signal: Option<Signal>,
2044 ) -> crate::testing::AutoReleasableTask
2045 where
2046 L: LockBefore<MmDumpable>,
2047 L: LockBefore<TaskRelease>,
2048 L: LockBefore<ProcessGroupState>,
2049 {
2050 let result = self
2051 .clone_task(
2052 locked,
2053 flags,
2054 exit_signal,
2055 UserRef::default(),
2056 UserRef::default(),
2057 UserRef::default(),
2058 )
2059 .expect("failed to create task in test");
2060
2061 result.into()
2062 }
2063
2064 pub fn check_ptrace_access_mode<L>(
2066 &self,
2067 locked: &mut Locked<L>,
2068 mode: PtraceAccessMode,
2069 target: &Task,
2070 ) -> Result<(), Errno>
2071 where
2072 L: LockBefore<MmDumpable>,
2073 {
2074 if self.thread_group().leader == target.thread_group().leader {
2077 return Ok(());
2078 }
2079
2080 let (uid, gid) = if mode.contains(PTRACE_MODE_FSCREDS) {
2092 let fscred = self.current_creds().as_fscred();
2093 (fscred.uid, fscred.gid)
2094 } else if mode.contains(PTRACE_MODE_REALCREDS) {
2095 let creds = self.current_creds();
2096 (creds.uid, creds.gid)
2097 } else {
2098 unreachable!();
2099 };
2100
2101 let target_creds = target.real_creds();
2111 if !(target_creds.uid == uid
2112 && target_creds.euid == uid
2113 && target_creds.saved_uid == uid
2114 && target_creds.gid == gid
2115 && target_creds.egid == gid
2116 && target_creds.saved_gid == gid)
2117 {
2118 security::check_task_capable(self, CAP_SYS_PTRACE)?;
2119 }
2120
2121 let dumpable = *target.mm()?.dumpable.lock(locked);
2127 match dumpable {
2128 DumpPolicy::User => (),
2129 DumpPolicy::Disable => security::check_task_capable(self, CAP_SYS_PTRACE)?,
2130 }
2131
2132 security::ptrace_access_check(self, target, mode)?;
2135
2136 Ok(())
2139 }
2140
2141 pub fn can_signal(
2142 &self,
2143 target: &Task,
2144 unchecked_signal: UncheckedSignal,
2145 ) -> Result<(), Errno> {
2146 if self.thread_group == target.thread_group {
2149 return Ok(());
2150 }
2151
2152 let self_creds = self.current_creds();
2153 let target_creds = target.real_creds();
2154 if self_creds.euid == target_creds.saved_uid
2164 || self_creds.euid == target_creds.uid
2165 || self_creds.uid == target_creds.uid
2166 || self_creds.uid == target_creds.saved_uid
2167 {
2168 return Ok(());
2169 }
2170
2171 if Signal::try_from(unchecked_signal) == Ok(SIGCONT) {
2172 let target_session = target.thread_group().read().process_group.session.leader;
2173 let self_session = self.thread_group().read().process_group.session.leader;
2174 if target_session == self_session {
2175 return Ok(());
2176 }
2177 }
2178
2179 security::check_task_capable(self, CAP_KILL)
2180 }
2181}
2182
2183impl ArchSpecific for CurrentTask {
2184 fn is_arch32(&self) -> bool {
2185 self.thread_state.is_arch32()
2186 }
2187}
2188
2189impl MemoryAccessor for CurrentTask {
2190 fn read_memory<'a>(
2191 &self,
2192 addr: UserAddress,
2193 bytes: &'a mut [MaybeUninit<u8>],
2194 ) -> Result<&'a mut [u8], Errno> {
2195 self.mm()?.unified_read_memory(self, addr, bytes)
2196 }
2197
2198 fn read_memory_partial_until_null_byte<'a>(
2199 &self,
2200 addr: UserAddress,
2201 bytes: &'a mut [MaybeUninit<u8>],
2202 ) -> Result<&'a mut [u8], Errno> {
2203 self.mm()?.unified_read_memory_partial_until_null_byte(self, addr, bytes)
2204 }
2205
2206 fn read_memory_partial<'a>(
2207 &self,
2208 addr: UserAddress,
2209 bytes: &'a mut [MaybeUninit<u8>],
2210 ) -> Result<&'a mut [u8], Errno> {
2211 self.mm()?.unified_read_memory_partial(self, addr, bytes)
2212 }
2213
2214 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2215 self.mm()?.unified_write_memory(self, addr, bytes)
2216 }
2217
2218 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2219 self.mm()?.unified_write_memory_partial(self, addr, bytes)
2220 }
2221
2222 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
2223 self.mm()?.unified_zero(self, addr, length)
2224 }
2225}
2226
2227impl TaskMemoryAccessor for CurrentTask {
2228 fn maximum_valid_address(&self) -> Option<UserAddress> {
2229 self.mm().ok().map(|mm| mm.maximum_valid_user_address)
2230 }
2231}
2232
2233pub enum ExceptionResult {
2234 Handled,
2236
2237 Signal(SignalInfo),
2239}
2240
2241#[cfg(test)]
2242mod tests {
2243 use crate::task::FullCredentials;
2244 use crate::testing::spawn_kernel_and_run;
2245
2246 #[::fuchsia::test]
2249 async fn test_override_creds_can_delegate_to_async_version() {
2250 spawn_kernel_and_run(async move |_, current_task| {
2251 assert_eq!(current_task.override_creds(FullCredentials::for_kernel(), || 0), 0);
2252 })
2253 .await;
2254 }
2255}