Avoiding sysctl at program startup using ELF aux vector (was: concurrent sysctl implementation)

Kostik Belousov kostikbel at gmail.com
Mon Jun 28 14:49:12 UTC 2010


On Wed, Jun 23, 2010 at 11:09:59PM +0200, Jeremie Le Hen wrote:
> Hi Kostik,
> 
> This patch seems to have faded out from memory.  Is it possible to go
> forward and commit it?
I refreshed the patch. Hopefully, nobody will object, and I commit it
shortly.

> 
> Thanks,
> Regards.
> 
> On Sat, Jul 25, 2009 at 12:29:16AM +0300, Kostik Belousov wrote:
> > Below is the prototype that seems to work for me both with patched and
> > old rtld on i386. Patch also contains bits for amd64 that I did not
> > tested yet. All other arches are not buildable for now.
> > 
> > Patch completely eliminates sysctl syscalls from the rtld and libc
> > startup. Without the patch, a single run of /bin/ls did 6 sysctls,
> > with the patch, no sysctls is queried at all.
> > 
Comparing with the originally posted patch, I added support for all
architectures, tested amd64 and ia32 on amd64, and converted getpagesizes(3)
that added two more startup sysctls.

Would be nice to get a testing for at least some !x86 architectures
before the commit, I added some people who helped me in past, to the Cc:.

diff --git a/lib/libc/gen/__getosreldate.c b/lib/libc/gen/__getosreldate.c
index 7e26845..1bed6d0 100644
--- a/lib/libc/gen/__getosreldate.c
+++ b/lib/libc/gen/__getosreldate.c
@@ -29,6 +29,8 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/sysctl.h>
+#include <errno.h>
+#include <link.h>
 
 int __getosreldate(void);
 
@@ -51,7 +53,15 @@ __getosreldate(void)
 
 	if (osreldate != 0)
 		return (osreldate);
-	
+
+	if (_rtld_aux_info != NULL)
+		error = _rtld_aux_info(AT_OSRELDATE, &osreldate,
+		    sizeof(osreldate));
+	else
+		error = ENOSYS;
+	if (error == 0 && osreldate != 0)
+		return (osreldate);
+
 	oid[0] = CTL_KERN;
 	oid[1] = KERN_OSRELDATE;
 	osrel = 0;
diff --git a/lib/libc/gen/getpagesize.c b/lib/libc/gen/getpagesize.c
index d796b9d..b8f0ec1 100644
--- a/lib/libc/gen/getpagesize.c
+++ b/lib/libc/gen/getpagesize.c
@@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/sysctl.h>
 
