summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-elf
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1999-08-30 01:50:41 +0000
committerjdp <jdp@FreeBSD.org>1999-08-30 01:50:41 +0000
commit7a67a7ee048e83361dbd4afda5c84ff0b8646542 (patch)
tree997498cd3ff38258372b4f509859c44bd0498400 /libexec/rtld-elf
parent4382ccec34f7f0bb2721459e301575176a175688 (diff)
downloadFreeBSD-src-7a67a7ee048e83361dbd4afda5c84ff0b8646542.zip
FreeBSD-src-7a67a7ee048e83361dbd4afda5c84ff0b8646542.tar.gz
When checking to see if a shared object is already loaded, look for
a device/inode match if no pathname match is found.
Diffstat (limited to 'libexec/rtld-elf')
-rw-r--r--libexec/rtld-elf/map_object.c7
-rw-r--r--libexec/rtld-elf/rtld.c33
-rw-r--r--libexec/rtld-elf/rtld.h5
3 files changed, 38 insertions, 7 deletions
diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
index 42cb3e5..ca353c7 100644
--- a/libexec/rtld-elf/map_object.c
+++ b/libexec/rtld-elf/map_object.c
@@ -27,6 +27,7 @@
#include <sys/param.h>
#include <sys/mman.h>
+#include <sys/stat.h>
#include <errno.h>
#include <stddef.h>
@@ -47,7 +48,7 @@ static int protflags(int); /* Elf flags -> mmap protection */
* for the shared object. Returns NULL on failure.
*/
Obj_Entry *
-map_object(int fd, const char *path)
+map_object(int fd, const char *path, const struct stat *sb)
{
Obj_Entry *obj;
union {
@@ -228,6 +229,10 @@ map_object(int fd, const char *path)
}
obj = obj_new();
+ if (sb != NULL) {
+ obj->dev = sb->st_dev;
+ obj->ino = sb->st_ino;
+ }
obj->mapbase = mapbase;
obj->mapsize = mapsize;
obj->textsize = round_page(segs[0]->p_vaddr + segs[0]->p_memsz) -
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 1e104ac..ef5f917 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -37,6 +37,7 @@
#include <sys/param.h>
#include <sys/mman.h>
+#include <sys/stat.h>
#include <dlfcn.h>
#include <err.h>
@@ -244,7 +245,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */
int fd = aux_info[AT_EXECFD]->a_un.a_val;
dbg("loading main program");
- obj_main = map_object(fd, argv0);
+ obj_main = map_object(fd, argv0, NULL);
close(fd);
if (obj_main == NULL)
die();
@@ -983,20 +984,42 @@ static Obj_Entry *
load_object(char *path)
{
Obj_Entry *obj;
+ int fd = -1;
+ struct stat sb;
for (obj = obj_list->next; obj != NULL; obj = obj->next)
if (strcmp(obj->path, path) == 0)
break;
- if (obj == NULL) { /* First use of this object, so we must map it in */
- int fd;
-
+ /*
+ * If we didn't find a match by pathname, open the file and check
+ * again by device and inode. This avoids false mismatches caused
+ * by multiple links or ".." in pathnames.
+ *
+ * To avoid a race, we open the file and use fstat() rather than
+ * using stat().
+ */
+ if (obj == NULL) {
if ((fd = open(path, O_RDONLY)) == -1) {
_rtld_error("Cannot open \"%s\"", path);
return NULL;
}
+ if (fstat(fd, &sb) == -1) {
+ _rtld_error("Cannot fstat \"%s\"", path);
+ close(fd);
+ return NULL;
+ }
+ for (obj = obj_list->next; obj != NULL; obj = obj->next) {
+ if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) {
+ close(fd);
+ break;
+ }
+ }
+ }
+
+ if (obj == NULL) { /* First use of this object, so we must map it in */
dbg("loading \"%s\"", path);
- obj = map_object(fd, path);
+ obj = map_object(fd, path, &sb);
close(fd);
if (obj == NULL) {
free(path);
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index d23932b..ab26d01 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -49,6 +49,7 @@ typedef unsigned char bool;
#define false 0
#define true 1
+struct stat;
struct Struct_Obj_Entry;
typedef struct Struct_Objlist_Entry {
@@ -82,6 +83,8 @@ typedef struct Struct_Obj_Entry {
Objlist dldags; /* Object belongs to these dlopened DAGs (%) */
Objlist dagmembers; /* DAG has these members (%) */
char *path; /* Pathname of underlying file (%) */
+ dev_t dev; /* Object's filesystem's device */
+ ino_t ino; /* Object's inode number */
unsigned long mark; /* Set to "curmark" to avoid repeat visits */
int refcount;
int dl_refcount; /* Number of times loaded by dlopen */
@@ -135,7 +138,7 @@ typedef struct Struct_Obj_Entry {
#define RTLD_VERSION 1
extern void _rtld_error(const char *, ...) __printflike(1, 2);
-extern Obj_Entry *map_object(int, const char *);
+extern Obj_Entry *map_object(int, const char *, const struct stat *);
extern void *xcalloc(size_t);
extern void *xmalloc(size_t);
extern char *xstrdup(const char *);
OpenPOWER on IntegriCloud