From owner-freebsd-hackers@FreeBSD.ORG Wed Jun 23 21:10:10 2010 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 13F741065670 for ; Wed, 23 Jun 2010 21:10:10 +0000 (UTC) (envelope-from jeremie@le-hen.org) Received: from smtp5-g21.free.fr (smtp5-g21.free.fr [212.27.42.5]) by mx1.freebsd.org (Postfix) with ESMTP id 968728FC15 for ; Wed, 23 Jun 2010 21:10:06 +0000 (UTC) Received: from endor.tataz.chchile.org (unknown [82.233.239.98]) by smtp5-g21.free.fr (Postfix) with ESMTP id AC46AD480E9; Wed, 23 Jun 2010 23:10:00 +0200 (CEST) Received: from felucia.tataz.chchile.org (felucia.tataz.chchile.org [192.168.1.9]) by endor.tataz.chchile.org (Postfix) with ESMTP id 828E933CD8; Wed, 23 Jun 2010 21:09:59 +0000 (UTC) Received: by felucia.tataz.chchile.org (Postfix, from userid 1000) id 72E2EA1274; Wed, 23 Jun 2010 21:09:59 +0000 (UTC) Date: Wed, 23 Jun 2010 23:09:59 +0200 From: Jeremie Le Hen To: Kostik Belousov Message-ID: <20100623210959.GA21260@felucia.tataz.chchile.org> References: <20090508214117.GY58540@hoeg.nl> <20090509113459.GD56667@e.0x20.net> <20090509121313.GA58540@hoeg.nl> <20090724073451.GH54986@felucia.tataz.chchile.org> <20090724081842.GF55190@deviant.kiev.zoral.com.ua> <20090724115404.GI54986@felucia.tataz.chchile.org> <20090724115649.GV68469@hoeg.nl> <20090724130928.GJ54986@felucia.tataz.chchile.org> <20090724134953.GW68469@hoeg.nl> <20090724212916.GQ55190@deviant.kiev.zoral.com.ua> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20090724212916.GQ55190@deviant.kiev.zoral.com.ua> User-Agent: Mutt/1.5.20 (2009-06-14) Cc: FreeBSD Hackers Subject: Re: Avoiding sysctl at program startup using ELF aux vector (was: concurrent sysctl implementation) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Jun 2010 21:10:10 -0000 Hi Kostik, This patch seems to have faded out from memory. Is it possible to go forward and commit it? 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. > > diff --git a/lib/libc/gen/__getosreldate.c b/lib/libc/gen/__getosreldate.c > index 69aac07..6a4e5ea 100644 > --- a/lib/libc/gen/__getosreldate.c > +++ b/lib/libc/gen/__getosreldate.c > @@ -29,6 +29,8 @@ __FBSDID("$FreeBSD$"); > > #include > #include > +#include > +#include > > /* > * This is private to libc. It is intended for wrapping syscall stubs in order > @@ -49,7 +51,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 > #include > > +#include > +#include > #include > > /* > @@ -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/stdlib/malloc.c b/lib/libc/stdlib/malloc.c > index 270d641..e479abe 100644 > --- a/lib/libc/stdlib/malloc.c > +++ b/lib/libc/stdlib/malloc.c > @@ -179,6 +179,7 @@ __FBSDID("$FreeBSD$"); > > #include > #include > +#include > #include > #include > #include > @@ -4769,7 +4770,10 @@ malloc_init_hard(void) > unsigned i; > int linklen; > char buf[PATH_MAX + 1]; > + int mib[2]; > + size_t len; > const char *opts; > + int error; > > malloc_mutex_lock(&init_lock); > if (malloc_initialized) { > @@ -4782,10 +4786,11 @@ malloc_init_hard(void) > } > > /* Get number of CPUs. */ > - { > - int mib[2]; > - size_t len; > - > + if (_rtld_aux_info != NULL) > + error = _rtld_aux_info(AT_NCPUS, &ncpus, sizeof(ncpus)); > + else > + error = ENOSYS; > + if (error != 0 || ncpus == 0) { > mib[0] = CTL_HW; > mib[1] = HW_NCPU; > len = sizeof(ncpus); > diff --git a/lib/libc/sys/stack_protector.c b/lib/libc/sys/stack_protector.c > index 63beebc..571f63c 100644 > --- a/lib/libc/sys/stack_protector.c > +++ b/lib/libc/sys/stack_protector.c > @@ -34,6 +34,8 @@ __FBSDID("$FreeBSD$"); > #include > #include > #include > +#include > +#include > #include > #include > #include > @@ -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/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c > index 8a32adf..a510884 100644 > --- a/libexec/rtld-elf/amd64/reloc.c > +++ b/libexec/rtld-elf/amd64/reloc.c > @@ -113,7 +113,7 @@ init_pltgot(Obj_Entry *obj) > > /* Process the non-PLT relocations. */ > int > -reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) > +reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, bool early) > { > const Elf_Rela *relalim; > const Elf_Rela *rela; > @@ -125,9 +125,13 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) > * The dynamic loader may be called from a thread, we have > * limited amounts of stack available so we cannot use alloca(). > */ > - cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); > - if (cache == MAP_FAILED) > + if (early) > cache = NULL; > + else { > + cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); > + if (cache == MAP_FAILED) > + cache = NULL; > + } > > relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize); > for (rela = obj->rela; rela < relalim; rela++) { > diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c > index ec83bff..2913d78 100644 > --- a/libexec/rtld-elf/i386/reloc.c > +++ b/libexec/rtld-elf/i386/reloc.c > @@ -114,7 +114,7 @@ init_pltgot(Obj_Entry *obj) > > /* Process the non-PLT relocations. */ > int > -reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) > +reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, bool early) > { > const Elf_Rel *rellim; > const Elf_Rel *rel; > @@ -126,9 +126,13 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) > * The dynamic loader may be called from a thread, we have > * limited amounts of stack available so we cannot use alloca(). > */ > - cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); > - if (cache == MAP_FAILED) > + if (early) > cache = NULL; > + else { > + cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); > + if (cache == MAP_FAILED) > + cache = NULL; > + } > > rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize); > for (rel = obj->rel; rel < rellim; rel++) { > diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c > index 721fe89..75a1c69 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 *); > @@ -116,7 +120,7 @@ static void objlist_push_head(Objlist *, Obj_Entry *); > static void objlist_push_tail(Objlist *, Obj_Entry *); > static void objlist_remove(Objlist *, Obj_Entry *); > static void *path_enumerate(const char *, path_enum_proc, void *); > -static int relocate_objects(Obj_Entry *, bool, Obj_Entry *); > +static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, bool early); > static int rtld_dirname(const char *, char *); > static int rtld_dirname_abs(const char *, char *); > static void rtld_exit(void); > @@ -188,6 +192,9 @@ extern Elf_Dyn _DYNAMIC; > #define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) > #endif > > +static int pagesize, osreldate, canary_len, ncpus; > +static char *canary; > + > /* > * 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)"; > @@ -519,7 +527,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) > allocate_initial_tls(obj_list); > > if (relocate_objects(obj_main, > - ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld) == -1) > + ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld, false) == -1) > die(); > > dbg("doing copy relocations"); > @@ -736,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) { > @@ -867,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: > @@ -958,6 +968,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); > @@ -975,6 +991,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 > @@ -1301,9 +1327,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. > @@ -1320,27 +1348,38 @@ 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. */ > assert(!objtmp.textrel); > #endif > - > /* > * Temporarily put the dynamic linker entry into the object list, so > * that symbols can be found. > */ > > - relocate_objects(&objtmp, true, &objtmp); > + relocate_objects(&objtmp, true, &objtmp, true); > } > - > /* Initialize the object list. */ > obj_tail = &obj_list; > > /* 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_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); > > @@ -1745,7 +1784,8 @@ objlist_remove(Objlist *list, Obj_Entry *obj) > * or -1 on failure. > */ > static int > -relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj) > +relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj, > + bool early) > { > Obj_Entry *obj; > > @@ -1770,7 +1810,7 @@ relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj) > } > > /* Process the non-PLT relocations. */ > - if (reloc_non_plt(obj, rtldobj)) > + if (reloc_non_plt(obj, rtldobj, early)) > return -1; > > if (obj->textrel) { /* Re-protected the text segment. */ > @@ -2022,7 +2062,8 @@ dlopen(const char *name, int mode) > if (result != -1 && ld_tracing) > goto trace; > if (result == -1 || > - (relocate_objects(obj, mode == RTLD_NOW, &obj_rtld)) == -1) { > + (relocate_objects(obj, mode == RTLD_NOW, &obj_rtld, false)) > + == -1) { > obj->dl_refcount--; > unref_dag(obj); > if (obj->refcount == 0) > @@ -3611,3 +3652,110 @@ 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_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/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h > index 06086b4..928e3ed 100644 > --- a/libexec/rtld-elf/rtld.h > +++ b/libexec/rtld-elf/rtld.h > @@ -286,7 +286,7 @@ const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long); > * MD function declarations. > */ > int do_copy_relocations(Obj_Entry *); > -int reloc_non_plt(Obj_Entry *, Obj_Entry *); > +int reloc_non_plt(Obj_Entry *, Obj_Entry *, bool); > int reloc_plt(Obj_Entry *); > int reloc_jmpslots(Obj_Entry *); > void allocate_initial_tls(Obj_Entry *); > diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h > index e5c95f7..d541b9e 100644 > --- a/sys/amd64/include/elf.h > +++ b/sys/amd64/include/elf.h > @@ -87,8 +87,12 @@ __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_COUNT 16 /* Count of defined aux entry types. */ > +#define AT_COUNT 20 /* Count of defined aux entry types. */ > > /* > * Relocation types. > diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c > index af8168e..acf2c34 100644 > --- a/sys/compat/ia32/ia32_sysvec.c > +++ b/sys/compat/ia32/ia32_sysvec.c > @@ -191,6 +191,7 @@ ia32_copyout_strings(struct image_params *imgp) > struct freebsd32_ps_strings *arginfo; > size_t execpath_len; > int szsigcode; > + char canary[sizeof(long) * 8]; > > /* > * Calculate string base and vector table pointers. > @@ -203,8 +204,9 @@ ia32_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((ARG_MAX - imgp->args->stringspace), sizeof(char *)); > > /* > * install sigcode > @@ -223,6 +225,14 @@ ia32_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)); > + > + /* > * If we have a valid auxargs ptr, prepare some room > * on the stack. > */ > @@ -239,8 +249,8 @@ ia32_copyout_strings(struct image_params *imgp) > * for argument of Runtime loader. > */ > vectp = (u_int32_t *) (destp - (imgp->args->argc + > - imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) * > - sizeof(u_int32_t)); > + imgp->args->envc + 2 + imgp->auxarg_size) > + * sizeof(u_int32_t)); > } else > /* > * The '+ 2' is for the null pointers at the end of each of > diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h > index af71ab8..a959e68 100644 > --- a/sys/i386/include/elf.h > +++ b/sys/i386/include/elf.h > @@ -90,8 +90,12 @@ __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_COUNT 16 /* Count of defined aux entry types. */ > +#define AT_COUNT 20 /* Count of defined aux entry types. */ > > /* > * Relocation types. > diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c > index e2c0a12..b2c1d45 100644 > --- a/sys/kern/imgact_elf.c > +++ b/sys/kern/imgact_elf.c > @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); > #include > #include > #include > +#include > #include > #include > #include > @@ -887,6 +888,12 @@ __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); > 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 3f36658..6bed93f 100644 > --- a/sys/kern/kern_exec.c > +++ b/sys/kern/kern_exec.c > @@ -380,6 +380,8 @@ do_execve(td, args, mac_p) > imgp->args = args; > imgp->execpath = imgp->freepath = NULL; > imgp->execpathp = 0; > + imgp->canary = 0; > + imgp->canarylen = 0; > > #ifdef MAC > error = mac_execve_enter(imgp, mac_p); > @@ -1175,6 +1177,7 @@ exec_copyout_strings(imgp) > struct proc *p; > size_t execpath_len; > int szsigcode; > + char canary[sizeof(long) * 8]; > > /* > * Calculate string base and vector table pointers. > @@ -1191,6 +1194,7 @@ 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((ARG_MAX - imgp->args->stringspace), sizeof(char *)); > > /* > @@ -1210,6 +1214,15 @@ 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); > + > + /* > * If we have a valid auxargs ptr, prepare some room > * on the stack. > */ > @@ -1226,8 +1239,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/sys/imgact.h b/sys/sys/imgact.h > index e6acc00..8acd184 100644 > --- a/sys/sys/imgact.h > +++ b/sys/sys/imgact.h > @@ -69,6 +69,8 @@ struct image_params { > char *execpath; > unsigned long execpathp; > char *freepath; > + unsigned long canary; > + int canarylen; > }; > > #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 > -- Jeremie Le Hen Humans are born free and equal. But some are more equal than others. Coluche