I submitted a substantial upgrade to rtld-elf (140k patch) to Sascha last week which adds functions like dl_iterate_phdr, dlvsym, and ktraces. With the exception of libmap functionality, that patch will bring up Dragonfly's RTLD to about level with cerca 2007 FreeBSD. Sascha intends to commit the patch this weekend.

There's been a lot of neat additions added to FreeBSD's rtld in the last two years, and I've already made significant progress on a second rtld-elf upgrade. My goal is that this second patch submission will bring DragonFly's rtld-elf on par with FreeBSD's rtld-elf as it stands today.

The new code is using auxinfo elements that don't currently exist on DragonFly. The attached patch will add the following Auxinfo types:

15 EXECPATH
16 CANARY
17 CANARYLEN
18 OSRELDATE
19 NCPUS
20 PAGESIZES
21 PAGESIZESLEN

(FreeBSD also defines 23 STACKPROT which I've ignored for now)


Please review the following patch that adds these auxinfo types and a new sysctl and incorporate if deemed error-free so I may continue with my rtld-elf upgrade project.

Regards,

John


diff --git a/sys/cpu/i386/include/elf.h b/sys/cpu/i386/include/elf.h
index ae950f3..eb65225 100644
--- a/sys/cpu/i386/include/elf.h
+++ b/sys/cpu/i386/include/elf.h
@@ -73,16 +73,16 @@ typedef struct {
 __ElfType(Auxinfo);
 
 /* Values for a_type. */
-#define AT_NULL                0       /* Terminates the vector. */
-#define AT_IGNORE      1       /* Ignored entry. */
-#define AT_EXECFD      2       /* File descriptor of program to load. */
-#define AT_PHDR                3       /* Program header of program already 
loaded. */
-#define AT_PHENT       4       /* Size of each program header entry. */
-#define AT_PHNUM       5       /* Number of program header entries. */
-#define AT_PAGESZ      6       /* Page size in bytes. */
-#define AT_BASE                7       /* Interpreter's base address. */
-#define AT_FLAGS       8       /* Flags (unused for i386). */
-#define AT_ENTRY       9       /* Where interpreter should transfer control. */
+#define        AT_NULL         0       /* Terminates the vector. */
+#define        AT_IGNORE       1       /* Ignored entry. */
+#define        AT_EXECFD       2       /* File descriptor of program to load. 
*/
+#define        AT_PHDR         3       /* Program header of program already 
loaded. */
+#define        AT_PHENT        4       /* Size of each program header entry. */
+#define        AT_PHNUM        5       /* Number of program header entries. */
+#define        AT_PAGESZ       6       /* Page size in bytes. */
+#define        AT_BASE         7       /* Interpreter's base address. */
+#define        AT_FLAGS        8       /* Flags (unused for i386). */
+#define        AT_ENTRY        9       /* Where interpreter should transfer 
control. */
 
 /*
  * The following non-standard values are used for passing information
@@ -92,19 +92,26 @@ __ElfType(Auxinfo);
  * Unfortunately, these overlap the Linux non-standard values, so they
  * must not be used in the same context.
  */
-#define AT_BRK         10      /* Starting point for sbrk and brk. */
-#define AT_DEBUG       11      /* Debugging level. */
+#define        AT_BRK          10      /* Starting point for sbrk and brk. */
+#define        AT_DEBUG        11      /* Debugging level. */
 
 /*
  * The following non-standard values are used in Linux ELF binaries.
  */
-#define AT_NOTELF      10      /* Program is not ELF ?? */
-#define AT_UID         11      /* Real uid. */
-#define AT_EUID                12      /* Effective uid. */
-#define AT_GID         13      /* Real gid. */
-#define AT_EGID                14      /* Effective gid. */
-
-#define AT_COUNT       15      /* Count of defined aux entry types. */
+#define        AT_NOTELF       10      /* Program is not ELF ?? */
+#define        AT_UID          11      /* Real uid. */
+#define        AT_EUID         12      /* Effective uid. */
+#define        AT_GID          13      /* Real gid. */
+#define        AT_EGID         14      /* Effective gid. */
+#define        AT_EXECPATH     15      /* Path to the executable. */
+#define        AT_CANARY       16      /* Canary for SSP. */
+#define        AT_CANARYLEN    17      /* Length of the canary. */
+#define        AT_OSRELDATE    18      /* OSRELDATE. */
+#define        AT_NCPUS        19      /* Number of CPUs. */
+#define        AT_PAGESIZES    20      /* Pagesizes. */
+#define        AT_PAGESIZESLEN 21      /* Number of pagesizes. */
+
+#define        AT_COUNT        22      /* Count of defined aux entry types. */
 
 /*
  * Relocation types.
diff --git a/sys/cpu/i386/include/param.h b/sys/cpu/i386/include/param.h
index cb90e4b..ebcc09e 100644
--- a/sys/cpu/i386/include/param.h
+++ b/sys/cpu/i386/include/param.h
@@ -132,6 +132,8 @@
 #define IOPAGES        2               /* pages of i/o permission bitmap */
 #define UPAGES 4               /* pages of u-area */
 
+#define MAXPAGESIZES   1       /* maximum number of supported page sizes */
+
 /*
  * Ceiling on amount of swblock kva space, can be changed via
  * kern.maxswzone /boot/loader.conf variable.
diff --git a/sys/cpu/x86_64/include/elf.h b/sys/cpu/x86_64/include/elf.h
index f57d450..35022d3 100644
--- a/sys/cpu/x86_64/include/elf.h
+++ b/sys/cpu/x86_64/include/elf.h
@@ -101,8 +101,15 @@ __ElfType(Auxinfo);
 #define        AT_EUID         12      /* Effective uid. */
 #define        AT_GID          13      /* Real gid. */
 #define        AT_EGID         14      /* Effective gid. */
-
-#define        AT_COUNT        15      /* Count of defined aux entry types. */
+#define        AT_EXECPATH     15      /* Path to the executable. */
+#define        AT_CANARY       16      /* Canary for SSP */
+#define        AT_CANARYLEN    17      /* Length of the canary. */
+#define        AT_OSRELDATE    18      /* OSRELDATE. */
+#define        AT_NCPUS        19      /* Number of CPUs. */
+#define        AT_PAGESIZES    20      /* Pagesizes. */
+#define        AT_PAGESIZESLEN 21      /* Number of pagesizes. */
+
+#define        AT_COUNT        22      /* Count of defined aux entry types. */
 
 /*
  * Relocation types.
diff --git a/sys/cpu/x86_64/include/param.h b/sys/cpu/x86_64/include/param.h
index d23ae69..6776858 100644
--- a/sys/cpu/x86_64/include/param.h
+++ b/sys/cpu/x86_64/include/param.h
@@ -147,6 +147,8 @@
 #define IOPAGES        2               /* pages of i/o permission bitmap */
 #define UPAGES 4               /* pages of u-area */
 
+#define MAXPAGESIZES   1       /* maximum number of supported page sizes */
+
 /*
  * Ceiling on amount of swblock kva space, can be changed via
  * kern.maxswzone /boot/loader.conf variable.  On 64 bit machines
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 72d3ef1..d523fb5 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -118,6 +118,8 @@ static struct sysentvec elf_freebsd_sysvec = {
        MINSIGSTKSZ
 };
 
+extern int osreldate;
+
 static Elf_Brandinfo freebsd_brand_info = {
                                                ELFOSABI_FREEBSD,
                                                "FreeBSD",
@@ -926,6 +928,18 @@ 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_OSRELDATE, osreldate);
+       if (imgp->canary != 0) {
+               AUXARGS_ENTRY(pos, AT_CANARY, imgp->canary);
+               AUXARGS_ENTRY(pos, AT_CANARYLEN, imgp->canarylen);
+       }
+       AUXARGS_ENTRY(pos, AT_NCPUS, ncpus);
+       if (imgp->pagesizes != 0) {
+               AUXARGS_ENTRY(pos, AT_PAGESIZES, imgp->pagesizes);
+               AUXARGS_ENTRY(pos, AT_PAGESIZESLEN, imgp->pagesizeslen);
+       }
        AUXARGS_ENTRY(pos, AT_NULL, 0);
 
        kfree(imgp->auxargs, M_TEMP);
@@ -990,8 +1004,6 @@ static int elf_putsigs(struct lwp *, elf_buf_t);
 static int elf_puttextvp(struct proc *, elf_buf_t);
 static int elf_putfiles(struct proc *, elf_buf_t, struct file *);
 
-extern int osreldate;
-
 int
 elf_coredump(struct lwp *lp, int sig, struct vnode *vp, off_t limit)
 {
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 08e9a10..e118550 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -219,6 +219,12 @@ 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->canary = 0;
+       imgp->canarylen = 0;
+       imgp->pagesizes = 0;
+       imgp->pagesizeslen = 0;
        imgp->image_header = NULL;
 
 interpret:
@@ -309,6 +315,15 @@ 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
         */
        stack_base = exec_copyout_strings(imgp);
@@ -518,6 +533,8 @@ exec_fail_dealloc:
                return (0);
        }
 
+       kfree(imgp->freepath, M_TEMP);
+
 exec_fail:
        /*
         * we're done here, clear P_INEXEC if we were the ones that
@@ -883,12 +900,20 @@ exec_copyout_strings(struct image_params *imgp)
        char *stringp, *destp;
        register_t *stack_base;
        struct ps_strings *arginfo;
+       size_t execpath_len;
        int szsigcode;
+       int szps;
+       char canary[sizeof(long) * 8];
 
+       szps = sizeof(pagesizes[0]) * MAXPAGESIZES;
        /*
         * 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)
@@ -896,6 +921,9 @@ exec_copyout_strings(struct image_params *imgp)
        else
                sgap = 0;
        destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - sgap -
+           roundup(execpath_len, sizeof(char *)) -
+           roundup(sizeof(canary), sizeof(char *)) -
+           roundup(szps, sizeof(char *)) -
            roundup((ARG_MAX - imgp->args->space), sizeof(char *));
 
        /*
@@ -906,6 +934,32 @@ exec_copyout_strings(struct image_params *imgp)
                    ((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);
+       }
+
+       /*
+        * Prepare the canary for SSP.
+        */
+       karc4rand(canary, sizeof(canary));
+       imgp->canary = (uintptr_t)arginfo - szsigcode - execpath_len -
+           sizeof(canary);
+       copyout(canary, (void *)imgp->canary, sizeof(canary));
+       imgp->canarylen = sizeof(canary);
+
+       /*
+        * Prepare the pagesizes array.
+        */
+       imgp->pagesizes = (uintptr_t)arginfo - szsigcode - execpath_len -
+           roundup(sizeof(canary), sizeof(char *)) - szps;
+       copyout(pagesizes, (void *)imgp->pagesizes, szps);
+       imgp->pagesizeslen = szps;
+
+       /*
         * If we have a valid auxargs ptr, prepare some room
         * on the stack.
         *
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index f65425b..e64df6f 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -158,6 +158,18 @@ static char        machine_arch[] = MACHINE_ARCH;
 SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD,
     machine_arch, 0, "Cpu architecture");
 
+u_long pagesizes[MAXPAGESIZES] = { PAGE_SIZE };
+
+static int
+sysctl_hw_pagesizes(SYSCTL_HANDLER_ARGS)
+{
+       int error = SYSCTL_OUT(req, pagesizes, sizeof(pagesizes));
+       return (error);
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, pagesizes, CTLTYPE_ULONG | CTLFLAG_RD,
+    NULL, 0, sysctl_hw_pagesizes, "LU", "Supported page sizes");
+
 char hostname[MAXHOSTNAMELEN];
 
 static int
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
index 40ca7c3..6ccd48b 100644
--- a/sys/sys/imgact.h
+++ b/sys/sys/imgact.h
@@ -68,6 +68,13 @@ 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;
+       unsigned long canary;
+       int canarylen;
+       unsigned long pagesizes;
+       int pagesizeslen;
 };
 
 #ifdef _KERNEL
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index fd60dd3..f33a1ab 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -70,6 +70,7 @@ extern int selwait;           /* select timeout address */
 extern u_char curpriority;     /* priority of current process */
 
 extern long physmem;           /* physical memory */
+extern u_long pagesizes[];     /* supported page sizes */
 
 extern cdev_t dumpdev;         /* dump device */
 extern u_int64_t dumplo64;     /* block number into dumpdev, start of dump */

Reply via email to