diff --git a/kernel/src/fs/procfs/pid/task/comm.rs b/kernel/src/fs/procfs/pid/task/comm.rs index cccc5f4f8..af3dc9813 100644 --- a/kernel/src/fs/procfs/pid/task/comm.rs +++ b/kernel/src/fs/procfs/pid/task/comm.rs @@ -26,7 +26,14 @@ impl CommFileOps { impl FileOps for CommFileOps { fn read_at(&self, offset: usize, writer: &mut VmWriter) -> Result { - let exe_path = self.0.executable_file().display_name(); + let vmar_guard = self.0.lock_vmar(); + let Some(vmar) = vmar_guard.as_ref() else { + // According to Linux behavior, return an empty string + // if the process is a zombie process. + return Ok(0); + }; + + let exe_path = vmar.process_vm().executable_file().display_name(); let last_component = exe_path.rsplit('/').next().unwrap_or(&exe_path); let mut comm = last_component.as_bytes().to_vec(); comm.truncate(TASK_COMM_LEN - 1); diff --git a/kernel/src/fs/procfs/pid/task/exe.rs b/kernel/src/fs/procfs/pid/task/exe.rs index 2616e5ba3..f6df52a56 100644 --- a/kernel/src/fs/procfs/pid/task/exe.rs +++ b/kernel/src/fs/procfs/pid/task/exe.rs @@ -29,7 +29,12 @@ impl ExeSymOps { impl SymOps for ExeSymOps { fn read_link(&self) -> Result { - let res = match self.0.executable_file() { + let vmar_guard = self.0.lock_vmar(); + let Some(vmar) = vmar_guard.as_ref() else { + return_errno_with_message!(Errno::ENOENT, "the process has exited"); + }; + + let res = match vmar.process_vm().executable_file().clone() { PathOrInode::Path(path) => SymbolicLink::Path(path), PathOrInode::Inode(inode) => SymbolicLink::Inode(inode), }; diff --git a/kernel/src/process/clone.rs b/kernel/src/process/clone.rs index 8d399fe3b..80126b7eb 100644 --- a/kernel/src/process/clone.rs +++ b/kernel/src/process/clone.rs @@ -20,7 +20,6 @@ use crate::{ fs::{ cgroupfs::CgroupMembership, file_table::{FdFlags, FileTable}, - fs_resolver::PathOrInode, thread_info::ThreadFsInfo, }, prelude::*, @@ -489,10 +488,10 @@ fn clone_child_process( let child_tid = allocate_posix_tid(); let child = { - let child_elf_file = process.executable_file(); let mut child_thread_builder = { - let child_thread_name = - ThreadName::new_from_executable_path(&child_elf_file.display_name()); + let child_thread_name = ThreadName::new_from_executable_path( + &child_vmar.process_vm().executable_file().display_name(), + ); let credentials = { let credentials = ctx.posix_thread.credentials(); @@ -517,7 +516,6 @@ fn clone_child_process( create_child_process( child_tid, - child_elf_file, child_vmar, child_resource_limits, child_nice, @@ -714,7 +712,6 @@ fn clone_ns_proxy( #[expect(clippy::too_many_arguments)] fn create_child_process( pid: Pid, - child_elf_file: PathOrInode, vmar: Arc, resource_limits: ResourceLimits, nice: Nice, @@ -725,7 +722,6 @@ fn create_child_process( ) -> Arc { let child_proc = Process::new( pid, - child_elf_file, vmar, resource_limits, nice, diff --git a/kernel/src/process/execve.rs b/kernel/src/process/execve.rs index d5ae90742..071f07888 100644 --- a/kernel/src/process/execve.rs +++ b/kernel/src/process/execve.rs @@ -142,7 +142,7 @@ fn do_execve_no_return( let elf_load_info = { let mut vmar = ctx.process.lock_vmar(); // Reset the virtual memory state. - unshare_and_renew_vmar(ctx, &mut vmar); + unshare_and_renew_vmar(ctx, &mut vmar, elf_file.clone()); // Load the binary into the process's address space program_to_load.load_to_vmar(vmar.unwrap(), fs_resolver)? }; @@ -166,7 +166,6 @@ fn do_execve_no_return( // Update the process's executable path and set the thread name let executable_path = elf_file.display_name(); *posix_thread.thread_name().lock() = ThreadName::new_from_executable_path(&executable_path); - process.set_executable_file(elf_file); // Unshare and reset signal dispositions to their default actions. unshare_and_reset_sigdispositions(process); diff --git a/kernel/src/process/process/init_proc.rs b/kernel/src/process/process/init_proc.rs index 258133f65..5e54dae60 100644 --- a/kernel/src/process/process/init_proc.rs +++ b/kernel/src/process/process/init_proc.rs @@ -47,14 +47,6 @@ fn create_init_process( argv: Vec, envp: Vec, ) -> Result> { - let pid = allocate_posix_tid(); - let process_vm = new_vmar_and_map(); - let resource_limits = ResourceLimits::default(); - let nice = Nice::default(); - let oom_score_adj = 0; - let sig_dispositions = Arc::new(Mutex::new(SigDispositions::default())); - let user_ns = UserNamespace::get_init_singleton().clone(); - let fs = { let fs_resolver = MountNamespace::get_init_singleton().new_fs_resolver(); ThreadFsInfo::new(fs_resolver) @@ -62,9 +54,16 @@ fn create_init_process( let fs_path = FsPath::try_from(executable_path)?; let elf_path = fs.resolver().read().lookup(&fs_path)?; + let pid = allocate_posix_tid(); + let process_vm = new_vmar_and_map(PathOrInode::Path(elf_path.clone())); + let resource_limits = ResourceLimits::default(); + let nice = Nice::default(); + let oom_score_adj = 0; + let sig_dispositions = Arc::new(Mutex::new(SigDispositions::default())); + let user_ns = UserNamespace::get_init_singleton().clone(); + let init_proc = Process::new( pid, - PathOrInode::Path(elf_path.clone()), process_vm, resource_limits, nice, @@ -114,11 +113,12 @@ fn create_init_task( let vmar = process.lock_vmar(); program_to_load.load_to_vmar(vmar.unwrap(), &fs_resolver)? }; - let mut user_ctx = UserContext::default(); user_ctx.set_instruction_pointer(elf_load_info.entry_point as _); user_ctx.set_stack_pointer(elf_load_info.user_stack_top as _); + let thread_name = ThreadName::new_from_executable_path(&elf_path.abs_path()); + let thread_builder = PosixThreadBuilder::new(tid, thread_name, Box::new(user_ctx), credentials) .process(Arc::downgrade(process)) .fs(Arc::new(fs)) diff --git a/kernel/src/process/process/mod.rs b/kernel/src/process/process/mod.rs index 8633ad8e5..924c2f7ea 100644 --- a/kernel/src/process/process/mod.rs +++ b/kernel/src/process/process/mod.rs @@ -21,7 +21,6 @@ use super::{ }; use crate::{ fs::cgroupfs::CgroupNode, - fs::fs_resolver::PathOrInode, prelude::*, process::{ signal::{sig_queues::SigQueues, Pollee}, @@ -87,8 +86,6 @@ pub struct Process { pub(super) pidfile_pollee: Pollee, // Mutable Part - /// The executable `PathOrInode`. - executable_file: RwLock, /// The threads tasks: Mutex, /// Process status @@ -215,10 +212,8 @@ impl Process { Some(Task::current()?.as_posix_thread()?.process()) } - #[expect(clippy::too_many_arguments)] pub(super) fn new( pid: Pid, - executable_file: PathOrInode, vmar: Arc, resource_limits: ResourceLimits, @@ -236,7 +231,6 @@ impl Process { Arc::new_cyclic(|process_ref: &Weak| Self { pid, tasks: Mutex::new(TaskSet::new()), - executable_file: RwLock::new(executable_file), vmar: Mutex::new(Some(vmar)), children_wait_queue, pidfile_pollee: Pollee::new(), @@ -294,14 +288,6 @@ impl Process { &self.tasks } - pub fn executable_file(&self) -> PathOrInode { - self.executable_file.read().clone() - } - - pub fn set_executable_file(&self, executable_file: PathOrInode) { - *self.executable_file.write() = executable_file; - } - pub fn resource_limits(&self) -> &ResourceLimits { &self.resource_limits } diff --git a/kernel/src/process/process_vm/mod.rs b/kernel/src/process/process_vm/mod.rs index c435dce1b..7b975f5e5 100644 --- a/kernel/src/process/process_vm/mod.rs +++ b/kernel/src/process/process_vm/mod.rs @@ -24,7 +24,7 @@ pub use self::{ InitStack, InitStackReader, INIT_STACK_SIZE, MAX_LEN_STRING_ARG, MAX_NR_STRING_ARGS, }, }; -use crate::{prelude::*, vm::vmar::Vmar}; +use crate::{fs::fs_resolver::PathOrInode, prelude::*, vm::vmar::Vmar}; /* * The user's virtual memory space layout looks like below. @@ -68,6 +68,8 @@ pub struct ProcessVm { init_stack: InitStack, /// The user heap heap: Heap, + /// The executable `PathOrInode`. + executable_file: PathOrInode, /// The base address for vDSO segment #[cfg(target_arch = "riscv64")] vdso_base: AtomicUsize, @@ -75,10 +77,11 @@ pub struct ProcessVm { impl ProcessVm { /// Creates a new `ProcessVm` without mapping anything. - pub fn new() -> Self { + fn new(executable_file: PathOrInode) -> Self { Self { init_stack: InitStack::new(), heap: Heap::new(), + executable_file, #[cfg(target_arch = "riscv64")] vdso_base: AtomicUsize::new(0), } @@ -89,6 +92,7 @@ impl ProcessVm { Self { init_stack: process_vm.init_stack.clone(), heap: process_vm.heap.clone(), + executable_file: process_vm.executable_file.clone(), #[cfg(target_arch = "riscv64")] vdso_base: AtomicUsize::new(process_vm.vdso_base.load(Ordering::Relaxed)), } @@ -104,6 +108,11 @@ impl ProcessVm { &self.heap } + /// Returns a reference to the executable `PathOrInode`. + pub fn executable_file(&self) -> &PathOrInode { + &self.executable_file + } + /// Maps and writes the initial portion of the main stack of a process. pub(super) fn map_and_write_init_stack( &self, @@ -194,8 +203,8 @@ impl<'a> ProcessVmarGuard<'a> { /// Creates a new VMAR and map the heap. /// /// This method should only be used to create a VMAR for the init process. -pub(super) fn new_vmar_and_map() -> Arc { - let new_vmar = Vmar::new(); +pub(super) fn new_vmar_and_map(executable_file: PathOrInode) -> Arc { + let new_vmar = Vmar::new(ProcessVm::new(executable_file)); new_vmar .process_vm() .heap() @@ -205,8 +214,12 @@ pub(super) fn new_vmar_and_map() -> Arc { } /// Unshares and renews the [`Vmar`] of the current process. -pub(super) fn unshare_and_renew_vmar(ctx: &Context, vmar: &mut ProcessVmarGuard) { - let new_vmar = Vmar::new(); +pub(super) fn unshare_and_renew_vmar( + ctx: &Context, + vmar: &mut ProcessVmarGuard, + executable_file: PathOrInode, +) { + let new_vmar = Vmar::new(ProcessVm::new(executable_file)); let guard = disable_preempt(); *ctx.thread_local.vmar().borrow_mut() = Some(new_vmar.clone()); new_vmar.vm_space().activate(); diff --git a/kernel/src/process/signal/mod.rs b/kernel/src/process/signal/mod.rs index 8f6264327..1852514ff 100644 --- a/kernel/src/process/signal/mod.rs +++ b/kernel/src/process/signal/mod.rs @@ -117,8 +117,8 @@ pub fn handle_pending_signal( match sig_default_action { SigDefaultAction::Core | SigDefaultAction::Term => { warn!( - "{:?}: terminating on signal {}", - ctx.process.executable_file().display_name(), + "PID {}: terminating on signal {}", + ctx.process.pid(), sig_num.sig_name() ); // We should exit current here, since we cannot restore a valid status from trap now. diff --git a/kernel/src/vm/vmar/mod.rs b/kernel/src/vm/vmar/mod.rs index db78508e5..803226bf6 100644 --- a/kernel/src/vm/vmar/mod.rs +++ b/kernel/src/vm/vmar/mod.rs @@ -49,11 +49,10 @@ pub struct Vmar { impl Vmar { /// Creates a new VMAR. - pub fn new() -> Arc { + pub fn new(process_vm: ProcessVm) -> Arc { let inner = VmarInner::new(); let vm_space = VmSpace::new(); let rss_counters = array::from_fn(|_| PerCpuCounter::new()); - let process_vm = ProcessVm::new(); Arc::new(Vmar { inner: RwMutex::new(inner), vm_space: Arc::new(vm_space),