tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Providing access to the ELF Auxillary Vector for all binaries



Hi all,
attached is a patch to provide all NetBSD binaries with a reference to
the auxillary vector. This is a minor change for dynamically linked
programs as the usual information are already used by ld.elf_so. It is a
major change for statically linked programs as it allows the
dl_iterate_phdr interface to work. This is usual for libunwind and TLS
support. This works as long as the PHDR is either explicitly or
implicitly part of the loaded segments. This seems to be the case on
NetBSD by default,  but could be enforced by modifying the linker script
accordingly.

The loop to find the end of environ can be eliminated if the
__ps_strings problem is fixed as that structure contains the number of
entries in environ.

Further changes could include a careful check of initial system calls
of typical process traces. One change to adopt from FreeBSD (IIRC) is to
include the initial seed for arc4random to save that system call etc.

Joerg
Index: src/lib/csu/alpha/crt0.c
===================================================================
--- src/lib/csu/alpha/crt0.c
+++ src/lib/csu/alpha/crt0.c
@@ -46,14 +46,19 @@
        const Obj_Entry *obj;                   /* from shared loader */
        struct ps_strings *ps_strings;
 {
        long argc;
        char **argv, *namep;
+       size_t i;
 
        argc = *(long *)sp;
        argv = sp + 1;
        environ = sp + 2 + argc;                /* 2: argc + NULL ending argv */
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(namep, '/')) == NULL)
                        __progname = namep;
                else

Index: src/lib/csu/arm_elf/crt0.c
===================================================================
--- src/lib/csu/arm_elf/crt0.c
+++ src/lib/csu/arm_elf/crt0.c
@@ -73,13 +73,19 @@
 
 void
 ___start(int argc, char **argv, char **envp, struct ps_strings *ps_strings,
        const Obj_Entry *obj, void (*cleanup)(void))
 {
+       size_t i;
        char *ap;
 
-       environ = envp;
+       environ = envp;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
+
        __ps_strings = ps_strings;
 
        if ((ap = argv[0])) {
                if ((__progname = _strrchr(ap, '/')) == NULL)
                        __progname = ap;

Index: src/lib/csu/common/crt0-common.c
===================================================================
--- src/lib/csu/common/crt0-common.c
+++ src/lib/csu/common/crt0-common.c
@@ -64,11 +64,12 @@
 extern void    _mcleanup(void);
 extern unsigned char __etext, __eprol;
 #endif /* MCRT0 */
 
 char           **environ;
-struct ps_strings *__ps_strings = 0;
+void           *__auxinfo;
+struct ps_strings *__ps_strings;
 
 static char     empty_string[] = "";
 char           *__progname = empty_string;
 
 void           ___start(int, char **, char **, void (*)(void),
@@ -86,11 +87,17 @@
 ___start(int argc, char **argv, char **envp,
     void (*cleanup)(void),                     /* from shared loader */
     const Obj_Entry *obj,                      /* from shared loader */
     struct ps_strings *ps_strings)
 {
+       size_t i;
+
        environ = envp;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if (argv[0] != NULL) {
                char *c;
                __progname = argv[0];
                for (c = argv[0]; *c; ++c) {

Index: src/lib/csu/common_elf/common.h
===================================================================
--- src/lib/csu/common_elf/common.h
+++ src/lib/csu/common_elf/common.h
@@ -65,10 +65,11 @@
 
 static char    *_strrchr(char *, int);
 
 char   **environ;
 char   *__progname = "";
+void   *__auxinfo;
 struct ps_strings *__ps_strings = 0;
 
 extern void    _init(void);
 extern void    _fini(void);
 

Index: src/lib/csu/hppa/crt0.c
===================================================================
--- src/lib/csu/hppa/crt0.c
+++ src/lib/csu/hppa/crt0.c
@@ -71,14 +71,19 @@
     int dp)
 {
        int argc;
        char **argv;
        int fini_plabel[2];
+       size_t i;
 
        argc = ps_strings->ps_nargvstr;
        argv = ps_strings->ps_argvstr;
        environ = ps_strings->ps_envstr;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(__progname, '/')) == NULL)
                        __progname = argv[0];
                else

Index: src/lib/csu/ia64/crt0.c
===================================================================
--- src/lib/csu/ia64/crt0.c
+++ src/lib/csu/ia64/crt0.c
@@ -45,10 +45,11 @@
     const Obj_Entry *obj,      /* from shared loader */
     struct ps_strings *ps_strings)
 {
        long argc;
        char **argv, *namep;
+       size_t i;
 
        __asm __volatile__ ("1:                                         \
                                { .mii                                  \
                                  mov           r15=@gprel(1b)  \n      \
                                  mov           r16=ip  ;;      \n      \
@@ -57,10 +58,14 @@
                                } ");
 
        argc = *(long *)sp;
        argv = sp + 1;
        environ = sp + 2 + argc;                /* 2: argc + NULL ending argv */
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(namep, '/')) == NULL)
                        __progname = namep;
                else

Index: src/lib/csu/m68k_elf/crt0.c
===================================================================
--- src/lib/csu/m68k_elf/crt0.c
+++ src/lib/csu/m68k_elf/crt0.c
@@ -60,11 +60,17 @@
 __start(int argc, char **argv, char **envp,
     void (*cleanup)(void),                     /* from shared loader */
     const Obj_Entry *obj,                      /* from shared loader */
     struct ps_strings *ps_strings)
 {
+       size_t i;
+
        environ = envp;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(__progname, '/')) == NULL)
                        __progname = argv[0];
                else

Index: src/lib/csu/mips/crt0.c
===================================================================
--- src/lib/csu/mips/crt0.c
+++ src/lib/csu/mips/crt0.c
@@ -64,10 +64,11 @@
     struct ps_strings *ps_strings)
 {
        char **ksp;
        char **argv, *namep;
        int argc;
+       size_t i;
 
        /*
         * Grab the argc, argv, and envp set up by the kernel.
         * Layout of stuff on the stack:
         *
@@ -119,10 +120,14 @@
 
 
        argc = *(int *)ksp;
        argv = ksp + 1;
        environ = ksp + 2 + argc;       /* 2: argc + NULL ending argv */
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(namep, '/')) == NULL)
                        __progname = namep;
                else