+#include <errno.h>
+#include <link.h>
 #include <unistd.h>
 
 /*
@@ -52,13 +54,23 @@ getpagesize()
 	int mib[2]; 
 	static int value;
 	size_t size;
+	int error;
+
+	if (value != 0)
+		return (value);
+
+	if (_rtld_aux_info != NULL)
+		error = _rtld_aux_info(AT_PAGESZ, &value, sizeof(value));
+	else
+		error = ENOSYS;
+	if (error == 0 && value != 0)
+		return (value);
+
+	mib[0] = CTL_HW;
+	mib[1] = HW_PAGESIZE;
+	size = sizeof value;
+	if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
+		return (-1);
 
-	if (!value) {
-		mib[0] = CTL_HW;
-		mib[1] = HW_PAGESIZE;
-		size = sizeof value;
-		if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
-			return (-1);
-	}
 	return (value);
 }
diff --git a/lib/libc/gen/getpagesizes.c b/lib/libc/gen/getpagesizes.c
index b0de939..bfeeef8 100644
--- a/lib/libc/gen/getpagesizes.c
+++ b/lib/libc/gen/getpagesizes.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 
 #include <errno.h>
+#include <link.h>
 
 /*
  * Retrieves page size information from the system.  Specifically, returns the
@@ -51,7 +52,7 @@ getpagesizes(size_t pagesize[], int nelem)
 	static u_long ps[MAXPAGESIZES];
 	static int nops;
 	size_t size;
-	int i; 
+	int error, i;
 
 	if (nelem < 0 || (nelem > 0 && pagesize == NULL)) {
 		errno = EINVAL;
@@ -59,9 +60,16 @@ getpagesizes(size_t pagesize[], int nelem)
 	}
 	/* Cache the result of the sysctl(2). */
 	if (nops == 0) {
-		size = sizeof(ps);
-		if (sysctlbyname("hw.pagesizes", ps, &size, NULL, 0) == -1)
-			return (-1);
+		if (_rtld_aux_info != NULL)
+			error = _rtld_aux_info(AT_PAGESIZES, ps, sizeof(ps));
+		else
+			error = ENOSYS;
+		if (error != 0 || ps[0] == 0) {
+			size = sizeof(ps);
+			if (sysctlbyname("hw.pagesizes", ps, &size, NULL, 0)
+			    == -1)
+				return (-1);
+		}
 		/* Count the number of page sizes that are supported. */
 		nops = size / sizeof(ps[0]);
 		while (nops > 0 && ps[nops - 1] == 0)
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 295a168..41be6d8 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -180,6 +180,7 @@ __FBSDID("$FreeBSD$");
 
 #include <errno.h>
 #include <limits.h>
+#include <link.h>
 #include <pthread.h>
 #include <sched.h>
 #include <stdarg.h>
@@ -5348,14 +5349,23 @@ small_size2bin_init_hard(void)
 static unsigned
 malloc_ncpus(void)
 {
+	int mib[2];
 	unsigned ret;
-	size_t retlen = sizeof(ret);
-	int mib[] = {CTL_HW, HW_NCPU};
+	int error;
+	size_t len;
 
-	if (sysctl(mib, sizeof(mib) / sizeof(int), &ret, &retlen,
-	    (void *)0, 0) == -1) {
-		/* Error. */
-		ret = 1;
+	if (_rtld_aux_info != NULL)
+		error = _rtld_aux_info(AT_NCPUS, &ret, sizeof(ret));
+	else
+		error = ENOSYS;
+	if (error != 0 || ret == 0) {
+		mib[0] = CTL_HW;
+		mib[1] = HW_NCPU;
+		len = sizeof(ret);
+		if (sysctl(mib, 2, &ret, &len, (void *)NULL, 0) == -1) {
+			/* Error. */
+			ret = 1;
+		}
 	}
 
 	return (ret);
diff --git a/lib/libc/sys/stack_protector.c b/lib/libc/sys/stack_protector.c
index 14c20eb..e868d3b 100644
--- a/lib/libc/sys/stack_protector.c
+++ b/lib/libc/sys/stack_protector.c
@@ -34,6 +34,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/sysctl.h>
 #include <sys/types.h>
+#include <errno.h>
+#include <link.h>
 #include <signal.h>
 #include <string.h>
 #include <syslog.h>
@@ -54,9 +56,17 @@ __guard_setup(void)
 {
 	int mib[2];
 	size_t len;
+	int error;
 
 	if (__stack_chk_guard[0] != 0)
 		return;
+	if (_rtld_aux_info != NULL)
+		error = _rtld_aux_info(AT_CANARY, __stack_chk_guard,
+		    sizeof(__stack_chk_guard));
+	else
+		error = ENOSYS;
+	if (error == 0 && __stack_chk_guard[0] != 0)
+		return;
 
 	mib[0] = CTL_KERN;
 	mib[1] = KERN_ARND;
diff --git a/libexec/rtld-elf/Symbol.map b/libexec/rtld-elf/Symbol.map
index ce1e3e5..f45f955 100644
--- a/libexec/rtld-elf/Symbol.map
+++ b/libexec/rtld-elf/Symbol.map
@@ -24,4 +24,5 @@ FBSDprivate_1.0 {
     _rtld_free_tls;
     _rtld_atfork_pre;
     _rtld_atfork_post;
+    _rtld_aux_info;
 };
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 8082656..6c5914c 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -40,6 +40,7 @@
 #include <sys/mount.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/sysctl.h>
 #include <sys/uio.h>
 #include <sys/utsname.h>
 #include <sys/ktrace.h>
@@ -84,6 +85,9 @@ typedef struct Struct_DoneList {
  */
 static const char *basename(const char *);
 static void die(void) __dead2;
+static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **,
+    const Elf_Dyn **);
+static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *);
 static void digest_dynamic(Obj_Entry *, int);
 static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
 static Obj_Entry *dlcheck(void *);
@@ -97,7 +101,7 @@ static char *find_library(const char *, const Obj_Entry *);
 static const char *gethints(void);
 static void init_dag(Obj_Entry *);
 static void init_dag1(Obj_Entry *, Obj_Entry *, DoneList *);
-static void init_rtld(caddr_t);
+static void init_rtld(caddr_t, Elf_Auxinfo **);
 static void initlist_add_neededs(Needed_Entry *, Objlist *);
 static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *);
 static bool is_exported(const Elf_Sym *);
@@ -188,6 +192,9 @@ extern Elf_Dyn _DYNAMIC;
 #define	RTLD_IS_DYNAMIC()	(&_DYNAMIC != NULL)
 #endif
 
+static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
+static char *canary, *pagesizes;
+
 /*
  * These are the functions the dynamic linker exports to application
  * programs.  They are the only symbols the dynamic linker is willing
@@ -214,6 +221,7 @@ static func_ptr_type exports[] = {
     (func_ptr_type) &dl_iterate_phdr,
     (func_ptr_type) &_rtld_atfork_pre,
     (func_ptr_type) &_rtld_atfork_post,
+    (func_ptr_type) &_rtld_aux_info,
     NULL
 };
 
@@ -350,7 +358,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
 
     /* Initialize and relocate ourselves. */
     assert(aux_info[AT_BASE] != NULL);
-    init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr);
+    init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info);
 
     __progname = obj_rtld.path;
     argv0 = argv[0] != NULL ? argv[0] : "(null)";
