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