From 7a67a7ee048e83361dbd4afda5c84ff0b8646542 Mon Sep 17 00:00:00 2001 From: jdp Date: Mon, 30 Aug 1999 01:50:41 +0000 Subject: When checking to see if a shared object is already loaded, look for a device/inode match if no pathname match is found. --- libexec/rtld-elf/map_object.c | 7 ++++++- libexec/rtld-elf/rtld.c | 33 ++++++++++++++++++++++++++++----- libexec/rtld-elf/rtld.h | 5 ++++- 3 files changed, 38 insertions(+), 7 deletions(-) (limited to 'libexec/rtld-elf') 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 #include +#include #include #include @@ -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 #include +#include #include #include @@ -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 *); -- cgit v1.1