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 <sys/param.h>
>  #include <sys/sysctl.h>
> +#include <errno.h>
> +#include <link.h>
>  
>  /*
>   * 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 <sys/param.h>
>  #include <sys/sysctl.h>
>  
> +#include <errno.h>
> +#include <link.h>
>  #include <unistd.h>
>  
>  /*
> @@ -52,13 +54,23 @@ getpagesize()
>       int mib[2]; 
>       static int value;
>       size_t size;
> +     int error;
> +
> +     if (value != 0)
> +             return (value);
> +
> +     if (_rtld_aux_info != NULL)
> +             error = _rtld_aux_info(AT_PAGESZ, &value, sizeof(value));
> +     else
> +             error = ENOSYS;
> +     if (error == 0 && value != 0)
> +             return (value);
> +
> +     mib[0] = CTL_HW;
> +     mib[1] = HW_PAGESIZE;
> +     size = sizeof value;
> +     if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
> +             return (-1);
>  
> -     if (!value) {
> -             mib[0] = CTL_HW;
> -             mib[1] = HW_PAGESIZE;
> -             size = sizeof value;
> -             if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
> -                     return (-1);
> -     }
>       return (value);
>  }
> diff --git a/lib/libc/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 <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;
>  
>       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 <sys/param.h>
>  #include <sys/sysctl.h>
>  #include <sys/types.h>
> +#include <errno.h>
> +#include <link.h>
>  #include <signal.h>
>  #include <string.h>
>  #include <syslog.h>
> @@ -54,9 +56,17 @@ __guard_setup(void)
>  {
>       int mib[2];
>       size_t len;
> +     int error;
>  
>       if (__stack_chk_guard[0] != 0)
>               return;
> +     if (_rtld_aux_info != NULL)
> +             error = _rtld_aux_info(AT_CANARY, __stack_chk_guard,
> +                 sizeof(__stack_chk_guard));
> +     else
> +             error = ENOSYS;
> +     if (error == 0 && __stack_chk_guard[0] != 0)
> +             return;
>  
>       mib[0] = CTL_KERN;
>       mib[1] = KERN_ARND;
> diff --git a/libexec/rtld-elf/Symbol.map b/libexec/rtld-elf/Symbol.map
> index ce1e3e5..f45f955 100644
> --- a/libexec/rtld-elf/Symbol.map
> +++ b/libexec/rtld-elf/Symbol.map
> @@ -24,4 +24,5 @@ FBSDprivate_1.0 {
>      _rtld_free_tls;
>      _rtld_atfork_pre;
>      _rtld_atfork_post;
> +    _rtld_aux_info;
>  };
> diff --git a/libexec/rtld-elf/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 <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 != 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 <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 != 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
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to