Added full binary path into the proc structure
authorDavide Libenzi <dlibenzi@google.com>
Thu, 22 Oct 2015 21:30:26 +0000 (14:30 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 18 Nov 2015 17:54:57 +0000 (09:54 -0800)
Added full binary path into the proc structure.
Fixed a bug where we would set the progname on the current process,
and not the new one.

Signed-off-by: Davide Libenzi <dlibenzi@google.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/env.h
kern/include/process.h
kern/include/umem.h
kern/src/process.c
kern/src/syscall.c
kern/src/umem.c

index 7163415..66fa3b3 100644 (file)
@@ -34,7 +34,16 @@ struct proc {
        spinlock_t proc_lock;
        struct user_context scp_ctx;    /* context for an SCP.  TODO: move to vc0 */
        char user[64]; /* user name */
+
+       /* This is effectively a (potentially short) version of argv[0].
+        */
        char progname[PROC_PROGNAME_SZ];
+
+       /* This is the full path of the binary which the current proc structure
+        * is tracking.
+        */
+       char *binary_path;
+
        pid_t pid;
        /* Tempting to add a struct proc *parent, but we'd need to protect the use
         * of that reference from concurrent parent-death (letting init inherit
index e6d8f7f..2aab783 100644 (file)
@@ -60,6 +60,7 @@ extern spinlock_t pid_hash_lock;
 /* Initialization */
 void proc_init(void);
 void proc_set_progname(struct proc *p, char *name);
+void proc_replace_binary_path(struct proc *p, char *path);
 void proc_init_procinfo(struct proc* p);
 void proc_init_procdata(struct proc* p);
 
index cec5ad8..108af94 100644 (file)
@@ -64,6 +64,8 @@ void user_memdup_free(struct proc *p, void *va);
 /* Same as memdup, but just does strings.  still needs memdup_freed */
 char *user_strdup(struct proc *p, const char *u_string, size_t strlen);
 char *user_strdup_errno(struct proc *p, const char *u_string, size_t strlen);
+char *copy_in_path(struct proc *p, const char *path, size_t path_l);
+void free_path(struct proc *p, char *t_path);
 void *kmalloc_errno(int len);
 bool uva_is_kva(struct proc *p, void *uva, void *kva);
 uintptr_t uva2kva(struct proc *p, void *uva);
index 317968a..7086ae3 100644 (file)
@@ -10,6 +10,7 @@
 #include <smp.h>
 #include <pmap.h>
 #include <trap.h>
+#include <umem.h>
 #include <schedule.h>
 #include <manager.h>
 #include <stdio.h>
@@ -261,6 +262,13 @@ void proc_set_progname(struct proc *p, char *name)
        strlcpy(p->progname, name, PROC_PROGNAME_SZ);
 }
 
+void proc_replace_binary_path(struct proc *p, char *path)
+{
+       if (p->binary_path)
+               free_path(p, p->binary_path);
+       p->binary_path = path;
+}
+
 /* Be sure you init'd the vcore lists before calling this. */
 void proc_init_procinfo(struct proc* p)
 {
@@ -305,7 +313,7 @@ error_t proc_alloc(struct proc **pp, struct proc *parent, int flags)
        if (!(p = kmem_cache_alloc(proc_cache, 0)))
                return -ENOMEM;
        /* zero everything by default, other specific items are set below */
-       memset(p, 0, sizeof(struct proc));
+       memset(p, 0, sizeof(*p));
 
        /* only one ref, which we pass back.  the old 'existence' ref is managed by
         * the ksched */
@@ -459,6 +467,7 @@ static void __proc_free(struct kref *kref)
 
        __vmm_struct_cleanup(p);
        p->progname[0] = 0;
+       free_path(p, p->binary_path);
        cclose(p->dot);
        cclose(p->slash);
        p->dot = p->slash = 0; /* catch bugs */
index fe6eed4..2f97695 100644 (file)
@@ -320,30 +320,6 @@ static struct proc *get_controllable_proc(struct proc *p, pid_t pid)
        return target;
 }
 
-/* Helper, copies a pathname from the process into the kernel.  Returns a string
- * on success, which you must free with free_path.  Returns 0 on failure and
- * sets errno.  On success, if you are tracing syscalls, it will store the
- * t_path in the trace data, clobbering whatever previously there. */
-static char *copy_in_path(struct proc *p, const char *path, size_t path_l)
-{
-       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-       struct systrace_record *t = pcpui->cur_kthread->trace;
-       char *t_path;
-       /* PATH_MAX includes the \0 */
-       if (unlikely(path_l > PATH_MAX)) {
-               set_errno(ENAMETOOLONG);
-               return 0;
-       }
-       t_path = user_strdup_errno(p, path, path_l);
-       if (unlikely(!t_path))
-               return 0;
-       if (unlikely(t)) {
-               t->datalen = MIN(sizeof(t->data), path_l);
-               memcpy(t->data, t_path, t->datalen);
-       }
-       return t_path;
-}
-
 static int unpack_argenv(struct argenv *argenv, size_t argenv_l,
                          int *argc_p, char ***argv_p,
                          int *envc_p, char ***envp_p)
@@ -382,12 +358,6 @@ static int unpack_argenv(struct argenv *argenv, size_t argenv_l,
        return 0;
 }
 
-/* Helper, frees a path that was allocated with copy_in_path. */
-static void free_path(struct proc *p, char *t_path)
-{
-       user_memdup_free(p, t_path);
-}
-
 /************** Utility Syscalls **************/
 
 static int sys_null(void)
@@ -558,28 +528,27 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
                return -1;
        /* TODO: 9ns support */
        program = do_file_open(t_path, O_READ, 0);
-       free_path(p, t_path);
        if (!program)
-               return -1;                      /* presumably, errno is already set */
+               goto error_user_memdup;
 
        /* Check the size of the argenv array, error out if too large. */
        if ((argenv_l < sizeof(struct argenv)) || (argenv_l > ARG_MAX)) {
                set_error(EINVAL, "The argenv array has an invalid size: %lu\n",
                                  argenv_l);
-               return -1;
+               goto error_user_memdup;
        }
        /* Copy the argenv array into a kernel buffer. Delay processing of the
         * array to load_elf(). */
        kargenv = user_memdup_errno(p, argenv, argenv_l);
        if (!kargenv) {
                set_errstr("Failed to copy in the args");
-               return -1;
+               goto error_user_memdup;
        }
        /* Unpack the argenv array into more usable variables. Integrity checking
         * done along side this as well. */
        if (unpack_argenv(kargenv, argenv_l, &argc, &argv, &envc, &envp)) {
                set_errstr("Failed to unpack the args");
-               goto early_error;
+               goto error_unpack;
        }
 
        /* TODO: need to split the proc creation, since you must load after setting
@@ -587,34 +556,37 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
        //new_p = proc_create(program, 0, 0);
        if (proc_alloc(&new_p, current, flags)) {
                set_errstr("Failed to alloc new proc");
-               goto mid_error;
+               goto error_proc_alloc;
        }
        /* close the CLOEXEC ones, even though this isn't really an exec */
        close_fdt(&new_p->open_files, TRUE);
        /* Load the elf. */
        if (load_elf(new_p, program, argc, argv, envc, envp)) {
                set_errstr("Failed to load elf");
-               goto late_error;
+               goto error_load_elf;
        }
        /* progname is argv0, which accounts for symlinks */
-       proc_set_progname(p, argc ? argv[0] : NULL);
+       proc_set_progname(new_p, argc ? argv[0] : NULL);
+       proc_replace_binary_path(new_p, t_path);
        kref_put(&program->f_kref);
        user_memdup_free(p, kargenv);
        __proc_ready(new_p);
        pid = new_p->pid;
        proc_decref(new_p);     /* give up the reference created in proc_create() */
        return pid;
-late_error:
+error_load_elf:
        set_errno(EINVAL);
        /* proc_destroy will decref once, which is for the ref created in
         * proc_create().  We don't decref again (the usual "+1 for existing"),
         * since the scheduler, which usually handles that, hasn't heard about the
         * process (via __proc_ready()). */
        proc_destroy(new_p);
-mid_error:
+error_proc_alloc:
        kref_put(&program->f_kref);
-early_error:
+error_unpack:
        user_memdup_free(p, kargenv);
+error_user_memdup:
+       free_path(p, t_path);
        return -1;
 }
 
