tech-userlevel archive

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

ld.so support for DF_1_{BIND_NOW,NODELETE,NOOPEN} / RTLD_{NODELETE,NOLOAD}



Here's a patch to add support as per the subject.

Any comments before I commit?

Should I change the values of RTLD_{DELETE,NOOPEN}? They're taken from FreeBSD.

I haven't written atf tests for nodelete as I'm not 100% sure how to dlopening dso with dependencies easily. Any suggestions?

Nick



Index: distrib/sets/lists/tests/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/tests/mi,v
retrieving revision 1.180
diff -u -p -u -r1.180 mi
--- distrib/sets/lists/tests/mi 17 Dec 2010 19:13:48 -0000      1.180
+++ distrib/sets/lists/tests/mi 19 Dec 2010 17:27:20 -0000
@@ -381,6 +381,8 @@
 ./usr/libdata/debug/usr/tests/lib/libutil/t_sockaddr_snprintf.debug    
tests-lib-debug         debug,atf
 ./usr/libdata/debug/usr/tests/libexec                                  
tests-lib-debug
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so                                
tests-libexec-debug
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen1.debug   
tests-libexec-debug     debug,atf
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen2.debug   
tests-libexec-debug     debug,atf
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-cleared.debug        
tests-libexec-debug     debug,atf
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-false.debug  
tests-libexec-debug     debug,atf
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlinfo.debug         
tests-libexec-debug     debug,atf
@@ -1618,6 +1620,9 @@
 ./usr/tests/libexec/Atffile                    tests-lib-tests         atf
 ./usr/tests/libexec/ld.elf_so                  tests-libexec-tests
 ./usr/tests/libexec/ld.elf_so/Atffile          tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/h_df_1_noopen1   tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/h_df_1_noopen2   tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/t_df_1_noopen    tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/t_dlerror-cleared        tests-libexec-tests     
atf
 ./usr/tests/libexec/ld.elf_so/t_dlerror-false  tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/t_dlinfo         tests-libexec-tests     atf
Index: include/dlfcn.h
===================================================================
RCS file: /cvsroot/src/include/dlfcn.h,v
retrieving revision 1.21
diff -u -p -u -r1.21 dlfcn.h
--- include/dlfcn.h     7 Jan 2010 07:35:35 -0000       1.21
+++ include/dlfcn.h     19 Dec 2010 17:27:20 -0000
@@ -64,6 +64,8 @@ __END_DECLS
 #define RTLD_NOW       2
 #define RTLD_GLOBAL    0x100           /* Allow global searches in object */
 #define RTLD_LOCAL     0x200
+#define RTLD_NODELETE  0x01000         /* Do not remove members. */
+#define RTLD_NOLOAD    0x02000         /* Do not load if not already loaded. */
 #if defined(_NETBSD_SOURCE)
 #define DL_LAZY                RTLD_LAZY       /* Compat */
 #endif
