MOS Source Code
Loading...
Searching...
No Matches
execve.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
4#include "mos/mm/cow.hpp"
7#include "mos/tasks/elf.hpp"
11#include "mos/tasks/thread.hpp"
12
14#include <mos/types.hpp>
15#include <mos/vector.hpp>
16#include <mos_stdlib.hpp>
17#include <mos_string.hpp>
18
19long process_do_execveat(fd_t dirfd, const char *path, const char *const argv[], const char *const envp[], int flags)
20{
21 auto thread = current_thread;
22 auto proc = current_process;
23
24 MOS_UNUSED(flags); // not implemented: AT_EMPTY_PATH, AT_SYMLINK_NOFOLLOW
25 auto f = vfs_openat(dirfd, path, OPEN_READ | OPEN_EXECUTE);
26 if (f.isErr())
27 return f.getErr();
28
29 auto file = f.get();
30
31 file->ref();
32 elf_header_t header;
33 if (!elf_read_and_verify_executable(f.get(), &header))
34 {
35 pr_warn("failed to read elf header");
36 file->unref();
37 return -ENOEXEC;
38 }
39
40 // backup argv and envp
43 mos::string path_copy = path;
44
45 int argc = 0;
46 while (argv && argv[argc])
47 {
48 argc++;
49 argv_copy.push_back(argv[argc - 1]);
50 }
51
52 if (argv_copy.empty())
53 argv_copy = { path };
54
55 int envc = 0;
56 while (envp && envp[envc])
57 {
58 envc++;
59 envp_copy.push_back(envp[envc - 1]);
60 }
61
62 // !! ====== point of no return ====== !! //
63
64 proc->name = f->dentry->name; // set process name to the name of the executable
65 thread->name = f->dentry->name; // set thread name to the name of the executable
66
67 spinlock_acquire(&thread->state_lock);
68
69 for (const auto &t : proc->thread_list)
70 {
71 if (t != thread)
72 {
73 signal_send_to_thread(t, SIGKILL); // nice
74 thread_wait_for_tid(t->tid);
75 spinlock_acquire(&t->state_lock);
78 }
79 }
80
81 proc->main_thread = thread; // make current thread the only thread
83 spinlock_release(&thread->state_lock);
84
85 // free old memory
86 spinlock_acquire(&proc->mm->mm_lock);
87 list_foreach(vmap_t, vmap, proc->mm->mmaps)
88 {
89 spinlock_acquire(&vmap->lock);
90 vmap_destroy(vmap); // no need to unlock because it's destroyed
91 }
92 spinlock_release(&proc->mm->mm_lock);
93
94 // the userspace stack for the current thread will also be freed, so we create a new one
95 if (thread->mode == THREAD_MODE_USER)
96 {
97 const size_t ustack_size = MOS_STACK_PAGES_USER * MOS_PAGE_SIZE;
98 auto stack_vmap = cow_allocate_zeroed_pages(proc->mm, ustack_size / MOS_PAGE_SIZE, MOS_ADDR_USER_STACK, VM_USER_RW);
99 if (stack_vmap.isErr())
100 {
101 pr_emerg("failed to allocate stack for new process");
102 process_exit(std::move(proc), 0, SIGKILL);
104 }
105
106 stack_init(&thread->u_stack, (void *) stack_vmap->vaddr, ustack_size);
108 }
109
110 elf_startup_info_t startup_info = {
111 .invocation = path_copy,
112 .auxv = {},
113 .argv = argv_copy,
114 .envp = envp_copy,
115 };
116
117 const bool filled = elf_do_fill_process(proc, file, header, &startup_info);
118 file->unref();
119
120 if (unlikely(!filled))
121 {
122 pr_emerg("failed to fill process, execve failed");
123 process_exit(std::move(proc), 0, SIGKILL);
125 }
126
127 memzero(proc->signal_info.handlers, sizeof(proc->signal_info.handlers)); // reset signal handlers
128
129 // close any files that are FD_CLOEXEC
130 for (int i = 0; i < MOS_PROCESS_MAX_OPEN_FILES; i++)
131 {
132 const auto &fd = proc->files[i];
133 if (IO::IsValid(fd.io) && (fd.flags & FD_FLAGS_CLOEXEC))
134 process_detach_fd(proc, i);
135 }
136
137 return 0;
138}
#define MOS_UNREACHABLE()
Definition assert.hpp:10
#define MOS_STACK_PAGES_USER
Definition autoconf.h:29
#define MOS_PROCESS_MAX_OPEN_FILES
Definition autoconf.h:26
#define MOS_ADDR_USER_STACK
Definition autoconf.h:1
#define MOS_PAGE_SIZE
Definition autoconf.h:6
uint8_t argc
Definition avr_io.c:15
auto push_back(const TItem &value) noexcept
Definition vector.hpp:143
auto empty() const noexcept
Definition vector.hpp:108
PtrResult< vmap_t > cow_allocate_zeroed_pages(MMContext *handle, size_t npages, ptr_t vaddr, VMFlags flags, bool exact=false)
Allocate zero-on-demand pages at a specific address.
Definition cow.cpp:81
bool elf_do_fill_process(Process *proc, FsBaseFile *file, elf_header_t elf, elf_startup_info_t *info)
Definition elf.cpp:232
bool elf_read_and_verify_executable(FsBaseFile *file, elf_header_t *header)
Definition elf.cpp:347
long process_do_execveat(fd_t dirfd, const char *path, const char *const argv[], const char *const envp[], int flags)
Definition execve.cpp:19
@ FD_FLAGS_CLOEXEC
Definition fs_types.h:49
@ OPEN_READ
Definition fs_types.h:28
@ OPEN_EXECUTE
Definition fs_types.h:30
MOSAPI void stack_init(downwards_stack_t *stack, void *mem_region_bottom, size_t size)
Definition stack.cpp:8
long signal_send_to_thread(Thread *target, signal_t signal)
Send a signal to a thread.
Definition signal.cpp:88
#define list_foreach(t, v, h)
Iterate over a list.
Definition list.hpp:89
void vmap_finalise_init(vmap_t *vmap, vmap_content_t content, vmap_type_t type)
Finalize the initialization of a vmap object.
Definition mm.cpp:254
void vmap_destroy(vmap_t *vmap)
Destroy a vmap object, and unmmap the region.
Definition mm.cpp:168
@ VMAP_TYPE_PRIVATE
Definition mm.hpp:33
@ VMAP_STACK
Definition mm.hpp:25
@ THREAD_MODE_USER
PtrResult< FsBaseFile > vfs_openat(int fd, mos::string_view path, OpenFlags flags)
Open a file at a given path.
Definition vfs.cpp:585
@ VM_USER_RW
Definition mm_types.hpp:26
#define MOS_UNUSED(x)
Definition mos_global.h:65
#define unlikely(x)
Definition mos_global.h:40
mos::basic_string< char > string
Definition string.hpp:395
#define current_thread
Definition platform.hpp:33
#define current_process
Definition platform.hpp:34
#define pr_warn(fmt,...)
Definition printk.hpp:38
#define pr_emerg(fmt,...)
Definition printk.hpp:39
void process_exit(Process *&&proc, u8 exit_code, signal_t signal)
Definition process.cpp:289
bool process_detach_fd(Process *process, fd_t fd)
Definition process.cpp:206
void platform_context_cleanup(Thread *thread)
#define memzero(ptr, size)
#define spinlock_acquire(lock)
Definition spinlock.hpp:64
#define spinlock_release(lock)
Definition spinlock.hpp:65
static bool IsValid(const IO *io)
Definition io.hpp:46
Definition mm.hpp:60
#define f(_fmt)
Definition syslog.hpp:160
void thread_destroy(Thread *thread)
Definition thread.cpp:52
bool thread_wait_for_tid(tid_t tid)
Definition thread.cpp:189
s32 fd_t
Definition types.h:77