@@ -791,6 +763,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
        t_path = copy_in_path(p, path, path_l);
        if (!t_path)
                return -1;
+       proc_replace_binary_path(p, t_path);
 
        disable_irqsave(&state);        /* protect cur_ctx */
        /* Can't exec if we don't have a current_ctx to restart (if we fail).  This
@@ -835,8 +808,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
 
        /* This could block: */
        /* TODO: 9ns support */
-       program = do_file_open(t_path, O_READ, 0);
-       free_path(p, t_path);
+       program = do_file_open(p->binary_path, O_READ, 0);
        if (!program)
                goto early_error;
        if (!is_valid_elf(program)) {
index 70865d0..46b066e 100644 (file)
@@ -208,3 +208,34 @@ uintptr_t uva2kva(struct proc *p, void *uva)
                return 0;
        return (uintptr_t)page2kva(u_page) + offset;
 }
+
+/* Helper, copies a pathname from the process into the kernel.  Returns a string
+ * on success, which you must free with free_path.  Returns 0 on failure and
+ * sets errno.  On success, if you are tracing syscalls, it will store the
+ * t_path in the trace data, clobbering whatever previously there. */
+char *copy_in_path(struct proc *p, const char *path, size_t path_l)
+{
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+       struct systrace_record *t = pcpui->cur_kthread->trace;
+       char *t_path;
+
+       /* PATH_MAX includes the \0 */
+       if (path_l > PATH_MAX) {
+               set_errno(ENAMETOOLONG);
+               return 0;
+       }
+       t_path = user_strdup_errno(p, path, path_l);
+       if (!t_path)
+               return 0;
+       if (t) {
+               t->datalen = MIN(sizeof(t->data), path_l);
+               memcpy(t->data, t_path, t->datalen);
+       }
+       return t_path;
+}
+
+/* Helper, frees a path that was allocated with copy_in_path. */
+void free_path(struct proc *p, char *t_path)
+{
+       user_memdup_free(p, t_path);
+}