Index: lib/libpthread/Makefile
===================================================================
RCS file: /cvsroot/src/lib/libpthread/Makefile,v
retrieving revision 1.70
diff -u -p -u -r1.70 Makefile
--- lib/libpthread/Makefile     6 Aug 2010 05:35:42 -0000       1.70
+++ lib/libpthread/Makefile     19 Dec 2010 17:27:20 -0000
@@ -33,6 +33,8 @@ CPPFLAGS+=-I${NETBSDSRCDIR}/sys -I${.CUR
 
 LIB=   pthread
 
+LDFLAGS+=      -Wl,-znodlopen
+
 #
 # NOTE: When you create a new file for libpthread, make sure that pthread.c
 # gets a reference to a symbol in that file.  Otherwise, Unix's stupid static
Index: share/man/man3/dlfcn.3
===================================================================
RCS file: /cvsroot/src/share/man/man3/dlfcn.3,v
retrieving revision 1.27
diff -u -p -u -r1.27 dlfcn.3
--- share/man/man3/dlfcn.3      24 Jan 2010 22:54:14 -0000      1.27
+++ share/man/man3/dlfcn.3      19 Dec 2010 17:27:20 -0000
@@ -65,24 +65,29 @@ under program control.
 The
 .Fn dlopen
 function takes the name of a shared object as the first argument.
-The shared object is mapped into the address space, relocated, and
-its external references are resolved in the same way as is done
-with the implicitly loaded shared libraries at program startup.
-.Pp
 The
 .Fa path
 argument can be specified as either an absolute pathname to a shared object
 or just the name of the shared object itself.
 When an absolute pathname is specified,
 only the path provided will be searched.
-When just a shared object name is specified, the same search rules apply that 
are
-used for
+When just a shared object name is specified, the same search rules apply that
+are used for
 .Dq intrinsic
 shared object searches.
+.Po
+see
+.Xr ld.elf_so 5
+.Pc
 .Pp
 Shared libraries take the following form:
 .Do lib Ns Ao name Ac Ns .so Ns Oo .xx Ns Oo .yy Oc Oc Dc .
 .Pp
+The shared object is mapped into the address space, relocated, and
+its external references are resolved in the same way as is done
+with the implicitly loaded shared libraries at program startup.
+.Pp
+The
 If the first argument is
 .Dv NULL ,
 .Fn dlopen
@@ -97,7 +102,7 @@ The
 .Fa mode
 parameter specifies symbol resolution time and symbol visibility.
 One of the following values may be used to specify symbol resolution time:
-.Bl -tag -width "RTLD_LAZYXX" -offset indent
+.Bl -tag -width "RTLD_GLOBALXX" -offset indent
 .It Dv RTLD_NOW
 Symbols are resolved immediately.
 .It Dv RTLD_LAZY
@@ -107,7 +112,7 @@ This is the default value if resolution 
 .Pp
 One of the following values may be used to specify symbol visibility:
 .Pp
-.Bl -tag -width "RTLD_GLOBAL" -compact -offset indent
+.Bl -tag -width "RTLD_GLOBALXX" -offset indent
 .It Dv RTLD_GLOBAL
 The object's symbols and the symbols of its dependencies will be visible to
 other objects.
@@ -126,6 +131,23 @@ and later opened with
 then it is promoted to
 .Dv RTLD_GLOBAL .
 .Pp
+Additionally, one of the following flags may be ORed into the
+.Fa mode
+argument:
+.Bl -tag -width "RTLD_NODELETEXX" -offset indent
+.It Dv RTLD_NODELETE
+Prevents unload of the loaded object on
+.Fn dlclose .
+The same behaviour may be requested by
+.Fl "z nodelete"
+option of the static linker
+.Xr ld 1 .
+.It Dv RTLD_NOLOAD
+Only return valid handle for the object if it is already loaded in
+the process address space, otherwise do not load the object and return
+.Dv NULL .
+.El
+.Pp
 .Fn dlopen
 returns a
 .Fa handle
@@ -192,13 +214,13 @@ Thus an object can reference its own sym
 dependencies without calling
 .Fn dlopen .
 .It Dv RTLD_DEFAULT
-All the visible shared objects and the executable will be searched in the 
order they
-were loaded.
+All the visible shared objects and the executable will be searched in the order
+they were loaded.
 .It Dv RTLD_NEXT
 The search for
 .Fa symbol
-is limited to the visible shared objects which were loaded after the one 
issuing the
-call to
+is limited to the visible shared objects which were loaded after the one
+issuing the call to
 .Fn dlsym .
 Thus, if
 .Fn dlsym
Index: sys/sys/exec_elf.h
===================================================================
RCS file: /cvsroot/src/sys/sys/exec_elf.h,v
retrieving revision 1.107
diff -u -p -u -r1.107 exec_elf.h
--- sys/sys/exec_elf.h  13 Dec 2010 19:37:32 -0000      1.107
+++ sys/sys/exec_elf.h  19 Dec 2010 17:27:21 -0000
@@ -668,7 +670,10 @@ typedef struct {
 #define        DT_HIPROC       0x7fffffff
 
 /* Flag values for DT_FLAGS_1 (incomplete) */
+#define        DF_1_BIND_NOW   0x00000001      /* Same as DF_BIND_NOW */
+#define        DF_1_NODELETE   0x00000008      /* Set the RTLD_NODELETE for 
object */
 #define        DF_1_INITFIRST  0x00000020      /* Object's init/fini take 
priority */
+#define        DF_1_NOOPEN     0x00000040      /* Do not allow loading on 
dlopen() */
 
 /*
  * Auxiliary Vectors
Index: libexec/ld.elf_so/headers.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/headers.c,v
retrieving revision 1.37
diff -u -p -u -r1.37 headers.c
--- libexec/ld.elf_so/headers.c 16 Oct 2010 17:48:12 -0000      1.37
+++ libexec/ld.elf_so/headers.c 19 Dec 2010 17:27:21 -0000
@@ -242,8 +242,14 @@ _rtld_digest_dynamic(const char *execnam
                        break;
 #endif
                case DT_FLAGS_1:
-                       obj->initfirst =
+                       obj->z_now =
+                           ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0);
+                       obj->z_nodelete =
+                           ((dynp->d_un.d_val & DF_1_NODELETE) != 0);
+                       obj->z_initfirst =
                            ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
+                       obj->z_noopen =
+                           ((dynp->d_un.d_val & DF_1_NOOPEN) != 0);
                        break;
                }
        }
Index: libexec/ld.elf_so/load.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/load.c,v
retrieving revision 1.41
diff -u -p -u -r1.41 load.c
--- libexec/ld.elf_so/load.c    19 Dec 2010 17:26:51 -0000      1.41
+++ libexec/ld.elf_so/load.c    19 Dec 2010 17:27:21 -0000
@@ -109,7 +109,7 @@ _rtld_objlist_find(Objlist *list, const 
  * on failure.
  */
 Obj_Entry *
-_rtld_load_object(const char *filepath, int mode)
+_rtld_load_object(const char *filepath, int flags)
 {
        Obj_Entry *obj;
        int fd = -1;
@@ -153,6 +153,18 @@ _rtld_load_object(const char *filepath, 
                        return NULL;
                _rtld_digest_dynamic(filepath, obj);
 
+               if (flags & _RTLD_DLOPEN) {
+                       if (obj->z_noopen || (flags & _RTLD_NOLOAD)) {
+                               dbg(("refusing to load non-loadable \"%s\"",
+                                   obj->path));
+                               _rtld_error("Cannot dlopen non-loadable %s",
+                                   obj->path);
+                               munmap(obj->mapbase, obj->mapsize);
+                               _rtld_obj_free(obj);
+                               return OBJ_ERR;
+                       }
+               }
+
                *_rtld_objtail = obj;
                _rtld_objtail = &obj->next;
                _rtld_objcount++;
@@ -168,12 +180,12 @@ _rtld_load_object(const char *filepath, 
 
        ++obj->refcount;
 #ifdef RTLD_LOADER
-       if (mode & RTLD_MAIN && !obj->mainref) {
+       if (flags & _RTLD_MAIN && !obj->mainref) {
                obj->mainref = 1;
                dbg(("adding %p (%s) to _rtld_list_main", obj, obj->path));
                _rtld_objlist_push_tail(&_rtld_list_main, obj);
        }
-       if (mode & RTLD_GLOBAL && !obj->globalref) {
+       if (flags & _RTLD_GLOBAL && !obj->globalref) {
                obj->globalref = 1;
                dbg(("adding %p (%s) to _rtld_list_global", obj, obj->path));
                _rtld_objlist_push_tail(&_rtld_list_global, obj);
@@ -183,7 +195,8 @@ _rtld_load_object(const char *filepath, 
 }
 
 static bool
-_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed, 
int mode)
+_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed,
+    int flags)
 {
        Library_Xform *x = _rtld_xforms;
        Obj_Entry *o = NULL;
@@ -240,7 +253,7 @@ _rtld_load_by_name(const char *name, Obj
                for (j = 0; j < RTLD_MAX_LIBRARY &&
                    x->entry[i].library[j] != NULL; j++) {
                        o = _rtld_load_library(x->entry[i].library[j], obj,
-                           mode);
+                           flags);
                        if (o == NULL) {
                                xwarnx("could not load %s for %s",
                                    x->entry[i].library[j], name);
@@ -266,7 +279,7 @@ _rtld_load_by_name(const char *name, Obj
        if (got)
                return true;
 
-       return ((*needed)->obj = _rtld_load_library(name, obj, mode)) != NULL;
+       return ((*needed)->obj = _rtld_load_library(name, obj, flags)) != NULL;
 }
 
 
@@ -276,7 +289,7 @@ _rtld_load_by_name(const char *name, Obj
  * returns -1 on failure.
  */
 int
-_rtld_load_needed_objects(Obj_Entry *first, int mode)
+_rtld_load_needed_objects(Obj_Entry *first, int flags)
 {
        Obj_Entry *obj;
        int status = 0;
@@ -287,11 +300,25 @@ _rtld_load_needed_objects(Obj_Entry *fir
                for (needed = obj->needed; needed != NULL;
                    needed = needed->next) {
                        const char *name = obj->strtab + needed->name;
-                       if (!_rtld_load_by_name(name, obj, &needed, mode))
+#ifdef RTLD_LOADER
+                       Obj_Entry *nobj;
+#endif
+                       if (!_rtld_load_by_name(name, obj, &needed,
+                           flags & ~_RTLD_NOLOAD))
                                status = -1;    /* FIXME - cleanup */
 #ifdef RTLD_LOADER
                        if (status == -1)
                                return status;
+
+                       if (flags & _RTLD_MAIN)
+                               continue;
+
+                       nobj = needed->obj;
+                       if (nobj->z_nodelete && !obj->ref_nodel) {
+                               dbg(("obj %s nodelete", nobj->path));
+                               _rtld_ref_dag(nobj);
+                               nobj->ref_nodel = true;
+                       }
 #endif
                }
        }
@@ -310,7 +337,7 @@ _rtld_preload(const char *preload_path)
        if (preload_path != NULL && *preload_path != '\0') {
                cp = buf = xstrdup(preload_path);
                while ((path = strsep(&cp, " :")) != NULL && status == 0) {
-                       if (!_rtld_load_object(path, RTLD_MAIN))
+                       if (!_rtld_load_object(path, _RTLD_MAIN))
                                status = -1;
                        else
                                dbg((" preloaded \"%s\"", path));
Index: libexec/ld.elf_so/reloc.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/reloc.c,v
retrieving revision 1.102
diff -u -p -u -r1.102 reloc.c
--- libexec/ld.elf_so/reloc.c   5 Apr 2010 14:01:26 -0000       1.102
+++ libexec/ld.elf_so/reloc.c   19 Dec 2010 17:27:22 -0000
@@ -195,7 +195,7 @@ _rtld_relocate_objects(Obj_Entry *first,
 #if defined(__hppa__)
                bind_now = 1;
 #endif
-               if (bind_now) {
+               if (obj->z_now || bind_now) {
                        dbg(("doing immediate PLT binding"));
                        if (_rtld_relocate_plt_objects(obj) < 0)
                                ok = 0;
Index: libexec/ld.elf_so/rtld.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/rtld.c,v
retrieving revision 1.136
diff -u -p -u -r1.136 rtld.c
--- libexec/ld.elf_so/rtld.c    19 Dec 2010 17:26:51 -0000      1.136
+++ libexec/ld.elf_so/rtld.c    19 Dec 2010 17:27:22 -0000
@@ -147,7 +147,7 @@ _rtld_call_fini_functions(int force)
                if (obj->refcount > 0 && !force) {
                        continue;
                }
-               if (obj->fini == NULL || obj->fini_called || obj->initfirst) {
+               if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) {
                        continue;
                }
                dbg (("calling fini function %s at %p",  obj->path,
@@ -188,7 +188,7 @@ _rtld_call_init_functions()
        /* First pass: objects marked with DF_1_INITFIRST. */
        SIMPLEQ_FOREACH(elm, &initlist, link) {
                obj = elm->obj;
-               if (obj->init == NULL || obj->init_called || !obj->initfirst) {
+               if (obj->init == NULL || obj->init_called || !obj->z_initfirst) 
{
                        continue;
                }
                dbg (("calling init function %s at %p (DF_1_INITFIRST)",
@@ -568,7 +568,7 @@ _rtld(Elf_Addr *sp, Elf_Addr relocbase)
        }
 
        dbg(("loading needed objects"));
-       if (_rtld_load_needed_objects(_rtld_objmain, RTLD_MAIN) == -1)
+       if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1)
                _rtld_die();
 
        dbg(("relocating objects"));
@@ -760,13 +760,35 @@ _rtld_unload_object(Obj_Entry *root, boo
        }
 }
 
+void
+_rtld_ref_dag(Obj_Entry *root)
+{
+       const Needed_Entry *needed;
+
+       assert(root);
+
+       ++root->refcount;
+
+       dbg(("incremented reference on \"%s\" (%d)", root->path,
+           root->refcount));
+       for (needed = root->needed; needed != NULL;
+            needed = needed->next) {
+               if (needed->obj != NULL)
+                       _rtld_ref_dag(needed->obj);
+       }
+}
+
 static void
 _rtld_unref_dag(Obj_Entry *root)
 {
 
        assert(root);
        assert(root->refcount != 0);
+
        --root->refcount;
+       dbg(("decremented reference on \"%s\" (%d)", root->path,
+           root->refcount));
+
        if (root->refcount == 0) {
                const Needed_Entry *needed;
 
@@ -815,6 +837,15 @@ dlopen(const char *name, int mode)
 {
        Obj_Entry **old_obj_tail = _rtld_objtail;
        Obj_Entry *obj = NULL;
+       int flags = _RTLD_DLOPEN;
+       bool nodelete;
+       bool now;
+
+       flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0;
+       flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0;
+       
+       nodelete = (mode & RTLD_NODELETE) ? true : false;
+       now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false;
 
        _rtld_debug.r_state = RT_ADD;
        _rtld_debug_state();
@@ -823,17 +854,18 @@ dlopen(const char *name, int mode)
                obj = _rtld_objmain;
                obj->refcount++;
        } else
-               obj = _rtld_load_library(name, _rtld_objmain, mode);
+               obj = _rtld_load_library(name, _rtld_objmain, flags);
+
 
        if (obj != NULL) {
                ++obj->dl_refcount;
                if (*old_obj_tail != NULL) {    /* We loaded something new. */
                        assert(*old_obj_tail == obj);
 
-                       if (_rtld_load_needed_objects(obj, mode) == -1 ||
+                       if (_rtld_load_needed_objects(obj, flags) == -1 ||
                            (_rtld_init_dag(obj),
                            _rtld_relocate_objects(obj,
-                           ((mode & 3) == RTLD_NOW))) == -1) {
+                           (now || obj->z_now))) == -1) {
                                _rtld_unload_object(obj, false);
                                obj->dl_refcount--;
                                obj = NULL;
@@ -841,6 +873,13 @@ dlopen(const char *name, int mode)
                                _rtld_call_init_functions();
                        }
                }
+               if (obj != NULL) {
+                       if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) {
+                               dbg(("dlopen obj %s nodelete", obj->path));
+                               _rtld_ref_dag(obj);
+                               obj->z_nodelete = obj->ref_nodel = true;
+                       }
+               }
        }
        _rtld_debug.r_state = RT_CONSISTENT;
        _rtld_debug_state();
Index: libexec/ld.elf_so/rtld.h
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/rtld.h,v
retrieving revision 1.96
diff -u -p -u -r1.96 rtld.h
--- libexec/ld.elf_so/rtld.h    5 Dec 2010 00:56:06 -0000       1.96
+++ libexec/ld.elf_so/rtld.h    19 Dec 2010 17:27:22 -0000
@@ -128,7 +128,6 @@ typedef struct _rtld_library_xform_t {
 
 #define RTLD_MAGIC     0xd550b87a
 #define RTLD_VERSION   1
-#define        RTLD_MAIN       0x800
 
 typedef struct Struct_Obj_Entry {
        Elf32_Word      magic;          /* Magic number (sanity check) */
@@ -202,10 +201,17 @@ typedef struct Struct_Obj_Entry {
                                         * called */
                        fini_called:1,  /* True if .fini function has been 
                                         * called */
-                       initfirst:1,    /* True if object's .init/.fini take
+                       z_now:1,        /* True if object's symbols should be
+                                          bound immediately */
+                       z_nodelete:1,   /* True if object should never be
+                                          unloaded */
+                       z_initfirst:1,  /* True if object's .init/.fini take
                                         * priority over others */
-                       phdr_loaded:1;  /* Phdr is loaded and doesn't need to
+                       z_noopen:1,     /* True if object should never be
+                                          dlopen'ed */
+                       phdr_loaded:1,  /* Phdr is loaded and doesn't need to
                                         * be freed. */
+                       ref_nodel:1;    /* Refcount increased to prevent 
dlclose */
 
        struct link_map linkmap;        /* for GDB */
 
@@ -251,6 +257,14 @@ extern Objlist _rtld_list_global;
 extern Objlist _rtld_list_main;
 extern Elf_Sym _rtld_sym_zero;
 
+#define        RTLD_MODEMASK 0x3
+
+/* Flags for _rtld_load_object() and friends. */
+#define        _RTLD_GLOBAL    0x01    /* Add object to global DAG. */
+#define        _RTLD_MAIN      0x02
+#define        _RTLD_NOLOAD    0x04    /* dlopen() specified RTLD_NOLOAD. */
+#define        _RTLD_DLOPEN    0x08    /* Load_object() called from dlopen(). 
*/
+
 /* rtld.c */
 
 /* We export these symbols using _rtld_symbol_lookup and is_exported. */
@@ -274,6 +288,7 @@ void _rtld_linkmap_delete(Obj_Entry *);
 void _rtld_objlist_push_head(Objlist *, Obj_Entry *);
 void _rtld_objlist_push_tail(Objlist *, Obj_Entry *);
 Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *);
+void _rtld_ref_dag(Obj_Entry *);
 
 /* expand.c */
 size_t _rtld_expand_path(char *, size_t, const char *, const char *,\
@@ -288,6 +303,7 @@ Obj_Entry *_rtld_load_object(const char 
 int _rtld_load_needed_objects(Obj_Entry *, int);
 int _rtld_preload(const char *);
 
+#define        OBJ_ERR (Obj_Entry *)(-1)
 /* path.c */
 void _rtld_add_paths(const char *, Search_Path **, const char *);
 void _rtld_process_hints(const char *, Search_Path **, Library_Xform **,
Index: libexec/ld.elf_so/search.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/search.c,v
retrieving revision 1.22
diff -u -p -u -r1.22 search.c
--- libexec/ld.elf_so/search.c  7 Aug 2010 19:47:34 -0000       1.22
+++ libexec/ld.elf_so/search.c  19 Dec 2010 17:27:23 -0000
@@ -67,7 +67,7 @@ static Obj_Entry *_rtld_search_library_p
 
 static Obj_Entry *
 _rtld_search_library_path(const char *name, size_t namelen,
-    const char *dir, size_t dirlen, int mode)
+    const char *dir, size_t dirlen, int flags)
 {
        char pathname[MAXPATHLEN];
        size_t pathnamelen;
@@ -93,7 +93,7 @@ _rtld_search_library_path(const char *na
        pathname[pathnamelen] = '\0';
 
        dbg(("  Trying \"%s\"", pathname));
-       obj = _rtld_load_object(pathname, mode);
+       obj = _rtld_load_object(pathname, flags);
        if (obj == NULL) {
                Search_Path *path;
 
@@ -115,7 +115,7 @@ _rtld_search_library_path(const char *na
  * loaded shared object, whose library search path will be searched.
  */
 Obj_Entry *
-_rtld_load_library(const char *name, const Obj_Entry *refobj, int mode)
+_rtld_load_library(const char *name, const Obj_Entry *refobj, int flags)
 {
        char tmperror[512], *tmperrorp;
        Search_Path *sp;
@@ -145,18 +145,18 @@ _rtld_load_library(const char *name, con
 
        for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next)
                if ((obj = _rtld_search_library_path(name, namelen,
-                   sp->sp_path, sp->sp_pathlen, mode)) != NULL)
+                   sp->sp_path, sp->sp_pathlen, flags)) != NULL)
                        goto pathfound;
 
        if (refobj != NULL)
                for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next)
                        if ((obj = _rtld_search_library_path(name,
-                           namelen, sp->sp_path, sp->sp_pathlen, mode)) != 
NULL)
+                           namelen, sp->sp_path, sp->sp_pathlen, flags)) != 
NULL)
                                goto pathfound;
 
        for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next)
                if ((obj = _rtld_search_library_path(name, namelen,
-                   sp->sp_path, sp->sp_pathlen, mode)) != NULL)
+                   sp->sp_path, sp->sp_pathlen, flags)) != NULL)
                        goto pathfound;
 
        _rtld_error("Shared object \"%s\" not found", name);
@@ -164,6 +164,12 @@ _rtld_load_library(const char *name, con
 
 pathfound:
        /*
+        * The library has been found, but it couldn't be loaded for some
+        * reason.
+        */
+       if (obj == OBJ_ERR)
+               return NULL;
+       /*
         * Successfully found a library; restore the dlerror state as it was
         * before _rtld_load_library() was called (any failed call to
         * _rtld_search_library_path() will set the dlerror state, but if the
@@ -177,5 +183,10 @@ pathfound:
        return obj;
 
 found:
-       return _rtld_load_object(pathname, mode);
+       obj = _rtld_load_object(pathname, flags);
+       if (obj == OBJ_ERR)
+               return NULL;
+
+       return obj;
 }
+
Index: tests/libexec/ld.elf_so/Makefile
===================================================================
RCS file: /cvsroot/src/tests/libexec/ld.elf_so/Makefile,v
retrieving revision 1.2
diff -u -p -u -r1.2 Makefile
--- tests/libexec/ld.elf_so/Makefile    14 Dec 2010 05:57:32 -0000      1.2
+++ tests/libexec/ld.elf_so/Makefile    19 Dec 2010 17:27:23 -0000
@@ -1,6 +1,8 @@
 # $NetBSD
 #
 
+NOMAN=         # defined
+
 .include <bsd.own.mk>
 
 TESTSDIR=      ${TESTSBASE}/libexec/ld.elf_so
@@ -9,4 +11,14 @@ TESTS_C+=     t_dlerror-cleared t_dlerror-fa
 
 LDADD.t_dlerror-false= -Wl,-rpath,/var/nonexistent/lib
 
+TESTS_SH+=             t_df_1_noopen
+
+BINDIR=                        ${TESTSDIR}
+PROGS+=                        h_df_1_noopen1
+SRCS.h_df_1_noopen1=   h_df_1_noopen.c
+
+PROGS+=                        h_df_1_noopen2
+SRCS.h_df_1_noopen2=   h_df_1_noopen.c
+LDADD.h_df_1_noopen2=  -lpthread
+
 .include <bsd.test.mk>
Index: tests/libexec/ld.elf_so/h_df_1_noopen.c
===================================================================
RCS file: tests/libexec/ld.elf_so/h_df_1_noopen.c
diff -N tests/libexec/ld.elf_so/h_df_1_noopen.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/libexec/ld.elf_so/h_df_1_noopen.c     19 Dec 2010 17:27:23 -0000
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <dlfcn.h>
+#include <err.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+       void *handle;
+
+       handle = dlopen("libpthread.so", RTLD_NOLOAD);
+       if (handle == NULL)
+               errx(1, dlerror());
+
+       printf("libpthread loaded successfully\n");
+       return 0;
+}
Index: tests/libexec/ld.elf_so/t_df_1_noopen.sh
===================================================================
RCS file: tests/libexec/ld.elf_so/t_df_1_noopen.sh
diff -N tests/libexec/ld.elf_so/t_df_1_noopen.sh
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/libexec/ld.elf_so/t_df_1_noopen.sh    19 Dec 2010 17:27:23 -0000
@@ -0,0 +1,61 @@
+# $NetBSD$
+#
+# Copyright (c) 2008 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+atf_test_case df_1_noopen1
+df_1_noopen1_head()
+{
+       atf_set "descr" "Checks DF_1_NOOPEN prevents dlopening of library"
+}
+df_1_noopen1_body()
+{
+       cat >expout <<EOF
+h_df_1_noopen1: Cannot dlopen non-loadable /usr/lib/libpthread.so
+EOF
+
+       atf_check -o file:expout "$(atf_get_srcdir)/h_df_1_noopen1"
+       atf_expect_exit 1 "libpthread is marked DF_1_NOOPEN"
+}
+
+atf_test_case df_1_noopen2
+df_1_noopen2_head()
+{
+       atf_set "descr" "Checks DF_1_NOOPEN is allowed on already loaded 
library"
+}
+df_1_noopen2_body()
+{
+       cat >expout <<EOF
+libpthread loaded successfully
+EOF
+
+       atf_check -o file:expout "$(atf_get_srcdir)/h_df_1_noopen2"
+}
+
+atf_init_test_cases()
+{
+       atf_add_test_case df_1_noopen1
+       atf_add_test_case df_1_noopen2
+}




Home | Main Index | Thread Index | Old Index