@@ -737,14 +745,16 @@ die(void)
  * information in its Obj_Entry structure.
  */
 static void
-digest_dynamic(Obj_Entry *obj, int early)
+digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
+    const Elf_Dyn **dyn_soname)
 {
     const Elf_Dyn *dynp;
     Needed_Entry **needed_tail = &obj->needed;
-    const Elf_Dyn *dyn_rpath = NULL;
-    const Elf_Dyn *dyn_soname = NULL;
     int plttype = DT_REL;
 
+    *dyn_rpath = NULL;
+    *dyn_soname = NULL;
+
     obj->bind_now = false;
     for (dynp = obj->dynamic;  dynp->d_tag != DT_NULL;  dynp++) {
 	switch (dynp->d_tag) {
@@ -868,11 +878,11 @@ digest_dynamic(Obj_Entry *obj, int early)
 	     * We have to wait until later to process this, because we
 	     * might not have gotten the address of the string table yet.
 	     */
-	    dyn_rpath = dynp;
+	    *dyn_rpath = dynp;
 	    break;
 
 	case DT_SONAME:
-	    dyn_soname = dynp;
+	    *dyn_soname = dynp;
 	    break;
 
 	case DT_INIT:
@@ -961,6 +971,12 @@ digest_dynamic(Obj_Entry *obj, int early)
 	obj->pltrelasize = obj->pltrelsize;
 	obj->pltrelsize = 0;
     }
+}
+
+static void
+digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath,
+    const Elf_Dyn *dyn_soname)
+{
 
     if (obj->z_origin && obj->origin_path == NULL) {
 	obj->origin_path = xmalloc(PATH_MAX);
@@ -978,6 +994,16 @@ digest_dynamic(Obj_Entry *obj, int early)
 	object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val);
 }
 
+static void
+digest_dynamic(Obj_Entry *obj, int early)
+{
+	const Elf_Dyn *dyn_rpath;
+	const Elf_Dyn *dyn_soname;
+
+	digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname);
+	digest_dynamic2(obj, dyn_rpath, dyn_soname);
+}
+
 /*
  * Process a shared object's program header.  This is used only for the
  * main program, when the kernel has already loaded the main program
@@ -1304,9 +1330,11 @@ init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp)
  * this function is to relocate the dynamic linker.
  */
 static void
-init_rtld(caddr_t mapbase)
+init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
 {
     Obj_Entry objtmp;	/* Temporary rtld object */
+    const Elf_Dyn *dyn_rpath;
+    const Elf_Dyn *dyn_soname;
 
     /*
      * Conjure up an Obj_Entry structure for the dynamic linker.
@@ -1323,7 +1351,7 @@ init_rtld(caddr_t mapbase)
 #endif
     if (RTLD_IS_DYNAMIC()) {
 	objtmp.dynamic = rtld_dynamic(&objtmp);
-	digest_dynamic(&objtmp, 1);
+	digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname);
 	assert(objtmp.needed == NULL);
 #if !defined(__mips__)
 	/* MIPS and SH{3,5} have a bogus DT_TEXTREL. */
@@ -1344,6 +1372,23 @@ init_rtld(caddr_t mapbase)
     /* Now that non-local variables can be accesses, copy out obj_rtld. */
     memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld));
 