Index: src/lib/csu/powerpc/crt0.c
===================================================================
--- src/lib/csu/powerpc/crt0.c
+++ src/lib/csu/powerpc/crt0.c
@@ -56,10 +56,11 @@
     const Obj_Entry *obj,                      /* from shared loader */
     void (*cleanup)(void),                     /* from shared loader */
     struct ps_strings *ps_strings)             /* NetBSD extension */
 {
        char *namep;
+       size_t i;
 
        /*
         * Initialize the Small Data Area registers.
         * _SDA_BASE is defined in the SVR4 ABI for PPC.
         * _SDA2_BASE is defined in the E[mbedded] ABI for PPC.
@@ -75,10 +76,14 @@
                else
                        __progname++;
        }
 
        environ = envp;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if (ps_strings != (struct ps_strings *)0)
                __ps_strings = ps_strings;
 
 #ifdef DYNAMIC

Index: src/lib/csu/powerpc64/crt0.c
===================================================================
--- src/lib/csu/powerpc64/crt0.c
+++ src/lib/csu/powerpc64/crt0.c
@@ -58,19 +58,24 @@
     const Obj_Entry *obj,                      /* from shared loader */
     void (*cleanup)(void),                     /* from shared loader */
     struct ps_strings *ps_strings)             /* NetBSD extension */
 {
        char *namep;
+       size_t i;
 
        if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(namep, '/')) == NULL)
                        __progname = namep;
                else
                        __progname++;
        }
 
        environ = envp;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if (ps_strings != (struct ps_strings *)0)
                __ps_strings = ps_strings;
 
 #ifdef DYNAMIC

Index: src/lib/csu/sh3_elf/crt0.c
===================================================================
--- src/lib/csu/sh3_elf/crt0.c
+++ src/lib/csu/sh3_elf/crt0.c
@@ -54,11 +54,17 @@
 ___start(int argc, char **argv, char **envp,
     void (*cleanup)(void),                     /* from shared loader */
     const Obj_Entry *obj,                      /* from shared loader */
     struct ps_strings *ps_strings)
 {
+       size_t i;
+
        environ = envp;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(__progname, '/')) == NULL)
                        __progname = argv[0];
                else

Index: src/lib/csu/sparc64/crt0.c
===================================================================
--- src/lib/csu/sparc64/crt0.c
+++ src/lib/csu/sparc64/crt0.c
@@ -75,14 +75,19 @@
     const Obj_Entry *obj,                      /* from shared loader */
     struct ps_strings *ps_strings)
 {
        long argc;
        char **argv, *namep;
+       size_t i;
 
        argc = *(long *)sp;
        argv = sp + 1;
        environ = sp + 2 + argc;                /* 2: argc + NULL ending argv */
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((namep = argv[0]) != NULL) {        /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(namep, '/')) == NULL)
                        __progname = namep;
                else

Index: src/lib/csu/sparc_elf/crt0.c
===================================================================
--- src/lib/csu/sparc_elf/crt0.c
+++ src/lib/csu/sparc_elf/crt0.c
@@ -64,11 +64,17 @@
 ___start(int argc, char **argv, char **envp,
     void (*cleanup)(void),                     /* from shared loader */
     const Obj_Entry *obj,                      /* from shared loader */
     struct ps_strings *ps_strings)
 {
+       size_t i;
+
        environ = envp;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(__progname, '/')) == NULL)
                        __progname = argv[0];
                else

