1use crate::arch::task::handle_hardware_exception;
6use crate::execution::{CreateDuringShutdown, TaskInfo, create_zircon_process};
7use crate::mm::{
8 DumpPolicy, MappingAccess, MemoryAccessor, MemoryAccessorExt, MemoryManager, TaskMemoryAccessor,
9};
10use crate::ptrace::{PtraceEvent, PtraceEventData, PtraceOptions, StopState};
11use crate::security;
12use crate::signals::{SignalInfo, send_standard_signal};
13use crate::task::loader::{
14 ResolvedProgram, load_executable, resolve_elf_interpreter, resolve_executable,
15};
16use crate::task::{
17 CurrentTaskCredentialsWriteGuard, ExitStatus, PageFaultExceptionReport, RobustListHeadPtr,
18 RunState, SeccompFilter, SeccompFilterContainer, SeccompState, SeccompStateValue, Task,
19 TaskFlags, TaskRunningState, ThreadState, Waiter,
20};
21use crate::vfs::{
22 AccessCheck, CreationStatus, DirEntry, DirectoryMode, FdFlags, FdNumber, FdTable, FileHandle,
23 FileMapping, FileWriteGuardMode, FsContext, FsStr, LookupContext, LookupVec,
24 MAX_SYMLINK_FOLLOWS, NamespaceNode, OpenAccessCheck, ResolveBase, SymlinkMode, SymlinkTarget,
25 new_pidfd,
26};
27use futures::FutureExt;
28use linux_uapi::CLONE_PIDFD;
29use starnix_logging::{CATEGORY_STARNIX, log_error, log_warn, track_file_not_found, track_stub};
30use starnix_registers::{HeapRegs, RegisterStorageEnum};
31use starnix_sync::{EventWaitGuard, UninterruptibleLock, WakeReason, assert_lock_level};
32use starnix_syscalls::SyscallResult;
33use starnix_syscalls::decls::Syscall;
34use starnix_task_command::TaskCommand;
35use starnix_types::futex_address::FutexAddress;
36use starnix_types::ownership::{Releasable, release_on_error};
37use starnix_types::user_buffer::UserBuffer;
38use starnix_uapi::auth::{
39 CAP_KILL, CAP_SYS_ADMIN, Credentials, FsCred, PTRACE_MODE_FSCREDS, PTRACE_MODE_REALCREDS,
40 PtraceAccessMode,
41};
42use starnix_uapi::device_id::DeviceId;
43use starnix_uapi::errors::Errno;
44use starnix_uapi::file_mode::{Access, FileMode};
45use starnix_uapi::open_flags::OpenFlags;
46use starnix_uapi::signals::{
47 SIGCHLD, SIGCONT, SIGILL, SIGKILL, SIGSEGV, SIGSYS, SIGTRAP, SigSet, Signal, 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_CLEAR_SIGHAND, CLONE_FILES, CLONE_FS,
53 CLONE_INTO_CGROUP, CLONE_NEWUTS, CLONE_PARENT, CLONE_PARENT_SETTID, CLONE_PTRACE, CLONE_SETTLS,
54 CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_THREAD, CLONE_VFORK, CLONE_VM, FUTEX_OWNER_DIED,
55 FUTEX_TID_MASK, ROBUST_LIST_LIMIT, SECCOMP_FILTER_FLAG_LOG, SECCOMP_FILTER_FLAG_NEW_LISTENER,
56 SECCOMP_FILTER_FLAG_TSYNC, SECCOMP_FILTER_FLAG_TSYNC_ESRCH, errno, error, pid_t, sock_filter,
57 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, Weak};
66use zx::sys::zx_restricted_state_t;
67
68use super::ThreadGroupLifecycleWaitValue;
69
70pub struct TaskBuilder {
71 pub task: Arc<Task>,
73
74 pub thread_state: ThreadState<HeapRegs>,
75}
76
77impl TaskBuilder {
78 pub fn new(task: Arc<Task>) -> Self {
79 Self { task, thread_state: Default::default() }
80 }
81
82 #[inline(always)]
83 pub fn release(self, _context: ()) {
84 Releasable::release(self, ());
85 }
86}
87
88impl From<TaskBuilder> for CurrentTask {
89 fn from(builder: TaskBuilder) -> Self {
90 Self::new(builder.task, builder.thread_state.into())
91 }
92}
93
94impl Releasable for TaskBuilder {
95 type Context<'a> = ();
96
97 fn release<'a>(self, _context: Self::Context<'a>) {
98 let current_task = CurrentTask::new(self.task, self.thread_state.into());
100 current_task.exit();
101 }
102}
103
104impl std::ops::Deref for TaskBuilder {
105 type Target = Task;
106 fn deref(&self) -> &Self::Target {
107 &self.task
108 }
109}
110
111pub struct CurrentTask {
124 pub task: Arc<Task>,
126
127 pub thread_state: ThreadState<RegisterStorageEnum>,
128
129 pub running_state: Option<Arc<TaskRunningState>>,
137
138 pub files: RefCell<Option<Arc<FdTable>>>,
145
146 pub mm: Option<Arc<MemoryManager>>,
148
149 pub current_creds: RefCell<CurrentCreds>,
153
154 pub security_state: security::CurrentTaskState,
155
156 _local_marker: PhantomData<*mut u8>,
158}
159
160pub enum CurrentCreds {
162 Cached(Arc<Credentials>),
167 Overridden(Arc<Credentials>),
169}
170
171impl CurrentCreds {
172 fn creds(&self) -> &Arc<Credentials> {
173 match self {
174 CurrentCreds::Cached(creds) => creds,
175 CurrentCreds::Overridden(creds) => creds,
176 }
177 }
178}
179
180impl Releasable for CurrentTask {
181 type Context<'a> = ();
182
183 fn release<'a>(self, _context: Self::Context<'a>) {
184 self.exit();
185 }
186}
187
188impl std::ops::Deref for CurrentTask {
189 type Target = Task;
190 fn deref(&self) -> &Self::Target {
191 &self.task
192 }
193}
194
195impl fmt::Debug for CurrentTask {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 self.task.fmt(f)
198 }
199}
200
201impl CurrentTask {
202 pub fn new(task: Arc<Task>, thread_state: ThreadState<RegisterStorageEnum>) -> Self {
203 let current_creds = RefCell::new(CurrentCreds::Cached(task.clone_creds()));
204 let running_state = task.running_state().expect("CurrentTask must have TaskRunningState");
205 let files = running_state.files().expect("CurrentTask must have FdTable");
206 let mm = running_state.mm.upgrade();
207 Self {
208 task,
209 thread_state,
210 running_state: Some(running_state),
211 files: RefCell::new(Some(files)),
212 mm,
213 current_creds,
214 security_state: Default::default(),
215 _local_marker: Default::default(),
216 }
217 }
218
219 pub fn exit(mut self) {
221 self.notify_robust_list();
227 let _ignored = self.clear_child_tid_if_needed();
228
229 self.signal_vfork();
230
231 if let Some(ref running_state) = self.running_state {
260 *running_state.files.lock() = None;
261 running_state.mm.update(None);
262 running_state.fs.update(&self, None);
263 }
264 self.running_state = None;
265
266 *self.files.borrow_mut() = None;
267 self.mm = None;
268 self.task.running_state.update(None);
269
270 self.trigger_delayed_releaser();
271
272 self.task.thread_group().remove(self.kernel().pids.lock(), &self.task);
278
279 self.ptrace_disconnect();
280 }
281
282 #[track_caller]
301 pub fn running_state(&self) -> &Arc<TaskRunningState> {
302 self.running_state.as_ref().expect("CurrentTask must have TaskRunningState")
303 }
304
305 #[track_caller]
312 pub fn files(&self) -> Arc<FdTable> {
313 self.files.borrow().as_ref().expect("CurrentTask must have FdTable").clone()
314 }
315
316 #[inline]
318 pub fn get_file(&self, fd: FdNumber) -> Result<FileHandle, Errno> {
319 self.files.borrow().as_ref().expect("CurrentTask must have FdTable").get(fd)
320 }
321
322 #[inline]
325 pub fn get_file_allowing_opath(&self, fd: FdNumber) -> Result<FileHandle, Errno> {
326 self.files.borrow().as_ref().expect("CurrentTask must have FdTable").get_allowing_opath(fd)
327 }
328
329 #[inline]
332 pub fn mm(&self) -> Result<&Arc<MemoryManager>, Errno> {
333 self.mm.as_ref().ok_or_else(|| errno!(EINVAL))
334 }
335
336 pub fn set_mm_for_test(&mut self, mm: Arc<MemoryManager>) {
337 self.running_state().mm.update(Some(mm.clone()));
338 self.mm = Some(mm);
339 }
340
341 #[track_caller]
348 pub fn fs(&self) -> Arc<FsContext> {
349 self.running_state().fs().expect("CurrentTask must have FsContext")
350 }
351
352 pub fn has_shared_fs(&self) -> bool {
354 self.fs().is_shared()
355 }
356
357 pub fn unshare_fs(&self) {
359 let new_fs = self.fs().fork();
360 self.running_state().fs.update(self, new_fs);
361 }
362
363 pub fn current_creds(&self) -> Ref<'_, Arc<Credentials>> {
368 Ref::map(self.current_creds.borrow(), CurrentCreds::creds)
369 }
370
371 pub fn current_fscred(&self) -> FsCred {
372 self.current_creds().as_fscred()
373 }
374
375 pub fn current_ucred(&self) -> ucred {
376 let creds = self.current_creds();
377 ucred { pid: self.get_pid(), uid: creds.uid, gid: creds.gid }
378 }
379
380 pub async fn override_creds_async<R>(
389 &self,
390 new_creds: Arc<Credentials>,
391 callback: impl AsyncFnOnce() -> R,
392 ) -> R {
393 let saved = self.current_creds.replace(CurrentCreds::Overridden(new_creds));
394 let result = callback().await;
395 self.current_creds.replace(saved);
396 result
397 }
398
399 pub fn override_creds<R>(
408 &self,
409 new_creds: Arc<Credentials>,
410 callback: impl FnOnce() -> R,
411 ) -> R {
412 self.override_creds_async(new_creds, async move || callback())
413 .now_or_never()
414 .expect("Future should be ready")
415 }
416
417 pub fn has_overridden_creds(&self) -> bool {
418 matches!(*self.current_creds.borrow(), CurrentCreds::Overridden(_))
419 }
420
421 pub fn trigger_delayed_releaser(&self) {
422 self.kernel().delayed_releaser.apply(self);
423 }
424
425 pub fn weak_task(&self) -> Weak<Task> {
426 Arc::downgrade(&self.task)
427 }
428
429 pub fn write_creds(&self) -> CurrentTaskCredentialsWriteGuard {
433 assert!(!self.has_overridden_creds());
434 self.persistent_info.write_current_task_creds()
435 }
436
437 pub fn set_creds(&self, creds: Credentials) {
440 let prev = self.current_creds();
441 let effective_or_fs_ugid_changed = creds.euid != prev.euid
442 || creds.egid != prev.egid
443 || creds.fsuid != prev.fsuid
444 || creds.fsgid != prev.fsgid;
445 std::mem::drop(prev);
446
447 if effective_or_fs_ugid_changed {
448 self.thread_group().write().set_parent_death_signal(None);
454
455 if let Ok(mm) = self.mm() {
471 mm.dumpable.store(self.kernel().system_limits.suid_dumpable.load());
472 }
473 }
474
475 let creds = Arc::new(creds);
476 self.write_creds().update(self, creds);
477 }
478
479 #[inline(always)]
480 pub fn release(self, _context: ()) {
481 Releasable::release(self, ());
482 }
483
484 pub fn set_syscall_restart_func<R: Into<SyscallResult>>(
485 &mut self,
486 f: impl FnOnce(&mut CurrentTask) -> Result<R, Errno> + Send + Sync + 'static,
487 ) {
488 self.thread_state.syscall_restart_func =
489 Some(Box::new(|current_task| Ok(f(current_task)?.into())));
490 }
491
492 pub fn add_file(&self, file: FileHandle, flags: FdFlags) -> Result<FdNumber, Errno> {
493 self.files().add(self, file, flags)
494 }
495
496 pub fn wait_with_temporary_mask<F, T>(
503 &mut self,
504 signal_mask: SigSet,
505 wait_function: F,
506 ) -> Result<T, Errno>
507 where
508 F: FnOnce(&CurrentTask) -> Result<T, Errno>,
509 {
510 self.write().set_temporary_signal_mask(signal_mask);
511 wait_function(self)
512 }
513
514 pub fn wake_or_wait_until_unstopped_async(&self, waiter: &Waiter) -> bool {
517 let group_state = self.thread_group().read();
518 let mut task_state = self.write();
519
520 let task_stop_state = self.load_stopped();
527 let group_stop_state = self.thread_group().load_stopped();
528 if ((task_stop_state == StopState::GroupStopped && group_stop_state.is_waking_or_awake())
529 || task_stop_state.is_waking_or_awake())
530 && (!task_state.is_ptrace_listening() || task_stop_state.is_force())
531 {
532 let new_state = if task_stop_state.is_waking_or_awake() {
533 task_stop_state.finalize()
534 } else {
535 group_stop_state.finalize()
536 };
537 if let Ok(new_state) = new_state {
538 task_state.set_stopped(new_state, None, Some(self), None);
539 drop(group_state);
540 drop(task_state);
541 self.thread_group().set_stopped(new_state, None, false);
547 return true;
548 }
549 }
550
551 if self.thread_group().load_stopped().is_stopped() || task_stop_state.is_stopped() {
553 group_state
556 .lifecycle_waiters
557 .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::Stopped);
558 task_state.wait_on_ptracer(&waiter);
559 } else if task_state.can_accept_ptrace_commands() {
560 task_state.wait_on_ptracer(&waiter);
563 } else if task_state.is_ptrace_listening() {
564 if let Some(ptrace) = &mut task_state.ptrace {
567 ptrace.set_last_signal(Some(SignalInfo::kernel(SIGTRAP)));
568 ptrace.set_last_event(Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0)));
569 }
570 task_state.wait_on_ptracer(&waiter);
571 task_state.notify_ptracers();
572 }
573 false
574 }
575
576 pub fn is_interrupt_pending(&self) -> bool {
578 self.read().is_interrupt_pending()
579 }
580
581 pub fn is_work_cancelled(&self) -> bool {
582 self.flags().contains(TaskFlags::WORK_CANCELLED)
583 }
584
585 pub fn run_in_state<F, T>(&self, run_state: RunState, callback: F) -> Result<T, Errno>
597 where
598 F: FnOnce() -> Result<T, Errno>,
599 {
600 assert!(!matches!(run_state, RunState::Event(_)), "use block_until for RunState::Event");
601 unsafe { self.run_in_state_internal(run_state, callback) }
603 }
604
605 unsafe fn run_in_state_internal<F, T>(
611 &self,
612 run_state: RunState,
613 callback: F,
614 ) -> Result<T, Errno>
615 where
616 F: FnOnce() -> Result<T, Errno>,
617 {
618 assert_ne!(run_state, RunState::Running);
619
620 assert_lock_level::<UninterruptibleLock>();
622
623 {
624 let mut state = self.write();
625 assert!(!state.is_blocked());
626
627 if self.is_exitted() || self.is_work_cancelled() {
630 return error!(EINTR);
631 }
632 if run_state.ignores_signals() {
633 if state.has_signal_pending(SIGKILL) {
635 return error!(EINTR);
636 }
637 } else if state.is_interrupt_pending() {
638 return error!(EINTR);
639 }
640 let _ = unsafe { state.set_run_state(run_state.clone()) };
642 }
643
644 let _reset_run_state = scopeguard::guard((), |()| {
645 let mut state = self.write();
646 let prev_run_state = unsafe { state.set_run_state(RunState::Running) };
648 assert_eq!(prev_run_state, run_state, "SignalState run state changed while waiting!");
649 });
650 let _waiting_guard = crate::task::ThreadLockupDetector::pause_tracking();
651 callback()
652 }
653
654 pub fn block_until(
655 &self,
656 guard: EventWaitGuard<'_>,
657 deadline: zx::MonotonicInstant,
658 ) -> Result<(), Errno> {
659 self.block_with_optional_owner_until(guard, None, deadline)
660 }
661
662 pub fn block_with_owner_until(
663 &self,
664 guard: EventWaitGuard<'_>,
665 new_owner: &zx::Thread,
666 deadline: zx::MonotonicInstant,
667 ) -> Result<(), Errno> {
668 self.block_with_optional_owner_until(guard, Some(new_owner), deadline)
669 }
670
671 pub fn block_with_optional_owner_until(
672 &self,
673 guard: EventWaitGuard<'_>,
674 new_owner: Option<&zx::Thread>,
675 deadline: zx::MonotonicInstant,
676 ) -> Result<(), Errno> {
677 unsafe {
681 let run_state = RunState::Event(crate::task::EventRef::new(guard.event()));
682 self.run_in_state_internal(run_state, move || {
683 guard.block_until(new_owner, deadline).map_err(|e| match e {
684 WakeReason::Interrupted => errno!(EINTR),
685 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
686 })
687 })
688 }
689 }
690
691 pub fn resolve_dir_fd<'a>(
695 &self,
696 dir_fd: FdNumber,
697 mut path: &'a FsStr,
698 flags: ResolveFlags,
699 ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
700 let path_is_absolute = path.starts_with(b"/");
701 if path_is_absolute {
702 if flags.contains(ResolveFlags::BENEATH) {
703 return error!(EXDEV);
704 }
705 path = &path[1..];
706 }
707
708 let dir = if path_is_absolute && !flags.contains(ResolveFlags::IN_ROOT) {
709 self.fs().root()
710 } else if dir_fd == FdNumber::AT_FDCWD {
711 self.fs().cwd()
712 } else {
713 let file = self.get_file_allowing_opath(dir_fd)?;
723 file.name.to_passive()
724 };
725
726 if !path.is_empty() {
727 if !dir.entry.node.is_dir() {
728 return error!(ENOTDIR);
729 }
730 dir.check_access(self, AccessCheck::for_internal(Access::EXEC))?;
731 }
732 Ok((dir, path.into()))
733 }
734
735 pub fn open_file(&self, path: &FsStr, flags: OpenFlags) -> Result<FileHandle, Errno> {
740 if flags.contains(OpenFlags::CREAT) {
741 return error!(EINVAL);
744 }
745 self.open_file_at(
746 FdNumber::AT_FDCWD,
747 path,
748 flags,
749 FileMode::default(),
750 ResolveFlags::empty(),
751 )
752 }
753
754 pub fn open_file_for_exec(
769 &self,
770 dir_fd: FdNumber,
771 path: &FsStr,
772 flags: OpenFlags,
773 ) -> Result<Arc<FileMapping>, Errno> {
774 debug_assert!(
775 (flags & !(OpenFlags::RDONLY | OpenFlags::NOFOLLOW)).is_empty(),
776 "unexpected flags passed to open_file_for_exec: {flags:?}"
777 );
778 if !(flags & !(OpenFlags::RDONLY | OpenFlags::NOFOLLOW)).is_empty() {
779 return error!(EINVAL);
780 }
781
782 let (dir, path) = self.resolve_dir_fd(dir_fd, path, ResolveFlags::empty())?;
783 let nofollow = flags.contains(OpenFlags::NOFOLLOW);
784 let mut context =
785 LookupContext::new(if nofollow { SymlinkMode::NoFollow } else { SymlinkMode::Follow });
786 context.update_for_path(path);
787 let name = self.lookup_path(&mut context, dir, path)?;
788
789 if nofollow && name.entry.node.info().mode.is_lnk() {
794 return error!(ELOOP);
795 }
796
797 if !name.entry.node.is_reg() {
801 return error!(EACCES);
802 }
803
804 let file = name.open(self, OpenAccessCheck::for_exec())?;
811 FileMapping::new(file, Some(FileWriteGuardMode::ExecMapping))
812 }
813
814 fn resolve_open_path(
825 &self,
826 context: &mut LookupContext,
827 dir: &NamespaceNode,
828 path: &FsStr,
829 mode: FileMode,
830 flags: OpenFlags,
831 ) -> Result<(NamespaceNode, bool), Errno> {
832 context.update_for_path(path);
833 let mut parent_content = context.with(SymlinkMode::Follow, context.directory_mode);
834 let (parent, basename) = self.lookup_parent(&mut parent_content, dir, path)?;
835 context.remaining_follows = parent_content.remaining_follows;
836
837 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
838
839 let mut child_context = context.with(SymlinkMode::NoFollow, DirectoryMode::AllowAny);
841
842 let child = if flags.contains(OpenFlags::CREAT)
843 && context.directory_mode != DirectoryMode::MustBeDirectory
844 && !DirEntry::is_reserved_name(basename)
845 {
846 let (child, status) = parent.open_create_node(
850 self,
851 basename,
852 mode.with_type(FileMode::IFREG),
853 DeviceId::NONE,
854 )?;
855 if status == CreationStatus::Created {
856 return Ok((child, true));
857 }
858 parent.resolve_child(self, &mut child_context, child)
863 } else {
864 parent.lookup_child(self, &mut child_context, basename)
865 };
866
867 match child {
868 Ok(name) => {
869 if name.entry.node.is_lnk() {
870 if flags.contains(OpenFlags::PATH)
871 && context.symlink_mode == SymlinkMode::NoFollow
872 {
873 return Ok((name, false));
886 }
887
888 if (!flags.contains(OpenFlags::PATH)
889 && context.symlink_mode == SymlinkMode::NoFollow)
890 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
891 || context.remaining_follows == 0
892 {
893 if must_create {
894 return error!(EEXIST);
897 }
898 return error!(ELOOP);
903 }
904
905 context.remaining_follows -= 1;
906 match name.readlink(self)? {
907 SymlinkTarget::Path(path) => {
908 let dir = if path[0] == b'/' { self.fs().root() } else { parent };
909 self.resolve_open_path(context, &dir, path.as_ref(), mode, flags)
910 }
911 SymlinkTarget::Node(name) => {
912 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS)
913 || name.entry.node.is_lnk()
914 {
915 error!(ELOOP)
916 } else {
917 Ok((name, false))
918 }
919 }
920 }
921 } else {
922 if must_create {
923 return error!(EEXIST);
924 }
925 Ok((name, false))
926 }
927 }
928 Err(e)
929 if e == errno!(ENOENT)
930 && flags.contains(OpenFlags::CREAT)
931 && context.directory_mode == DirectoryMode::MustBeDirectory =>
932 {
933 error!(EISDIR)
936 }
937 Err(e) => Err(e),
938 }
939 }
940
941 pub fn open_file_at(
951 &self,
952 dir_fd: FdNumber,
953 path: &FsStr,
954 flags: impl Into<OpenAccessCheck>,
955 mode: FileMode,
956 resolve_flags: ResolveFlags,
957 ) -> Result<FileHandle, Errno> {
958 if path.is_empty() {
959 return error!(ENOENT);
960 }
961
962 let (dir, path) = self.resolve_dir_fd(dir_fd, path, resolve_flags)?;
963 self.open_namespace_node_at(dir, path, flags, mode, resolve_flags)
964 }
965
966 pub fn open_namespace_node_at(
967 &self,
968 dir: NamespaceNode,
969 path: &FsStr,
970 open_check: impl Into<OpenAccessCheck>,
971 mode: FileMode,
972 mut resolve_flags: ResolveFlags,
973 ) -> Result<FileHandle, Errno> {
974 let open_check = open_check.into();
975 let mut flags = open_check.open_flags() | OpenFlags::LARGEFILE;
977 let opath = flags.contains(OpenFlags::PATH);
978 if opath {
979 const ALLOWED_FLAGS: OpenFlags = OpenFlags::from_bits_truncate(
982 OpenFlags::PATH.bits()
983 | OpenFlags::CLOEXEC.bits()
984 | OpenFlags::DIRECTORY.bits()
985 | OpenFlags::NOFOLLOW.bits(),
986 );
987 flags &= ALLOWED_FLAGS;
988 }
989
990 if flags.contains(OpenFlags::TMPFILE) && !flags.can_write() {
991 return error!(EINVAL);
992 }
993
994 let nofollow = flags.contains(OpenFlags::NOFOLLOW);
995 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
996
997 let symlink_mode =
998 if nofollow || must_create { SymlinkMode::NoFollow } else { SymlinkMode::Follow };
999
1000 let resolve_base = match (
1001 resolve_flags.contains(ResolveFlags::BENEATH),
1002 resolve_flags.contains(ResolveFlags::IN_ROOT),
1003 ) {
1004 (false, false) => ResolveBase::None,
1005 (true, false) => ResolveBase::Beneath(dir.clone()),
1006 (false, true) => ResolveBase::InRoot(dir.clone()),
1007 (true, true) => return error!(EINVAL),
1008 };
1009
1010 if resolve_base != ResolveBase::None {
1014 resolve_flags.insert(ResolveFlags::NO_MAGICLINKS);
1015 }
1016
1017 let mut context = LookupContext {
1018 symlink_mode,
1019 remaining_follows: MAX_SYMLINK_FOLLOWS,
1020 directory_mode: if flags.contains(OpenFlags::DIRECTORY) {
1021 DirectoryMode::MustBeDirectory
1022 } else {
1023 DirectoryMode::AllowAny
1024 },
1025 resolve_flags,
1026 resolve_base,
1027 };
1028 let (name, created) = match self.resolve_open_path(&mut context, &dir, path, mode, flags) {
1029 Ok((n, c)) => (n, c),
1030 Err(e) => {
1031 let mut abs_path = dir.path(&self.fs());
1032 abs_path.extend(&**path);
1033 track_file_not_found(abs_path);
1034 return Err(e);
1035 }
1036 };
1037
1038 let name = if flags.contains(OpenFlags::TMPFILE) {
1039 if flags.contains(OpenFlags::CREAT) {
1041 return error!(EINVAL);
1042 }
1043 name.create_tmpfile(self, mode.with_type(FileMode::IFREG), flags)?
1044 } else {
1045 let mode = name.entry.node.info().mode;
1046
1047 if !opath && nofollow && mode.is_lnk() {
1059 return error!(ELOOP);
1060 }
1061
1062 if mode.is_dir() {
1063 if flags.can_write()
1064 || flags.contains(OpenFlags::CREAT)
1065 || flags.contains(OpenFlags::TRUNC)
1066 {
1067 return error!(EISDIR);
1068 }
1069 if flags.contains(OpenFlags::DIRECT) {
1070 return error!(EINVAL);
1071 }
1072 } else if context.directory_mode == DirectoryMode::MustBeDirectory {
1073 return error!(ENOTDIR);
1074 }
1075
1076 if flags.contains(OpenFlags::TRUNC) && mode.is_reg() && !created {
1077 name.truncate(self, 0)?;
1083 }
1084
1085 name
1086 };
1087
1088 let file = if created {
1095 name.open(self, OpenAccessCheck::skip(flags))?
1096 } else {
1097 name.open(self, OpenAccessCheck::new(flags, open_check.access_check()))?
1098 };
1099
1100 if !opath {
1104 security::file_open(self, &file)?;
1105 }
1106
1107 Ok(file)
1108 }
1109
1110 pub fn lookup_parent_at<'a>(
1118 &self,
1119 context: &mut LookupContext,
1120 dir_fd: FdNumber,
1121 path: &'a FsStr,
1122 ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
1123 let (dir, path) = self.resolve_dir_fd(dir_fd, path, ResolveFlags::empty())?;
1124 self.lookup_parent(context, &dir, path)
1125 }
1126
1127 pub fn lookup_parent<'a>(
1142 &self,
1143 context: &mut LookupContext,
1144 dir: &NamespaceNode,
1145 path: &'a FsStr,
1146 ) -> Result<(NamespaceNode, &'a FsStr), Errno> {
1147 context.update_for_path(path);
1148
1149 let components = split_path(path);
1150 if components.is_empty() {
1151 return Ok((dir.clone(), Default::default()));
1152 }
1153 let result = dir.lookup_children(self, context, &components[0..components.len() - 1])?;
1154 Ok((result, components.last().unwrap()))
1155 }
1156
1157 pub fn lookup_path(
1164 &self,
1165 context: &mut LookupContext,
1166 dir: NamespaceNode,
1167 path: &FsStr,
1168 ) -> Result<NamespaceNode, Errno> {
1169 let components = split_path(path);
1170 dir.lookup_children(self, context, &components)
1171 }
1172
1173 pub fn lookup_path_from_root(&self, path: &FsStr) -> Result<NamespaceNode, Errno> {
1177 let mut context = LookupContext::default();
1178 self.lookup_path(&mut context, self.fs().root(), path)
1179 }
1180
1181 pub fn exec(
1182 &mut self,
1183 executable: Arc<FileMapping>,
1184 path: CString,
1185 argv: Vec<CString>,
1186 environ: Vec<CString>,
1187 ) -> Result<(), Errno> {
1188 let writable_creds = self.write_creds();
1190
1191 let mut resolved_program = ResolvedProgram::new(self, executable, path, argv, environ);
1197 security::bprm_creds_for_exec(self, &mut resolved_program)?;
1198 resolve_executable(self, &mut resolved_program)?;
1199 security::bprm_creds_from_file(self, &mut resolved_program)?;
1200 resolve_elf_interpreter(self, &mut resolved_program)?;
1201
1202 if self.thread_group().read().tasks_count() > 1 {
1203 track_stub!(TODO("https://fxbug.dev/297434895"), "exec on multithread process");
1204 return error!(EINVAL);
1205 }
1206
1207 if let Err(err) = self.finish_exec(resolved_program, writable_creds) {
1209 log_warn!("unrecoverable error in exec: {err:?}");
1210
1211 send_standard_signal(self, SignalInfo::forced(SIGSEGV));
1212 return Err(err);
1213 }
1214
1215 let tid = self.get_tid() as u64;
1216 self.ptrace().on_event(PtraceOptions::TRACEEXEC, tid);
1217 self.signal_vfork();
1218 self.task.thread_group.sync_syscall_log_level();
1219
1220 Ok(())
1221 }
1222
1223 fn finish_exec(
1227 &mut self,
1228 resolved_program: ResolvedProgram,
1229 writable_creds: CurrentTaskCredentialsWriteGuard,
1230 ) -> Result<(), Errno> {
1231 let elf_arch_width = resolved_program.arch_width().ok_or_else(|| errno!(EINVAL))?;
1232
1233 self.notify_robust_list();
1237
1238 let new_mm = MemoryManager::exec(
1240 self.thread_group().root_vmar.unowned(),
1241 self.mm().ok().cloned(),
1242 resolved_program.file.name().to_passive(),
1243 elf_arch_width,
1244 )?;
1245
1246 let dumpable = if resolved_program.secure_exec {
1255 self.kernel().system_limits.suid_dumpable.load()
1256 } else {
1257 DumpPolicy::User
1258 };
1259 new_mm.dumpable.store(dumpable);
1260
1261 self.running_state().mm.update(Some(new_mm.clone()));
1262 self.mm = Some(new_mm);
1263
1264 self.running_state().unshare_files(self);
1280 self.files().exec();
1281
1282 if resolved_program.secure_exec {
1289 self.thread_group().write().set_parent_death_signal(None);
1290 }
1291
1292 {
1293 let mut state = self.write();
1294 state.set_sigaltstack(None);
1295 state.robust_list_head = RobustListHeadPtr::null(self);
1296 }
1297
1298 security::bprm_committing_creds(self, &resolved_program)?;
1299
1300 let new_creds = Arc::new(resolved_program.creds.clone());
1301 writable_creds.update(self, new_creds);
1302
1303 self.thread_group().timers.reset_for_exec(self);
1307
1308 self.thread_group().signal_actions.reset_for_exec();
1309 security::bprm_committed_creds(self)?;
1310
1311 let command_name = TaskCommand::from_path_bytes(resolved_program.path().to_bytes());
1312 let start_info = load_executable(self, resolved_program)?;
1313
1314 let regs: zx_restricted_state_t = start_info.into();
1315 self.thread_state.registers.load(regs);
1316 self.thread_state.extended_pstate.reset_with_arch(self.thread_state.arch_width());
1317
1318 {
1320 let mut thread_group_state = self.thread_group().write();
1321 thread_group_state.exit_signal = Some(SIGCHLD);
1322 for child in thread_group_state.children() {
1323 let _token = starnix_sync::allow_subclass();
1327 let mut child_state = child.write();
1328 child_state.exit_signal = Some(SIGCHLD);
1329 }
1330 }
1331
1332 self.thread_group().write().did_exec = true;
1333
1334 self.set_command_name(command_name);
1335
1336 Ok(())
1337 }
1338
1339 pub fn set_command_name(&self, new_name: TaskCommand) {
1340 self.task.set_command_name(new_name.clone());
1342 let leader_command = self.thread_group().read().leader_command();
1343 starnix_logging::set_current_task_info(new_name, leader_command, self.pid.id, self.tid.id);
1344 }
1345
1346 pub fn add_seccomp_filter(
1347 &mut self,
1348 code: Vec<sock_filter>,
1349 flags: u32,
1350 ) -> Result<SyscallResult, Errno> {
1351 let mut notifier = None;
1352 if flags & SECCOMP_FILTER_FLAG_NEW_LISTENER != 0 {
1353 notifier = Some(SeccompFilterContainer::create_notifier());
1354 }
1355
1356 let new_filter = Arc::new(SeccompFilter::from_cbpf(
1357 &code,
1358 self.thread_group().next_seccomp_filter_id.add(1),
1359 flags & SECCOMP_FILTER_FLAG_LOG != 0,
1360 notifier.clone(),
1361 )?);
1362
1363 let mut maybe_fd: Option<FdNumber> = None;
1364 if let Some(notifier) = notifier {
1365 maybe_fd = Some(SeccompFilterContainer::register_listener(self, notifier)?);
1366 }
1367
1368 let state = self.thread_group().write();
1371
1372 if self.seccomp_filter_state.get() == SeccompStateValue::Strict {
1373 return error!(EINVAL);
1374 }
1375
1376 if flags & SECCOMP_FILTER_FLAG_TSYNC != 0 {
1377 let mut filters: SeccompFilterContainer = self.read().seccomp_filters.clone();
1383
1384 let tasks = state.tasks();
1388 for task in &tasks {
1389 if task.tid.id == self.tid.id {
1390 continue;
1391 }
1392 let other_task_state = task.read();
1393
1394 if task.seccomp_filter_state.get() == SeccompStateValue::Strict {
1396 return Self::seccomp_tsync_error(task.tid.id, flags);
1397 }
1398
1399 if !other_task_state.seccomp_filters.can_sync_to(&filters) {
1401 return Self::seccomp_tsync_error(task.tid.id, flags);
1402 }
1403 }
1404
1405 filters.add_filter(new_filter, code.len() as u16)?;
1407
1408 for task in &tasks {
1409 let mut other_task_state = task.write();
1410
1411 other_task_state.enable_no_new_privs();
1412 other_task_state.seccomp_filters = filters.clone();
1413 task.seccomp_filter_state.set_always_allow(&filters.always_allow);
1414 task.set_seccomp_state(SeccompStateValue::UserDefined)?;
1415 }
1416 } else {
1417 let mut task_state = self.task.write();
1418
1419 task_state.seccomp_filters.add_filter(new_filter, code.len() as u16)?;
1420 let always_allow = task_state.seccomp_filters.always_allow;
1421 self.seccomp_filter_state.set_always_allow(&always_allow);
1422 self.set_seccomp_state(SeccompStateValue::UserDefined)?;
1423 }
1424
1425 if let Some(fd) = maybe_fd { Ok(fd.into()) } else { Ok(().into()) }
1426 }
1427
1428 #[inline]
1429 pub fn run_seccomp_filters(
1430 &mut self,
1431 syscall: &Syscall,
1432 ) -> Option<Result<SyscallResult, Errno>> {
1433 if !self.is_arch32()
1434 && self.seccomp_filter_state.is_syscall_always_allowed(syscall.decl.number)
1435 {
1436 return None;
1437 }
1438 self.run_seccomp_filters_slow(syscall)
1439 }
1440
1441 #[cold]
1442 #[inline(never)]
1443 fn run_seccomp_filters_slow(
1444 &mut self,
1445 syscall: &Syscall,
1446 ) -> Option<Result<SyscallResult, Errno>> {
1447 if self.seccomp_filter_state.get() == SeccompStateValue::Strict {
1450 return SeccompState::do_strict(self, syscall);
1451 }
1452
1453 let result = self.task.read().seccomp_filters.run_all(self, syscall);
1455
1456 SeccompState::do_user_defined(result, self, syscall)
1457 }
1458
1459 fn seccomp_tsync_error(id: i32, flags: u32) -> Result<SyscallResult, Errno> {
1460 if flags & SECCOMP_FILTER_FLAG_TSYNC_ESRCH != 0 { error!(ESRCH) } else { Ok(id.into()) }
1466 }
1467
1468 pub fn notify_robust_list(&self) {
1474 let task_state = self.write();
1475 let robust_list_addr = task_state.robust_list_head.addr();
1476 if robust_list_addr == UserAddress::NULL {
1477 return;
1479 }
1480 let robust_list_res = self.read_multi_arch_object(task_state.robust_list_head);
1481
1482 let head = if let Ok(head) = robust_list_res {
1483 head
1484 } else {
1485 return;
1486 };
1487
1488 let offset = head.futex_offset;
1489
1490 let mut entries_count = 0;
1491 let mut curr_ptr = head.list.next;
1492 while curr_ptr.addr() != robust_list_addr.into() && entries_count < ROBUST_LIST_LIMIT {
1493 let curr_ref = self.read_multi_arch_object(curr_ptr);
1494
1495 let curr = if let Ok(curr) = curr_ref {
1496 curr
1497 } else {
1498 return;
1499 };
1500
1501 let Some(futex_base) = curr_ptr.addr().checked_add_signed(offset) else {
1502 return;
1503 };
1504
1505 let futex_addr = match FutexAddress::try_from(futex_base) {
1506 Ok(addr) => addr,
1507 Err(_) => {
1508 return;
1509 }
1510 };
1511
1512 let Ok(mm) = self.mm() else {
1513 log_error!("Asked to notify robust list futexes in system task.");
1514 return;
1515 };
1516 let futex = if let Ok(futex) = mm.atomic_load_u32_relaxed(futex_addr) {
1517 futex
1518 } else {
1519 return;
1520 };
1521
1522 if (futex & FUTEX_TID_MASK) as i32 == self.tid.id {
1523 let owner_died = FUTEX_OWNER_DIED | futex;
1524 if mm.atomic_store_u32_relaxed(futex_addr, owner_died).is_err() {
1525 return;
1526 }
1527 }
1528 curr_ptr = curr.next;
1529 entries_count += 1;
1530 }
1531 }
1532
1533 pub(crate) fn handle_page_fault(
1534 &self,
1535 decoded: PageFaultExceptionReport,
1536 status: zx::Status,
1537 ) -> ExceptionResult {
1538 if let Ok(mm) = self.mm() {
1539 mm.handle_page_fault(decoded, status)
1540 } else {
1541 panic!(
1542 "system task is handling a major page fault status={:?}, report={:?}",
1543 status, decoded
1544 );
1545 }
1546 }
1547
1548 pub fn process_exception(&self, report: &zx::ExceptionReport) -> ExceptionResult {
1550 if let Some(result) = handle_hardware_exception(self, report) {
1551 return result;
1552 }
1553
1554 match report.ty {
1555 zx::ExceptionType::General => {
1556 log_error!("Unrecognized general exception: {:?}", report);
1557 ExceptionResult::Signal(SignalInfo::kernel(SIGILL))
1558 }
1559 zx::ExceptionType::ProcessNameChanged => {
1560 log_error!("Received unexpected process name changed exception");
1561 ExceptionResult::Handled
1562 }
1563 zx::ExceptionType::ProcessStarting
1564 | zx::ExceptionType::ThreadStarting
1565 | zx::ExceptionType::ThreadExiting => {
1566 log_error!("Received unexpected task lifecycle exception");
1567 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1568 }
1569 zx::ExceptionType::PolicyError(policy_code) => {
1570 log_error!(policy_code:?; "Received Zircon policy error exception");
1571 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1572 }
1573 zx::ExceptionType::UnknownUserGenerated { code, data } => {
1574 log_error!(code:?, data:?; "Received unexpected unknown user generated exception");
1575 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1576 }
1577 zx::ExceptionType::Unknown { ty, code, data } => {
1578 log_error!(ty:?, code:?, data:?; "Received unexpected exception");
1579 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1580 }
1581 _ => {
1582 log_error!("Received unknown zircon exception: {:?}", report.ty);
1583 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1584 }
1585 }
1586 }
1587
1588 pub fn clone_task(
1598 &self,
1599 flags: u64,
1600 child_exit_signal: Option<Signal>,
1601 user_parent_tid: UserRef<pid_t>,
1602 user_child_tid: UserRef<pid_t>,
1603 user_pidfd: UserRef<FdNumber>,
1604 ) -> Result<TaskBuilder, Errno> {
1605 const IMPLEMENTED_FLAGS: u64 = ((CLONE_VM
1606 | CLONE_FS
1607 | CLONE_FILES
1608 | CLONE_SIGHAND
1609 | CLONE_THREAD
1610 | CLONE_SYSVSEM
1611 | CLONE_SETTLS
1612 | CLONE_PARENT
1613 | CLONE_PARENT_SETTID
1614 | CLONE_PIDFD
1615 | CLONE_CHILD_CLEARTID
1616 | CLONE_CHILD_SETTID
1617 | CLONE_VFORK
1618 | CLONE_NEWUTS
1619 | CLONE_PTRACE) as u64)
1620 | CLONE_CLEAR_SIGHAND;
1621
1622 const VALID_FLAGS: u64 = (CLONE_INTO_CGROUP << 1) - 1;
1627
1628 let clone_files = flags & (CLONE_FILES as u64) != 0;
1631 let clone_fs = flags & (CLONE_FS as u64) != 0;
1632 let clone_parent = flags & (CLONE_PARENT as u64) != 0;
1633 let clone_parent_settid = flags & (CLONE_PARENT_SETTID as u64) != 0;
1634 let clone_pidfd = flags & (CLONE_PIDFD as u64) != 0;
1635 let clone_child_cleartid = flags & (CLONE_CHILD_CLEARTID as u64) != 0;
1636 let clone_child_settid = flags & (CLONE_CHILD_SETTID as u64) != 0;
1637 let clone_sysvsem = flags & (CLONE_SYSVSEM as u64) != 0;
1638 let clone_ptrace = flags & (CLONE_PTRACE as u64) != 0;
1639 let clone_thread = flags & (CLONE_THREAD as u64) != 0;
1640 let clone_vm = flags & (CLONE_VM as u64) != 0;
1641 let clone_sighand = flags & (CLONE_SIGHAND as u64) != 0;
1642 let clone_vfork = flags & (CLONE_VFORK as u64) != 0;
1643 let clone_newuts = flags & (CLONE_NEWUTS as u64) != 0;
1644 let clone_into_cgroup = flags & CLONE_INTO_CGROUP != 0;
1645 let clone_clear_sighand = flags & (CLONE_CLEAR_SIGHAND as u64) != 0;
1646
1647 if clone_ptrace {
1648 track_stub!(TODO("https://fxbug.dev/322874630"), "CLONE_PTRACE");
1649 }
1650
1651 if clone_sysvsem {
1652 track_stub!(TODO("https://fxbug.dev/322875185"), "CLONE_SYSVSEM");
1653 }
1654
1655 if clone_into_cgroup {
1656 track_stub!(TODO("https://fxbug.dev/403612570"), "CLONE_INTO_CGROUP");
1657 }
1658
1659 if clone_sighand && !clone_vm {
1660 return error!(EINVAL);
1661 }
1662 if clone_clear_sighand && clone_sighand {
1663 return error!(EINVAL);
1664 }
1665 if clone_thread && !clone_sighand {
1666 return error!(EINVAL);
1667 }
1668
1669 if clone_pidfd && clone_thread {
1670 return error!(EINVAL);
1671 }
1672 if clone_pidfd && clone_parent_settid && user_parent_tid.addr() == user_pidfd.addr() {
1673 return error!(EINVAL);
1676 }
1677
1678 if flags & !VALID_FLAGS != 0 {
1679 return error!(EINVAL);
1680 }
1681
1682 if clone_vm && !clone_thread {
1683 if !clone_vfork {
1694 track_stub!(
1695 TODO("https://fxbug.dev/322875227"),
1696 "CLONE_VM without CLONE_THREAD or CLONE_VFORK"
1697 );
1698 }
1699 } else if clone_thread && !clone_vm {
1700 track_stub!(TODO("https://fxbug.dev/322875167"), "CLONE_THREAD without CLONE_VM");
1701 return error!(ENOSYS);
1702 }
1703
1704 if flags & !IMPLEMENTED_FLAGS != 0 {
1705 track_stub!(
1706 TODO("https://fxbug.dev/322875130"),
1707 "clone unknown flags",
1708 flags & !IMPLEMENTED_FLAGS
1709 );
1710 return error!(ENOSYS);
1711 }
1712
1713 let fs = if clone_fs { self.fs() } else { self.fs().fork() };
1714 let files = if clone_files {
1715 self.running_state().share_files()
1716 } else {
1717 self.running_state().fork_files()
1718 }
1719 .expect("Task must have FdTable");
1720
1721 let kernel = self.kernel();
1722
1723 let mut pids = kernel.pids.lock();
1724
1725 let mut cgroup2_pid_table = kernel.cgroups.lock_cgroup2_pid_table();
1729 let child_kernel_signals = cgroup2_pid_table
1731 .maybe_create_freeze_signal(&self.pid)
1732 .into_iter()
1733 .collect::<VecDeque<_>>();
1734
1735 let pid;
1736 let command;
1737 let creds;
1738 let scheduler_state;
1739 let no_new_privs;
1740 let seccomp_filters;
1741 let seccomp_state;
1742 let robust_list_head = RobustListHeadPtr::null(self);
1743 let child_signal_mask;
1744 let timerslack_ns;
1745 let uts_ns;
1746
1747 let TaskInfo { thread_group, memory_manager } = {
1748 let weak_original_parent;
1751 let original_parent;
1752 let create_during_shutdown;
1755
1756 let (thread_group_state, creator_task) = {
1758 let thread_group_state = self.thread_group().write();
1759 create_during_shutdown = if thread_group_state.is_deferred_shutdown_process() {
1760 CreateDuringShutdown::UntilDeadline
1761 } else {
1762 CreateDuringShutdown::Never
1763 };
1764 if clone_parent {
1765 weak_original_parent =
1768 thread_group_state.parent.clone().ok_or_else(|| errno!(EINVAL))?;
1769 let creator_task = weak_original_parent.creator_task().cloned();
1770 std::mem::drop(thread_group_state);
1771 original_parent = weak_original_parent.upgrade();
1772 (original_parent.write(), creator_task)
1773 } else {
1774 (thread_group_state, Some(self.weak_task()))
1775 }
1776 };
1777
1778 scheduler_state = self.scheduler_state.lock().fork();
1779 let state = self.read();
1780
1781 no_new_privs = state.no_new_privs();
1782 seccomp_filters = state.seccomp_filters.clone();
1783 seccomp_state = SeccompState::from(&self.seccomp_filter_state);
1787 child_signal_mask = state.signal_mask();
1788
1789 pid = pids.allocate_pid()?;
1790 command = self.command();
1791 creds = self.current_creds().clone();
1792 timerslack_ns = state.timerslack_ns;
1793
1794 uts_ns = if clone_newuts {
1795 security::check_task_capable(self, CAP_SYS_ADMIN)?;
1796 state.uts_ns.read().fork()
1797 } else {
1798 state.uts_ns.clone()
1799 };
1800
1801 if clone_thread {
1802 TaskInfo {
1803 thread_group: self.thread_group().clone(),
1804 memory_manager: self.mm().ok().cloned(),
1805 }
1806 } else {
1807 std::mem::drop(state);
1811 let signal_actions = if clone_sighand {
1812 self.thread_group().signal_actions.clone()
1813 } else if clone_clear_sighand {
1814 let actions = self.thread_group().signal_actions.fork();
1815 actions.reset_for_exec();
1816 actions
1817 } else {
1818 self.thread_group().signal_actions.fork()
1819 };
1820 let task_info = {
1821 fuchsia_trace::duration!(CATEGORY_STARNIX, "create_zircon_process");
1822 create_zircon_process(
1823 kernel,
1824 Some(thread_group_state),
1825 pid.clone(),
1826 child_exit_signal,
1827 signal_actions,
1828 command.clone(),
1829 create_during_shutdown,
1830 )?
1831 };
1832
1833 if let Some(parent) = &mut task_info.thread_group.write().parent {
1834 parent.set_creator_task(creator_task);
1835 }
1836
1837 cgroup2_pid_table.inherit_cgroup(self.thread_group(), &task_info.thread_group);
1838
1839 task_info
1840 }
1841 };
1842
1843 std::mem::drop(cgroup2_pid_table);
1848
1849 let vfork_event = if clone_vfork { Some(Arc::new(zx::Event::create())) } else { None };
1851
1852 let abstract_socket_namespace;
1855 let abstract_vsock_namespace;
1856 {
1857 let running_state = self.running_state();
1858 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
1859 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
1860 }
1861
1862 let sid_pid = thread_group.read().session.clone();
1863
1864 let mut child = TaskBuilder::new(Task::new(
1865 pid,
1866 command,
1867 thread_group,
1868 files,
1869 memory_manager,
1870 fs,
1871 creds,
1872 abstract_socket_namespace,
1873 abstract_vsock_namespace,
1874 child_signal_mask,
1875 child_kernel_signals,
1876 vfork_event,
1877 scheduler_state,
1878 uts_ns,
1879 no_new_privs,
1880 seccomp_state,
1881 seccomp_filters,
1882 robust_list_head,
1883 timerslack_ns,
1884 ));
1885 let parent_cpuset_path = self.read().cpuset_path.clone();
1886 child.task.write().cpuset_path = parent_cpuset_path;
1887
1888 release_on_error!(child, {
1889 pids.add_task(Arc::clone(&child.task));
1893
1894 #[cfg(any(test, debug_assertions))]
1898 {
1899 if !clone_thread {
1902 let _l1 = self.thread_group().read();
1903 let _token = starnix_sync::allow_subclass();
1907 let _l2 = child.thread_group().read();
1908 }
1909 }
1910
1911 if clone_thread {
1912 self.thread_group().add(Arc::clone(&child.task))?;
1913 std::mem::drop(pids);
1914 } else {
1915 child.thread_group().add(Arc::clone(&child.task))?;
1916 pids.attach_pgid(&child.thread_group().pgid(), child.thread_group());
1917 pids.attach_sid(&sid_pid, child.thread_group());
1918 std::mem::drop(pids);
1919
1920 if let Some(ct) = self.thread_group().controlling_terminal() {
1926 let mut child_state = child.thread_group().write();
1927 if child_state.session == sid_pid
1928 && ct.terminal.read().controlling_session() == Some(&sid_pid)
1929 {
1930 child_state.controlling_terminal = Some(ct);
1931 }
1932 }
1933
1934 let (sigaltstack, signal_mask) = {
1939 let state = self.read();
1940 (state.sigaltstack(), state.signal_mask())
1941 };
1942 let mut child_state = child.write();
1943 child_state.set_sigaltstack(sigaltstack);
1944 child_state.set_signal_mask(signal_mask);
1945 }
1946
1947 if !clone_vm {
1948 assert!(!clone_thread);
1951 let child_mm = MemoryManager::snapshot_of(
1952 self.mm()?,
1953 child.thread_group.root_vmar.unowned(),
1954 self.thread_state.arch_width(),
1955 )?;
1956 child.running_state()?.mm.update(Some(child_mm));
1957 }
1958
1959 if clone_parent_settid {
1960 self.write_object(user_parent_tid, &child.tid.id)?;
1961 }
1962
1963 if clone_child_cleartid {
1964 child.write().clear_child_tid = user_child_tid;
1965 }
1966
1967 if clone_child_settid {
1968 child.write_object(user_child_tid, &child.tid.id)?;
1969 }
1970
1971 if clone_pidfd {
1972 let file = new_pidfd(self, child.pid.clone(), OpenFlags::empty())?;
1973 let pidfd = self.add_file(file, FdFlags::CLOEXEC)?;
1974 self.write_object(user_pidfd, &pidfd)?;
1975 }
1976
1977 if clone_vm && !clone_thread {
1981 let child_mm = MemoryManager::snapshot_of(
1982 self.mm()?,
1983 child.thread_group.root_vmar.unowned(),
1984 self.thread_state.arch_width(),
1985 )?;
1986 child.running_state()?.mm.update(Some(child_mm));
1987 }
1988
1989 child.thread_state = self.thread_state.snapshot::<HeapRegs>();
1990 Ok(())
1991 });
1992
1993 #[cfg(any(test, debug_assertions))]
1996 {
1997 let _l1 = child.thread_group().read();
1998 let _l2 = child.read();
1999 }
2000
2001 Ok(child)
2002 }
2003
2004 pub fn set_stopped_and_notify(&self, stopped: StopState, siginfo: Option<SignalInfo>) {
2007 let maybe_signal_info = {
2008 let mut state = self.write();
2009 state.set_stopped(stopped, siginfo, Some(self), None);
2010 state.prepare_signal_info(stopped)
2011 };
2012
2013 if let Some((tracer, signal_info)) = maybe_signal_info {
2014 if let Some(tracer) = tracer.upgrade() {
2015 tracer.write().send_signal(signal_info);
2016 }
2017 }
2018
2019 if !stopped.is_in_progress() {
2020 let parent = self.thread_group().read().parent.clone();
2021 if let Some(parent) = parent {
2022 parent
2023 .upgrade()
2024 .write()
2025 .lifecycle_waiters
2026 .notify_value(ThreadGroupLifecycleWaitValue::ChildStatus);
2027 }
2028 }
2029 }
2030
2031 pub fn block_if_stopped(&mut self) -> bool {
2038 if !self.finalize_stop_state() {
2039 return false;
2040 }
2041 self.block_while_stopped();
2042
2043 let captured_state = self.write().take_captured_state();
2045 if let Some(captured) = captured_state {
2046 if captured.dirty {
2047 self.thread_state.replace_registers(&captured.thread_state);
2048 }
2049 }
2050 true
2051 }
2052
2053 fn finalize_stop_state(&self) -> bool {
2055 let stopped = self.load_stopped();
2056
2057 if self.thread_group().set_stopped(StopState::GroupStopped, None, true)
2060 == StopState::GroupStopped
2061 {
2062 let signal = self.thread_group().read().last_signal.clone();
2063 let event = Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0));
2065 self.write().set_stopped(StopState::GroupStopped, signal, Some(self), event);
2066 return true;
2067 }
2068
2069 if stopped.is_stopping_or_stopped() {
2071 if let Ok(stopped) = stopped.finalize() {
2072 self.set_stopped_and_notify(stopped, None);
2073 }
2074 return true;
2075 }
2076
2077 false
2078 }
2079
2080 fn block_while_stopped(&mut self) {
2083 let waiter = Waiter::new();
2084 loop {
2085 if self.is_exitted() {
2088 self.thread_group().set_stopped(StopState::ForceAwake, None, false);
2089 self.write().set_stopped(StopState::ForceAwake, None, Some(self), None);
2090 return;
2091 }
2092
2093 if self.wake_or_wait_until_unstopped_async(&waiter) {
2094 return;
2095 }
2096
2097 waiter.stop(self);
2098
2099 self.finalize_stop_state();
2102 }
2103 }
2104
2105 pub fn kill_thread_group(&mut self, exit_status: ExitStatus) {
2108 Arc::clone(self.thread_group()).kill(exit_status, Some(self));
2109 }
2110
2111 pub fn clone_task_builder_for_test(
2114 &self,
2115 flags: u64,
2116 exit_signal: Option<Signal>,
2117 ) -> TaskBuilder {
2118 let result = self
2119 .clone_task(
2120 flags,
2121 exit_signal,
2122 UserRef::default(),
2123 UserRef::default(),
2124 UserRef::default(),
2125 )
2126 .expect("failed to create task in test");
2127 result.task.write().set_spawned();
2128 result
2129 }
2130
2131 pub fn clone_task_for_test(
2134 &self,
2135 flags: u64,
2136 exit_signal: Option<Signal>,
2137 ) -> crate::testing::AutoReleasableTask {
2138 self.clone_task_builder_for_test(flags, exit_signal).into()
2139 }
2140
2141 pub fn check_ptrace_access_mode(
2143 &self,
2144 mode: PtraceAccessMode,
2145 target: &Task,
2146 ) -> Result<(), Errno> {
2147 if self.pid == target.pid {
2150 return Ok(());
2151 }
2152
2153 let (uid, gid) = if mode.contains(PTRACE_MODE_FSCREDS) {
2165 let fscred = self.current_creds().as_fscred();
2166 (fscred.uid, fscred.gid)
2167 } else if mode.contains(PTRACE_MODE_REALCREDS) {
2168 let creds = self.current_creds();
2169 (creds.uid, creds.gid)
2170 } else {
2171 unreachable!();
2172 };
2173
2174 let creds_match = {
2184 let check = |target_creds: &Credentials| {
2185 target_creds.uid == uid
2186 && target_creds.euid == uid
2187 && target_creds.saved_uid == uid
2188 && target_creds.gid == gid
2189 && target_creds.egid == gid
2190 && target_creds.saved_gid == gid
2191 };
2192 if mode.contains(PtraceAccessMode::ATTACH) {
2193 check(&target.persistent_info.lock_creds())
2194 } else {
2195 check(&target.real_creds())
2196 }
2197 };
2198 if !creds_match {
2199 security::check_task_ptrace_capable(self, mode)?;
2200 }
2201
2202 if let Ok(mm) = target.mm() {
2210 let dumpable = mm.dumpable.load();
2211 match dumpable {
2212 DumpPolicy::User => (),
2213 DumpPolicy::Disable => {
2214 security::check_task_ptrace_capable(self, mode)?;
2215 }
2216 }
2217 }
2218
2219 security::ptrace_access_check(self, target, mode)?;
2222
2223 Ok(())
2226 }
2227
2228 pub fn can_signal(
2229 &self,
2230 target: &Task,
2231 unchecked_signal: UncheckedSignal,
2232 ) -> Result<(), Errno> {
2233 if self.thread_group == target.thread_group {
2236 return Ok(());
2237 }
2238
2239 let self_creds = self.current_creds();
2240 let target_creds = target.real_creds();
2241 if self_creds.euid == target_creds.saved_uid
2251 || self_creds.euid == target_creds.uid
2252 || self_creds.uid == target_creds.uid
2253 || self_creds.uid == target_creds.saved_uid
2254 {
2255 return Ok(());
2256 }
2257
2258 if Signal::try_from(unchecked_signal) == Ok(SIGCONT) {
2259 let target_session = target.thread_group().read().session.clone();
2260 let self_session = self.thread_group().read().session.clone();
2261 if target_session == self_session {
2262 return Ok(());
2263 }
2264 }
2265
2266 security::check_task_capable(self, CAP_KILL)
2267 }
2268}
2269
2270impl ArchSpecific for CurrentTask {
2271 fn is_arch32(&self) -> bool {
2272 self.thread_state.is_arch32()
2273 }
2274}
2275
2276impl MemoryAccessor for CurrentTask {
2277 fn read_memory<'a>(
2278 &self,
2279 addr: UserAddress,
2280 bytes: &'a mut [MaybeUninit<u8>],
2281 ) -> Result<&'a mut [u8], Errno> {
2282 self.mm()?.unified_read_memory(self, addr, bytes)
2283 }
2284
2285 fn read_memory_partial_until_null_byte<'a>(
2286 &self,
2287 addr: UserAddress,
2288 bytes: &'a mut [MaybeUninit<u8>],
2289 ) -> Result<&'a mut [u8], Errno> {
2290 self.mm()?.unified_read_memory_partial_until_null_byte(self, addr, bytes)
2291 }
2292
2293 fn read_memory_partial<'a>(
2294 &self,
2295 addr: UserAddress,
2296 bytes: &'a mut [MaybeUninit<u8>],
2297 ) -> Result<&'a mut [u8], Errno> {
2298 self.mm()?.unified_read_memory_partial(self, addr, bytes)
2299 }
2300
2301 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2302 self.mm()?.unified_write_memory(self, addr, bytes)
2303 }
2304
2305 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2306 self.mm()?.unified_write_memory_partial(self, addr, bytes)
2307 }
2308
2309 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
2310 self.mm()?.unified_zero(self, addr, length)
2311 }
2312}
2313
2314impl TaskMemoryAccessor for CurrentTask {
2315 fn maximum_valid_address(&self) -> Option<UserAddress> {
2316 self.mm().ok().map(|mm| mm.maximum_valid_user_address)
2317 }
2318
2319 fn ensure_buffers_mapped_in_user_vmar(
2320 &self,
2321 buffers: &[UserBuffer],
2322 access: MappingAccess,
2323 ) -> Result<(), Errno> {
2324 let mut ranges = buffers
2325 .iter()
2326 .filter(|b| !b.is_empty())
2327 .map(|b| (b.address, Some(b.length)))
2328 .peekable();
2329 if ranges.peek().is_some() {
2330 self.mm()?.ensure_ranges_mapped_in_user_vmar_for_access(ranges, access)?;
2331 }
2332 Ok(())
2333 }
2334}
2335
2336pub enum ExceptionResult {
2337 Handled,
2339
2340 Signal(SignalInfo),
2342}
2343
2344fn split_path(path: &FsStr) -> LookupVec<&FsStr> {
2345 path.split(|c| *c == b'/').filter(|p| !p.is_empty()).map(<&FsStr>::from).collect()
2346}
2347
2348#[cfg(test)]
2349mod tests {
2350 use super::*;
2351 use crate::ptrace::{PtraceAttachType, ptrace_attach};
2352 use crate::testing::{create_task, spawn_kernel_and_run};
2353 use starnix_uapi::CLONE_FS;
2354 use starnix_uapi::auth::{Credentials, PTRACE_MODE_READ_FSCREDS};
2355 use std::sync::Arc;
2356
2357 #[::fuchsia::test]
2360 async fn test_override_creds_can_delegate_to_async_version() {
2361 spawn_kernel_and_run(async move |current_task| {
2362 assert_eq!(current_task.override_creds(Credentials::root(), || 0), 0);
2363 })
2364 .await;
2365 }
2366
2367 #[::fuchsia::test]
2372 async fn test_exit_releases_fs_while_running_state_is_referenced() {
2373 spawn_kernel_and_run(async move |current_task| {
2374 let task = create_task(current_task.kernel(), "task");
2375 let running_state = task.task.running_state().expect("task should be running");
2376 let fs = Arc::downgrade(&task.fs());
2377
2378 std::mem::drop(task);
2380
2381 assert!(running_state.fs().is_err());
2382 assert!(fs.upgrade().is_none(), "FsContext should be dropped by exit()");
2383 })
2384 .await;
2385 }
2386
2387 #[::fuchsia::test]
2388 async fn test_has_shared_fs_ignores_transient_refs() {
2389 spawn_kernel_and_run(async move |current_task| {
2390 assert!(!current_task.has_shared_fs());
2391
2392 let transient_fs = current_task.fs();
2393 assert!(!current_task.has_shared_fs());
2394 std::mem::drop(transient_fs);
2395 })
2396 .await;
2397 }
2398
2399 #[::fuchsia::test]
2400 async fn test_has_shared_fs_clone_and_unshare() {
2401 spawn_kernel_and_run(async move |current_task| {
2402 let child = current_task.clone_task_for_test(CLONE_FS as u64, Some(SIGCHLD));
2403 assert!(current_task.has_shared_fs());
2404 assert!(child.has_shared_fs());
2405
2406 child.unshare_fs();
2407 assert!(!current_task.has_shared_fs());
2408 assert!(!child.has_shared_fs());
2409 })
2410 .await;
2411 }
2412
2413 #[::fuchsia::test]
2414 async fn test_has_shared_fs_cleared_on_peer_exit() {
2415 spawn_kernel_and_run(async move |current_task| {
2416 let child = current_task.clone_task_for_test(CLONE_FS as u64, Some(SIGCHLD));
2417 let child_running_state =
2418 child.task.running_state().expect("child task should be running");
2419 assert!(current_task.has_shared_fs());
2420
2421 std::mem::drop(child);
2422 assert!(!current_task.has_shared_fs());
2423 std::mem::drop(child_running_state);
2424 })
2425 .await;
2426 }
2427
2428 #[::fuchsia::test]
2429 async fn test_check_ptrace_access_mode() {
2430 spawn_kernel_and_run(async move |current_task| {
2431 let system_tg = current_task.kernel().kthreads.system_thread_group();
2432 let system_task = system_tg.leader.get_task().unwrap();
2433 let mode = PTRACE_MODE_READ_FSCREDS;
2434
2435 assert_eq!(
2437 ptrace_attach(
2438 current_task,
2439 &system_tg.leader,
2440 PtraceAttachType::Attach,
2441 UserAddress::NULL
2442 ),
2443 error!(EPERM)
2444 );
2445
2446 assert_eq!(current_task.check_ptrace_access_mode(mode, &system_task), Ok(()));
2448
2449 let unpriv_creds = Arc::new(Credentials::with_ids(1000, 1000));
2451 let res = current_task.override_creds(unpriv_creds.clone(), || {
2452 current_task.check_ptrace_access_mode(mode, &system_task)
2453 });
2454 assert_eq!(res, error!(EPERM));
2455
2456 let target_task = create_task(¤t_task.kernel(), "target");
2460 target_task.set_creds(Credentials::with_ids(1000, 1000));
2461 assert_eq!(target_task.mm().unwrap().dumpable.load(), DumpPolicy::Disable);
2462
2463 let res = current_task.override_creds(unpriv_creds.clone(), || {
2464 current_task.check_ptrace_access_mode(mode, &target_task)
2465 });
2466 assert_eq!(res, error!(EPERM));
2467
2468 assert_eq!(current_task.check_ptrace_access_mode(mode, &target_task), Ok(()));
2469
2470 let exited_task_ref = Arc::clone(&target_task.task);
2472 std::mem::drop(target_task);
2473 assert!(exited_task_ref.mm().is_err());
2474
2475 let res = current_task.override_creds(unpriv_creds, || {
2476 current_task.check_ptrace_access_mode(mode, &exited_task_ref)
2477 });
2478 assert_eq!(res, Ok(()));
2479
2480 let other_creds = Arc::new(Credentials::with_ids(2000, 2000));
2481 let res = current_task.override_creds(other_creds, || {
2482 current_task.check_ptrace_access_mode(mode, &exited_task_ref)
2483 });
2484 assert_eq!(res, error!(EPERM));
2485
2486 assert_eq!(current_task.check_ptrace_access_mode(mode, &exited_task_ref), Ok(()));
2487 })
2488 .await;
2489 }
2490}