summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Wooding <kjell@cvs.openbsd.org>2004-07-05 00:47:41 +0000
committerKjell Wooding <kjell@cvs.openbsd.org>2004-07-05 00:47:41 +0000
commit82e4f3eea83b547ac6c4cfd8b18a12b4eae2248c (patch)
tree268c36a330c68a2c7f0edfc5fd49936ca5383969
parentacc4658306c75f40488561ff70a796bb05e57812 (diff)
Fix an issue where a shared library could be loaded at two different
locations by resolving all dlopens back to a dev/inode. i.e. Don't load a library if the dev/inode it stats back to matches one already in our list. fix started (and ok'ed) drahn@. ok deraadt@. "doesn't break anything yet" pval@ art@ brad@
-rw-r--r--libexec/ld.so/library.c20
-rw-r--r--libexec/ld.so/library_mquery.c22
-rw-r--r--libexec/ld.so/resolve.c7
-rw-r--r--libexec/ld.so/resolve.h6
4 files changed, 49 insertions, 6 deletions
diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c
index d2c7e2d1504..aecb3ac9813 100644
--- a/libexec/ld.so/library.c
+++ b/libexec/ld.so/library.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library.c,v 1.33 2003/09/02 15:17:51 drahn Exp $ */
+/* $OpenBSD: library.c,v 1.34 2004/07/05 00:47:40 kjell Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -362,6 +362,7 @@ _dl_tryload_shlib(const char *libname, int type)
Elf_Dyn *dynp = 0;
Elf_Ehdr *ehdr;
Elf_Phdr *phdp;
+ struct stat sb;
#define ROUND_PG(x) (((x) + align) & ~(align))
#define TRUNC_PG(x) ((x) & ~(align))
@@ -378,6 +379,19 @@ _dl_tryload_shlib(const char *libname, int type)
return(0);
}
+ if ( _dl_fstat(libfile, &sb) < 0) {
+ _dl_errno = DL_CANT_OPEN;
+ return(0);
+ }
+
+ for (object = _dl_objects; object != NULL; object = object->next) {
+ if (object->dev == sb.st_dev &&
+ object->inode == sb.st_ino) {
+ _dl_close(libfile);
+ return(object);
+ }
+ }
+
_dl_read(libfile, hbuf, sizeof(hbuf));
ehdr = (Elf_Ehdr *)hbuf;
if (ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1 ||
@@ -491,7 +505,11 @@ _dl_tryload_shlib(const char *libname, int type)
if (object) {
object->load_size = maxva - minva; /*XXX*/
object->load_list = load_list;
+ /* set inode, dev from stat info */
+ object->dev = sb.st_dev;
+ object->inode = sb.st_ino;
} else {
+ /* XXX not possible. object cannot come back NULL */
_dl_munmap((void *)libaddr, maxva - minva);
_dl_load_list_free(load_list);
}
diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c
index 97691a42311..0ea683dd7ad 100644
--- a/libexec/ld.so/library_mquery.c
+++ b/libexec/ld.so/library_mquery.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library_mquery.c,v 1.13 2003/09/02 15:17:51 drahn Exp $ */
+/* $OpenBSD: library_mquery.c,v 1.14 2004/07/05 00:47:40 kjell Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -368,7 +368,8 @@ _dl_tryload_shlib(const char *libname, int type)
int off;
int size;
Elf_Addr load_end = 0;
-
+ struct stat sb;
+
#define ROUND_PG(x) (((x) + align) & ~(align))
#define TRUNC_PG(x) ((x) & ~(align))
@@ -384,6 +385,19 @@ _dl_tryload_shlib(const char *libname, int type)
return(0);
}
+ if ( _dl_fstat(libfile, &sb) < 0) {
+ _dl_errno = DL_CANT_OPEN;
+ return(0);
+ }
+
+ for (object = _dl_objects; object != NULL; object = object->next) {
+ if (object->dev == sb.st_dev &&
+ object->inode == sb.st_ino) {
+ _dl_close(libfile);
+ return(object);
+ }
+ }
+
_dl_read(libfile, hbuf, sizeof(hbuf));
ehdr = (Elf_Ehdr *)hbuf;
if (ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1 ||
@@ -530,7 +544,11 @@ retry:
if (object) {
object->load_size = (Elf_Addr)load_end - (Elf_Addr)lowld->start;
object->load_list = lowld;
+ /* set inode, dev from stat info */
+ object->dev = sb.st_dev;
+ object->inode = sb.st_ino;
} else {
+ /* XXX no point. object is never returned NULL */
_dl_load_list_free(lowld);
}
return(object);
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index 871b5a0af53..2c6155b3e9d 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.23 2004/05/25 18:07:20 mickey Exp $ */
+/* $OpenBSD: resolve.c,v 1.24 2004/07/05 00:47:40 kjell Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -76,7 +76,6 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, const u_long *dl_data,
_dl_printf("objname [%s], dynp %p, dl_data %p, objtype %x laddr %lx, loff %lx\n",
objname, dynp, dl_data, objtype, laddr, loff);
#endif
-
object = _dl_malloc(sizeof(elf_object_t));
object->prev = object->next = NULL;
@@ -144,6 +143,10 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, const u_long *dl_data,
object->refcount = 1;
object->first_child = NULL;
object->last_child = NULL;
+ /* default dev, inode for dlopen-able objects. */
+ object->dev = 0;
+ object->inode = 0;
+
return(object);
}
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index 15973beb419..1f949b7e7e3 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.30 2004/05/25 18:07:20 mickey Exp $ */
+/* $OpenBSD: resolve.h,v 1.31 2004/07/05 00:47:40 kjell Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -122,6 +122,10 @@ typedef struct elf_object {
struct dep_node *first_child;
struct dep_node *last_child;
+
+ /* for object confirmation */
+ dev_t dev;
+ ino_t inode;
} elf_object_t;
struct dep_node {