When checking to see if a shared object is already loaded, look for

a device/inode match if no pathname match is found.
This commit is contained in:
John Polstra 1999-08-30 01:50:41 +00:00
parent 926ea445fe
commit 7360ae0f2a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=50609
3 changed files with 38 additions and 7 deletions

View File

@ -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) -

View File

@ -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);

View File

@ -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 *);