From: John Marino Date: Sat, 30 Nov 2013 09:47:20 +0000 (+0100) Subject: rtld: Implement Interpose DSO flag X-Git-Tag: v3.9.0~1089 X-Git-Url: https://gitweb.dragonflybsd.org/~nant/dragonfly.git/commitdiff_plain/22f5846a17808dfa6cb3d59db7e21c3d8d7b49e5 rtld: Implement Interpose DSO flag This implementation was sponsored by FreeBSD Foundation. Taken from: SVN 256101 (07 OCT 2013) --- diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 1a9a47f1d0..968a526d13 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -116,6 +116,7 @@ static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); static void objlist_init(Objlist *); static void objlist_push_head(Objlist *, Obj_Entry *); static void objlist_push_tail(Objlist *, Obj_Entry *); +static void objlist_put_after(Objlist *, Obj_Entry *, Obj_Entry *); static void objlist_remove(Objlist *, Obj_Entry *); static void *path_enumerate(const char *, path_enum_proc, void *); static int relocate_object_dag(Obj_Entry *root, bool bind_now, @@ -323,6 +324,7 @@ ld_utrace_log(int event, void *handle, void *mapbase, size_t mapsize, func_ptr_type _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) { + Obj_Entry *last_interposer; Elf_Auxinfo *aux_info[AT_COUNT]; int i; int argc; @@ -566,8 +568,14 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) die(); /* Make a list of all objects loaded at startup. */ + last_interposer = obj_main; for (obj = obj_list; obj != NULL; obj = obj->next) { - objlist_push_tail(&list_main, obj); + if (obj->z_interpose && obj != obj_main) { + objlist_put_after(&list_main, last_interposer, obj); + last_interposer = obj; + } else { + objlist_push_tail(&list_main, obj); + } obj->refcount++; } @@ -1199,6 +1207,8 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, obj->z_nodelete = true; if (dynp->d_un.d_val & DF_1_LOADFLTR) obj->z_loadfltr = true; + if (dynp->d_un.d_val & DF_1_INTERPOSE) + obj->z_interpose = true; if (dynp->d_un.d_val & DF_1_NODEFLIB) obj->z_nodeflib = true; break; @@ -2031,6 +2041,7 @@ static int load_preload_objects(void) { char *p = ld_preload; + Obj_Entry *obj; static const char delim[] = " \t:;"; if (p == NULL) @@ -2040,7 +2051,6 @@ load_preload_objects(void) while (*p != '\0') { size_t len = strcspn(p, delim); char savech; - Obj_Entry *obj; SymLook req; int res; @@ -2049,6 +2059,7 @@ load_preload_objects(void) obj = load_object(p, -1, NULL, 0); if (obj == NULL) return -1; /* XXX - cleanup */ + obj->z_interpose = true; p[len] = savech; p += len; p += strspn(p, delim); @@ -2463,6 +2474,23 @@ objlist_push_tail(Objlist *list, Obj_Entry *obj) STAILQ_INSERT_TAIL(list, elm, link); } +static void +objlist_put_after(Objlist *list, Obj_Entry *listobj, Obj_Entry *obj) +{ + Objlist_Entry *elm, *listelm; + + STAILQ_FOREACH(listelm, list, link) { + if (listelm->obj == listobj) + break; + } + elm = NEW(Objlist_Entry); + elm->obj = obj; + if (listelm != NULL) + STAILQ_INSERT_AFTER(list, listelm, elm, link); + else + STAILQ_INSERT_TAIL(list, elm, link); +} + static void objlist_remove(Objlist *list, Obj_Entry *obj) { diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index e5e9cb0ab9..58e7aef9fb 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -242,6 +242,7 @@ typedef struct Struct_Obj_Entry { bool z_nodelete : 1; /* Do not unload the object and dependencies */ bool z_noopen : 1; /* Do not load on dlopen */ bool z_loadfltr : 1; /* Immediately load filtees */ + bool z_interpose : 1; /* Interpose all objects but main */ bool z_nodeflib : 1; /* Don't search default /usr/lib path */ bool ref_nodel : 1; /* Refcount increased to prevent dlclose */ bool init_scanned: 1; /* Object is already on init list. */