From owner-freebsd-hackers@FreeBSD.ORG Mon Jun 28 14:49:12 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 92D851065670; Mon, 28 Jun 2010 14:49:12 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from mail.zoral.com.ua (mx0.zoral.com.ua [91.193.166.200]) by mx1.freebsd.org (Postfix) with ESMTP id 2B7B88FC1C; Mon, 28 Jun 2010 14:49:10 +0000 (UTC) Received: from deviant.kiev.zoral.com.ua (root@deviant.kiev.zoral.com.ua [10.1.1.148]) by mail.zoral.com.ua (8.14.2/8.14.2) with ESMTP id o5SEn19w049074 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 28 Jun 2010 17:49:01 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: from deviant.kiev.zoral.com.ua (kostik@localhost [127.0.0.1]) by deviant.kiev.zoral.com.ua (8.14.4/8.14.4) with ESMTP id o5SEn1YB073388; Mon, 28 Jun 2010 17:49:01 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: (from kostik@localhost) by deviant.kiev.zoral.com.ua (8.14.4/8.14.4/Submit) id o5SEmxOn073387; Mon, 28 Jun 2010 17:48:59 +0300 (EEST) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: deviant.kiev.zoral.com.ua: kostik set sender to kostikbel@gmail.com using -f Date: Mon, 28 Jun 2010 17:48:59 +0300 From: Kostik Belousov To: Jeremie Le Hen Message-ID: <20100628144858.GA13238@deviant.kiev.zoral.com.ua> References: <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> <20100623210959.GA21260@felucia.tataz.chchile.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="Cu2X4S6QpqS+1MBM" Content-Disposition: inline In-Reply-To: <20100623210959.GA21260@felucia.tataz.chchile.org> User-Agent: Mutt/1.4.2.3i X-Virus-Scanned: clamav-milter 0.95.2 at skuns.kiev.zoral.com.ua X-Virus-Status: Clean X-Spam-Status: No, score=-2.3 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_50, DNS_FROM_OPENWHOIS autolearn=no version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on skuns.kiev.zoral.com.ua Cc: FreeBSD Hackers , marius@freebsd.org, nwhitehorn@freebsd.org 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: Mon, 28 Jun 2010 14:49:12 -0000 --Cu2X4S6QpqS+1MBM Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Wed, Jun 23, 2010 at 11:09:59PM +0200, Jeremie Le Hen wrote: > Hi Kostik, >=20 > 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. >=20 > Thanks, > Regards. >=20 > 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. > >=20 > > 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. > >=20 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$"); =20 #include #include +#include +#include =20 int __getosreldate(void); =20 @@ -51,7 +53,15 @@ __getosreldate(void) =20 if (osreldate !=3D 0) return (osreldate); -=09 + + if (_rtld_aux_info !=3D NULL) + error =3D _rtld_aux_info(AT_OSRELDATE, &osreldate, + sizeof(osreldate)); + else + error =3D ENOSYS; + if (error =3D=3D 0 && osreldate !=3D 0) + return (osreldate); + oid[0] =3D CTL_KERN; oid[1] =3D KERN_OSRELDATE; osrel =3D 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 =20 +#include +#include #include =20 /* @@ -52,13 +54,23 @@ getpagesize() int mib[2];=20 static int value; size_t size; + int error; + + if (value !=3D 0) + return (value); + + if (_rtld_aux_info !=3D NULL) + error =3D _rtld_aux_info(AT_PAGESZ, &value, sizeof(value)); + else + error =3D ENOSYS; + if (error =3D=3D 0 && value !=3D 0) + return (value); + + mib[0] =3D CTL_HW; + mib[1] =3D HW_PAGESIZE; + size =3D sizeof value; + if (sysctl(mib, 2, &value, &size, NULL, 0) =3D=3D -1) + return (-1); =20 - if (!value) { - mib[0] =3D CTL_HW; - mib[1] =3D HW_PAGESIZE; - size =3D sizeof value; - if (sysctl(mib, 2, &value, &size, NULL, 0) =3D=3D -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 =20 #include +#include =20 /* * 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;=20 + int error, i; =20 if (nelem < 0 || (nelem > 0 && pagesize =3D=3D NULL)) { errno =3D EINVAL; @@ -59,9 +60,16 @@ getpagesizes(size_t pagesize[], int nelem) } /* Cache the result of the sysctl(2). */ if (nops =3D=3D 0) { - size =3D sizeof(ps); - if (sysctlbyname("hw.pagesizes", ps, &size, NULL, 0) =3D=3D -1) - return (-1); + if (_rtld_aux_info !=3D NULL) + error =3D _rtld_aux_info(AT_PAGESIZES, ps, sizeof(ps)); + else + error =3D ENOSYS; + if (error !=3D 0 || ps[0] =3D=3D 0) { + size =3D sizeof(ps); + if (sysctlbyname("hw.pagesizes", ps, &size, NULL, 0) + =3D=3D -1) + return (-1); + } /* Count the number of page sizes that are supported. */ nops =3D size / sizeof(ps[0]); while (nops > 0 && ps[nops - 1] =3D=3D 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$"); =20 #include #include +#include #include #include #include @@ -5348,14 +5349,23 @@ small_size2bin_init_hard(void) static unsigned malloc_ncpus(void) { + int mib[2]; unsigned ret; - size_t retlen =3D sizeof(ret); - int mib[] =3D {CTL_HW, HW_NCPU}; + int error; + size_t len; =20 - if (sysctl(mib, sizeof(mib) / sizeof(int), &ret, &retlen, - (void *)0, 0) =3D=3D -1) { - /* Error. */ - ret =3D 1; + if (_rtld_aux_info !=3D NULL) + error =3D _rtld_aux_info(AT_NCPUS, &ret, sizeof(ret)); + else + error =3D ENOSYS; + if (error !=3D 0 || ret =3D=3D 0) { + mib[0] =3D CTL_HW; + mib[1] =3D HW_NCPU; + len =3D sizeof(ret); + if (sysctl(mib, 2, &ret, &len, (void *)NULL, 0) =3D=3D -1) { + /* Error. */ + ret =3D 1; + } } =20 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 #include #include +#include +#include #include #include #include @@ -54,9 +56,17 @@ __guard_setup(void) { int mib[2]; size_t len; + int error; =20 if (__stack_chk_guard[0] !=3D 0) return; + if (_rtld_aux_info !=3D NULL) + error =3D _rtld_aux_info(AT_CANARY, __stack_chk_guard, + sizeof(__stack_chk_guard)); + else + error =3D ENOSYS; + if (error =3D=3D 0 && __stack_chk_guard[0] !=3D 0) + return; =20 mib[0] =3D CTL_KERN; mib[1] =3D 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 #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,9 @@ extern Elf_Dyn _DYNAMIC; #define RTLD_IS_DYNAMIC() (&_DYNAMIC !=3D NULL) #endif =20 +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[] =3D { (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 }; =20 @@ -350,7 +358,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry= **objp) =20 /* Initialize and relocate ourselves. */ assert(aux_info[AT_BASE] !=3D 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); =20 __progname =3D obj_rtld.path; argv0 =3D argv[0] !=3D 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 =3D &obj->needed; - const Elf_Dyn *dyn_rpath =3D NULL; - const Elf_Dyn *dyn_soname =3D NULL; int plttype =3D DT_REL; =20 + *dyn_rpath =3D NULL; + *dyn_soname =3D NULL; + obj->bind_now =3D false; for (dynp =3D obj->dynamic; dynp->d_tag !=3D 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 =3D dynp; + *dyn_rpath =3D dynp; break; =20 case DT_SONAME: - dyn_soname =3D dynp; + *dyn_soname =3D dynp; break; =20 case DT_INIT: @@ -961,6 +971,12 @@ digest_dynamic(Obj_Entry *obj, int early) obj->pltrelasize =3D obj->pltrelsize; obj->pltrelsize =3D 0; } +} + +static void +digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath, + const Elf_Dyn *dyn_soname) +{ =20 if (obj->z_origin && obj->origin_path =3D=3D NULL) { obj->origin_path =3D 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); } =20 +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; =20 /* * 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 =3D rtld_dynamic(&objtmp); - digest_dynamic(&objtmp, 1); + digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname); assert(objtmp.needed =3D=3D 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)); =20 + if (aux_info[AT_PAGESZ] !=3D NULL) + pagesize =3D aux_info[AT_PAGESZ]->a_un.a_val; + if (aux_info[AT_OSRELDATE] !=3D NULL) + osreldate =3D aux_info[AT_OSRELDATE]->a_un.a_val; + if (aux_info[AT_CANARY] !=3D NULL && aux_info[AT_CANARYLEN] !=3D NULL)= { + canary =3D aux_info[AT_CANARY]->a_un.a_ptr; + canary_len =3D aux_info[AT_CANARYLEN]->a_un.a_val; + } + if (aux_info[AT_PAGESIZES] !=3D NULL && aux_info[AT_PAGESIZESLEN] !=3D= NULL) { + pagesizes =3D aux_info[AT_PAGESIZES]->a_un.a_ptr; + pagesizes_len =3D aux_info[AT_PAGESIZESLEN]->a_un.a_val; + } + if (aux_info[AT_NCPUS] !=3D NULL) + ncpus =3D 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 =3D xstrdup(PATH_RTLD); =20 @@ -3630,3 +3675,118 @@ fetch_ventry(const Obj_Entry *obj, unsigned long sy= mnum) } return NULL; } + +static int +__getosreldate(void) +{ + static int osreldate; + size_t len; + int oid[2]; + int error, osrel; + + oid[0] =3D CTL_KERN; + oid[1] =3D KERN_OSRELDATE; + osrel =3D 0; + len =3D sizeof(osrel); + error =3D sysctl(oid, 2, &osrel, &len, NULL, 0); + if (error =3D=3D 0 && osrel > 0 && len =3D=3D sizeof(osrel)) + osreldate =3D osrel; + return (osreldate); +} + +static int +__getpagesize(void) +{ + int mib[2]; + static int value; + size_t size; + + mib[0] =3D CTL_HW; + mib[1] =3D HW_PAGESIZE; + size =3D sizeof value; + if (sysctl(mib, 2, &value, &size, NULL, 0) =3D=3D -1) + return (-1); + + return (value); +} + +static int +__getncpus(void) +{ + int mib[2]; + size_t len; + int n; + + mib[0] =3D CTL_HW; + mib[1] =3D HW_NCPU; + len =3D sizeof(ncpus); + if (sysctl(mib, 2, &n, &len, (void *) 0, 0) =3D=3D -1) + n =3D 1; + return (n); +} + +int +_rtld_aux_info(int aux, void *buf, int buflen) +{ + int res; + + switch (aux) { + case AT_CANARY: + if (canary !=3D NULL && canary_len >=3D buflen) { + memcpy(buf, canary, buflen); + memset(canary, 0, canary_len); + canary =3D NULL; + res =3D 0; + } else + res =3D ENOENT; + break; + case AT_PAGESIZES: + if (pagesizes !=3D NULL && pagesizes_len >=3D buflen) { + memcpy(buf, pagesizes, buflen); + res =3D 0; + } else + res =3D ENOENT; + break; + + case AT_PAGESZ: + if (buflen =3D=3D sizeof(int)) { + if (pagesize =3D=3D 0) + pagesize =3D __getpagesize(); + if (pagesize !=3D 0) { + *(int *)buf =3D pagesize; + res =3D 0; + } else + res =3D ENOENT; + } else + res =3D EINVAL; + break; + case AT_OSRELDATE: + if (buflen =3D=3D sizeof(int)) { + if (osreldate =3D=3D 0) + osreldate =3D __getosreldate(); + if (osreldate !=3D 0) { + *(int *)buf =3D osreldate; + res =3D 0; + } else + res =3D ENOENT; + } else + res =3D EINVAL; + break; + case AT_NCPUS: + if (buflen =3D=3D sizeof(int)) { + if (ncpus =3D=3D 0) + ncpus =3D __getncpus(); + if (ncpus !=3D 0) { + *(int *)buf =3D ncpus; + res =3D 0; + } else + res =3D ENOENT; + } else + res =3D EINVAL; + break; + default: + res =3D 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. */ =20 /* * 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. */ =20 #define R_ARM_COUNT 33 /* Count of defined relocation types. */ =20 diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/f= reebsd32_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_d= ata *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; =20 @@ -2543,8 +2545,10 @@ freebsd32_copyout_strings(struct image_params *imgp) arginfo =3D (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS; szsigcode =3D *(imgp->proc->p_sysent->sv_szsigcode); destp =3D (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 *)); =20 /* * install sigcode @@ -2563,6 +2567,25 @@ freebsd32_copyout_strings(struct image_params *imgp) } =20 /* + * Prepare the canary for SSP. + */ + arc4rand(canary, sizeof(canary), 0); + imgp->canary =3D (uintptr_t)arginfo - szsigcode - execpath_len - + sizeof(canary); + copyout(canary, (void *)imgp->canary, sizeof(canary)); + imgp->canarylen =3D sizeof(canary); + + /* + * Prepare the pagesizes array. + */ + for (i =3D 0; i < MAXPAGESIZES; i++) + pagesizes32[i] =3D (uint32_t)pagesizes[i]; + imgp->pagesizes =3D (uintptr_t)arginfo - szsigcode - execpath_len - + roundup(sizeof(canary), sizeof(char *)) - sizeof(pagesizes32); + copyout(pagesizes32, (void *)imgp->pagesizes, sizeof(pagesizes32)); + imgp->pagesizeslen =3D 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. */ =20 /* * 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. */ =20 /* * 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 #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 !=3D 0) AUXARGS_ENTRY(pos, AT_EXECPATH, imgp->execpathp); + AUXARGS_ENTRY(pos, AT_OSRELDATE, imgp->proc->p_osrel); + if (imgp->canary !=3D 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 !=3D 0) { + AUXARGS_ENTRY(pos, AT_PAGESIZES, imgp->pagesizes); + AUXARGS_ENTRY(pos, AT_PAGESIZESLEN, imgp->pagesizeslen); + } AUXARGS_ENTRY(pos, AT_NULL, 0); =20 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 =3D args; imgp->execpath =3D imgp->freepath =3D NULL; imgp->execpathp =3D 0; + imgp->canary =3D 0; + imgp->canarylen =3D 0; + imgp->pagesizes =3D 0; + imgp->pagesizeslen =3D 0; =20 #ifdef MAC error =3D 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]; =20 + szps =3D 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 =3D *(p->p_sysent->sv_szsigcode); destp =3D (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 *)); =20 /* @@ -1219,6 +1227,23 @@ exec_copyout_strings(imgp) } =20 /* + * Prepare the canary for SSP. + */ + arc4rand(canary, sizeof(canary), 0); + imgp->canary =3D (uintptr_t)arginfo - szsigcode - execpath_len - + sizeof(canary); + copyout(canary, (void *)imgp->canary, sizeof(canary)); + imgp->canarylen =3D sizeof(canary); + + /* + * Prepare the pagesizes array. + */ + imgp->pagesizes =3D (uintptr_t)arginfo - szsigcode - execpath_len - + roundup(sizeof(canary), sizeof(char *)) - szps; + copyout(pagesizes, (void *)imgp->pagesizes, szps); + imgp->pagesizeslen =3D 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 =3D (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. */ =20 -#define AT_COUNT 16 /* Count of defined aux entry types. */ +#define AT_COUNT 22 /* Count of defined aux entry types. */ =20 #define ET_DYN_LOAD_ADDR 0x0120000 =20 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. */ =20 /* * 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. */ =20 -#define AT_COUNT 16 /* Count of defined aux entry types. */ +#define AT_COUNT 22 /* Count of defined aux entry types. */ =20 /* Define "machine" characteristics */ #if __ELF_WORD_SIZE =3D=3D 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. */ =20 -#define AT_COUNT 16 /* Count of defined aux entry types. */ +#define AT_COUNT 22 /* Count of defined aux entry types. */ =20 /* Define "machine" characteristics */ #if __ELF_WORD_SIZE =3D=3D 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; }; =20 #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 =20 typedef int (*__dl_iterate_hdr_callback)(struct dl_phdr_info *, size_t, vo= id *); 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 =20 __END_DECLS =20 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=3D auxinfo +NO_MAN=3D +WARNS?=3D 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 =3D getpagesizes(NULL, 0); + if (nelem =3D=3D -1) + err(1, "getpagesizes(NULL, 0)"); + ps =3D malloc(nelem * sizeof(size_t)); + if (ps =3D=3D NULL) + err(1, "malloc"); + nelem =3D getpagesizes(ps, nelem); + if (nelem =3D=3D -1) + err(1, "getpagesizes"); + printf("Supported page sizes:"); + for (i =3D 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); +} --Cu2X4S6QpqS+1MBM Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (FreeBSD) iEYEARECAAYFAkwotloACgkQC3+MBN1Mb4hJ6QCaAqBNJoWUXpzc4oXayue3iSMs CL0AoKIdgVvQWeCpSmwIl0rzGCgweFzh =hsGK -----END PGP SIGNATURE----- --Cu2X4S6QpqS+1MBM--