mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-02 07:28:21 +00:00
kernel: execve syscall
This commit is contained in:
@@ -11,6 +11,7 @@ extern syscall_getpid
|
|||||||
extern syscall_fstat
|
extern syscall_fstat
|
||||||
extern syscall_fstatat
|
extern syscall_fstatat
|
||||||
extern syscall_fork
|
extern syscall_fork
|
||||||
|
extern syscall_execve
|
||||||
syscalltab:
|
syscalltab:
|
||||||
dq syscall_print
|
dq syscall_print
|
||||||
dq syscall_mmap
|
dq syscall_mmap
|
||||||
@@ -24,7 +25,8 @@ dq syscall_getpid
|
|||||||
dq syscall_fstat
|
dq syscall_fstat
|
||||||
dq syscall_fstatat
|
dq syscall_fstatat
|
||||||
dq syscall_fork
|
dq syscall_fork
|
||||||
syscallcount equ 12
|
dq syscall_execve
|
||||||
|
syscallcount equ 13
|
||||||
section .text
|
section .text
|
||||||
global arch_syscall_entry
|
global arch_syscall_entry
|
||||||
; on entry:
|
; on entry:
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
#include <kernel/syscalls.h>
|
||||||
|
#include <kernel/alloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <kernel/vmm.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <kernel/elf.h>
|
||||||
|
#include <kernel/scheduler.h>
|
||||||
|
#include <logging.h>
|
||||||
|
|
||||||
|
static void freevec(char **v) {
|
||||||
|
char **it = v;
|
||||||
|
while (*it)
|
||||||
|
free(*it++);
|
||||||
|
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
syscallret_t syscall_execve(context_t *context, char *upath, char *uargv[], char *uenvp[]) {
|
||||||
|
syscallret_t ret = {
|
||||||
|
.ret = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO user str ops
|
||||||
|
char *path = alloc(strlen(upath) + 1);
|
||||||
|
if (path == NULL) {
|
||||||
|
ret.errno = ENOMEM;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
strcpy(path, upath);
|
||||||
|
|
||||||
|
size_t argsize = 0;
|
||||||
|
size_t envsize = 0;
|
||||||
|
char **argv = NULL;
|
||||||
|
char **envp = NULL;
|
||||||
|
vmmcontext_t *vmmctx = NULL;
|
||||||
|
vmmcontext_t *oldctx = _cpu()->vmmctx;
|
||||||
|
vnode_t *node = NULL;
|
||||||
|
vnode_t *refnode = NULL;
|
||||||
|
char *interp = NULL;
|
||||||
|
|
||||||
|
while (uargv[argsize++]);
|
||||||
|
while (uenvp[envsize++]);
|
||||||
|
|
||||||
|
argv = alloc((argsize + 1) * sizeof(char *));
|
||||||
|
envp = alloc((envsize + 1) * sizeof(char *));
|
||||||
|
|
||||||
|
if (argv == NULL || envp == NULL) {
|
||||||
|
ret.errno = ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < argsize - 1; ++i) {
|
||||||
|
argv[i] = alloc(strlen(uargv[i]) + 1);
|
||||||
|
if (argv[i] == NULL) {
|
||||||
|
ret.errno = ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
strcpy(argv[i], uargv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < envsize - 1; ++i) {
|
||||||
|
envp[i] = alloc(strlen(uenvp[i]) + 1);
|
||||||
|
if (envp[i] == NULL) {
|
||||||
|
ret.errno = ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
strcpy(envp[i], uenvp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vmmctx = vmm_newcontext();
|
||||||
|
if (vmmctx == NULL) {
|
||||||
|
ret.errno = ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
refnode = *path == '/' ? sched_getroot() : sched_getcwd();
|
||||||
|
|
||||||
|
ret.errno = vfs_lookup(&node, vfsroot, "/usr/bin/bash", NULL, 0);
|
||||||
|
if (ret.errno)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
// TODO permission and type checks and all
|
||||||
|
|
||||||
|
vmm_switchcontext(vmmctx);
|
||||||
|
|
||||||
|
auxv64list_t auxv64;
|
||||||
|
void *entry;
|
||||||
|
ret.errno = elf_load(node, NULL, &entry, &interp, &auxv64);
|
||||||
|
if (ret.errno)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (interp) {
|
||||||
|
vnode_t *interpnode;
|
||||||
|
ret.errno = vfs_open(vfsroot, interp, 0, &interpnode);
|
||||||
|
if (ret.errno)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
auxv64list_t interpauxv;
|
||||||
|
char *interpinterp = NULL;
|
||||||
|
ret.errno = elf_load(interpnode, INTERP_BASE, &entry, &interpinterp, &interpauxv);
|
||||||
|
if (ret.errno)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
__assert(interpinterp == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stack = elf_preparestack(STACK_TOP, &auxv64, argv, envp);
|
||||||
|
if (stack == NULL) {
|
||||||
|
ret.errno = ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO kill other threads and close CLOEXEC fds
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(path);
|
||||||
|
if (argv)
|
||||||
|
freevec(argv);
|
||||||
|
|
||||||
|
if (envp)
|
||||||
|
freevec(envp);
|
||||||
|
|
||||||
|
if (vmmctx && ret.errno) {
|
||||||
|
vmm_switchcontext(oldctx);
|
||||||
|
vmm_destroycontext(vmmctx, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refnode)
|
||||||
|
VOP_RELEASE(refnode);
|
||||||
|
|
||||||
|
if (node)
|
||||||
|
VOP_RELEASE(node);
|
||||||
|
|
||||||
|
if (interp)
|
||||||
|
free(interp);
|
||||||
|
|
||||||
|
if (ret.errno == 0) {
|
||||||
|
// TODO sync mmap files (unmap all lower memory first before destroying context?)
|
||||||
|
vmm_destroycontext(oldctx, 0);
|
||||||
|
CTX_SP(context) = (uint64_t)stack;
|
||||||
|
CTX_IP(context) = (uint64_t)entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("exec ret: %lu %lu\n", ret.ret, ret.errno);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -133,10 +133,10 @@ index 0000000..e5b087a
|
|||||||
+
|
+
|
||||||
diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..3961e7f
|
index 0000000..e108341
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
+++ mlibc-workdir/sysdeps/astral/generic/generic.cpp
|
||||||
@@ -0,0 +1,185 @@
|
@@ -0,0 +1,190 @@
|
||||||
+#include <bits/ensure.h>
|
+#include <bits/ensure.h>
|
||||||
+#include <mlibc/debug.hpp>
|
+#include <mlibc/debug.hpp>
|
||||||
+#include <mlibc/all-sysdeps.hpp>
|
+#include <mlibc/all-sysdeps.hpp>
|
||||||
@@ -200,6 +200,11 @@ index 0000000..3961e7f
|
|||||||
+ return 0;
|
+ return 0;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ int sys_execve(const char *path, char *const argv[], char *const envp[]) {
|
||||||
|
+ long ret = 0;
|
||||||
|
+ return syscall(SYSCALL_EXECVE, &ret, (uint64_t)path, (uint64_t)argv, (uint64_t)envp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ int sys_fork(pid_t *pid) {
|
+ int sys_fork(pid_t *pid) {
|
||||||
+ long ret = 0;
|
+ long ret = 0;
|
||||||
+ long error = syscall(SYSCALL_FORK, &ret);
|
+ long error = syscall(SYSCALL_FORK, &ret);
|
||||||
@@ -341,10 +346,10 @@ index 0000000..990eca0
|
|||||||
+#endif
|
+#endif
|
||||||
diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..16c462d
|
index 0000000..e23be0d
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
+++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h
|
||||||
@@ -0,0 +1,35 @@
|
@@ -0,0 +1,36 @@
|
||||||
+#ifndef _SYSCALL_H_INCLUDE
|
+#ifndef _SYSCALL_H_INCLUDE
|
||||||
+#define _SYSCALL_H_INCLUDE
|
+#define _SYSCALL_H_INCLUDE
|
||||||
+
|
+
|
||||||
@@ -360,6 +365,7 @@ index 0000000..16c462d
|
|||||||
+#define SYSCALL_FSTAT 9
|
+#define SYSCALL_FSTAT 9
|
||||||
+#define SYSCALL_FSTATAT 10
|
+#define SYSCALL_FSTATAT 10
|
||||||
+#define SYSCALL_FORK 11
|
+#define SYSCALL_FORK 11
|
||||||
|
+#define SYSCALL_EXECVE 12
|
||||||
+
|
+
|
||||||
+#include <stddef.h>
|
+#include <stddef.h>
|
||||||
+#include <stdint.h>
|
+#include <stdint.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user