Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 17 Dec 2009 19:53:16 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r200645 - in stable/8: libexec/rtld-elf sys/sys
Message-ID:  <200912171953.nBHJrGbw048176@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Thu Dec 17 19:53:16 2009
New Revision: 200645
URL: http://svn.freebsd.org/changeset/base/200645

Log:
  MFC r199829:
  Implement rtld part of the support for -z nodlopen (see ld(1)).
  
  MFC r199877:
  Allow to load not-openable dso when tracing. This fixes ldd on such dso or
  dso linked to non-openable object.
  Remove '\n' at the end of error message.
  End comments with dot.

Modified:
  stable/8/libexec/rtld-elf/rtld.c
  stable/8/libexec/rtld-elf/rtld.h
  stable/8/sys/sys/elf_common.h
Directory Properties:
  stable/8/libexec/rtld-elf/   (props changed)
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/libexec/rtld-elf/rtld.c
==============================================================================
--- stable/8/libexec/rtld-elf/rtld.c	Thu Dec 17 19:48:54 2009	(r200644)
+++ stable/8/libexec/rtld-elf/rtld.c	Thu Dec 17 19:53:16 2009	(r200645)
@@ -87,7 +87,7 @@ static void die(void) __dead2;
 static void digest_dynamic(Obj_Entry *, int);
 static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
 static Obj_Entry *dlcheck(void *);
-static Obj_Entry *do_load_object(int, const char *, char *, struct stat *);
+static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int);
 static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *);
 static bool donelist_check(DoneList *, const Obj_Entry *);
 static void errmsg_restore(char *);
