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