svn commit: r200645 - in stable/8: libexec/rtld-elf sys/sys
Konstantin Belousov
kib at FreeBSD.org
Thu Dec 17 19:53:17 UTC 2009
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. */
More information about the svn-src-stable
mailing list