OSDN Git Service

ldd: take LD_LIBRARY_PATH into account
authorCarmelo Amoroso <carmelo.amoroso@st.com>
Fri, 14 Oct 2011 10:04:58 +0000 (12:04 +0200)
committerCarmelo Amoroso <carmelo.amoroso@st.com>
Tue, 18 Oct 2011 09:23:55 +0000 (11:23 +0200)
Extend the environment variables adding the LD_LIBRARY_PATH
if actually passed when doing shared library tracings through
the ld.so trace capability.
This is possible only using the system dynamic linker in stand-alone
mode to avoid any vulnerability.

Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
utils/Makefile.in
utils/ldd.c

index 65364d7..b634b81 100644 (file)
@@ -12,7 +12,7 @@ CFLAGS-utils := \
     $(SSP_ALL_CFLAGS) \
     -I$(top_srcdir)ldso/include \
     -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
-    -DUCLIBC_LDSO=$(UCLIBC_LDSO) \
+    -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" \
     -I$(top_srcdir)/$(KERNEL_HEADERS) \
     -DNOT_IN_libc \
     -B$(top_builddir)lib \
index 6d08efd..c56ddc8 100644 (file)
 #define ELFDATAM       ELFDATA2MSB
 #endif
 
+#define ARRAY_SIZE(v)  (sizeof(v) / sizeof(*v))
+#define TRUSTED_LDSO   UCLIBC_RUNTIME_PREFIX "lib/" UCLIBC_LDSO
+
 struct library {
        char *name;
        int resolved;
@@ -698,16 +701,59 @@ foo:
                                "LD_TRACE_LOADED_OBJECTS=1",
                                NULL
                        };
-
+                       char * lib_path = getenv("LD_LIBRARY_PATH");
+
+#ifdef __LDSO_STANDALONE_SUPPORT__
+                       /* The 'extended' environment inclusing the LD_LIBRARY_PATH */
+                       static char *ext_environment[ARRAY_SIZE(environment) + 1];
+                       char **envp = (char **) environment;
+
+                       if (lib_path) {
+                               /*
+                                * If the LD_LIBRARY_PATH is set, it needs to include it
+                                * into the environment for the new process to be spawned
+                                */
+                               char ** eenvp = (char **) ext_environment;
+
+                               /* Copy the N-1 environment's entries */
+                               while (*envp)
+                                       *eenvp++=*envp++;
+
+                               /* Make room for LD_LIBRARY_PATH */
+                               *eenvp = (char *) malloc(sizeof("LD_LIBRARY_PATH=")
+                                                                         + strlen(lib_path));
+                               strcpy(*eenvp, "LD_LIBRARY_PATH=");
+                               strcat(*eenvp, lib_path);
+                               lib_path = *eenvp;
+                               /* ext_environment[size] is already NULL */
+
+                               /* Use the extended environment */
+                               envp = ext_environment;
+                       }
+                       if ((pid = vfork()) == 0) {
+                               /*
+                                * Force to use the standard dynamic linker in stand-alone mode.
+                                * It will fails at runtime if support is not actually available
+                                */
+                               execle(TRUSTED_LDSO, TRUSTED_LDSO, filename, NULL, envp);
+                               _exit(0xdead);
+                       }
+#else
                        if ((pid = vfork()) == 0) {
                                /* Cool, it looks like we should be able to actually
                                 * run this puppy.  Do so now... */
                                execle(filename, filename, NULL, environment);
                                _exit(0xdead);
                        }
-
+#endif
                        /* Wait till it returns */
                        waitpid(pid, &status, 0);
+
+#ifdef __LDSO_STANDALONE_SUPPORT__
+                       /* Do not leak */
+                       free(lib_path);
+#endif
+
                        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
                                return 1;
                        }