+    if (aux_info[AT_PAGESZ] != NULL)
+	    pagesize = aux_info[AT_PAGESZ]->a_un.a_val;
+    if (aux_info[AT_OSRELDATE] != NULL)
+	    osreldate = aux_info[AT_OSRELDATE]->a_un.a_val;
+    if (aux_info[AT_CANARY] != NULL && aux_info[AT_CANARYLEN] != NULL) {
+	    canary = aux_info[AT_CANARY]->a_un.a_ptr;
+	    canary_len = aux_info[AT_CANARYLEN]->a_un.a_val;
+    }
+    if (aux_info[AT_PAGESIZES] != NULL && aux_info[AT_PAGESIZESLEN] != NULL) {
+	    pagesizes = aux_info[AT_PAGESIZES]->a_un.a_ptr;
+	    pagesizes_len = aux_info[AT_PAGESIZESLEN]->a_un.a_val;
+    }
+    if (aux_info[AT_NCPUS] != NULL)
+	    ncpus = aux_info[AT_NCPUS]->a_un.a_val;
+
+    digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname);
+
     /* Replace the path with a dynamically allocated copy. */
     obj_rtld.path = xstrdup(PATH_RTLD);
 
@@ -3630,3 +3675,118 @@ fetch_ventry(const Obj_Entry *obj, unsigned long symnum)
     }
     return NULL;
 }
+
+static int
+__getosreldate(void)
+{
+	static int osreldate;
+	size_t len;
+	int oid[2];
+	int error, osrel;
+
+	oid[0] = CTL_KERN;
+	oid[1] = KERN_OSRELDATE;
+	osrel = 0;
+	len = sizeof(osrel);
+	error = sysctl(oid, 2, &osrel, &len, NULL, 0);
+	if (error == 0 && osrel > 0 && len == sizeof(osrel))
+		osreldate = osrel;
+	return (osreldate);
+}
+
+static int
+__getpagesize(void)
+{
+	int mib[2];
+	static int value;
+	size_t size;
+
+	mib[0] = CTL_HW;
+	mib[1] = HW_PAGESIZE;
+	size = sizeof value;
+	if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
+		return (-1);
+
+	return (value);
+}
+
+static int
+__getncpus(void)
+{
+	int mib[2];
+	size_t len;
+	int n;
+
+	mib[0] = CTL_HW;
+	mib[1] = HW_NCPU;
+	len = sizeof(ncpus);
+	if (sysctl(mib, 2, &n, &len, (void *) 0, 0) == -1)
+		n = 1;
+	return (n);
+}
+
+int
+_rtld_aux_info(int aux, void *buf, int buflen)
+{
+	int res;
+
+	switch (aux) {
+	case AT_CANARY:
+		if (canary != NULL && canary_len >= buflen) {
+			memcpy(buf, canary, buflen);
+			memset(canary, 0, canary_len);
+			canary = NULL;
+			res = 0;
+		} else
+			res = ENOENT;
+		break;
+	case AT_PAGESIZES:
+		if (pagesizes != NULL && pagesizes_len >= buflen) {
+			memcpy(buf, pagesizes, buflen);
+			res = 0;
+		} else
+			res = ENOENT;
+		break;
+
+	case AT_PAGESZ:
+		if (buflen == sizeof(int)) {
+			if (pagesize == 0)
+				pagesize = __getpagesize();
+			if (pagesize != 0) {
+				*(int *)buf = pagesize;
+				res = 0;
+			} else
+				res = ENOENT;
+		} else
+			res = EINVAL;
+		break;
+	case AT_OSRELDATE:
+		if (buflen == sizeof(int)) {
+			if (osreldate == 0)
+				osreldate = __getosreldate();
+			if (osreldate != 0) {
+				*(int *)buf = osreldate;
+				res = 0;
+			} else
+				res = ENOENT;
+		} else
+			res = EINVAL;
+		break;
+	case AT_NCPUS:
+		if (buflen == sizeof(int)) {
+			if (ncpus == 0)
+				ncpus = __getncpus();
+			if (ncpus != 0) {
+				*(int *)buf = ncpus;
+				res = 0;
+			} else
+				res = ENOENT;
+		} else
+			res = EINVAL;
+		break;
+	default:
+		res = ENOENT;
+		break;
+	}
+	return (res);
+}
diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h
index 678f5d3..1f5c754 100644
--- a/sys/amd64/include/elf.h
+++ b/sys/amd64/include/elf.h
@@ -88,8 +88,14 @@ __ElfType(Auxinfo);
 #define	AT_GID		13	/* Real gid. */
 #define	AT_EGID		14	/* Effective gid. */
 #define	AT_EXECPATH	15	/* Path to the executable. */
