diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 0db5911..2c3d392 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -7,7 +7,7 @@ SRCS+= __getosreldate.c __xuname.c \ _once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \ _thread_init.c \ - alarm.c arc4random.c assert.c basename.c check_utility_compat.c \ + alarm.c arc4random.c assert.c aux.c basename.c check_utility_compat.c \ clock.c closedir.c confstr.c \ crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \ dlfcn.c drand48.c erand48.c err.c errlst.c errno.c \ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 42404bc..5ba1860 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -492,4 +492,6 @@ FBSDprivate_1.0 { _libc_sem_timedwait_compat; _libc_sem_post_compat; _libc_sem_getvalue_compat; + + __elf_aux_vector; }; diff --git a/lib/libc/gen/__getosreldate.c b/lib/libc/gen/__getosreldate.c index 7e26845..980f9ef 100644 --- a/lib/libc/gen/__getosreldate.c +++ b/lib/libc/gen/__getosreldate.c @@ -29,6 +29,9 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include +#include "libc_private.h" int __getosreldate(void); @@ -51,7 +54,11 @@ __getosreldate(void) if (osreldate != 0) return (osreldate); - + + error = _elf_aux_info(AT_OSRELDATE, &osreldate, sizeof(osreldate)); + if (error == 0 && osreldate != 0) + return (osreldate); + oid[0] = CTL_KERN; oid[1] = KERN_OSRELDATE; osrel = 0; diff --git a/lib/libc/gen/aux.c b/lib/libc/gen/aux.c new file mode 100644 index 0000000..b5c079b --- /dev/null +++ b/lib/libc/gen/aux.c @@ -0,0 +1,146 @@ +/*- + * Copyright 2010 Konstantin Belousov . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include +#include +#include +#include +#include +#include "un-namespace.h" +#include "libc_private.h" + +Elf_Auxinfo *__elf_aux_vector; + +static pthread_once_t aux_once = PTHREAD_ONCE_INIT; + +static int pagesize, osreldate, canary_len, ncpus, pagesizes_len; +static char *canary, *pagesizes; + +static void +init_aux(void) +{ + Elf_Auxinfo *aux; + + for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) { + switch (aux->a_type) { + case AT_CANARY: + canary = (char *)(aux->a_un.a_ptr); + break; + + case AT_CANARYLEN: + canary_len = aux->a_un.a_val; + break; + + case AT_PAGESIZES: + pagesizes = (char *)(aux->a_un.a_ptr); + break; + + case AT_PAGESIZESLEN: + pagesizes_len = aux->a_un.a_val; + break; + + case AT_PAGESZ: + pagesize = aux->a_un.a_val; + break; + + case AT_OSRELDATE: + osreldate = aux->a_un.a_val; + break; + + case AT_NCPUS: + ncpus = aux->a_un.a_val; + break; + } + } +} + +int +_elf_aux_info(int aux, void *buf, int buflen) +{ + int res; + + if (__elf_aux_vector == NULL) + return (ENOSYS); + _once(&aux_once, init_aux); + + 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) { + *(int *)buf = pagesize; + res = 0; + } else + res = ENOENT; + } else + res = EINVAL; + break; + case AT_OSRELDATE: + if (buflen == sizeof(int)) { + 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) { + *(int *)buf = ncpus; + res = 0; + } else + res = ENOENT; + } else + res = EINVAL; + break; + default: + res = ENOENT; + break; + } + return (res); +} diff --git a/lib/libc/gen/getosreldate.c b/lib/libc/gen/getosreldate.c index 086da6a..83bdc85 100644 --- a/lib/libc/gen/getosreldate.c +++ b/lib/libc/gen/getosreldate.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -45,15 +46,17 @@ getosreldate(void) int mib[2]; size_t size; int value; - char *temp; + if ((temp = getenv("OSVERSION"))) { + value = atoi(temp); + return (value); + } + mib[0] = CTL_KERN; mib[1] = KERN_OSRELDATE; size = sizeof value; if (sysctl(mib, 2, &value, &size, NULL, 0) == -1) return (-1); - if ((temp = getenv("OSVERSION"))) - value = atoi(temp); return (value); } diff --git a/lib/libc/gen/getpagesize.c b/lib/libc/gen/getpagesize.c index d796b9d..f4b8128 100644 --- a/lib/libc/gen/getpagesize.c +++ b/lib/libc/gen/getpagesize.c @@ -36,8 +36,12 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include +#include "libc_private.h" + /* * This is unlikely to change over the running time of any * program, so we cache the result to save some syscalls. @@ -52,13 +56,20 @@ getpagesize() int mib[2]; static int value; size_t size; + int error; + + if (value != 0) + return (value); + + error = _elf_aux_info(AT_PAGESZ, &value, sizeof(value)); + 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..534fe9e 100644 --- a/lib/libc/gen/getpagesizes.c +++ b/lib/libc/gen/getpagesizes.c @@ -32,6 +32,9 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +#include "libc_private.h" /* * Retrieves page size information from the system. Specifically, returns the @@ -51,7 +54,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 +62,13 @@ getpagesizes(size_t pagesize[], int nelem) } /* Cache the result of the sysctl(2). */ if (nops == 0) { + error = _elf_aux_info(AT_PAGESIZES, ps, sizeof(ps)); size = sizeof(ps); - if (sysctlbyname("hw.pagesizes", ps, &size, NULL, 0) == -1) - return (-1); + if (error != 0 || ps[0] == 0) { + 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/include/libc_private.h b/lib/libc/include/libc_private.h index cb0b407..570441b 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -213,4 +213,6 @@ extern int __sys_fcntl(int, int, ...); /* execve() with PATH processing to implement posix_spawnp() */ int _execvpe(const char *, char * const *, char * const *); +int _elf_aux_info(int aux, void *buf, int buflen); + #endif /* _LIBC_PRIVATE_H_ */ diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index 1b581d4..f1a13ef 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -180,6 +180,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -194,6 +195,8 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" +#include "libc_private.h" + #define RB_COMPACT #include "rb.h" #if (defined(MALLOC_TCACHE) && defined(MALLOC_STATS)) @@ -5353,14 +5356,20 @@ 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}; - - if (sysctl(mib, sizeof(mib) / sizeof(int), &ret, &retlen, - (void *)0, 0) == -1) { - /* Error. */ - ret = 1; + int error; + size_t len; + + error = _elf_aux_info(AT_NCPUS, &ret, sizeof(ret)); + 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..b0108f9 100644 --- a/lib/libc/sys/stack_protector.c +++ b/lib/libc/sys/stack_protector.c @@ -34,10 +34,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include #include +#include "libc_private.h" extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); @@ -54,9 +57,14 @@ __guard_setup(void) { int mib[2]; size_t len; + int error; if (__stack_chk_guard[0] != 0) return; + error = _elf_aux_info(AT_CANARY, __stack_chk_guard, + sizeof(__stack_chk_guard)); + if (error == 0 && __stack_chk_guard[0] != 0) + return; mib[0] = CTL_KERN; mib[1] = KERN_ARND; diff --git a/libexec/rtld-elf/malloc.c b/libexec/rtld-elf/malloc.c index 3da5bee..38ae89a 100644 --- a/libexec/rtld-elf/malloc.c +++ b/libexec/rtld-elf/malloc.c @@ -48,6 +48,7 @@ static char *rcsid = "$FreeBSD$"; */ #include +#include #include #include #include @@ -152,6 +153,26 @@ botch(s) static void xprintf(const char *, ...); #define TRACE() xprintf("TRACE %s:%d\n", __FILE__, __LINE__) +extern int pagesize; + +static int +rtld_getpagesize(void) +{ + int mib[2]; + size_t size; + + if (pagesize != 0) + return (pagesize); + + mib[0] = CTL_HW; + mib[1] = HW_PAGESIZE; + size = sizeof(pagesize); + if (sysctl(mib, 2, &pagesize, &size, NULL, 0) == -1) + return (-1); + return (pagesize); + +} + void * malloc(nbytes) size_t nbytes; @@ -166,7 +187,7 @@ malloc(nbytes) * align break pointer so all data will be page aligned. */ if (pagesz == 0) { - pagesz = n = getpagesize(); + pagesz = n = rtld_getpagesize(); if (morepages(NPOOLPAGES) == 0) return NULL; op = (union overhead *)(pagepool_start); diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 8082656..a13ecb7 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -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,8 @@ extern Elf_Dyn _DYNAMIC; #define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) #endif +int osreldate, pagesize; + /* * These are the functions the dynamic linker exports to application * programs. They are the only symbols the dynamic linker is willing @@ -350,7 +356,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)"; @@ -535,6 +541,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) dbg("initializing key program variables"); set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); set_program_var("environ", env); + set_program_var("__elf_aux_vector", aux); dbg("initializing thread locks"); lockdflt_init(); @@ -737,14 +744,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 +877,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 +970,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 +993,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 +1329,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 +1350,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 +1371,13 @@ 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; + + digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname); + /* Replace the path with a dynamically allocated copy. */ obj_rtld.path = xstrdup(PATH_RTLD); @@ -3630,3 +3664,23 @@ fetch_ventry(const Obj_Entry *obj, unsigned long symnum) } return NULL; } + +int +__getosreldate(void) +{ + size_t len; + int oid[2]; + int error, osrel; + + if (osreldate != 0) + return (osreldate); + + 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); +} 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 579d81b..8da3833 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -2525,11 +2525,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; @@ -2545,8 +2547,10 @@ freebsd32_copyout_strings(struct image_params *imgp) sv_psstrings; 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 @@ -2565,6 +2569,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..e29ddfa 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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, osreldate); + 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 c60e329..c4bdb91 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -385,6 +385,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); @@ -1197,8 +1201,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. @@ -1214,6 +1220,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 *)); /* @@ -1233,6 +1241,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. */ @@ -1249,8 +1274,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 25c2506..e1a5bc8 100644 --- a/sys/powerpc/include/elf.h +++ b/sys/powerpc/include/elf.h @@ -99,8 +99,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 8c183ad..b54815f 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -71,6 +71,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/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 \ 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 + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include + +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); +}