This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Bug fix: Warning for unsupported DF_1_* flags when LD_DEBUG=files.


H.J. and I both agreed that the dynamic linker should assert when
it saw a DF_1_* flag that it couldn't support, and that is exactly
what went into master with commit 7e1be741255c40a2d71ea7c888eff39a3aaa32e9.
Unfortunately it turns out that we can't be quite that restrictive.

We received feedback that the additional assert had broken Valgrind.
It turns out some userspace applications have always been setting DF_1_*
flags we don't support; binutils sets them, and glibc ignores them.

As an example Valgrind's build uses:
PRELOAD_LDFLAGS_COMMON_LINUX  = -nodefaultlibs -shared -Wl,-z,interpose,-z,initfirst

Therefore we can't assert on unsupported flags or we risk breaking 
previously working programs. This needs to be fixed ASAP before we
release 2.17 or there will be problems running Valgrind and other
applications.

The following patch converts the assertion into a warning that can
be seen when running the linker with LD_DEBUG=files or LD_DEBUG=all.
At the very least we'll be providing diagnostics for unsupported flags.

With the patch applied you can do the following:

* Build a DSO with DF_1_INTERPOSE set.

  gcc -shared -fPIC -o libfoo.so foo.c -Wl,-z,interpose -Wl,--soname=libfoo.so

* Run an application with LD_DEBUG=files or LD_DEBUG=all and LD_PRELOAD=./libfoo.so

      8402:     file=/bin/ls [0];  generating link map
      8402:       dynamic: 0x000000000061ae08  base: 0x0000000000000000   size: 0x000000000021c280
      8402:         entry: 0x00000000004026e0  phdr: 0x0000000000400040  phnum:                  9
      8402:
      8402:
      8402:     file=./libfoo.so [0];  needed by /bin/ls [0]
      8402:     file=./libfoo.so [0];  generating link map
      8402:
      8402:     WARNING: Unsupported flag value(s) of 0x400 in DT_FLAGS_1.
      8402:       dynamic: 0x00007fe1ca2cde20  base: 0x00007fe1ca0cd000   size: 0x0000000000201020
      8402:         entry: 0x00007fe1ca0cd4e0  phdr: 0x00007fe1ca0cd040  phnum:                  7
      ...

* Receive a `WARNING: ...' as the DSO is loaded

  The printed value is the OR of all the unsupported flags detected in DT_FLAGS_1
  for the DSO.

  In this case just:
  elf.h:#define DF_1_INTERPOSE    0x00000400      /* Object is used to interpose.  */

It is safe to use _dl_debug_printf in all of the callers of this code.
The most critical caller is the early relocation in rtld, but that sets
RTLD_BOOTSTRAP and disables the DT_FLAGS_1 parsing at compile time.

No regressions on x86-64.

I'll check this in on Friday if nobody objects to the warning message or comments.

2012-11-28  Carlos O'Donell  <carlos@systemhalted.org>

	* elf/get-dynamic-info.h (elf_get_dynamic_info): Warn
	for unsupported DF_1_* bits when DL_DEBUG_FILES is set.

diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
index 9e018de..026f246 100644
--- a/elf/get-dynamic-info.h
+++ b/elf/get-dynamic-info.h
@@ -151,8 +151,16 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
     {
       l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
 
-      /* Only DT_1_SUPPORTED_MASK bits are allowed.  */
-      assert ((l->l_flags_1 & ~DT_1_SUPPORTED_MASK) == 0);
+      /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like
+	 to assert this, but we can't. Users have been setting
+	 unsupported DF_1_* flags for a long time and glibc has ignored
+	 them. Therefore to avoid breaking existing applications the
+	 best we can do is add a warning during debugging with the
+	 intent of notifying the user of the problem.  */
+      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)
+	  && l->l_flags_1 & ~DT_1_SUPPORTED_MASK)
+	_dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.\n",
+			  l->l_flags_1 & ~DT_1_SUPPORTED_MASK);
 
       if (l->l_flags_1 & DF_1_NOW)
 	info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)];
---

Cheers,
Carlos.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]