-
-#define	AT_COUNT	16	/* Count of defined aux entry types. */
+#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/arm/include/elf.h b/sys/arm/include/elf.h
index 0660ba6..4cb2ae3 100644
--- a/sys/arm/include/elf.h
+++ b/sys/arm/include/elf.h
@@ -76,8 +76,14 @@ __ElfType(Auxinfo);
 #define AT_GID          13      /* Real gid. */
 #define AT_EGID         14      /* Effective gid. */
 #define	AT_EXECPATH	15	/* Path to the executable. */
-
-#define AT_COUNT        16      /* Count of defined aux entry types. */
+#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. */
 
 #define	R_ARM_COUNT		33	/* Count of defined relocation types. */
 
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index f0fde2b..cc4172c 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -2524,11 +2524,13 @@ syscall32_helper_unregister(struct syscall_helper_data *sd)
 register_t *
 freebsd32_copyout_strings(struct image_params *imgp)
 {
-	int argc, envc;
+	int argc, envc, i;
 	u_int32_t *vectp;
 	char *stringp, *destp;
 	u_int32_t *stack_base;
 	struct freebsd32_ps_strings *arginfo;
+	char canary[sizeof(long) * 8];
+	int32_t pagesizes32[MAXPAGESIZES];
 	size_t execpath_len;
 	int szsigcode;
 
@@ -2543,8 +2545,10 @@ freebsd32_copyout_strings(struct image_params *imgp)
 	arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS;
 	szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
 	destp =	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
-		roundup(execpath_len, sizeof(char *)) -
-		roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
+	    roundup(execpath_len, sizeof(char *)) -
+	    roundup(sizeof(canary), sizeof(char *)) -
+	    roundup(sizeof(pagesizes32), sizeof(char *)) -
+	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
 
 	/*
 	 * install sigcode
@@ -2563,6 +2567,25 @@ freebsd32_copyout_strings(struct image_params *imgp)
 	}
 
 	/*
+	 * Prepare the canary for SSP.
+	 */
+	arc4rand(canary, sizeof(canary), 0);
+	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.
+	 */
+	for (i = 0; i < MAXPAGESIZES; i++)
+		pagesizes32[i] = (uint32_t)pagesizes[i];
+	imgp->pagesizes = (uintptr_t)arginfo - szsigcode - execpath_len -
+	    roundup(sizeof(canary), sizeof(char *)) - sizeof(pagesizes32);
+	copyout(pagesizes32, (void *)imgp->pagesizes, sizeof(pagesizes32));
+	imgp->pagesizeslen = sizeof(pagesizes32);
+
+	/*
 	 * If we have a valid auxargs ptr, prepare some room
 	 * on the stack.
 	 */
diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h
index 37ee279..6490f2a 100644
--- a/sys/i386/include/elf.h
+++ b/sys/i386/include/elf.h
@@ -90,8 +90,14 @@ __ElfType(Auxinfo);
 #define	AT_GID		13	/* Real gid. */
 #define	AT_EGID		14	/* Effective gid. */
 #define	AT_EXECPATH	15	/* Path to the executable. */
-
-#define	AT_COUNT	16	/* Count of defined aux entry types. */
+#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/ia64/include/elf.h b/sys/ia64/include/elf.h
index 27182db..ab7706b 100644
--- a/sys/ia64/include/elf.h
+++ b/sys/ia64/include/elf.h
@@ -89,8 +89,14 @@ __ElfType(Auxinfo);
 #define	AT_GID		13	/* Real gid. */
 #define	AT_EGID		14	/* Effective gid. */
 #define	AT_EXECPATH	15	/* Path to the executable. */
-
-#define	AT_COUNT	16	/* Count of defined aux entry types. */
+#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. */
 
 /*
  * Values for e_flags.
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index c48e0f5..88c64e9 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/procfs.h>
 #include <sys/resourcevar.h>
 #include <sys/sf_buf.h>
+#include <sys/smp.h>
 #include <sys/systm.h>
 #include <sys/signalvar.h>
 #include <sys/stat.h>
@@ -972,6 +973,16 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
 	AUXARGS_ENTRY(pos, AT_BASE, args->base);
 	if (imgp->execpathp != 0)
 		AUXARGS_ENTRY(pos, AT_EXECPATH, imgp->execpathp);
+	AUXARGS_ENTRY(pos, AT_OSRELDATE, imgp->proc->p_osrel);
+	if (imgp->canary != 0) {
+		AUXARGS_ENTRY(pos, AT_CANARY, imgp->canary);
+		AUXARGS_ENTRY(pos, AT_CANARYLEN, imgp->canarylen);
+	}
+	AUXARGS_ENTRY(pos, AT_NCPUS, mp_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);
 
 	free(imgp->auxargs, M_TEMP);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 149e6df..1387529 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -386,6 +386,10 @@ do_execve(td, args, mac_p)
 	imgp->args = args;
 	imgp->execpath = imgp->freepath = NULL;
 	imgp->execpathp = 0;
+	imgp->canary = 0;
+	imgp->canarylen = 0;
+	imgp->pagesizes = 0;
+	imgp->pagesizeslen = 0;
 
 #ifdef MAC
 	error = mac_execve_enter(imgp, mac_p);
@@ -1183,8 +1187,10 @@ exec_copyout_strings(imgp)
 	struct ps_strings *arginfo;
 	struct proc *p;
 	size_t execpath_len;
-	int szsigcode;
+	int szsigcode, 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.
@@ -1200,6 +1206,8 @@ exec_copyout_strings(imgp)
 		szsigcode = *(p->p_sysent->sv_szsigcode);
 	destp =	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
 	    roundup(execpath_len, sizeof(char *)) -
+	    roundup(sizeof(canary), sizeof(char *)) -
+	    roundup(szps, sizeof(char *)) -
 	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
 
 	/*
@@ -1219,6 +1227,23 @@ exec_copyout_strings(imgp)
 	}
 
 	/*
+	 * Prepare the canary for SSP.
+	 */
+	arc4rand(canary, sizeof(canary), 0);
+	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.
 	 */
@@ -1235,8 +1260,8 @@ exec_copyout_strings(imgp)
 		 * for argument of Runtime loader.
 		 */
 		vectp = (char **)(destp - (imgp->args->argc +
-		    imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
-		    sizeof(char *));
+		    imgp->args->envc + 2 + imgp->auxarg_size)
+		    * sizeof(char *));
 	} else {
 		/*
 		 * The '+ 2' is for the null pointers at the end of each of
diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h
index 2d6ca3e..2646181 100644
--- a/sys/mips/include/elf.h
+++ b/sys/mips/include/elf.h
@@ -251,8 +251,14 @@ __ElfType(Auxinfo);
 #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	16	/* Count of defined aux entry types. */
+#define	AT_COUNT	22	/* Count of defined aux entry types. */
 
 #define	ET_DYN_LOAD_ADDR 0x0120000
 
diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h
index e01488d..5ea3281 100644
--- a/sys/powerpc/include/elf.h
+++ b/sys/powerpc/include/elf.h
@@ -78,8 +78,14 @@ __ElfType(Auxinfo);
 #define	AT_ICACHEBSIZE	11	/* Instruction cache block size for the uP. */
 #define	AT_UCACHEBSIZE	12	/* Cache block size, or `0' if cache not unified. */
 #define	AT_EXECPATH	13	/* Path to the executable. */
-
-#define	AT_COUNT	14	/* Count of defined aux entry types. */
+#define	AT_CANARY	14	/* Canary for SSP */
+#define	AT_CANARYLEN	15	/* Length of the canary. */
+#define	AT_OSRELDATE	16	/* OSRELDATE. */
+#define	AT_NCPUS	17	/* Number of CPUs. */
+#define	AT_PAGESIZES	18	/* Pagesizes. */
+#define	AT_PAGESIZESLEN	19	/* Number of pagesizes. */
+
+#define	AT_COUNT	20	/* Count of defined aux entry types. */
 
 /*
  * Relocation types.
diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h
index 2a66670..0618434 100644
--- a/sys/sparc64/include/elf.h
+++ b/sys/sparc64/include/elf.h
@@ -84,8 +84,14 @@ __ElfType(Auxinfo);
 #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	16	/* Count of defined aux entry types. */
+#define	AT_COUNT	22	/* Count of defined aux entry types. */
 
 /* Define "machine" characteristics */
 #if __ELF_WORD_SIZE == 32
diff --git a/sys/sun4v/include/elf.h b/sys/sun4v/include/elf.h
index 2a66670..0618434 100644
--- a/sys/sun4v/include/elf.h
+++ b/sys/sun4v/include/elf.h
@@ -84,8 +84,14 @@ __ElfType(Auxinfo);
 #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	16	/* Count of defined aux entry types. */
+#define	AT_COUNT	22	/* Count of defined aux entry types. */
 
 /* Define "machine" characteristics */
 #if __ELF_WORD_SIZE == 32
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
index 1d1e361..3d1a049 100644
--- a/sys/sys/imgact.h
+++ b/sys/sys/imgact.h
@@ -70,6 +70,10 @@ struct image_params {
 	char *execpath;
 	unsigned long execpathp;
 	char *freepath;
+	unsigned long canary;
+	int canarylen;
+	unsigned long pagesizes;
+	int pagesizeslen;
 };
 
 #ifdef _KERNEL
diff --git a/sys/sys/link_elf.h b/sys/sys/link_elf.h
index 98840a5..30f3d75 100644
--- a/sys/sys/link_elf.h
+++ b/sys/sys/link_elf.h
@@ -92,6 +92,10 @@ __BEGIN_DECLS
 
 typedef int (*__dl_iterate_hdr_callback)(struct dl_phdr_info *, size_t, void *);
 extern int dl_iterate_phdr(__dl_iterate_hdr_callback, void *);
+extern int _rtld_aux_info(int, void *, int);
+#ifndef IN_RTLD
+#pragma weak _rtld_aux_info
+#endif
 
 __END_DECLS
 
diff --git a/tools/test/auxinfo/Makefile b/tools/test/auxinfo/Makefile
new file mode 100644
index 0000000..d0ba464
--- /dev/null
+++ b/tools/test/auxinfo/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD
+
+PROG=	auxinfo
+NO_MAN=
+WARNS?=	6
+
+.include <bsd.prog.mk>
\ No newline at end of file
diff --git a/tools/test/auxinfo/auxinfo.c b/tools/test/auxinfo/auxinfo.c
new file mode 100644
index 0000000..374bed8
--- /dev/null
+++ b/tools/test/auxinfo/auxinfo.c
@@ -0,0 +1,58 @@
+/*
+ * This file is in public domain.
+ * Written by Konstantin Belousov <kib at freebsd.org>
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/mman.h>
+#include <err.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static void
+test_pagesizes(void)
+{
+	size_t *ps;
+	int i, nelem;
+
+	nelem = getpagesizes(NULL, 0);
+	if (nelem == -1)
+		err(1, "getpagesizes(NULL, 0)");
+	ps = malloc(nelem * sizeof(size_t));
+	if (ps == NULL)
+		err(1, "malloc");
+	nelem = getpagesizes(ps, nelem);
+	if (nelem == -1)
+		err(1, "getpagesizes");
+	printf("Supported page sizes:");
+	for (i = 0; i < nelem; i++)
+		printf(" %jd", (intmax_t)ps[i]);
+	printf("\n");
+}
+
+static void
+test_pagesize(void)
+{
+
+	printf("Pagesize: %d\n", getpagesize());
+}
+
+static void
+test_osreldate(void)
+{
+
+	printf("OSRELDATE: %d\n", getosreldate());
+}
+
+int
+main(int argc __unused, char *argv[] __unused)
+{
+
+	test_pagesizes();
+	test_pagesize();
+	test_osreldate();
+	return (0);
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20100628/da26c936/attachment.pgp


More information about the freebsd-hackers mailing list