1 #include <lunaix/exec.h>
3 #include <lunaix/load.h>
4 #include <lunaix/mm/mmap.h>
5 #include <lunaix/mm/valloc.h>
6 #include <lunaix/mm/vmm.h>
7 #include <lunaix/process.h>
8 #include <lunaix/sched.h>
9 #include <lunaix/spike.h>
10 #include <lunaix/status.h>
11 #include <lunaix/syscall.h>
12 #include <lunaix/syscall_utils.h>
15 #include <asm/mm_defs.h>
17 #include <klibc/string.h>
19 #define _push(ptr, type, val) \
21 ptr = __ptr(&((type*)ptr)[-1]); \
22 *((type*)ptr) = (val); \
26 __place_arrayptrs(struct exec_host* container, struct exec_arrptr* param)
31 unsigned int* reloc_off;
33 usp_top = container->stack_top;
35 ptrs = (ptr_t*)param->raw;
38 _push(usp, unsigned int, 0);
44 reloc_off = valloc(len * sizeof(unsigned int));
47 size_t el_sz, sz_acc = 0;
48 for (int i = 0; i < len; i++)
51 el_sz = strnlen(el, MAX_PARAM_SIZE) + 1;
55 strncpy((char*)usp, el, el_sz);
57 reloc_off[i] = sz_acc;
62 ptr_t* toc = (ptr_t*)(usp) - 1;
66 for (int i = 0, j = len - 1; i < len; i++, j--)
68 toc[-i] = usp_top - (ptr_t)reloc_off[j];
71 toc[-len] = (ptr_t)len;
73 usp = __ptr(&toc[-len]);
74 param->copied = __ptr(&toc[-len + 1]);
79 container->stack_top = usp;
84 exec_init_container(struct exec_host* param,
85 struct thread* thread,
90 assert(thread->ustack);
91 ptr_t ustack_top = align_stack(thread->ustack->end - 1);
92 *param = (struct exec_host)
94 .proc = thread->process,
105 .stack_top = ustack_top
110 count_length(struct exec_arrptr* param)
113 ptr_t* arr = (ptr_t*)param->raw;
120 for (; i < MAX_PARAM_LEN && arr[i]; i++);
123 return i > 0 && arr[i] ? E2BIG : 0;
127 save_process_cmd(struct proc_info* proc, struct exec_arrptr* argv)
129 ptr_t ptr, *argv_ptrs;
136 argv_ptrs = (ptr_t*)argv->copied;
137 cmd_ = (char*)valloc(argv->size);
140 while ((ptr = *argv_ptrs)) {
141 cmd_ = strcpy(cmd_, (const char*)ptr);
147 proc->cmd_len = argv->size;
152 __place_params(struct exec_host* container)
156 errno = __place_arrayptrs(container, &container->envp);
161 errno = __place_arrayptrs(container, &container->argv);
168 exec_load(struct exec_host* container, struct v_file* executable)
172 struct exec_arrptr* argv = &container->argv;
173 struct exec_arrptr* envp = &container->envp;
175 struct proc_info* proc = container->proc;
176 struct proc_mm* pvms = vmspace(proc);
179 mem_unmap_region(container->vms_mnt, pvms->heap);
183 if (!active_vms(container->vms_mnt)) {
185 TODO Setup remote mapping of user stack for later use
187 fail("not implemented");
191 if ((errno = count_length(argv))) {
195 if ((errno = count_length(envp))) {
199 errno = __place_params(container);
204 save_process_cmd(proc, argv);
205 container->inode = executable->inode;
207 errno = load_executable(&container->exe, executable);
217 exec_load_byname(struct exec_host* container, const char* filename)
220 struct v_dnode* dnode;
223 if ((errno = vfs_walk_proc(filename, &dnode, NULL, 0))) {
227 if (!check_allow_execute(dnode->inode)) {
232 if (!check_itype_any(dnode->inode, F_FILE)) {
237 if ((errno = vfs_open(dnode, &file))) {
241 errno = exec_load(container, file);
243 // It shouldn't matter which pid we passed. As the only reader is
244 // in current context and we must finish read at this point,
245 // therefore the dead-lock condition will not exist and the pid
246 // for arbitration has no use.
247 vfs_pclose(file, container->proc->pid);
254 exec_kexecve(const char* filename, const char* argv[], const char* envp[])
257 struct exec_host container;
259 assert(argv && envp);
261 exec_init_container(&container, current_thread, VMS_SELF, argv, envp);
263 errno = exec_load_byname(&container, filename);
269 ptr_t entry = container.exe.entry;
272 j_usr(container.stack_top, entry);
279 __DEFINE_LXSYSCALL3(int,
290 struct exec_host container;
292 if (!argv || !envp) {
298 &container, current_thread, VMS_SELF, argv, envp);
300 if ((errno = exec_load_byname(&container, filename))) {
304 // we will jump to new entry point (_u_start) upon syscall's
305 // return so execve 'will not return' from the perspective of it's invoker
306 exec_arch_prepare_entry(current_thread, &container);
308 // these become meaningless once execved!
309 current_thread->ustack_top = 0;
310 signal_reset_context(¤t_thread->sigctx);
311 signal_reset_registry(__current->sigreg);
313 acl = container.inode->acl;
314 if (fsacl_test(acl, suid)) {
315 current_set_euid(container.inode->uid);
318 if (fsacl_test(acl, sgid)) {
319 current_set_egid(container.inode->gid);
324 store_retval(DO_STATUS(errno));
326 // Always yield the process that want execve!
329 // this will never get executed!