summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/init/init.c2
-rw-r--r--src/lib/libc/src/l5/spawn.c15
-rw-r--r--src/sys/arch/amd64/os/os_proc.c8
-rw-r--r--src/sys/include/sys/limits.h2
-rw-r--r--src/sys/include/sys/proc.h16
-rw-r--r--src/sys/os/os_proc.c103
6 files changed, 133 insertions, 13 deletions
diff --git a/src/cmd/init/init.c b/src/cmd/init/init.c
index befaa18..6b05bfa 100644
--- a/src/cmd/init/init.c
+++ b/src/cmd/init/init.c
@@ -34,7 +34,7 @@ void
main(void)
{
char shell_path[] = "/usr/bin/hush";
- char *argv_dmmy[] = {NULL};
+ char *argv_dmmy[] = { "/usr/bin/hush", NULL };
spawn(shell_path, argv_dmmy);
for (;;);
diff --git a/src/lib/libc/src/l5/spawn.c b/src/lib/libc/src/l5/spawn.c
index 9f0c80b..50ade53 100644
--- a/src/lib/libc/src/l5/spawn.c
+++ b/src/lib/libc/src/l5/spawn.c
@@ -28,6 +28,7 @@
*/
#include <sys/spawn.h>
+#include <sys/proc.h>
#include <sys/syscall.h>
#include <stddef.h>
#include <errno.h>
@@ -35,14 +36,24 @@
int
spawn(const char *path, char **argv)
{
+ struct penv_blk blk;
+ size_t argc = 0;
+
if (path == NULL || argv == NULL) {
return -EINVAL;
}
- /* TODO: We must handle the penv_blk */
+ /* Get the argument count */
+ while (argv[argc++] != NULL);
+ --argc;
+
+ /* Setup the penv block */
+ blk.argv = argv;
+ blk.argc = argc;
+
return syscall(
SYS_spawn,
(uintptr_t)path,
- 0
+ (uintptr_t)&blk
);
}
diff --git a/src/sys/arch/amd64/os/os_proc.c b/src/sys/arch/amd64/os/os_proc.c
index b8e7c99..f2eb2b3 100644
--- a/src/sys/arch/amd64/os/os_proc.c
+++ b/src/sys/arch/amd64/os/os_proc.c
@@ -38,6 +38,7 @@
#include <machine/gdt.h>
#include <machine/frame.h>
#include <machine/lapic.h>
+#include <os/kalloc.h>
#include <string.h>
extern struct proc g_rootproc;
@@ -237,6 +238,7 @@ md_proc_kill(struct proc *procp, int flags)
{
const size_t PSIZE = DEFAULT_PAGESIZE;
struct proc *self;
+ struct penv_blk *envblk;
struct pcore *core = this_core();
struct md_pcb *pcbp;
struct vm_range *range;
@@ -259,6 +261,12 @@ md_proc_kill(struct proc *procp, int flags)
vm_free_frame(range->pa_base, range->len / PSIZE);
}
+ if ((envblk = procp->envblk) != NULL) {
+ ptrbox_terminate(procp->envblk_box);
+ kfree(envblk->argv);
+ procp->envblk = NULL;
+ }
+
/* Release the VAS */
pcbp = &procp->pcb;
mmu_free_vas(&pcbp->vas);
diff --git a/src/sys/include/sys/limits.h b/src/sys/include/sys/limits.h
index 5e32233..180d3fc 100644
--- a/src/sys/include/sys/limits.h
+++ b/src/sys/include/sys/limits.h
@@ -37,5 +37,7 @@
#define SC_MAX 64 /* Max syscalls */
#define SCWIN_MAX 2 /* Max syscall windows */
#define FD_MAX 256 /* Max file descriptors */
+#define NARG_MAX 16 /* Max arguments */
+#define ARG_LEN 64 /* Max length per argument */
#endif /* !_SYS_LIMITS_H_ */
diff --git a/src/sys/include/sys/proc.h b/src/sys/include/sys/proc.h
index ea89d4c..5bffc3e 100644
--- a/src/sys/include/sys/proc.h
+++ b/src/sys/include/sys/proc.h
@@ -35,12 +35,15 @@
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/queue.h>
+#if defined(_KERNEL)
+#include <lib/ptrbox.h>
#include <os/mac.h>
#include <os/signal.h>
#include <os/spinlock.h>
#include <os/filedesc.h>
#include <vm/vm.h>
#include <machine/pcb.h> /* standard */
+#endif /* _KERNEL */
/*
* The stack starts here and grows down
@@ -48,18 +51,20 @@
#define STACK_TOP 0xBFFFFFFF
#define STACK_LEN 4096
-#if defined(_KERNEL)
-
/*
* Process environment block, used to store arguments
* and other information.
*
- * @pid: PID of the process that owns this block
+ * @argv: Argument vector
+ * @argc: Argument count
*/
struct penv_blk {
- pid_t pid;
+ char **argv;
+ uint16_t argc;
};
+#if defined(_KERNEL)
+
/*
* A process describes a running program image
* on the system.
@@ -81,7 +86,8 @@ struct proc {
struct md_pcb pcb;
struct syscall_domain scdom;
struct filedesc *fdtab[FD_MAX];
- struct penv_blk envblk;
+ struct penv_blk *envblk;
+ struct ptrbox *envblk_box;
mac_level_t level;
struct spinlock maplist_lock;
sigtab_t sigtab;
diff --git a/src/sys/os/os_proc.c b/src/sys/os/os_proc.c
index 14f8ceb..27ffac8 100644
--- a/src/sys/os/os_proc.c
+++ b/src/sys/os/os_proc.c
@@ -32,6 +32,7 @@
#include <sys/errno.h>
#include <sys/cdefs.h>
#include <sys/queue.h>
+#include <sys/syslog.h>
#include <sys/panic.h>
#include <sys/proc.h>
#include <sys/cpuvar.h>
@@ -47,6 +48,94 @@
static pid_t next_pid = 0;
/*
+ * Copy a process environment block from userland
+ */
+static struct penv_blk *
+penv_blk_cpy(struct proc *procp, struct penv_blk *u_blk)
+{
+ struct penv_blk *blk;
+ int error;
+ char argbuf[ARG_LEN];
+ char **u_argv;
+ char *arg;
+ uint16_t i;
+
+ if (u_blk == NULL) {
+ return NULL;
+ }
+
+ /* Allocate a kernel copy */
+ blk = kalloc(sizeof(*blk));
+ if (blk == NULL) {
+ return NULL;
+ }
+
+ /* Copy in the user side */
+ memset(blk, 0, sizeof(*blk));
+ error = copyin(u_blk, blk, sizeof(*blk));
+ if (error < 0) {
+ printf("penv_blk_cpy: bad u_blk\n");
+ kfree(blk);
+ return NULL;
+ }
+
+ /* Too many args? */
+ if (blk->argc > NARG_MAX) {
+ printf("penv_blk_cpy: argc > ARG_MAX!!\n");
+ kfree(blk);
+ return NULL;
+ }
+
+ /* Allocate a pointer box for args */
+ if (ptrbox_init(&procp->envblk_box) < 0) {
+ return NULL;
+ }
+
+ /* Allocate a new string store */
+ u_argv = blk->argv;
+ blk->argv = ptrbox_alloc(
+ sizeof(char *) * blk->argc,
+ procp->envblk_box
+ );
+ if (blk->argv == NULL) {
+ kfree(blk);
+ return NULL;
+ }
+
+ /* Dup each arg */
+ for (i = 0; i < blk->argc; ++i) {
+ error = proc_check_addr(
+ procp,
+ (uintptr_t)&u_argv[i],
+ sizeof(char *)
+ );
+
+ /* Is the address valid? */
+ if (error != 0) {
+ printf("penv_blk_cpy: bad arg pointer (%d)\n", i);
+ break;
+ }
+
+ error = copyinstr(u_argv[i], argbuf, ARG_LEN);
+ if (error < 0) {
+ printf("penv_blk_cpy: bad arg pointer (%d)\n", i);
+ break;
+ }
+
+ blk->argv[i] = ptrbox_strdup(argbuf, procp->envblk_box);
+ }
+
+ /* Cleanup on error */
+ if (error != 0) {
+ ptrbox_terminate(procp->envblk_box);
+ kfree(blk);
+ blk = NULL;
+ }
+
+ return blk;
+}
+
+/*
* Deallocate saved memory ranges
*
* @proc: Process to target
@@ -204,19 +293,22 @@ proc_spawn(const char *path, struct penv_blk *envbp)
panic("spawn: failed to arbitrate core\n");
}
- if (envbp != NULL) {
- memcpy(&proc->envblk, envbp, sizeof(proc->envblk));
- }
-
+ proc->envblk = envbp;
md_set_ip(proc, elf.entrypoint);
sched_enq(&core->scq, proc);
return proc->pid;
}
+/*
+ * ARG0: Pathname to spawn
+ * ARG1: Process environment block
+ */
scret_t
sys_spawn(struct syscall_args *scargs)
{
const char *u_path = SCARG(scargs, const char *, 0);
+ struct penv_blk *u_blk = SCARG(scargs, struct penv_blk *, 1);
+ struct penv_blk *envblk;
char buf[PATH_MAX];
int error;
@@ -225,5 +317,6 @@ sys_spawn(struct syscall_args *scargs)
return error;
}
- return proc_spawn(buf, NULL);
+ envblk = penv_blk_cpy(proc_self(), u_blk);
+ return proc_spawn(buf, envblk);
}