Index: src/lib/csu/vax_elf/crt0.c
===================================================================
--- src/lib/csu/vax_elf/crt0.c
+++ src/lib/csu/vax_elf/crt0.c
@@ -61,11 +61,17 @@
 ___start(int argc, char **argv, char **envp,
     void (*cleanup)(void),                     /* from shared loader */
     const Obj_Entry *obj,                      /* from shared loader */
     struct ps_strings *ps_strings)
 {
+       size_t i;
+
        environ = envp;
+
+       for (i = 0; environ[i] != NULL; )
+               ++i;
+       __auxinfo = &environ[i + 1];
 
        if ((__progname = argv[0]) != NULL) {   /* NULL ptr if argc = 0 */
                if ((__progname = _strrchr(__progname, '/')) == NULL)
                        __progname = argv[0];
                else

Index: src/lib/libc/dlfcn/dlfcn_elf.c
===================================================================
--- src/lib/libc/dlfcn/dlfcn_elf.c
+++ src/lib/libc/dlfcn/dlfcn_elf.c
@@ -28,11 +28,15 @@
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
 __RCSID("$NetBSD: dlfcn_elf.c,v 1.7 2010/10/16 10:27:07 skrll Exp $");
 #endif /* LIBC_SCCS and not lint */
 
+#include "reentrant.h"
 #include "namespace.h"
+#include <errno.h>
+#include <string.h>
+#include <elf.h>
 
 #undef dlopen
 #undef dlclose
 #undef dlsym
 #undef dlerror
@@ -126,13 +130,58 @@
 {
 
        return -1;
 }
 
+static once_t dl_iterate_phdr_once = ONCE_INITIALIZER;
+static const char *dlpi_name;
+static const Elf_Phdr *dlpi_phdr;
+static Elf_Half dlpi_phnum;
+
+/*
+ * Declare as common symbol to allow new libc with older binaries to
+ * not trigger an undefined reference.
+ */
+void *__auxinfo;
+
+static void
+dl_iterate_phdr_setup(void)
+{
+       const AuxInfo *aux;
+
+       if (__auxinfo == NULL)
+               return;
+
+       for (aux = __auxinfo; aux->a_type != AT_NULL; ++aux) {
+               switch (aux->a_type) {
+               case AT_PHDR:
+                       dlpi_phdr = (void *)aux->a_v;
+                       break;
+               case AT_PHNUM:
+                       dlpi_phnum = aux->a_v;
+                       break;
+               case AT_SUN_EXECNAME:
+                       dlpi_name = (void *)aux->a_v;
+                       break;
+               }
+       }
+}
+
 /*ARGSUSED*/
 int
 dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
     void *data)
 {
+       struct dl_phdr_info phdr_info;
+
+       if (__auxinfo == NULL)
+               return EOPNOTSUPP;
+
+       thr_once(&dl_iterate_phdr_once, dl_iterate_phdr_setup);
+
+       memset(&phdr_info, 0, sizeof(phdr_info));
+       phdr_info.dlpi_phdr = dlpi_phdr;
+       phdr_info.dlpi_phnum = dlpi_phnum;
+       phdr_info.dlpi_name = dlpi_name;
 
-       return 0;
+       return callback(&phdr_info, sizeof(phdr_info), data);
 }

Index: src/sys/compat/netbsd32/netbsd32_exec_elf32.c
===================================================================
--- src/sys/compat/netbsd32/netbsd32_exec_elf32.c
+++ src/sys/compat/netbsd32/netbsd32_exec_elf32.c
@@ -113,11 +113,11 @@
 {
        if (itp && epp->ep_interp == NULL) {
                extern const char machine32[];
                (void)compat_elf_check_interp(epp, itp, machine32);
        }
-       epp->ep_flags |= EXEC_32;
+       epp->ep_flags |= EXEC_32 | EXEC_FORCEAUX;
        epp->ep_vm_minaddr = VM_MIN_ADDRESS;
        epp->ep_vm_maxaddr = USRSTACK32;
 #ifdef ELF_INTERP_NON_RELOCATABLE
        *pos = ELF_LINK_ADDR;
 #endif

Index: src/sys/kern/exec_elf.c
===================================================================
--- src/sys/kern/exec_elf.c
+++ src/sys/kern/exec_elf.c
@@ -931,7 +931,8 @@
        if ((error = ELF_MD_PROBE_FUNC(l, epp, eh, itp, pos)) != 0)
                return error;
 #elif defined(ELF_INTERP_NON_RELOCATABLE)
        *pos = ELF_LINK_ADDR;
 #endif
+       epp->ep_flags |= EXEC_FORCEAUX;
        return 0;
 }



Home | Main Index | Thread Index | Old Index