Add 7 more auxinfo types to support RTLD upgrade
John Marino
dragonflybsd at marino.st
Thu Feb 17 11:55:46 PST 2011
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 */
More information about the Submit
mailing list