@@ -103,7 +103,7 @@ static void initlist_add_objects(Obj_Ent
 static bool is_exported(const Elf_Sym *);
 static void linkmap_add(Obj_Entry *);
 static void linkmap_delete(Obj_Entry *);
-static int load_needed_objects(Obj_Entry *);
+static int load_needed_objects(Obj_Entry *, int);
 static int load_preload_objects(void);
 static Obj_Entry *load_object(const char *, const Obj_Entry *, int);
 static Obj_Entry *obj_from_addr(const void *);
@@ -485,7 +485,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
     preload_tail = obj_tail;
 
     dbg("loading needed objects");
-    if (load_needed_objects(obj_main) == -1)
+    if (load_needed_objects(obj_main, 0) == -1)
 	die();
 
     /* Make a list of all objects loaded at startup. */
@@ -932,6 +932,8 @@ digest_dynamic(Obj_Entry *obj, int early
 #endif
 
 	case DT_FLAGS_1:
+		if (dynp->d_un.d_val & DF_1_NOOPEN)
+		    obj->z_noopen = true;
 		if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust)
 		    obj->z_origin = true;
 		if (dynp->d_un.d_val & DF_1_GLOBAL)
@@ -1425,7 +1427,7 @@ is_exported(const Elf_Sym *def)
  * returns -1 on failure.
  */
 static int
-load_needed_objects(Obj_Entry *first)
+load_needed_objects(Obj_Entry *first, int flags)
 {
     Obj_Entry *obj, *obj1;
 
@@ -1434,7 +1436,7 @@ load_needed_objects(Obj_Entry *first)
 
 	for (needed = obj->needed;  needed != NULL;  needed = needed->next) {
 	    obj1 = needed->obj = load_object(obj->strtab + needed->name, obj,
-		false);
+		flags & ~RTLD_LO_NOLOAD);
 	    if (obj1 == NULL && !ld_tracing)
 		return -1;
 	    if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) {
@@ -1465,7 +1467,7 @@ load_preload_objects(void)
 
 	savech = p[len];
 	p[len] = '\0';
-	if (load_object(p, NULL, false) == NULL)
+	if (load_object(p, NULL, 0) == NULL)
 	    return -1;	/* XXX - cleanup */
 	p[len] = savech;
 	p += len;
@@ -1482,7 +1484,7 @@ load_preload_objects(void)
  * on failure.
  */
 static Obj_Entry *
-load_object(const char *name, const Obj_Entry *refobj, int noload)
+load_object(const char *name, const Obj_Entry *refobj, int flags)
 {
     Obj_Entry *obj;
     int fd = -1;
@@ -1528,11 +1530,11 @@ load_object(const char *name, const Obj_
 	close(fd);
 	return obj;
     }
-    if (noload)
+    if (flags & RTLD_LO_NOLOAD)
 	return (NULL);
 
     /* First use of this object, so we must map it in */
-    obj = do_load_object(fd, name, path, &sb);
+    obj = do_load_object(fd, name, path, &sb, flags);
     if (obj == NULL)
 	free(path);
     close(fd);
@@ -1541,7 +1543,8 @@ load_object(const char *name, const Obj_
 }
 
 static Obj_Entry *
-do_load_object(int fd, const char *name, char *path, struct stat *sbp)
+do_load_object(int fd, const char *name, char *path, struct stat *sbp,
+  int flags)
 {
     Obj_Entry *obj;
     struct statfs fs;
@@ -1568,6 +1571,14 @@ do_load_object(int fd, const char *name,
     object_add_name(obj, name);
     obj->path = path;
     digest_dynamic(obj, 0);
+    if (obj->z_noopen && (flags & (RTLD_LO_DLOPEN | RTLD_LO_TRACE)) ==
+      RTLD_LO_DLOPEN) {
+	dbg("refusing to load non-loadable \"%s\"", obj->path);
+	_rtld_error("Cannot dlopen non-loadable %s", obj->path);
+	munmap(obj->mapbase, obj->mapsize);
+	obj_free(obj);
+	return (NULL);
+    }
 
     *obj_tail = obj;
     obj_tail = &obj->next;
@@ -1986,14 +1997,18 @@ dlopen(const char *name, int mode)
     Obj_Entry **old_obj_tail;
     Obj_Entry *obj;
     Objlist initlist;
-    int result, lockstate, nodelete, noload;
+    int result, lockstate, nodelete, lo_flags;
 
     LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name);
     ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1";
     if (ld_tracing != NULL)
 	environ = (char **)*get_program_var_addr("environ");
     nodelete = mode & RTLD_NODELETE;
-    noload = mode & RTLD_NOLOAD;
+    lo_flags = RTLD_LO_DLOPEN;
+    if (mode & RTLD_NOLOAD)
+	    lo_flags |= RTLD_LO_NOLOAD;
+    if (ld_tracing != NULL)
+	    lo_flags |= RTLD_LO_TRACE;
 
     objlist_init(&initlist);
 
@@ -2006,7 +2021,7 @@ dlopen(const char *name, int mode)
 	obj = obj_main;
 	obj->refcount++;
     } else {
-	obj = load_object(name, obj_main, noload);
+	obj = load_object(name, obj_main, lo_flags);
     }
 
     if (obj) {
@@ -2016,7 +2031,7 @@ dlopen(const char *name, int mode)
 	mode &= RTLD_MODEMASK;
 	if (*old_obj_tail != NULL) {		/* We loaded something new. */
 	    assert(*old_obj_tail == obj);
-	    result = load_needed_objects(obj);
+	    result = load_needed_objects(obj, RTLD_LO_DLOPEN);
 	    init_dag(obj);
 	    if (result != -1)
 		result = rtld_verify_versions(&obj->dagmembers);

Modified: stable/8/libexec/rtld-elf/rtld.h
==============================================================================
--- stable/8/libexec/rtld-elf/rtld.h	Thu Dec 17 19:48:54 2009	(r200644)
+++ stable/8/libexec/rtld-elf/rtld.h	Thu Dec 17 19:53:16 2009	(r200645)
@@ -218,6 +218,7 @@ typedef struct Struct_Obj_Entry {
     bool phdr_alloc : 1;	/* Phdr is allocated and needs to be freed. */
     bool z_origin : 1;		/* Process rpath and soname tokens */
     bool z_nodelete : 1;	/* Do not unload the object and dependencies */
+    bool z_noopen : 1;		/* Do not load on dlopen */
     bool ref_nodel : 1;		/* Refcount increased to prevent dlclose */
     bool init_scanned: 1;	/* Object is already on init list. */
     bool on_fini_list: 1;	/* Object is already on fini list. */
@@ -240,6 +241,11 @@ typedef struct Struct_Obj_Entry {
 #define SYMLOOK_DLSYM	0x02	/* Return newes versioned symbol. Used by
 				   dlsym. */
 
+/* Flags for load_object(). */
+#define	RTLD_LO_NOLOAD	0x01	/* dlopen() specified RTLD_NOLOAD. */
+#define	RTLD_LO_DLOPEN	0x02	/* Load_object() called from dlopen(). */
+#define	RTLD_LO_TRACE	0x04	/* Only tracing. */
+
 /*
  * Symbol cache entry used during relocation to avoid multiple lookups
  * of the same symbol.

Modified: stable/8/sys/sys/elf_common.h
==============================================================================
--- stable/8/sys/sys/elf_common.h	Thu Dec 17 19:48:54 2009	(r200644)
+++ stable/8/sys/sys/elf_common.h	Thu Dec 17 19:53:16 2009	(r200645)
@@ -471,6 +471,7 @@ typedef struct {
 #define	DF_1_BIND_NOW	0x00000001	/* Same as DF_BIND_NOW */
 #define	DF_1_GLOBAL	0x00000002	/* Set the RTLD_GLOBAL for object */
 #define	DF_1_NODELETE	0x00000008	/* Set the RTLD_NODELETE for object */
+#define	DF_1_NOOPEN     0x00000040	/* Do not allow loading on dlopen() */
 #define	DF_1_ORIGIN	0x00000080	/* Process $ORIGIN */
 
 /* Values for n_type.  Used in core files. */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200912171953.nBHJrGbw048176>