diff options
author | Kjell Wooding <kjell@cvs.openbsd.org> | 2004-07-05 00:47:41 +0000 |
---|---|---|
committer | Kjell Wooding <kjell@cvs.openbsd.org> | 2004-07-05 00:47:41 +0000 |
commit | 82e4f3eea83b547ac6c4cfd8b18a12b4eae2248c (patch) | |
tree | 268c36a330c68a2c7f0edfc5fd49936ca5383969 | |
parent | acc4658306c75f40488561ff70a796bb05e57812 (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.c | 20 | ||||
-rw-r--r-- | libexec/ld.so/library_mquery.c | 22 | ||||
-rw-r--r-- | libexec/ld.so/resolve.c | 7 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 6 |
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 { |