1use crate::arch::task::handle_hardware_exception;
6use crate::execution::{TaskInfo, create_zircon_process};
7use crate::mm::{DumpPolicy, MemoryAccessor, MemoryAccessorExt, MemoryManager, TaskMemoryAccessor};
8use crate::ptrace::{PtraceCoreState, PtraceEvent, PtraceEventData, PtraceOptions, StopState};
9use crate::security;
10use crate::signals::{SignalDetail, 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 CurrentTaskCredentialsWriteGuard, ExitStatus, PageFaultExceptionReport, RobustListHeadPtr,
15 RunState, SeccompFilter, SeccompFilterContainer, SeccompNotifierHandle, SeccompState,
16 SeccompStateValue, Task, TaskFlags, TaskRunningState, ThreadState, Waiter,
17};
18use crate::vfs::{
19 CheckAccessReason, FdFlags, FdNumber, FileHandle, FsContext, FsStr, LookupContext, LookupVec,
20 MAX_SYMLINK_FOLLOWS, NamespaceNode, ResolveBase, SymlinkMode, SymlinkTarget, new_pidfd,
21};
22use fuchsia_rcu::RcuReadGuard;
23use futures::FutureExt;
24use linux_uapi::CLONE_PIDFD;
25use starnix_logging::{CATEGORY_STARNIX, log_error, log_warn, track_file_not_found, track_stub};
26use starnix_registers::{HeapRegs, RegisterStorageEnum};
27use starnix_stack::clean_stack;
28use starnix_sync::{
29 EventWaitGuard, FileOpsCore, LockBefore, LockEqualOrBefore, Locked, MmDumpable,
30 ProcessGroupState, TaskRelease, UninterruptibleLock, Unlocked, WakeReason, assert_lock_level,
31};
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_uapi::auth::{
38 CAP_KILL, CAP_SYS_ADMIN, CAP_SYS_PTRACE, Credentials, FsCred, PTRACE_MODE_FSCREDS,
39 PTRACE_MODE_REALCREDS, PtraceAccessMode,
40};
41use starnix_uapi::device_id::DeviceId;
42use starnix_uapi::errors::Errno;
43use starnix_uapi::file_mode::{Access, AccessCheck, FileMode};
44use starnix_uapi::open_flags::OpenFlags;
45use starnix_uapi::signals::{
46 SIGCHLD, SIGCONT, SIGILL, SIGKILL, SIGSEGV, SIGSYS, SIGTRAP, SigSet, Signal, UncheckedSignal,
47};
48use starnix_uapi::user_address::{ArchSpecific, UserAddress, UserRef};
49use starnix_uapi::vfs::ResolveFlags;
50use starnix_uapi::{
51 CLONE_CHILD_CLEARTID, CLONE_CHILD_SETTID, CLONE_CLEAR_SIGHAND, CLONE_FILES, CLONE_FS,
52 CLONE_INTO_CGROUP, CLONE_NEWUTS, CLONE_PARENT, CLONE_PARENT_SETTID, CLONE_PTRACE, CLONE_SETTLS,
53 CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_THREAD, CLONE_VFORK, CLONE_VM, FUTEX_OWNER_DIED,
54 FUTEX_TID_MASK, ROBUST_LIST_LIMIT, SECCOMP_FILTER_FLAG_LOG, SECCOMP_FILTER_FLAG_NEW_LISTENER,
55 SECCOMP_FILTER_FLAG_TSYNC, SECCOMP_FILTER_FLAG_TSYNC_ESRCH, clone_args, errno, error, pid_t,
56 sock_filter, ucred,
57};
58use std::cell::{Ref, RefCell};
59use std::collections::VecDeque;
60use std::ffi::CString;
61use std::fmt;
62use std::marker::PhantomData;
63use std::mem::MaybeUninit;
64use std::sync::{Arc, Weak};
65use zx::sys::zx_restricted_state_t;
66
67use super::ThreadGroupLifecycleWaitValue;
68
69pub struct TaskBuilder {
70 pub task: Arc<Task>,
72
73 pub thread_state: ThreadState<HeapRegs>,
74}
75
76impl TaskBuilder {
77 pub fn new(task: Arc<Task>) -> Self {
78 Self { task, thread_state: Default::default() }
79 }
80
81 #[inline(always)]
82 pub fn release<L>(self, locked: &mut Locked<L>)
83 where
84 L: LockBefore<TaskRelease>,
85 {
86 let locked = locked.cast_locked::<TaskRelease>();
87 Releasable::release(self, locked);
88 }
89}
90
91impl From<TaskBuilder> for CurrentTask {
92 fn from(builder: TaskBuilder) -> Self {
93 Self::new(builder.task, builder.thread_state.into())
94 }
95}
96
97impl Releasable for TaskBuilder {
98 type Context<'a> = &'a mut Locked<TaskRelease>;
99
100 fn release<'a>(self, locked: Self::Context<'a>) {
101 let current_task = CurrentTask::new(self.task, self.thread_state.into());
103 current_task.exit(locked);
104 }
105}
106
107impl std::ops::Deref for TaskBuilder {
108 type Target = Task;
109 fn deref(&self) -> &Self::Target {
110 &self.task
111 }
112}
113
114pub struct CurrentTask {
127 pub task: Arc<Task>,
129
130 pub thread_state: ThreadState<RegisterStorageEnum>,
131
132 pub current_creds: RefCell<CurrentCreds>,
136
137 pub security_state: security::CurrentTaskState,
138
139 _local_marker: PhantomData<*mut u8>,
141}
142
143pub enum CurrentCreds {
145 Cached(Arc<Credentials>),
150 Overridden(Arc<Credentials>),
152}
153
154impl CurrentCreds {
155 fn creds(&self) -> &Arc<Credentials> {
156 match self {
157 CurrentCreds::Cached(creds) => creds,
158 CurrentCreds::Overridden(creds) => creds,
159 }
160 }
161}
162
163impl Releasable for CurrentTask {
164 type Context<'a> = &'a mut Locked<TaskRelease>;
165
166 fn release<'a>(self, locked: Self::Context<'a>) {
167 self.exit(locked);
168 }
169}
170
171impl std::ops::Deref for CurrentTask {
172 type Target = Task;
173 fn deref(&self) -> &Self::Target {
174 &self.task
175 }
176}
177
178impl fmt::Debug for CurrentTask {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 self.task.fmt(f)
181 }
182}
183
184impl CurrentTask {
185 pub fn new(task: Arc<Task>, thread_state: ThreadState<RegisterStorageEnum>) -> Self {
186 let current_creds = RefCell::new(CurrentCreds::Cached(task.clone_creds()));
187 Self {
188 task,
189 thread_state,
190 current_creds,
191 security_state: Default::default(),
192 _local_marker: Default::default(),
193 }
194 }
195
196 pub fn exit(&self, locked: &mut Locked<TaskRelease>) {
198 self.notify_robust_list();
204 let _ignored = self.clear_child_tid_if_needed(locked);
205
206 self.signal_vfork();
207
208 if let Ok(running_state) = self.task.running_state() {
210 running_state.files.release();
211 running_state.mm.update(None);
212 }
213 self.running_state.update(None);
214
215 self.trigger_delayed_releaser(locked);
216
217 self.task.thread_group().remove(locked, self.kernel().pids.write(), &self.task);
223
224 self.ptrace_disconnect();
225 }
226
227 #[track_caller]
234 pub fn running_state(&self) -> RcuReadGuard<TaskRunningState> {
235 self.task.running_state().expect("CurrentTask must have TaskRunningState")
236 }
237
238 pub fn fs(&self) -> Arc<FsContext> {
239 self.running_state().fs()
240 }
241
242 pub fn has_shared_fs(&self) -> bool {
243 let fs = self.fs();
244 Arc::strong_count(&fs) > 2usize
247 }
248
249 pub fn unshare_fs(&self) {
250 let new_fs = self.fs().fork();
251 self.running_state().fs.update(new_fs);
252 }
253
254 pub fn current_creds(&self) -> Ref<'_, Arc<Credentials>> {
259 Ref::map(self.current_creds.borrow(), CurrentCreds::creds)
260 }
261
262 pub fn current_fscred(&self) -> FsCred {
263 self.current_creds().as_fscred()
264 }
265
266 pub fn current_ucred(&self) -> ucred {
267 let creds = self.current_creds();
268 ucred { pid: self.get_pid(), uid: creds.uid, gid: creds.gid }
269 }
270
271 pub async fn override_creds_async<R>(
280 &self,
281 new_creds: Arc<Credentials>,
282 callback: impl AsyncFnOnce() -> R,
283 ) -> R {
284 let saved = self.current_creds.replace(CurrentCreds::Overridden(new_creds));
285 let result = callback().await;
286 self.current_creds.replace(saved);
287 result
288 }
289
290 pub fn override_creds<R>(
299 &self,
300 new_creds: Arc<Credentials>,
301 callback: impl FnOnce() -> R,
302 ) -> R {
303 self.override_creds_async(new_creds, async move || callback())
304 .now_or_never()
305 .expect("Future should be ready")
306 }
307
308 pub fn has_overridden_creds(&self) -> bool {
309 matches!(*self.current_creds.borrow(), CurrentCreds::Overridden(_))
310 }
311
312 pub fn trigger_delayed_releaser<L>(&self, locked: &mut Locked<L>)
313 where
314 L: LockEqualOrBefore<FileOpsCore>,
315 {
316 let locked = locked.cast_locked::<FileOpsCore>();
317 self.kernel().delayed_releaser.apply(locked, self);
318 }
319
320 pub fn weak_task(&self) -> Weak<Task> {
321 Arc::downgrade(&self.task)
322 }
323
324 pub fn write_creds(&self) -> CurrentTaskCredentialsWriteGuard {
328 assert!(!self.has_overridden_creds());
329 self.persistent_info.write_current_task_creds()
330 }
331
332 pub fn set_creds(&self, creds: Credentials) {
335 let creds = Arc::new(creds);
336 self.write_creds().update(self, creds);
337 }
338
339 #[inline(always)]
340 pub fn release<L>(self, locked: &mut Locked<L>)
341 where
342 L: LockBefore<TaskRelease>,
343 {
344 let locked = locked.cast_locked::<TaskRelease>();
345 Releasable::release(self, locked);
346 }
347
348 pub fn set_syscall_restart_func<R: Into<SyscallResult>>(
349 &mut self,
350 f: impl FnOnce(&mut Locked<Unlocked>, &mut CurrentTask) -> Result<R, Errno>
351 + Send
352 + Sync
353 + 'static,
354 ) {
355 self.thread_state.syscall_restart_func =
356 Some(Box::new(|locked, current_task| Ok(f(locked, current_task)?.into())));
357 }
358
359 pub fn add_file<L>(
360 &self,
361 locked: &mut Locked<L>,
362 file: FileHandle,
363 flags: FdFlags,
364 ) -> Result<FdNumber, Errno>
365 where
366 L: LockEqualOrBefore<FileOpsCore>,
367 {
368 self.running_state().files.add(locked, self, file, flags)
369 }
370
371 pub fn get_file(&self, fd: FdNumber) -> Result<FileHandle, Errno> {
372 self.running_state().files.get(fd)
373 }
374
375 pub fn get_file_allowing_opath(&self, fd: FdNumber) -> Result<FileHandle, Errno> {
376 self.running_state().files.get_allowing_opath(fd)
377 }
378
379 pub fn wait_with_temporary_mask<F, T, L>(
386 &mut self,
387 locked: &mut Locked<L>,
388 signal_mask: SigSet,
389 wait_function: F,
390 ) -> Result<T, Errno>
391 where
392 L: LockEqualOrBefore<FileOpsCore>,
393 F: FnOnce(&mut Locked<L>, &CurrentTask) -> Result<T, Errno>,
394 {
395 {
396 let mut state = self.write();
397 state.set_flags(TaskFlags::TEMPORARY_SIGNAL_MASK, true);
398 state.set_temporary_signal_mask(signal_mask);
399 }
400 wait_function(locked, self)
401 }
402
403 pub fn wake_or_wait_until_unstopped_async(&self, waiter: &Waiter) -> bool {
406 let group_state = self.thread_group().read();
407 let mut task_state = self.write();
408
409 let task_stop_state = self.load_stopped();
416 let group_stop_state = self.thread_group().load_stopped();
417 if ((task_stop_state == StopState::GroupStopped && group_stop_state.is_waking_or_awake())
418 || task_stop_state.is_waking_or_awake())
419 && (!task_state.is_ptrace_listening() || task_stop_state.is_force())
420 {
421 let new_state = if task_stop_state.is_waking_or_awake() {
422 task_stop_state.finalize()
423 } else {
424 group_stop_state.finalize()
425 };
426 if let Ok(new_state) = new_state {
427 task_state.set_stopped(new_state, None, Some(self), None);
428 drop(group_state);
429 drop(task_state);
430 self.thread_group().set_stopped(new_state, None, false);
436 return true;
437 }
438 }
439
440 if self.thread_group().load_stopped().is_stopped() || task_stop_state.is_stopped() {
442 group_state
445 .lifecycle_waiters
446 .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::Stopped);
447 task_state.wait_on_ptracer(&waiter);
448 } else if task_state.can_accept_ptrace_commands() {
449 task_state.wait_on_ptracer(&waiter);
452 } else if task_state.is_ptrace_listening() {
453 if let Some(ptrace) = &mut task_state.ptrace {
456 ptrace.set_last_signal(Some(SignalInfo::kernel(SIGTRAP)));
457 ptrace.set_last_event(Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0)));
458 }
459 task_state.wait_on_ptracer(&waiter);
460 task_state.notify_ptracers();
461 }
462 false
463 }
464
465 pub fn run_in_state<F, T>(&self, run_state: RunState, callback: F) -> Result<T, Errno>
476 where
477 F: FnOnce() -> Result<T, Errno>,
478 {
479 assert_ne!(run_state, RunState::Running);
480
481 assert_lock_level::<UninterruptibleLock>();
483 clean_stack();
486
487 {
488 let mut state = self.write();
489 assert!(!state.is_blocked());
490
491 if matches!(run_state, RunState::Frozen(_)) {
492 if state.has_signal_pending(SIGKILL) {
495 return error!(EINTR);
496 }
497 } else if state.is_any_signal_pending() && !state.is_ptrace_listening() {
498 return error!(EINTR);
501 }
502 state.set_run_state(run_state.clone());
503 }
504
505 let _waiting_guard = crate::task::ThreadLockupDetector::pause_tracking();
506 let result = callback();
507
508 {
509 let mut state = self.write();
510 assert_eq!(
511 state.run_state(),
512 run_state,
513 "SignalState run state changed while waiting!"
514 );
515 state.set_run_state(RunState::Running);
516 };
517
518 result
519 }
520
521 pub fn block_until(
522 &self,
523 guard: EventWaitGuard<'_>,
524 deadline: zx::MonotonicInstant,
525 ) -> Result<(), Errno> {
526 self.run_in_state(RunState::Event(guard.event().clone()), move || {
527 guard.block_until(None, deadline).map_err(|e| match e {
528 WakeReason::Interrupted => errno!(EINTR),
529 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
530 })
531 })
532 }
533
534 pub fn block_with_owner_until(
535 &self,
536 guard: EventWaitGuard<'_>,
537 new_owner: &zx::Thread,
538 deadline: zx::MonotonicInstant,
539 ) -> Result<(), Errno> {
540 self.run_in_state(RunState::Event(guard.event().clone()), move || {
541 guard.block_until(Some(new_owner), deadline).map_err(|e| match e {
542 WakeReason::Interrupted => errno!(EINTR),
543 WakeReason::DeadlineExpired => errno!(ETIMEDOUT),
544 })
545 })
546 }
547
548 pub fn resolve_dir_fd<'a, L>(
552 &self,
553 locked: &mut Locked<L>,
554 dir_fd: FdNumber,
555 mut path: &'a FsStr,
556 flags: ResolveFlags,
557 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
558 where
559 L: LockEqualOrBefore<FileOpsCore>,
560 {
561 let path_is_absolute = path.starts_with(b"/");
562 if path_is_absolute {
563 if flags.contains(ResolveFlags::BENEATH) {
564 return error!(EXDEV);
565 }
566 path = &path[1..];
567 }
568
569 let dir = if path_is_absolute && !flags.contains(ResolveFlags::IN_ROOT) {
570 self.fs().root()
571 } else if dir_fd == FdNumber::AT_FDCWD {
572 self.fs().cwd()
573 } else {
574 let file = self.get_file_allowing_opath(dir_fd)?;
584 file.name.to_passive()
585 };
586
587 if !path.is_empty() {
588 if !dir.entry.node.is_dir() {
589 return error!(ENOTDIR);
590 }
591 dir.check_access(
592 locked,
593 self,
594 Access::EXEC,
595 CheckAccessReason::InternalPermissionChecks,
596 )?;
597 }
598 Ok((dir, path.into()))
599 }
600
601 pub fn open_file(
606 &self,
607 locked: &mut Locked<Unlocked>,
608 path: &FsStr,
609 flags: OpenFlags,
610 ) -> Result<FileHandle, Errno> {
611 if flags.contains(OpenFlags::CREAT) {
612 return error!(EINVAL);
615 }
616 self.open_file_at(
617 locked,
618 FdNumber::AT_FDCWD,
619 path,
620 flags,
621 FileMode::default(),
622 ResolveFlags::empty(),
623 AccessCheck::default(),
624 )
625 }
626
627 fn resolve_open_path<L>(
638 &self,
639 locked: &mut Locked<L>,
640 context: &mut LookupContext,
641 dir: &NamespaceNode,
642 path: &FsStr,
643 mode: FileMode,
644 flags: OpenFlags,
645 ) -> Result<(NamespaceNode, bool), Errno>
646 where
647 L: LockEqualOrBefore<FileOpsCore>,
648 {
649 context.update_for_path(path);
650 let mut parent_content = context.with(SymlinkMode::Follow);
651 let (parent, basename) = self.lookup_parent(locked, &mut parent_content, dir, path)?;
652 context.remaining_follows = parent_content.remaining_follows;
653
654 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
655
656 let mut child_context = context.with(SymlinkMode::NoFollow);
658 child_context.must_be_directory = false;
659
660 match parent.lookup_child(locked, self, &mut child_context, basename) {
661 Ok(name) => {
662 if name.entry.node.is_lnk() {
663 if flags.contains(OpenFlags::PATH)
664 && context.symlink_mode == SymlinkMode::NoFollow
665 {
666 return Ok((name, false));
679 }
680
681 if (!flags.contains(OpenFlags::PATH)
682 && context.symlink_mode == SymlinkMode::NoFollow)
683 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
684 || context.remaining_follows == 0
685 {
686 if must_create {
687 return error!(EEXIST);
690 }
691 return error!(ELOOP);
696 }
697
698 context.remaining_follows -= 1;
699 match name.readlink(locked, self)? {
700 SymlinkTarget::Path(path) => {
701 let dir = if path[0] == b'/' { self.fs().root() } else { parent };
702 self.resolve_open_path(
703 locked,
704 context,
705 &dir,
706 path.as_ref(),
707 mode,
708 flags,
709 )
710 }
711 SymlinkTarget::Node(name) => {
712 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS)
713 || name.entry.node.is_lnk()
714 {
715 error!(ELOOP)
716 } else {
717 Ok((name, false))
718 }
719 }
720 }
721 } else {
722 if must_create {
723 return error!(EEXIST);
724 }
725 Ok((name, false))
726 }
727 }
728 Err(e) if e == errno!(ENOENT) && flags.contains(OpenFlags::CREAT) => {
729 if context.must_be_directory {
730 return error!(EISDIR);
731 }
732 Ok((
733 parent.open_create_node(
734 locked,
735 self,
736 basename,
737 mode.with_type(FileMode::IFREG),
738 DeviceId::NONE,
739 flags,
740 )?,
741 true,
742 ))
743 }
744 Err(e) => Err(e),
745 }
746 }
747
748 pub fn open_file_at(
758 &self,
759 locked: &mut Locked<Unlocked>,
760 dir_fd: FdNumber,
761 path: &FsStr,
762 flags: OpenFlags,
763 mode: FileMode,
764 resolve_flags: ResolveFlags,
765 access_check: AccessCheck,
766 ) -> Result<FileHandle, Errno> {
767 if path.is_empty() {
768 return error!(ENOENT);
769 }
770
771 let (dir, path) = self.resolve_dir_fd(locked, dir_fd, path, resolve_flags)?;
772 self.open_namespace_node_at(locked, dir, path, flags, mode, resolve_flags, access_check)
773 }
774
775 pub fn open_namespace_node_at(
776 &self,
777 locked: &mut Locked<Unlocked>,
778 dir: NamespaceNode,
779 path: &FsStr,
780 flags: OpenFlags,
781 mode: FileMode,
782 mut resolve_flags: ResolveFlags,
783 access_check: AccessCheck,
784 ) -> Result<FileHandle, Errno> {
785 let mut flags = flags | OpenFlags::LARGEFILE;
787 let opath = flags.contains(OpenFlags::PATH);
788 if opath {
789 const ALLOWED_FLAGS: OpenFlags = OpenFlags::from_bits_truncate(
792 OpenFlags::PATH.bits()
793 | OpenFlags::CLOEXEC.bits()
794 | OpenFlags::DIRECTORY.bits()
795 | OpenFlags::NOFOLLOW.bits(),
796 );
797 flags &= ALLOWED_FLAGS;
798 }
799
800 if flags.contains(OpenFlags::TMPFILE) && !flags.can_write() {
801 return error!(EINVAL);
802 }
803
804 let nofollow = flags.contains(OpenFlags::NOFOLLOW);
805 let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
806
807 let symlink_mode =
808 if nofollow || must_create { SymlinkMode::NoFollow } else { SymlinkMode::Follow };
809
810 let resolve_base = match (
811 resolve_flags.contains(ResolveFlags::BENEATH),
812 resolve_flags.contains(ResolveFlags::IN_ROOT),
813 ) {
814 (false, false) => ResolveBase::None,
815 (true, false) => ResolveBase::Beneath(dir.clone()),
816 (false, true) => ResolveBase::InRoot(dir.clone()),
817 (true, true) => return error!(EINVAL),
818 };
819
820 if resolve_base != ResolveBase::None {
824 resolve_flags.insert(ResolveFlags::NO_MAGICLINKS);
825 }
826
827 let mut context = LookupContext {
828 symlink_mode,
829 remaining_follows: MAX_SYMLINK_FOLLOWS,
830 must_be_directory: flags.contains(OpenFlags::DIRECTORY),
831 resolve_flags,
832 resolve_base,
833 };
834 let (name, created) =
835 match self.resolve_open_path(locked, &mut context, &dir, path, mode, flags) {
836 Ok((n, c)) => (n, c),
837 Err(e) => {
838 let mut abs_path = dir.path(&self.fs());
839 abs_path.extend(&**path);
840 track_file_not_found(abs_path);
841 return Err(e);
842 }
843 };
844
845 let name = if flags.contains(OpenFlags::TMPFILE) {
846 if flags.contains(OpenFlags::CREAT) {
848 return error!(EINVAL);
849 }
850 name.create_tmpfile(locked, self, mode.with_type(FileMode::IFREG), flags)?
851 } else {
852 let mode = name.entry.node.info().mode;
853
854 if !opath && nofollow && mode.is_lnk() {
866 return error!(ELOOP);
867 }
868
869 if mode.is_dir() {
870 if flags.can_write()
871 || flags.contains(OpenFlags::CREAT)
872 || flags.contains(OpenFlags::TRUNC)
873 {
874 return error!(EISDIR);
875 }
876 if flags.contains(OpenFlags::DIRECT) {
877 return error!(EINVAL);
878 }
879 } else if context.must_be_directory {
880 return error!(ENOTDIR);
881 }
882
883 if flags.contains(OpenFlags::TRUNC) && mode.is_reg() && !created {
884 name.truncate(locked, self, 0)?;
890 }
891
892 name
893 };
894
895 let access_check = if created { AccessCheck::skip() } else { access_check };
902 let file = name.open(locked, self, flags, access_check)?;
903
904 if !opath {
908 security::file_open(self, &file)?;
909 }
910
911 Ok(file)
912 }
913
914 pub fn lookup_parent_at<'a, L>(
922 &self,
923 locked: &mut Locked<L>,
924 context: &mut LookupContext,
925 dir_fd: FdNumber,
926 path: &'a FsStr,
927 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
928 where
929 L: LockEqualOrBefore<FileOpsCore>,
930 {
931 let (dir, path) = self.resolve_dir_fd(locked, dir_fd, path, ResolveFlags::empty())?;
932 self.lookup_parent(locked, context, &dir, path)
933 }
934
935 pub fn lookup_parent<'a, L>(
950 &self,
951 locked: &mut Locked<L>,
952 context: &mut LookupContext,
953 dir: &NamespaceNode,
954 path: &'a FsStr,
955 ) -> Result<(NamespaceNode, &'a FsStr), Errno>
956 where
957 L: LockEqualOrBefore<FileOpsCore>,
958 {
959 context.update_for_path(path);
960
961 let components = split_path(path);
962 if components.is_empty() {
963 return Ok((dir.clone(), Default::default()));
964 }
965 let result =
966 dir.lookup_children(locked, self, context, &components[0..components.len() - 1])?;
967 Ok((result, components.last().unwrap()))
968 }
969
970 pub fn lookup_path<L>(
977 &self,
978 locked: &mut Locked<L>,
979 context: &mut LookupContext,
980 dir: NamespaceNode,
981 path: &FsStr,
982 ) -> Result<NamespaceNode, Errno>
983 where
984 L: LockEqualOrBefore<FileOpsCore>,
985 {
986 let components = split_path(path);
987 dir.lookup_children(locked, self, context, &components)
988 }
989
990 pub fn lookup_path_from_root<L>(
994 &self,
995 locked: &mut Locked<L>,
996 path: &FsStr,
997 ) -> Result<NamespaceNode, Errno>
998 where
999 L: LockEqualOrBefore<FileOpsCore>,
1000 {
1001 let mut context = LookupContext::default();
1002 self.lookup_path(locked, &mut context, self.fs().root(), path)
1003 }
1004
1005 pub fn exec(
1006 &mut self,
1007 locked: &mut Locked<Unlocked>,
1008 executable: FileHandle,
1009 path: CString,
1010 argv: Vec<CString>,
1011 environ: Vec<CString>,
1012 ) -> Result<(), Errno> {
1013 if !executable.name.entry.node.is_reg() {
1017 return error!(EACCES);
1018 }
1019
1020 executable.name.check_access(locked, self, Access::EXEC, CheckAccessReason::Exec)?;
1025
1026 let mut resolved_elf =
1029 resolve_executable(locked, self, executable.clone(), path.clone(), argv, environ)?;
1030
1031 let writable_creds = self.write_creds();
1033
1034 let (no_new_privs, is_ptraced) = {
1045 let state = self.read();
1046 (state.no_new_privs(), state.is_ptraced())
1047 };
1048
1049 let enable_suid = self.kernel().features.enable_suid && !no_new_privs && !is_ptraced;
1050 if enable_suid {
1051 resolved_elf.file.name.apply_suid_and_sgid(&mut resolved_elf.creds);
1052 }
1053
1054 resolved_elf.secure_exec |= resolved_elf.creds.exec(&self.current_creds());
1055
1056 if no_new_privs {
1062 resolved_elf.creds.cap_permitted &= self.current_creds().cap_permitted;
1063 resolved_elf.creds.cap_effective &= resolved_elf.creds.cap_permitted;
1064 }
1065
1066 security::bprm_creds_for_exec(self, &executable.name, &mut resolved_elf)?;
1068
1069 if self.thread_group().read().tasks_count() > 1 {
1070 track_stub!(TODO("https://fxbug.dev/297434895"), "exec on multithread process");
1071 return error!(EINVAL);
1072 }
1073
1074 if let Err(err) = self.finish_exec(locked, path, resolved_elf, writable_creds) {
1076 log_warn!("unrecoverable error in exec: {err:?}");
1077
1078 send_standard_signal(locked, self, SignalInfo::forced(SIGSEGV));
1079 return Err(err);
1080 }
1081
1082 self.ptrace_event(locked, PtraceOptions::TRACEEXEC, self.task.tid as u64);
1083 self.signal_vfork();
1084 self.task.thread_group.sync_syscall_log_level();
1085
1086 Ok(())
1087 }
1088
1089 fn finish_exec(
1093 &mut self,
1094 locked: &mut Locked<Unlocked>,
1095 path: CString,
1096 resolved_elf: ResolvedElf,
1097 writable_creds: CurrentTaskCredentialsWriteGuard,
1098 ) -> Result<(), Errno> {
1099 self.notify_robust_list();
1103
1104 let mm = {
1106 let new_mm = MemoryManager::exec(
1107 self.thread_group().root_vmar.unowned(),
1108 self.mm().ok(),
1109 resolved_elf.file.name.to_passive(),
1110 resolved_elf.arch_width,
1111 )?;
1112 self.running_state().mm.update(Some(new_mm.clone()));
1113 new_mm
1114 };
1115 self.running_state().files.unshare();
1136 self.running_state().files.exec(locked, self);
1137
1138 {
1139 let mut state = self.write();
1140
1141 let dumpable =
1150 if resolved_elf.secure_exec { DumpPolicy::Disable } else { DumpPolicy::User };
1151 *mm.dumpable.lock(locked) = dumpable;
1152
1153 state.set_sigaltstack(None);
1154 state.robust_list_head = RobustListHeadPtr::null(self);
1155 }
1164
1165 security::bprm_committing_creds(locked, self, &resolved_elf)?;
1166
1167 let new_creds = Arc::new(resolved_elf.creds.clone());
1168 writable_creds.update(self, new_creds);
1169
1170 let start_info = load_executable(self, resolved_elf, &path)?;
1171
1172 let regs: zx_restricted_state_t = start_info.into();
1173 self.thread_state.registers.load(regs);
1174 self.thread_state.extended_pstate.reset();
1175 self.thread_group().signal_actions.reset_for_exec();
1176
1177 {
1179 let mut thread_group_state = self.thread_group().write();
1180 thread_group_state.exit_signal = Some(SIGCHLD);
1181 for (_, weak_child) in &mut thread_group_state.children {
1182 if let Some(child) = weak_child.upgrade() {
1183 let mut child_state = child.write();
1184 child_state.exit_signal = Some(SIGCHLD);
1185 }
1186 }
1187 }
1188
1189 security::bprm_committed_creds(locked, self)?;
1190
1191 self.thread_group().write().did_exec = true;
1192
1193 self.set_command_name(TaskCommand::from_path_bytes(path.to_bytes()));
1194
1195 Ok(())
1196 }
1197
1198 pub fn set_command_name(&self, new_name: TaskCommand) {
1199 self.task.set_command_name(new_name.clone());
1201 let leader_command = self.thread_group().read().leader_command();
1202 starnix_logging::set_current_task_info(
1203 new_name,
1204 leader_command,
1205 self.thread_group().leader,
1206 self.tid,
1207 );
1208 }
1209
1210 pub fn add_seccomp_filter(
1211 &mut self,
1212 locked: &mut Locked<Unlocked>,
1213 code: Vec<sock_filter>,
1214 flags: u32,
1215 ) -> Result<SyscallResult, Errno> {
1216 let new_filter = Arc::new(SeccompFilter::from_cbpf(
1217 &code,
1218 self.thread_group().next_seccomp_filter_id.add(1),
1219 flags & SECCOMP_FILTER_FLAG_LOG != 0,
1220 )?);
1221
1222 let mut maybe_fd: Option<FdNumber> = None;
1223
1224 if flags & SECCOMP_FILTER_FLAG_NEW_LISTENER != 0 {
1225 maybe_fd = Some(SeccompFilterContainer::create_listener(locked, self)?);
1226 }
1227
1228 let state = self.thread_group().write();
1231
1232 if flags & SECCOMP_FILTER_FLAG_TSYNC != 0 {
1233 let mut filters: SeccompFilterContainer = self.read().seccomp_filters.clone();
1239
1240 let tasks = state.tasks();
1244 for task in &tasks {
1245 if task.tid == self.tid {
1246 continue;
1247 }
1248 let other_task_state = task.read();
1249
1250 if task.seccomp_filter_state.get() == SeccompStateValue::Strict {
1252 return Self::seccomp_tsync_error(task.tid, flags);
1253 }
1254
1255 if !other_task_state.seccomp_filters.can_sync_to(&filters) {
1257 return Self::seccomp_tsync_error(task.tid, flags);
1258 }
1259 }
1260
1261 filters.add_filter(new_filter, code.len() as u16)?;
1263
1264 for task in &tasks {
1265 let mut other_task_state = task.write();
1266
1267 other_task_state.enable_no_new_privs();
1268 other_task_state.seccomp_filters = filters.clone();
1269 task.set_seccomp_state(SeccompStateValue::UserDefined)?;
1270 }
1271 } else {
1272 let mut task_state = self.task.write();
1273
1274 task_state.seccomp_filters.add_filter(new_filter, code.len() as u16)?;
1275 self.set_seccomp_state(SeccompStateValue::UserDefined)?;
1276 }
1277
1278 if let Some(fd) = maybe_fd { Ok(fd.into()) } else { Ok(().into()) }
1279 }
1280
1281 pub fn run_seccomp_filters(
1282 &mut self,
1283 locked: &mut Locked<Unlocked>,
1284 syscall: &Syscall,
1285 ) -> Option<Result<SyscallResult, Errno>> {
1286 if self.seccomp_filter_state.get() == SeccompStateValue::Strict {
1289 return SeccompState::do_strict(locked, self, syscall);
1290 }
1291
1292 let result = self.task.read().seccomp_filters.run_all(self, syscall);
1294
1295 SeccompState::do_user_defined(locked, result, self, syscall)
1296 }
1297
1298 fn seccomp_tsync_error(id: i32, flags: u32) -> Result<SyscallResult, Errno> {
1299 if flags & SECCOMP_FILTER_FLAG_TSYNC_ESRCH != 0 { error!(ESRCH) } else { Ok(id.into()) }
1305 }
1306
1307 pub fn notify_robust_list(&self) {
1313 let task_state = self.write();
1314 let robust_list_addr = task_state.robust_list_head.addr();
1315 if robust_list_addr == UserAddress::NULL {
1316 return;
1318 }
1319 let robust_list_res = self.read_multi_arch_object(task_state.robust_list_head);
1320
1321 let head = if let Ok(head) = robust_list_res {
1322 head
1323 } else {
1324 return;
1325 };
1326
1327 let offset = head.futex_offset;
1328
1329 let mut entries_count = 0;
1330 let mut curr_ptr = head.list.next;
1331 while curr_ptr.addr() != robust_list_addr.into() && entries_count < ROBUST_LIST_LIMIT {
1332 let curr_ref = self.read_multi_arch_object(curr_ptr);
1333
1334 let curr = if let Ok(curr) = curr_ref {
1335 curr
1336 } else {
1337 return;
1338 };
1339
1340 let Some(futex_base) = curr_ptr.addr().checked_add_signed(offset) else {
1341 return;
1342 };
1343
1344 let futex_addr = match FutexAddress::try_from(futex_base) {
1345 Ok(addr) => addr,
1346 Err(_) => {
1347 return;
1348 }
1349 };
1350
1351 let Ok(mm) = self.mm() else {
1352 log_error!("Asked to notify robust list futexes in system task.");
1353 return;
1354 };
1355 let futex = if let Ok(futex) = mm.atomic_load_u32_relaxed(futex_addr) {
1356 futex
1357 } else {
1358 return;
1359 };
1360
1361 if (futex & FUTEX_TID_MASK) as i32 == self.tid {
1362 let owner_died = FUTEX_OWNER_DIED | futex;
1363 if mm.atomic_store_u32_relaxed(futex_addr, owner_died).is_err() {
1364 return;
1365 }
1366 }
1367 curr_ptr = curr.next;
1368 entries_count += 1;
1369 }
1370 }
1371
1372 pub fn get_seccomp_notifier(&mut self) -> Option<SeccompNotifierHandle> {
1374 self.task.write().seccomp_filters.notifier.clone()
1375 }
1376
1377 pub fn set_seccomp_notifier(&mut self, notifier: Option<SeccompNotifierHandle>) {
1378 self.task.write().seccomp_filters.notifier = notifier;
1379 }
1380
1381 pub(crate) fn handle_page_fault(
1382 &self,
1383 locked: &mut Locked<Unlocked>,
1384 decoded: PageFaultExceptionReport,
1385 status: zx::Status,
1386 ) -> ExceptionResult {
1387 if let Ok(mm) = self.mm() {
1388 mm.handle_page_fault(locked, decoded, status)
1389 } else {
1390 panic!(
1391 "system task is handling a major page fault status={:?}, report={:?}",
1392 status, decoded
1393 );
1394 }
1395 }
1396
1397 pub fn process_exception(
1399 &self,
1400 locked: &mut Locked<Unlocked>,
1401 report: &zx::ExceptionReport,
1402 ) -> ExceptionResult {
1403 if let Some(result) = handle_hardware_exception(locked, self, report) {
1404 return result;
1405 }
1406
1407 match report.ty {
1408 zx::ExceptionType::General => {
1409 log_error!("Unrecognized general exception: {:?}", report);
1410 ExceptionResult::Signal(SignalInfo::kernel(SIGILL))
1411 }
1412 zx::ExceptionType::ProcessNameChanged => {
1413 log_error!("Received unexpected process name changed exception");
1414 ExceptionResult::Handled
1415 }
1416 zx::ExceptionType::ProcessStarting
1417 | zx::ExceptionType::ThreadStarting
1418 | zx::ExceptionType::ThreadExiting => {
1419 log_error!("Received unexpected task lifecycle exception");
1420 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1421 }
1422 zx::ExceptionType::PolicyError(policy_code) => {
1423 log_error!(policy_code:?; "Received Zircon policy error exception");
1424 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1425 }
1426 zx::ExceptionType::UnknownUserGenerated { code, data } => {
1427 log_error!(code:?, data:?; "Received unexpected unknown user generated exception");
1428 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1429 }
1430 zx::ExceptionType::Unknown { ty, code, data } => {
1431 log_error!(ty:?, code:?, data:?; "Received unexpected exception");
1432 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1433 }
1434 _ => {
1435 log_error!("Received unknown zircon exception: {:?}", report.ty);
1436 ExceptionResult::Signal(SignalInfo::kernel(SIGSYS))
1437 }
1438 }
1439 }
1440
1441 pub fn clone_task<L>(
1451 &self,
1452 locked: &mut Locked<L>,
1453 flags: u64,
1454 child_exit_signal: Option<Signal>,
1455 user_parent_tid: UserRef<pid_t>,
1456 user_child_tid: UserRef<pid_t>,
1457 user_pidfd: UserRef<FdNumber>,
1458 ) -> Result<TaskBuilder, Errno>
1459 where
1460 L: LockBefore<MmDumpable>,
1461 L: LockBefore<TaskRelease>,
1462 L: LockBefore<ProcessGroupState>,
1463 {
1464 const IMPLEMENTED_FLAGS: u64 = ((CLONE_VM
1465 | CLONE_FS
1466 | CLONE_FILES
1467 | CLONE_SIGHAND
1468 | CLONE_THREAD
1469 | CLONE_SYSVSEM
1470 | CLONE_SETTLS
1471 | CLONE_PARENT
1472 | CLONE_PARENT_SETTID
1473 | CLONE_PIDFD
1474 | CLONE_CHILD_CLEARTID
1475 | CLONE_CHILD_SETTID
1476 | CLONE_VFORK
1477 | CLONE_NEWUTS
1478 | CLONE_PTRACE) as u64)
1479 | CLONE_CLEAR_SIGHAND;
1480
1481 const VALID_FLAGS: u64 = (CLONE_INTO_CGROUP << 1) - 1;
1486
1487 let clone_files = flags & (CLONE_FILES as u64) != 0;
1490 let clone_fs = flags & (CLONE_FS as u64) != 0;
1491 let clone_parent = flags & (CLONE_PARENT as u64) != 0;
1492 let clone_parent_settid = flags & (CLONE_PARENT_SETTID as u64) != 0;
1493 let clone_pidfd = flags & (CLONE_PIDFD as u64) != 0;
1494 let clone_child_cleartid = flags & (CLONE_CHILD_CLEARTID as u64) != 0;
1495 let clone_child_settid = flags & (CLONE_CHILD_SETTID as u64) != 0;
1496 let clone_sysvsem = flags & (CLONE_SYSVSEM as u64) != 0;
1497 let clone_ptrace = flags & (CLONE_PTRACE as u64) != 0;
1498 let clone_thread = flags & (CLONE_THREAD as u64) != 0;
1499 let clone_vm = flags & (CLONE_VM as u64) != 0;
1500 let clone_sighand = flags & (CLONE_SIGHAND as u64) != 0;
1501 let clone_vfork = flags & (CLONE_VFORK as u64) != 0;
1502 let clone_newuts = flags & (CLONE_NEWUTS as u64) != 0;
1503 let clone_into_cgroup = flags & CLONE_INTO_CGROUP != 0;
1504 let clone_clear_sighand = flags & (CLONE_CLEAR_SIGHAND as u64) != 0;
1505
1506 if clone_ptrace {
1507 track_stub!(TODO("https://fxbug.dev/322874630"), "CLONE_PTRACE");
1508 }
1509
1510 if clone_sysvsem {
1511 track_stub!(TODO("https://fxbug.dev/322875185"), "CLONE_SYSVSEM");
1512 }
1513
1514 if clone_into_cgroup {
1515 track_stub!(TODO("https://fxbug.dev/403612570"), "CLONE_INTO_CGROUP");
1516 }
1517
1518 if clone_sighand && !clone_vm {
1519 return error!(EINVAL);
1520 }
1521 if clone_clear_sighand && clone_sighand {
1522 return error!(EINVAL);
1523 }
1524 if clone_thread && !clone_sighand {
1525 return error!(EINVAL);
1526 }
1527
1528 if clone_pidfd && clone_thread {
1529 return error!(EINVAL);
1530 }
1531 if clone_pidfd && clone_parent_settid && user_parent_tid.addr() == user_pidfd.addr() {
1532 return error!(EINVAL);
1535 }
1536
1537 if flags & !VALID_FLAGS != 0 {
1538 return error!(EINVAL);
1539 }
1540
1541 if clone_vm && !clone_thread {
1542 if !clone_vfork {
1553 track_stub!(
1554 TODO("https://fxbug.dev/322875227"),
1555 "CLONE_VM without CLONE_THREAD or CLONE_VFORK"
1556 );
1557 }
1558 } else if clone_thread && !clone_vm {
1559 track_stub!(TODO("https://fxbug.dev/322875167"), "CLONE_THREAD without CLONE_VM");
1560 return error!(ENOSYS);
1561 }
1562
1563 if flags & !IMPLEMENTED_FLAGS != 0 {
1564 track_stub!(
1565 TODO("https://fxbug.dev/322875130"),
1566 "clone unknown flags",
1567 flags & !IMPLEMENTED_FLAGS
1568 );
1569 return error!(ENOSYS);
1570 }
1571
1572 let fs = if clone_fs { self.fs() } else { self.fs().fork() };
1573 let files = if clone_files {
1574 self.running_state().files.clone()
1575 } else {
1576 self.running_state().files.fork()
1577 };
1578
1579 let kernel = self.kernel();
1580
1581 let mut pids = kernel.pids.write();
1582
1583 let mut cgroup2_pid_table = kernel.cgroups.lock_cgroup2_pid_table();
1587 let child_kernel_signals = cgroup2_pid_table
1589 .maybe_create_freeze_signal(self.thread_group())
1590 .into_iter()
1591 .collect::<VecDeque<_>>();
1592
1593 let pid;
1594 let command;
1595 let creds;
1596 let scheduler_state;
1597 let no_new_privs;
1598 let seccomp_filters;
1599 let robust_list_head = RobustListHeadPtr::null(self);
1600 let child_signal_mask;
1601 let timerslack_ns;
1602 let uts_ns;
1603
1604 let TaskInfo { thread_group, memory_manager } = {
1605 let weak_original_parent;
1608 let original_parent;
1609
1610 let thread_group_state = {
1612 let thread_group_state = self.thread_group().write();
1613 if clone_parent {
1614 weak_original_parent =
1617 thread_group_state.parent.clone().ok_or_else(|| errno!(EINVAL))?;
1618 std::mem::drop(thread_group_state);
1619 original_parent = weak_original_parent.upgrade();
1620 original_parent.write()
1621 } else {
1622 thread_group_state
1623 }
1624 };
1625
1626 let state = self.read();
1627
1628 no_new_privs = state.no_new_privs();
1629 seccomp_filters = state.seccomp_filters.clone();
1630 child_signal_mask = state.signal_mask();
1631
1632 pid = pids.allocate_pid();
1633 command = self.command();
1634 creds = self.current_creds().clone();
1635 scheduler_state = state.scheduler_state.fork();
1636 timerslack_ns = state.timerslack_ns;
1637
1638 uts_ns = if clone_newuts {
1639 security::check_task_capable(self, CAP_SYS_ADMIN)?;
1640 state.uts_ns.read().fork()
1641 } else {
1642 state.uts_ns.clone()
1643 };
1644
1645 if clone_thread {
1646 TaskInfo {
1647 thread_group: self.thread_group().clone(),
1648 memory_manager: self.mm().ok(),
1649 }
1650 } else {
1651 std::mem::drop(state);
1655 let signal_actions = if clone_sighand {
1656 self.thread_group().signal_actions.clone()
1657 } else if clone_clear_sighand {
1658 let actions = self.thread_group().signal_actions.fork();
1659 actions.reset_for_exec();
1660 actions
1661 } else {
1662 self.thread_group().signal_actions.fork()
1663 };
1664 let process_group = thread_group_state.process_group.clone();
1665
1666 let task_info = {
1667 fuchsia_trace::duration!(CATEGORY_STARNIX, "create_zircon_process");
1668 create_zircon_process(
1669 locked,
1670 kernel,
1671 Some(thread_group_state),
1672 pid,
1673 child_exit_signal,
1674 process_group,
1675 signal_actions,
1676 command.clone(),
1677 )?
1678 };
1679
1680 cgroup2_pid_table.inherit_cgroup(self.thread_group(), &task_info.thread_group);
1681
1682 task_info
1683 }
1684 };
1685
1686 std::mem::drop(cgroup2_pid_table);
1691
1692 let vfork_event = if clone_vfork { Some(Arc::new(zx::Event::create())) } else { None };
1694
1695 let abstract_socket_namespace;
1698 let abstract_vsock_namespace;
1699 {
1700 let running_state = self.running_state();
1701 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
1702 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
1703 }
1704
1705 let mut child = TaskBuilder::new(Task::new(
1706 pid,
1707 command,
1708 thread_group,
1709 files,
1710 memory_manager,
1711 fs,
1712 creds,
1713 abstract_socket_namespace,
1714 abstract_vsock_namespace,
1715 child_signal_mask,
1716 child_kernel_signals,
1717 vfork_event,
1718 scheduler_state,
1719 uts_ns,
1720 no_new_privs,
1721 SeccompState::from(&self.seccomp_filter_state),
1722 seccomp_filters,
1723 robust_list_head,
1724 timerslack_ns,
1725 ));
1726
1727 release_on_error!(child, locked, {
1728 pids.add_task(Arc::clone(&child.task));
1732 std::mem::drop(pids);
1733
1734 #[cfg(any(test, debug_assertions))]
1738 {
1739 if !clone_thread {
1742 let _l1 = self.thread_group().read();
1743 let _l2 = child.thread_group().read();
1744 }
1745 }
1746
1747 if clone_thread {
1748 self.thread_group().add(Arc::clone(&child.task))?;
1749 } else {
1750 child.thread_group().add(Arc::clone(&child.task))?;
1751
1752 let mut child_state = child.write();
1758 let state = self.read();
1759 child_state.set_sigaltstack(state.sigaltstack());
1760 child_state.set_signal_mask(state.signal_mask());
1761 }
1762
1763 if !clone_vm {
1764 assert!(!clone_thread);
1767 let child_mm = MemoryManager::snapshot_of(
1768 locked,
1769 &self.mm()?,
1770 child.thread_group.root_vmar.unowned(),
1771 self.thread_state.arch_width(),
1772 )?;
1773 child.running_state()?.mm.update(Some(child_mm));
1774 }
1775
1776 if clone_parent_settid {
1777 self.write_object(user_parent_tid, &child.tid)?;
1778 }
1779
1780 if clone_child_cleartid {
1781 child.write().clear_child_tid = user_child_tid;
1782 }
1783
1784 if clone_child_settid {
1785 child.write_object(user_child_tid, &child.tid)?;
1786 }
1787
1788 if clone_pidfd {
1789 let locked = locked.cast_locked::<TaskRelease>();
1790 let file = new_pidfd(
1791 locked,
1792 self,
1793 child.thread_group(),
1794 &*child.mm()?,
1795 OpenFlags::empty(),
1796 );
1797 let pidfd = self.add_file(locked, file, FdFlags::CLOEXEC)?;
1798 self.write_object(user_pidfd, &pidfd)?;
1799 }
1800
1801 if clone_vm && !clone_thread {
1805 let child_mm = MemoryManager::snapshot_of(
1806 locked,
1807 &self.mm()?,
1808 child.thread_group.root_vmar.unowned(),
1809 self.thread_state.arch_width(),
1810 )?;
1811 child.running_state()?.mm.update(Some(child_mm));
1812 }
1813
1814 child.thread_state = self.thread_state.snapshot::<HeapRegs>();
1815 Ok(())
1816 });
1817
1818 #[cfg(any(test, debug_assertions))]
1821 {
1822 let _l1 = child.thread_group().read();
1823 let _l2 = child.read();
1824 }
1825
1826 Ok(child)
1827 }
1828
1829 pub fn set_stopped_and_notify(&self, stopped: StopState, siginfo: Option<SignalInfo>) {
1832 let maybe_signal_info = {
1833 let mut state = self.write();
1834 state.copy_state_from(self);
1835 state.set_stopped(stopped, siginfo, Some(self), None);
1836 state.prepare_signal_info(stopped)
1837 };
1838
1839 if let Some((tracer, signal_info)) = maybe_signal_info {
1840 if let Some(tracer) = tracer.upgrade() {
1841 tracer.write().send_signal(signal_info);
1842 }
1843 }
1844
1845 if !stopped.is_in_progress() {
1846 let parent = self.thread_group().read().parent.clone();
1847 if let Some(parent) = parent {
1848 parent
1849 .upgrade()
1850 .write()
1851 .lifecycle_waiters
1852 .notify_value(ThreadGroupLifecycleWaitValue::ChildStatus);
1853 }
1854 }
1855 }
1856
1857 pub fn block_if_stopped(&mut self, locked: &mut Locked<Unlocked>) -> bool {
1864 if self.finalize_stop_state() {
1865 self.block_while_stopped(locked);
1866 true
1867 } else {
1868 false
1869 }
1870 }
1871
1872 fn finalize_stop_state(&mut self) -> bool {
1875 let stopped = self.load_stopped();
1876
1877 if !stopped.is_stopping_or_stopped() {
1878 let captured_state = self.write().take_captured_state();
1880 if let Some(captured) = captured_state {
1881 if captured.dirty {
1882 self.thread_state.replace_registers(&captured.thread_state);
1883 }
1884 }
1885 }
1886
1887 if self.thread_group().set_stopped(StopState::GroupStopped, None, true)
1890 == StopState::GroupStopped
1891 {
1892 let signal = self.thread_group().read().last_signal.clone();
1893 let event = Some(PtraceEventData::new_from_event(PtraceEvent::Stop, 0));
1895 self.write().set_stopped(StopState::GroupStopped, signal, Some(self), event);
1896 return true;
1897 }
1898
1899 if stopped.is_stopping_or_stopped() {
1901 if let Ok(stopped) = stopped.finalize() {
1902 self.set_stopped_and_notify(stopped, None);
1903 }
1904 return true;
1905 }
1906
1907 false
1908 }
1909
1910 fn block_while_stopped(&mut self, locked: &mut Locked<Unlocked>) {
1913 let waiter = Waiter::with_options(WaiterOptions::IGNORE_SIGNALS);
1914 loop {
1915 if self.is_exitted() {
1918 self.thread_group().set_stopped(StopState::ForceAwake, None, false);
1919 self.write().set_stopped(StopState::ForceAwake, None, Some(self), None);
1920 return;
1921 }
1922
1923 if self.wake_or_wait_until_unstopped_async(&waiter) {
1924 return;
1925 }
1926
1927 let _: Result<(), Errno> = waiter.wait(locked, self);
1929
1930 self.finalize_stop_state();
1933 }
1934 }
1935
1936 pub fn get_ptrace_core_state_for_clone(
1939 &mut self,
1940 clone_args: &clone_args,
1941 ) -> (PtraceOptions, Option<PtraceCoreState>) {
1942 let state = self.write();
1943 if let Some(ptrace) = &state.ptrace {
1944 ptrace.get_core_state_for_clone(clone_args)
1945 } else {
1946 (PtraceOptions::empty(), None)
1947 }
1948 }
1949
1950 pub fn ptrace_event(
1958 &mut self,
1959 locked: &mut Locked<Unlocked>,
1960 trace_kind: PtraceOptions,
1961 msg: u64,
1962 ) {
1963 if !trace_kind.is_empty() {
1964 {
1965 let mut state = self.write();
1966 if let Some(ptrace) = &mut state.ptrace {
1967 if !ptrace.has_option(trace_kind) {
1968 if trace_kind == PtraceOptions::TRACEEXEC && !ptrace.is_seized() {
1971 send_signal_first(locked, self, state, SignalInfo::kernel(SIGTRAP));
1973 }
1974
1975 return;
1976 }
1977 let ptrace_event = PtraceEvent::from_option(&trace_kind) as u32;
1978 let siginfo = SignalInfo::with_detail(
1979 SIGTRAP,
1980 ((ptrace_event << 8) | SIGTRAP.number()) as i32,
1981 SignalDetail::None,
1982 );
1983 state.set_stopped(
1984 StopState::PtraceEventStopping,
1985 Some(siginfo),
1986 None,
1987 Some(PtraceEventData::new(trace_kind, msg)),
1988 );
1989 } else {
1990 return;
1991 }
1992 }
1993 self.block_if_stopped(locked);
1994 }
1995 }
1996
1997 pub fn kill_thread_group(&mut self, locked: &mut Locked<Unlocked>, exit_status: ExitStatus) {
2000 self.ptrace_event(
2001 locked,
2002 PtraceOptions::TRACEEXIT,
2003 exit_status.signal_info_status() as u64,
2004 );
2005 self.thread_group().kill(locked, exit_status, None);
2006 }
2007
2008 pub fn clone_task_builder_for_test<L>(
2011 &self,
2012 locked: &mut Locked<L>,
2013 flags: u64,
2014 exit_signal: Option<Signal>,
2015 ) -> TaskBuilder
2016 where
2017 L: LockBefore<MmDumpable>,
2018 L: LockBefore<TaskRelease>,
2019 L: LockBefore<ProcessGroupState>,
2020 {
2021 let result = self
2022 .clone_task(
2023 locked,
2024 flags,
2025 exit_signal,
2026 UserRef::default(),
2027 UserRef::default(),
2028 UserRef::default(),
2029 )
2030 .expect("failed to create task in test");
2031 result.task.write().set_spawned();
2032 result
2033 }
2034
2035 pub fn clone_task_for_test<L>(
2038 &self,
2039 locked: &mut Locked<L>,
2040 flags: u64,
2041 exit_signal: Option<Signal>,
2042 ) -> crate::testing::AutoReleasableTask
2043 where
2044 L: LockBefore<MmDumpable>,
2045 L: LockBefore<TaskRelease>,
2046 L: LockBefore<ProcessGroupState>,
2047 {
2048 self.clone_task_builder_for_test(locked, flags, exit_signal).into()
2049 }
2050
2051 pub fn check_ptrace_access_mode<L>(
2053 &self,
2054 locked: &mut Locked<L>,
2055 mode: PtraceAccessMode,
2056 target: &Task,
2057 ) -> Result<(), Errno>
2058 where
2059 L: LockBefore<MmDumpable>,
2060 {
2061 if self.thread_group().leader == target.thread_group().leader {
2064 return Ok(());
2065 }
2066
2067 let (uid, gid) = if mode.contains(PTRACE_MODE_FSCREDS) {
2079 let fscred = self.current_creds().as_fscred();
2080 (fscred.uid, fscred.gid)
2081 } else if mode.contains(PTRACE_MODE_REALCREDS) {
2082 let creds = self.current_creds();
2083 (creds.uid, creds.gid)
2084 } else {
2085 unreachable!();
2086 };
2087
2088 let target_creds = target.persistent_info.lock_creds();
2098 if !(target_creds.uid == uid
2099 && target_creds.euid == uid
2100 && target_creds.saved_uid == uid
2101 && target_creds.gid == gid
2102 && target_creds.egid == gid
2103 && target_creds.saved_gid == gid)
2104 {
2105 security::check_task_capable(self, CAP_SYS_PTRACE)?;
2106 }
2107
2108 let dumpable = *target.mm()?.dumpable.lock(locked);
2114 match dumpable {
2115 DumpPolicy::User => (),
2116 DumpPolicy::Disable => security::check_task_capable(self, CAP_SYS_PTRACE)?,
2117 }
2118
2119 security::ptrace_access_check(self, target, mode)?;
2122
2123 Ok(())
2126 }
2127
2128 pub fn can_signal(
2129 &self,
2130 target: &Task,
2131 unchecked_signal: UncheckedSignal,
2132 ) -> Result<(), Errno> {
2133 if self.thread_group == target.thread_group {
2136 return Ok(());
2137 }
2138
2139 let self_creds = self.current_creds();
2140 let target_creds = target.real_creds();
2141 if self_creds.euid == target_creds.saved_uid
2151 || self_creds.euid == target_creds.uid
2152 || self_creds.uid == target_creds.uid
2153 || self_creds.uid == target_creds.saved_uid
2154 {
2155 return Ok(());
2156 }
2157
2158 if Signal::try_from(unchecked_signal) == Ok(SIGCONT) {
2159 let target_session = target.thread_group().read().process_group.session.leader;
2160 let self_session = self.thread_group().read().process_group.session.leader;
2161 if target_session == self_session {
2162 return Ok(());
2163 }
2164 }
2165
2166 security::check_task_capable(self, CAP_KILL)
2167 }
2168}
2169
2170impl ArchSpecific for CurrentTask {
2171 fn is_arch32(&self) -> bool {
2172 self.thread_state.is_arch32()
2173 }
2174}
2175
2176impl MemoryAccessor for CurrentTask {
2177 fn read_memory<'a>(
2178 &self,
2179 addr: UserAddress,
2180 bytes: &'a mut [MaybeUninit<u8>],
2181 ) -> Result<&'a mut [u8], Errno> {
2182 self.mm()?.unified_read_memory(self, addr, bytes)
2183 }
2184
2185 fn read_memory_partial_until_null_byte<'a>(
2186 &self,
2187 addr: UserAddress,
2188 bytes: &'a mut [MaybeUninit<u8>],
2189 ) -> Result<&'a mut [u8], Errno> {
2190 self.mm()?.unified_read_memory_partial_until_null_byte(self, addr, bytes)
2191 }
2192
2193 fn read_memory_partial<'a>(
2194 &self,
2195 addr: UserAddress,
2196 bytes: &'a mut [MaybeUninit<u8>],
2197 ) -> Result<&'a mut [u8], Errno> {
2198 self.mm()?.unified_read_memory_partial(self, addr, bytes)
2199 }
2200
2201 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2202 self.mm()?.unified_write_memory(self, addr, bytes)
2203 }
2204
2205 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2206 self.mm()?.unified_write_memory_partial(self, addr, bytes)
2207 }
2208
2209 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
2210 self.mm()?.unified_zero(self, addr, length)
2211 }
2212}
2213
2214impl TaskMemoryAccessor for CurrentTask {
2215 fn maximum_valid_address(&self) -> Option<UserAddress> {
2216 self.mm().ok().map(|mm| mm.maximum_valid_user_address)
2217 }
2218}
2219
2220pub enum ExceptionResult {
2221 Handled,
2223
2224 Signal(SignalInfo),
2226}
2227
2228fn split_path(path: &FsStr) -> LookupVec<&FsStr> {
2229 path.split(|c| *c == b'/').filter(|p| !p.is_empty()).map(<&FsStr>::from).collect()
2230}
2231
2232#[cfg(test)]
2233mod tests {
2234 use crate::testing::spawn_kernel_and_run;
2235 use starnix_uapi::auth::Credentials;
2236
2237 #[::fuchsia::test]
2240 async fn test_override_creds_can_delegate_to_async_version() {
2241 spawn_kernel_and_run(async move |_, current_task| {
2242 assert_eq!(current_task.override_creds(Credentials::root(), || 0), 0);
2243 })
2244 .await;
2245 }
2246}