kernel: Implement ELF auxinfo entry type AT_EXECPATH
authorJohn Marino <draco@marino.st>
Sat, 23 Apr 2011 19:44:10 +0000 (21:44 +0200)
committerJohn Marino <draco@marino.st>
Thu, 28 Apr 2011 20:06:31 +0000 (22:06 +0200)
Refer to issue 2005.
The new RTLD can optionally use AT_EXECPATH for some of its new
functionality such as libmap.conf and dynamic token expansion.
In the absence of this kernel support, RTLD has a fallback
mechanism that works most of the time, but using it takes a
performance hit.

This patch was tested for some time by various people prior to
the 2.10 branch being created.

sys/kern/imgact_elf.c
sys/kern/kern_exec.c
sys/sys/imgact.h

index 72d3ef1..099d1db 100644 (file)
@@ -926,6 +926,8 @@ elf_freebsd_fixup(register_t **stack_base, struct image_params *imgp)
        AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
        AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
        AUXARGS_ENTRY(pos, AT_BASE, args->base);
+       if (imgp->execpathp != 0)
+               AUXARGS_ENTRY(pos, AT_EXECPATH, imgp->execpathp);
        AUXARGS_ENTRY(pos, AT_NULL, 0);
 
        kfree(imgp->auxargs, M_TEMP);
index 6174a93..f27d4e1 100644 (file)
@@ -24,7 +24,6 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_exec.c,v 1.107.2.15 2002/07/30 15:40:46 nectar Exp $
- * $DragonFly: src/sys/kern/kern_exec.c,v 1.64 2008/10/26 04:29:19 sephe Exp $
  */
 
 #include <sys/param.h>
@@ -222,6 +221,8 @@ kern_execve(struct nlookupdata *nd, struct image_args *args)
        imgp->vp = NULL;
        imgp->firstpage = NULL;
        imgp->ps_strings = 0;
+       imgp->execpath = imgp->freepath = NULL;
+       imgp->execpathp = 0;
        imgp->image_header = NULL;
 
 interpret:
@@ -311,6 +312,18 @@ interpret:
                goto interpret;
        }
 
+       /*
+        * Do the best to calculate the full path to the image file
+        */
+       if (imgp->auxargs != NULL &&
+          ((args->fname != NULL && args->fname[0] == '/') ||
+           vn_fullpath(imgp->proc,
+                       imgp->vp,
+                       &imgp->execpath,
+                       &imgp->freepath,
+                       0) != 0))
+               imgp->execpath = args->fname;
+
        /*
         * Copy out strings (args and env) and initialize stack base
         */
@@ -533,6 +546,9 @@ exec_fail_dealloc:
                return (0);
        }
 
+       if (imgp->freepath)
+               kfree(imgp->freepath, M_TEMP);
+
 exec_fail:
        /*
         * we're done here, clear P_INEXEC if we were the ones that
@@ -894,12 +910,17 @@ exec_copyout_strings(struct image_params *imgp)
        char *stringp, *destp;
        register_t *stack_base;
        struct ps_strings *arginfo;
+       size_t execpath_len;
        int szsigcode;
 
        /*
         * Calculate string base and vector table pointers.
         * Also deal with signal trampoline code for this exec type.
         */
+       if (imgp->execpath != NULL && imgp->auxargs != NULL)
+               execpath_len = strlen(imgp->execpath) + 1;
+       else
+               execpath_len = 0;
        arginfo = (struct ps_strings *)PS_STRINGS;
        szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
        if (stackgap_random != 0)
@@ -907,6 +928,7 @@ exec_copyout_strings(struct image_params *imgp)
        else
                sgap = 0;
        destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - sgap -
+           roundup(execpath_len, sizeof(char *)) -
            roundup((ARG_MAX - imgp->args->space), sizeof(char *));
 
        /*
@@ -916,6 +938,16 @@ exec_copyout_strings(struct image_params *imgp)
                copyout(imgp->proc->p_sysent->sv_sigcode,
                    ((caddr_t)arginfo - szsigcode), szsigcode);
 
+       /*
+        * Copy the image path for the rtld
+        */
+       if (execpath_len != 0) {
+               imgp->execpathp = (uintptr_t)arginfo
+                                 - szsigcode
+                                 - execpath_len;
+               copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len);
+       }
+
        /*
         * If we have a valid auxargs ptr, prepare some room
         * on the stack.
@@ -926,7 +958,8 @@ exec_copyout_strings(struct image_params *imgp)
         */
        if (imgp->auxargs) {
                vectp = (char **)(destp - (imgp->args->argc +
-                       imgp->args->envc + 2 + AT_COUNT * 2) * sizeof(char*));
+                       imgp->args->envc + 2 + (AT_COUNT * 2) + execpath_len) *
+                       sizeof(char*));
        } else {
                vectp = (char **)(destp - (imgp->args->argc +
                        imgp->args->envc + 2) * sizeof(char*));
index 40ca7c3..18e9f6e 100644 (file)
@@ -68,6 +68,9 @@ struct image_params {
        struct lwbuf *firstpage;        /* first page that we mapped */
        struct lwbuf firstpage_cache;
        unsigned long ps_strings; /* PS_STRINGS for BSD/OS binaries */
+       char *execpath;
+       unsigned long execpathp;
+       char *freepath;
 };
 
 #ifdef _KERNEL