Date: Sat, 25 Jul 2009 00:29:16 +0300 From: Kostik Belousov <kostikbel@gmail.com> To: Ed Schouten <ed@80386.nl> Cc: FreeBSD Hackers <freebsd-hackers@freebsd.org>, Jeremie Le Hen <jeremie@le-hen.org> Subject: Re: concurrent sysctl implementation Message-ID: <20090724212916.GQ55190@deviant.kiev.zoral.com.ua> In-Reply-To: <20090724134953.GW68469@hoeg.nl> References: <d9f479c10905050239u5d6d8304y1f63e41eabee8624@mail.gmail.com> <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>
next in thread | previous in thread | raw e-mail | index | archive | help
--nmEd1AIGA/JIgsXT Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Jul 24, 2009 at 03:49:53PM +0200, Ed Schouten wrote: > * Jeremie Le Hen <jeremie@le-hen.org> wrote: > > On Fri, Jul 24, 2009 at 01:56:49PM +0200, Ed Schouten wrote: > > > * Jeremie Le Hen <jeremie@le-hen.org> wrote: > > > > On Fri, Jul 24, 2009 at 11:18:42AM +0300, Kostik Belousov wrote: > > > > > On Fri, Jul 24, 2009 at 09:34:51AM +0200, Jeremie Le Hen wrote: > > > > > > Hi Ed, > > > > > >=20 > > > > > > Sorry for the late reply. > > > > > >=20 > > > > > > On Sat, May 09, 2009 at 02:13:13PM +0200, Ed Schouten wrote: > > > > > > > We probably could. I think I discussed this with Robert Watso= n some time > > > > > > > ago and we could use things like ELF hints. But still, that d= oesn't > > > > > > > prevent us from reaching this limitation later on. > > > > > >=20 > > > > > > Can you elaborate a little? Are you talking about elf-hints.h? > > > > > > I don't see where we can get randomness from it. > > > > >=20 > > > > > The thing is called ELF auxillary information vector. It is used = to > > > > > supply some useful information for interpreter from the kernel, > > > > > see include/machine/elf.h for AT_* entries. > > > >=20 > > > > Ah ok, so the idea is to generate a new hint, for instance AT_RANDO= M, > > > > generated at link time, that will be used to fill the canary at exe= c(2) > > > > time? > > >=20 > > > Very short answer: yes! > >=20 > > Ok thanks. But this would make stack protection useless for local > > attacks on suid binaries that are world-readable since the attacker > > could read the ELF aux vector and compute the canary. =20 >=20 > Wait wait wait. It seems you were only partially right (and Kostik > corrected you): >=20 > We could add AT_RANDOM, but this value will be filled in by the kernel > when starting the process. This means the random value is not stored in > the binary. 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$"); =20 #include <sys/param.h> #include <sys/sysctl.h> +#include <errno.h> +#include <link.h> =20 /* * This is private to libc. It is intended for wrapping syscall stubs in = order @@ -49,7 +51,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 <sys/param.h> #include <sys/sysctl.h> =20 +#include <errno.h> +#include <link.h> #include <unistd.h> =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/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$"); =20 #include <errno.h> #include <limits.h> +#include <link.h> #include <pthread.h> #include <sched.h> #include <stdarg.h> @@ -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; =20 malloc_mutex_lock(&init_lock); if (malloc_initialized) { @@ -4782,10 +4786,11 @@ malloc_init_hard(void) } =20 /* Get number of CPUs. */ - { - int mib[2]; - size_t len; - + if (_rtld_aux_info !=3D NULL) + error =3D _rtld_aux_info(AT_NCPUS, &ncpus, sizeof(ncpus)); + else + error =3D ENOSYS; + if (error !=3D 0 || ncpus =3D=3D 0) { mib[0] =3D CTL_HW; mib[1] =3D HW_NCPU; len =3D 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 <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; =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/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) =20 /* 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 =3D mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); - if (cache =3D=3D MAP_FAILED) + if (early) cache =3D NULL; + else { + cache =3D mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); + if (cache =3D=3D MAP_FAILED) + cache =3D NULL; + } =20 relalim =3D (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize); for (rela =3D 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) =20 /* 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 =3D mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); - if (cache =3D=3D MAP_FAILED) + if (early) cache =3D NULL; + else { + cache =3D mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); + if (cache =3D=3D MAP_FAILED) + cache =3D NULL; + } =20 rellim =3D (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize); for (rel =3D 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 <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 *); @@ -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 !=3D NULL) #endif =20 +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[] =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)"; @@ -519,7 +527,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry= **objp) allocate_initial_tls(obj_list); =20 if (relocate_objects(obj_main, - ld_bind_now !=3D NULL && *ld_bind_now !=3D '\0', &obj_rtld) =3D=3D -1) + ld_bind_now !=3D NULL && *ld_bind_now !=3D '\0', &obj_rtld, false) =3D=3D= -1) die(); =20 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 =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) { @@ -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 =3D dynp; + *dyn_rpath =3D dynp; break; =20 case DT_SONAME: - dyn_soname =3D dynp; + *dyn_soname =3D dynp; break; =20 case DT_INIT: @@ -958,6 +968,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); @@ -975,6 +991,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 @@ -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; =20 /* * 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 =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. */ assert(!objtmp.textrel); #endif - /* * Temporarily put the dynamic linker entry into the object list, so * that symbols can be found. */ =20 - relocate_objects(&objtmp, true, &objtmp); + relocate_objects(&objtmp, true, &objtmp, true); } - /* Initialize the object list. */ obj_tail =3D &obj_list; =20 /* 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_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 @@ -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; =20 @@ -1770,7 +1810,7 @@ relocate_objects(Obj_Entry *first, bool bind_now, Obj= _Entry *rtldobj) } =20 /* Process the non-PLT relocations. */ - if (reloc_non_plt(obj, rtldobj)) + if (reloc_non_plt(obj, rtldobj, early)) return -1; =20 if (obj->textrel) { /* Re-protected the text segment. */ @@ -2022,7 +2062,8 @@ dlopen(const char *name, int mode) if (result !=3D -1 && ld_tracing) goto trace; if (result =3D=3D -1 || - (relocate_objects(obj, mode =3D=3D RTLD_NOW, &obj_rtld)) =3D=3D -1)= { + (relocate_objects(obj, mode =3D=3D RTLD_NOW, &obj_rtld, false)) + =3D=3D -1) { obj->dl_refcount--; unref_dag(obj); if (obj->refcount =3D=3D 0) @@ -3611,3 +3652,110 @@ 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_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/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, uns= igned 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. */ =20 -#define AT_COUNT 16 /* Count of defined aux entry types. */ +#define AT_COUNT 20 /* Count of defined aux entry types. */ =20 /* * 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]; =20 /* * Calculate string base and vector table pointers. @@ -203,8 +204,9 @@ ia32_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((ARG_MAX - imgp->args->stringspace), sizeof(char *)); =20 /* * install sigcode @@ -223,6 +225,14 @@ ia32_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)); + + /* * 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 =3D (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. */ =20 -#define AT_COUNT 16 /* Count of defined aux entry types. */ +#define AT_COUNT 20 /* Count of defined aux entry types. */ =20 /* * 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 <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> @@ -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 !=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); 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 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 =3D args; imgp->execpath =3D imgp->freepath =3D NULL; imgp->execpathp =3D 0; + imgp->canary =3D 0; + imgp->canarylen =3D 0; =20 #ifdef MAC error =3D 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]; =20 /* * Calculate string base and vector table pointers. @@ -1191,6 +1194,7 @@ 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((ARG_MAX - imgp->args->stringspace), sizeof(char *)); =20 /* @@ -1210,6 +1214,15 @@ 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); + + /* * 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 =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/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; }; =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 --nmEd1AIGA/JIgsXT Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) iEYEARECAAYFAkpqJ6sACgkQC3+MBN1Mb4gcHACeKgssoIm9mDtZJ/1UcKVIeWfr JOYAoJRHu7mGijbYJVLJHFrYlwSXP9NQ =aN41 -----END PGP SIGNATURE----- --nmEd1AIGA/JIgsXT--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090724212916.GQ55190>