Module Name:    src
Committed By:   skrll
Date:           Fri Dec 24 12:41:44 UTC 2010

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/include: dlfcn.h
        src/lib/libpthread: Makefile
        src/libexec/ld.elf_so: headers.c load.c reloc.c rtld.c rtld.h search.c
        src/share/man/man3: dlfcn.3
        src/sys/sys: exec_elf.h
        src/tests/libexec/ld.elf_so: Makefile
Added Files:
        src/tests/libexec/ld.elf_so: h_df_1_noopen.c t_df_1_noopen.sh

Log Message:
Add support for DF_1_BIND_NOW, DF_1_NODELETE and DF_1_NOOPEN marked
objects, and the RTLD_NODELETE and RTLD_NOLOAD flags to dlopen(3).

Mark libpthread as DF_1_NOOPEN and use it to test the functionality.

Somewhat taken from FreeBSD.

Fixes PR 42029.

OK from christos and joerg.


To generate a diff of this commit:
cvs rdiff -u -r1.187 -r1.188 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.21 -r1.22 src/include/dlfcn.h
cvs rdiff -u -r1.70 -r1.71 src/lib/libpthread/Makefile
cvs rdiff -u -r1.37 -r1.38 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.41 -r1.42 src/libexec/ld.elf_so/load.c
cvs rdiff -u -r1.102 -r1.103 src/libexec/ld.elf_so/reloc.c
cvs rdiff -u -r1.136 -r1.137 src/libexec/ld.elf_so/rtld.c
cvs rdiff -u -r1.96 -r1.97 src/libexec/ld.elf_so/rtld.h
cvs rdiff -u -r1.22 -r1.23 src/libexec/ld.elf_so/search.c
cvs rdiff -u -r1.27 -r1.28 src/share/man/man3/dlfcn.3
cvs rdiff -u -r1.107 -r1.108 src/sys/sys/exec_elf.h
cvs rdiff -u -r1.2 -r1.3 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/libexec/ld.elf_so/h_df_1_noopen.c \
    src/tests/libexec/ld.elf_so/t_df_1_noopen.sh

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.187 src/distrib/sets/lists/tests/mi:1.188
--- src/distrib/sets/lists/tests/mi:1.187	Thu Dec 23 15:27:44 2010
+++ src/distrib/sets/lists/tests/mi	Fri Dec 24 12:41:42 2010
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.187 2010/12/23 15:27:44 pgoyette Exp $
+# $NetBSD: mi,v 1.188 2010/12/24 12:41:42 skrll Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -387,6 +387,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
@@ -1632,6 +1634,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: src/include/dlfcn.h
diff -u src/include/dlfcn.h:1.21 src/include/dlfcn.h:1.22
--- src/include/dlfcn.h:1.21	Thu Jan  7 07:35:35 2010
+++ src/include/dlfcn.h	Fri Dec 24 12:41:42 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: dlfcn.h,v 1.21 2010/01/07 07:35:35 skrll Exp $	*/
+/*	$NetBSD: dlfcn.h,v 1.22 2010/12/24 12:41:42 skrll Exp $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -64,6 +64,8 @@
 #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: src/lib/libpthread/Makefile
diff -u src/lib/libpthread/Makefile:1.70 src/lib/libpthread/Makefile:1.71
--- src/lib/libpthread/Makefile:1.70	Fri Aug  6 05:35:42 2010
+++ src/lib/libpthread/Makefile	Fri Dec 24 12:41:42 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.70 2010/08/06 05:35:42 christos Exp $
+#	$NetBSD: Makefile,v 1.71 2010/12/24 12:41:42 skrll Exp $
 #
 
 WARNS=	4
@@ -33,6 +33,8 @@
 
 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: src/libexec/ld.elf_so/headers.c
diff -u src/libexec/ld.elf_so/headers.c:1.37 src/libexec/ld.elf_so/headers.c:1.38
--- src/libexec/ld.elf_so/headers.c:1.37	Sat Oct 16 17:48:12 2010
+++ src/libexec/ld.elf_so/headers.c	Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: headers.c,v 1.37 2010/10/16 17:48:12 skrll Exp $	 */
+/*	$NetBSD: headers.c,v 1.38 2010/12/24 12:41:43 skrll Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: headers.c,v 1.37 2010/10/16 17:48:12 skrll Exp $");
+__RCSID("$NetBSD: headers.c,v 1.38 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -242,8 +242,14 @@
 			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: src/libexec/ld.elf_so/load.c
diff -u src/libexec/ld.elf_so/load.c:1.41 src/libexec/ld.elf_so/load.c:1.42
--- src/libexec/ld.elf_so/load.c:1.41	Sun Dec 19 17:26:51 2010
+++ src/libexec/ld.elf_so/load.c	Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: load.c,v 1.41 2010/12/19 17:26:51 skrll Exp $	 */
+/*	$NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: load.c,v 1.41 2010/12/19 17:26:51 skrll Exp $");
+__RCSID("$NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -109,7 +109,7 @@
  * 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 @@
 			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 @@
 
 	++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 @@
 }
 
 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 @@
 		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 @@
 	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 @@
  * 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 @@
 		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 @@
 	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: src/libexec/ld.elf_so/reloc.c
diff -u src/libexec/ld.elf_so/reloc.c:1.102 src/libexec/ld.elf_so/reloc.c:1.103
--- src/libexec/ld.elf_so/reloc.c:1.102	Mon Apr  5 14:01:26 2010
+++ src/libexec/ld.elf_so/reloc.c	Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: reloc.c,v 1.102 2010/04/05 14:01:26 joerg Exp $	 */
+/*	$NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -39,7 +39,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: reloc.c,v 1.102 2010/04/05 14:01:26 joerg Exp $");
+__RCSID("$NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -195,7 +195,7 @@
 #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: src/libexec/ld.elf_so/rtld.c
diff -u src/libexec/ld.elf_so/rtld.c:1.136 src/libexec/ld.elf_so/rtld.c:1.137
--- src/libexec/ld.elf_so/rtld.c:1.136	Sun Dec 19 17:26:51 2010
+++ src/libexec/ld.elf_so/rtld.c	Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.c,v 1.136 2010/12/19 17:26:51 skrll Exp $	 */
+/*	$NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.136 2010/12/19 17:26:51 skrll Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -147,7 +147,7 @@
 		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 @@
 	/* 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 @@
 	}
 
 	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 @@
 	}
 }
 
+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 @@
 {
 	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 @@
 		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 @@
 				_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: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.96 src/libexec/ld.elf_so/rtld.h:1.97
--- src/libexec/ld.elf_so/rtld.h:1.96	Sun Dec  5 00:56:06 2010
+++ src/libexec/ld.elf_so/rtld.h	Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.h,v 1.96 2010/12/05 00:56:06 joerg Exp $	 */
+/*	$NetBSD: rtld.h,v 1.97 2010/12/24 12:41:43 skrll Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -128,7 +128,6 @@
 
 #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 @@
 					 * 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_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_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 @@
 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: src/libexec/ld.elf_so/search.c
diff -u src/libexec/ld.elf_so/search.c:1.22 src/libexec/ld.elf_so/search.c:1.23
--- src/libexec/ld.elf_so/search.c:1.22	Sat Aug  7 19:47:34 2010
+++ src/libexec/ld.elf_so/search.c	Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: search.c,v 1.22 2010/08/07 19:47:34 joerg Exp $	 */
+/*	$NetBSD: search.c,v 1.23 2010/12/24 12:41:43 skrll Exp $	 */
 
 /*
  * Copyright 1996 Matt Thomas <[email protected]>
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: search.c,v 1.22 2010/08/07 19:47:34 joerg Exp $");
+__RCSID("$NetBSD: search.c,v 1.23 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -67,7 +67,7 @@
 
 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 @@
 	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 @@
  * 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 @@
 
 	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 @@
 
 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 @@
 	return obj;
 
 found:
-	return _rtld_load_object(pathname, mode);
+	obj = _rtld_load_object(pathname, flags);
+	if (obj == OBJ_ERR)
+		return NULL;
+
+	return obj;
 }
+

Index: src/share/man/man3/dlfcn.3
diff -u src/share/man/man3/dlfcn.3:1.27 src/share/man/man3/dlfcn.3:1.28
--- src/share/man/man3/dlfcn.3:1.27	Sun Jan 24 22:54:14 2010
+++ src/share/man/man3/dlfcn.3	Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-.\"	$NetBSD: dlfcn.3,v 1.27 2010/01/24 22:54:14 wiz Exp $
+.\"	$NetBSD: dlfcn.3,v 1.28 2010/12/24 12:41:43 skrll Exp $
 .\"
 .\" Copyright (c) 1998 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -65,24 +65,29 @@
 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 @@
 .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 @@
 .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 @@
 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 @@
 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: src/sys/sys/exec_elf.h
diff -u src/sys/sys/exec_elf.h:1.107 src/sys/sys/exec_elf.h:1.108
--- src/sys/sys/exec_elf.h:1.107	Mon Dec 13 19:37:32 2010
+++ src/sys/sys/exec_elf.h	Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: exec_elf.h,v 1.107 2010/12/13 19:37:32 joerg Exp $	*/
+/*	$NetBSD: exec_elf.h,v 1.108 2010/12/24 12:41:43 skrll Exp $	*/
 
 /*-
  * Copyright (c) 1994 The NetBSD Foundation, Inc.
@@ -668,7 +668,10 @@
 #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: src/tests/libexec/ld.elf_so/Makefile
diff -u src/tests/libexec/ld.elf_so/Makefile:1.2 src/tests/libexec/ld.elf_so/Makefile:1.3
--- src/tests/libexec/ld.elf_so/Makefile:1.2	Tue Dec 14 05:57:32 2010
+++ src/tests/libexec/ld.elf_so/Makefile	Fri Dec 24 12:41:43 2010
@@ -1,6 +1,8 @@
 # $NetBSD
 #
 
+NOMAN=		# defined
+
 .include <bsd.own.mk>
 
 TESTSDIR=	${TESTSBASE}/libexec/ld.elf_so
@@ -9,4 +11,14 @@
 
 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>

Added files:

Index: src/tests/libexec/ld.elf_so/h_df_1_noopen.c
diff -u /dev/null src/tests/libexec/ld.elf_so/h_df_1_noopen.c:1.1
--- /dev/null	Fri Dec 24 12:41:44 2010
+++ src/tests/libexec/ld.elf_so/h_df_1_noopen.c	Fri Dec 24 12:41:43 2010
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by
+ *
+ * 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.
+ */
+
+#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: src/tests/libexec/ld.elf_so/t_df_1_noopen.sh
diff -u /dev/null src/tests/libexec/ld.elf_so/t_df_1_noopen.sh:1.1
--- /dev/null	Fri Dec 24 12:41:44 2010
+++ src/tests/libexec/ld.elf_so/t_df_1_noopen.sh	Fri Dec 24 12:41:43 2010
@@ -0,0 +1,64 @@
+# $NetBSD: t_df_1_noopen.sh,v 1.1 2010/12/24 12:41:43 skrll Exp $
+#
+# Copyright (c) 2010 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by
+#
+# 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
+}

Reply via email to