MOS Source Code
Loading...
Searching...
No Matches
execve.c
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
4#include "mos/mm/cow.h"
6#include "mos/syslog/printk.h"
7#include "mos/tasks/elf.h"
8#include "mos/tasks/process.h"
9#include "mos/tasks/signal.h"
11#include "mos/tasks/thread.h"
12
14#include <mos/types.h>
15#include <mos_stdlib.h>
16#include <mos_string.h>
17
18long process_do_execveat(process_t *process, fd_t dirfd, const char *path, const char *const argv[], const char *const envp[], int flags)
19{
20 thread_t *const thread = current_thread;
21 process_t *const proc = current_process;
22
23 MOS_ASSERT(thread->owner == process); // why
24
25 MOS_UNUSED(flags); // not implemented: AT_EMPTY_PATH, AT_SYMLINK_NOFOLLOW
26 file_t *f = vfs_openat(dirfd, path, OPEN_READ | OPEN_EXECUTE);
27 if (IS_ERR(f))
28 return PTR_ERR(f);
29
30 io_ref(&f->io);
31 elf_header_t header;
32 if (!elf_read_and_verify_executable(f, &header))
33 {
34 pr_warn("failed to read elf header");
35 io_unref(&f->io);
36 return -ENOEXEC;
37 }
38
39 // backup argv and envp
40 const char **argv_copy = NULL;
41 const char **envp_copy = NULL;
42 const char *path_copy = strdup(path);
43
44 int argc = 0;
45 while (argv && argv[argc])
46 {
47 argc++;
48 argv_copy = krealloc(argv_copy, (argc + 1) * sizeof(char *));
49 argv_copy[argc - 1] = strdup(argv[argc - 1]);
50 }
51
52 if (!argv_copy)
53 {
54 argv_copy = kmalloc(sizeof(char *) * 2);
55 argv_copy[0] = strdup(path);
56 argv_copy[1] = NULL;
57 argc = 1;
58 }
59
60 argv_copy[argc] = NULL;
61
62 int envc = 0;
63 while (envp && envp[envc])
64 {
65 envc++;
66 envp_copy = krealloc(envp_copy, (envc + 1) * sizeof(char *));
67 envp_copy[envc - 1] = strdup(envp[envc - 1]);
68 }
69
70 if (!envp_copy)
71 {
72 envp_copy = kmalloc(sizeof(char *) * 1);
73 envp_copy[0] = NULL;
74 envc = 0;
75 }
76
77 envp_copy[envc] = NULL;
78
79 // !! ====== point of no return ====== !! //
80
81 if (proc->name)
82 kfree(proc->name);
83 if (thread->name)
84 kfree(thread->name);
85
86 proc->name = strdup(f->dentry->name); // set process name to the name of the executable
87 thread->name = strdup(f->dentry->name); // set thread name to the name of the executable
88
90
91 list_foreach(thread_t, t, process->threads)
92 {
93 if (t != thread)
94 {
95 signal_send_to_thread(t, SIGKILL); // nice
96 thread_wait_for_tid(t->tid);
97 spinlock_acquire(&t->state_lock);
100 }
101 }
102
103 proc->main_thread = thread; // make current thread the only thread
106
107 // free old memory
108 spinlock_acquire(&proc->mm->mm_lock);
109 list_foreach(vmap_t, vmap, proc->mm->mmaps)
110 {
111 spinlock_acquire(&vmap->lock);
112 vmap_destroy(vmap); // no need to unlock because it's destroyed
113 }
114 spinlock_release(&proc->mm->mm_lock);
115
116 // the userspace stack for the current thread will also be freed, so we create a new one
117 if (thread->mode == THREAD_MODE_USER)
118 {
119 const size_t ustack_size = MOS_STACK_PAGES_USER * MOS_PAGE_SIZE;
121 stack_init(&thread->u_stack, (void *) stack_vmap->vaddr, ustack_size);
123 }
124
125 elf_startup_info_t startup_info = {
126 .argc = argc,
127 .argv = argv_copy,
128 .envc = envc,
129 .envp = envp_copy,
130 .auxv = { 0 },
131 .invocation = path_copy,
132 };
133
134 const bool filled = elf_do_fill_process(proc, f, header, &startup_info);
135 io_unref(&f->io);
136
137 // free old argv and envp
138 for (int i = 0; i < argc; i++)
139 kfree(argv_copy[i]);
140 kfree(argv_copy);
141 for (int i = 0; i < envc; i++)
142 kfree(envp_copy[i]);
143 kfree(envp_copy);
144 kfree(path_copy);
145
146 if (unlikely(!filled))
147 {
148 pr_emerg("failed to fill process, execve failed");
149 process_exit(proc, 0, SIGKILL);
151 }
152
153 memzero(proc->signal_info.handlers, sizeof(proc->signal_info.handlers)); // reset signal handlers
154
155 // close any files that are FD_CLOEXEC
156 for (int i = 0; i < MOS_PROCESS_MAX_OPEN_FILES; i++)
157 {
158 if (io_valid(proc->files[i].io) && (proc->files[i].flags & FD_FLAGS_CLOEXEC))
159 process_detach_fd(proc, i);
160 }
161
162 platform_regs_t *const regs = platform_thread_regs(thread);
164}
#define MOS_ASSERT(cond)
Definition assert.h:14
#define MOS_UNREACHABLE()
Definition assert.h:11
#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
vmap_t * cow_allocate_zeroed_pages(mm_context_t *handle, size_t npages, ptr_t vaddr, valloc_flags hints, vm_flags flags)
Allocate zero-on-demand pages at a specific address.
Definition cow.c:79
__nodiscard bool elf_read_and_verify_executable(file_t *file, elf_header_t *header)
Definition elf.c:338
__nodiscard bool elf_do_fill_process(process_t *proc, file_t *file, elf_header_t elf, elf_startup_info_t *info)
Definition elf.c:230
long process_do_execveat(process_t *process, fd_t dirfd, const char *path, const char *const argv[], const char *const envp[], int flags)
Definition execve.c:18
@ 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.c:8
long signal_send_to_thread(thread_t *target, signal_t signal)
Send a signal to a thread.
Definition signal.c:92
MOSAPI char * strdup(const char *src)
#define list_foreach(t, v, h)
Iterate over a list.
Definition list.h:83
void vmap_finalise_init(vmap_t *vmap, vmap_content_t content, vmap_type_t type)
Finalize the initialization of a vmap object.
Definition mm.c:257
void vmap_destroy(vmap_t *vmap)
Destroy a vmap object, and unmmap the region.
Definition mm.c:171
@ VMAP_TYPE_PRIVATE
Definition mm.h:31
@ VMAP_STACK
Definition mm.h:23
@ VALLOC_DEFAULT
Default allocation flags.
Definition paging.h:21
@ THREAD_MODE_USER
Definition task_types.h:22
file_t * vfs_openat(int fd, const char *path, open_flags flags)
Open a file at a given path.
Definition vfs.c:578
io_t * io_ref(io_t *io)
Definition io.c:73
__nodiscard bool io_valid(const io_t *io)
Definition io.c:127
io_t * io_unref(io_t *io)
Definition io.c:92
const char ** argv
Definition kmain.c:44
size_t argc
Definition kmain.c:43
#define MOS_UNUSED(x)
Definition mos_global.h:64
#define unlikely(x)
Definition mos_global.h:40
#define NULL
Definition pb_syshdr.h:46
#define current_thread
Definition platform.h:30
@ VM_USER_RW
Definition platform.h:54
#define current_process
Definition platform.h:31
#define pr_warn(fmt,...)
Definition printk.h:38
#define pr_emerg(fmt,...)
Definition printk.h:39
void process_exit(process_t *process, u8 exit_code, signal_t signal)
Definition process.c:281
bool process_detach_fd(process_t *process, fd_t fd)
Definition process.c:200
void platform_return_to_userspace(platform_regs_t *regs)
platform_regs_t * platform_thread_regs(const thread_t *thread)
void platform_context_cleanup(thread_t *thread)
#define memzero(ptr, size)
Definition rpc_client.c:40
#define spinlock_acquire(lock)
Definition spinlock.h:61
#define spinlock_release(lock)
Definition spinlock.h:62
const char * name
Definition vfs_types.h:118
fd_flags_t flags
Definition task_types.h:37
io_t * io
Definition task_types.h:36
io_t io
Definition vfs_types.h:199
dentry_t * dentry
Definition vfs_types.h:200
spinlock_t mm_lock
protects [pgd] and the [mmaps] list (the list itself, not the vmap_t objects)
Definition platform.h:81
list_head mmaps
Definition platform.h:83
sigaction_t handlers[SIGNAL_MAX_N]
signal handlers
Definition task_types.h:30
mm_context_t * mm
Definition task_types.h:59
process_signal_info_t signal_info
signal handling info
Definition task_types.h:64
const char * name
Definition task_types.h:46
list_head threads
Definition task_types.h:57
thread_t * main_thread
Definition task_types.h:56
fd_type files[MOS_PROCESS_MAX_OPEN_FILES]
Definition task_types.h:54
thread_mode mode
user-mode thread or kernel-mode
Definition task_types.h:81
downwards_stack_t u_stack
user-mode stack
Definition task_types.h:84
const char * name
Definition task_types.h:78
spinlock_t state_lock
protects the thread state
Definition task_types.h:82
process_t * owner
Definition task_types.h:79
Definition mm.h:58
ptr_t vaddr
Definition mm.h:62
void thread_destroy(thread_t *thread)
Definition thread.c:46
bool thread_wait_for_tid(tid_t tid)
Definition thread.c:175
s32 fd_t
Definition types.h:81