This is the mail archive of the libc-alpha@sources.redhat.com 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]

nsswitch.c loads shared libraries without specifying __RTLD_DLOPEN.


Hi,

I've just compiled and installed a reasonably fresh (20041104) copy of
the toolchain and various packages and am now confronted with a problem
loading one of the shared libraries.
The problem manifests itself using the nss subsystem, in combination
with the libnss_ldap library.

A very simple testcase that triggers the problem:

====
#include <sys/types.h>
#include <pwd.h>

#define NONEXISTENTUID 12000
main()
{
  getpwuid(NONEXISTENTUID);
}
====
The NONEXISTENTUID should refer to a uid that can not be resolved using
other services.

My nsswitch.conf entry for the 'passwd' database is:

passwd: files ldap

Whenever I perform a lookup for a name that is not resolvable by the
'files' service, it tries to load the libnss_ldap library and all the
auxiliary libraries that it depends on.
It is during that process that I receive a segmentation fault 
(loading 'libcrypto.so.0.9.7').

Using gdb, I can pinpoint the location where the segfault occurs:

Line 1335 in elf/dl-load.c: __stack_prot |= PROT_EXEC;

This is what I think is going on:

As 'readelf -l libcrypto.so.0.9.7' confirms it:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg
Align
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4

the, 'libcrypto' library needs its stack to be executable.

in 'nss/nsswitch.c', the service specific shared library is loaded at
line 344:
  ni->library->lib_handle = __libc_dlopen (shlib_name);

According to 'include/dlfcn.h', line 15:
#define __libc_dlopen(name) __libc_dlopen_mode (name, RTLD_LAZY);

So here the problem is: __libc_dlopen_mode is called without specifying
the __RTLD_DLOPEN flag, so the condition at 

  Line 1321 of elf/dl-load.c:  if (mode & __RTLD_DLOPEN)

is always false, and as a result, an attempt to modify __stack_prot is
made at line 1335 of elf/dl-load.c.
Because __stack_prot has the attribute_relro attribute, the
segmentation fault is generated.

The way I see it there are two possible solutions to this problem:
1) modify 'nss/nsswitch.c' at line 344 to:
  ni->library->lib_handle = 
    __libc_dlopen_mode (shlib_name, (__RTLD_DLOPEN | RTLD_LAZY));
or
2) modify 'include/dlfcn.h' at line 15 to:
#define __libc_dlopen(name) \
          __libc_dlopen_mode (name, (__RTLD_DLOPEN | RTLD_LAZY));

I cannot foresee the consequences of these changes, so I leave this up
to you guys.

I personnaly tried the first option because I thought it had the least
impact and this indeed seems to work for me.

In case I'm totally wrong about this, I'd appreciate some hints about
what to do instead.

As an afterthought: Searching for this in bugzilla, I found a bug report
that might be related to this:

  http://sources.redhat.com/bugzilla/show_bug.cgi?id=419
   (ld.so crashes if libgcc_s.so.1 has an executable stack)

It think so because at various locations in the glibc tree,
'libgcc_s.so.1' is loaded by means of 

  void *handle = __libc_dlopen ("libgcc_s.so.1");

which, as I explained above, doesn't pass the __RTLD_DLOPEN flag.
That could therefore be the cause of the segmentation fault there,
so if option 2) above would be chosen, those kinds of problems
would also be fixed.

Regards,

Vincent Newsum.

PS: Here is the patch that I applied:

=======

diff -Naur glibc-2.3.4-20041104.orig/nss/nsswitch.c
glibc-2.3.4-20041104/nss/nsswitch.c
--- glibc-2.3.4-20041104.orig/nss/nsswitch.c	2004-06-15
22:10:03.000000000 +0200
+++ glibc-2.3.4-20041104/nss/nsswitch.c	2004-11-07 11:14:19.628167352
+0100
@@ -341,7 +341,8 @@
 				  ".so"),
 			__nss_shlib_revision);
 
-	      ni->library->lib_handle = __libc_dlopen (shlib_name);
+	      ni->library->lib_handle = __libc_dlopen_mode (shlib_name,
+							    (__RTLD_DLOPEN | RTLD_LAZY));
 	      if (ni->library->lib_handle == NULL)
 		{
 		  /* Failed to load the library.  */

-- 
------------------------------------------------------------------------------
The disclaimer that applies to e-mail from
TNO Physics and Electronics Laboratory
can be found on: http://www.tno.nl/disclaimer/email.html
------------------------------------------------------------------------------


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