From d0a94902b29c71b75c5fcfc5b196fb7f162e7f31 Mon Sep 17 00:00:00 2001 From: jdp Date: Sun, 18 Jul 1999 00:02:19 +0000 Subject: Change many asserts into normal errors. They were all for conditions caused by invalid shared objects rather than by internal errors. Enable format string mismatch checking for _rtld_error(). --- libexec/rtld-elf/map_object.c | 62 ++++++++++++++++++++++++++----------------- libexec/rtld-elf/rtld.c | 36 ++++++++++++++++--------- libexec/rtld-elf/rtld.h | 6 ++--- 3 files changed, 65 insertions(+), 39 deletions(-) (limited to 'libexec/rtld-elf') diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c index a393bb8..523a80b 100644 --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -22,13 +22,12 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: map_object.c,v 1.1.1.1 1998/03/07 19:24:35 jdp Exp $ + * $Id: map_object.c,v 1.2 1998/09/04 19:03:57 dfr Exp $ */ #include #include -#include #include #include #include @@ -39,14 +38,15 @@ static int protflags(int); /* Elf flags -> mmap protection */ /* - * Map a shared object into memory. The argument is a file descriptor, + * Map a shared object into memory. The "fd" argument is a file descriptor, * which must be open on the object and positioned at its beginning. + * The "path" argument is a pathname that is used only for error messages. * * The return value is a pointer to a newly-allocated Obj_Entry structure * for the shared object. Returns NULL on failure. */ Obj_Entry * -map_object(int fd) +map_object(int fd, const char *path) { Obj_Entry *obj; union { @@ -78,7 +78,7 @@ map_object(int fd) caddr_t bss_addr; if ((nbytes = read(fd, u.buf, PAGE_SIZE)) == -1) { - _rtld_error("Read error: %s", strerror(errno)); + _rtld_error("%s: read error: %s", path, strerror(errno)); return NULL; } @@ -88,25 +88,25 @@ map_object(int fd) || u.hdr.e_ident[EI_MAG1] != ELFMAG1 || u.hdr.e_ident[EI_MAG2] != ELFMAG2 || u.hdr.e_ident[EI_MAG3] != ELFMAG3) { - _rtld_error("Invalid file format"); + _rtld_error("%s: invalid file format", path); return NULL; } if (u.hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS || u.hdr.e_ident[EI_DATA] != ELF_TARG_DATA) { - _rtld_error("Unsupported file layout"); + _rtld_error("%s: unsupported file layout", path); return NULL; } if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT || u.hdr.e_version != EV_CURRENT) { - _rtld_error("Unsupported file version"); + _rtld_error("%s: unsupported file version", path); return NULL; } if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) { - _rtld_error("Unsupported file type"); + _rtld_error("%s: unsupported file type", path); return NULL; } if (u.hdr.e_machine != ELF_TARG_MACH) { - _rtld_error("Unsupported machine"); + _rtld_error("%s: unsupported machine", path); return NULL; } @@ -115,9 +115,15 @@ map_object(int fd) * not strictly required by the ABI specification, but it seems to * always true in practice. And, it simplifies things considerably. */ - assert(u.hdr.e_phentsize == sizeof(Elf_Phdr)); - assert(u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE); - assert(u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= nbytes); + if (u.hdr.e_phentsize != sizeof(Elf_Phdr)) { + _rtld_error( + "%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path); + return NULL; + } + if (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) > nbytes) { + _rtld_error("%s: program header too large", path); + return NULL; + } /* * Scan the program header entries, and save key information. @@ -134,7 +140,10 @@ map_object(int fd) switch (phdr->p_type) { case PT_LOAD: - assert(nsegs < 2); + if (nsegs >= 2) { + _rtld_error("%s: too many PT_LOAD segments", path); + return NULL; + } segs[nsegs] = phdr; ++nsegs; break; @@ -151,13 +160,18 @@ map_object(int fd) ++phdr; } if (phdyn == NULL) { - _rtld_error("Object is not dynamically-linked"); + _rtld_error("%s: object is not dynamically-linked", path); return NULL; } - assert(nsegs == 2); - assert(segs[0]->p_align >= PAGE_SIZE); - assert(segs[1]->p_align >= PAGE_SIZE); + if (nsegs < 2) { + _rtld_error("%s: too few PT_LOAD segments", path); + return NULL; + } + if (segs[0]->p_align < PAGE_SIZE || segs[1]->p_align < PAGE_SIZE) { + _rtld_error("%s: PT_LOAD segments not page-aligned", path); + return NULL; + } /* * Map the entire address space of the object, to stake out our @@ -172,13 +186,13 @@ map_object(int fd) mapbase = mmap(base_addr, mapsize, protflags(segs[0]->p_flags), MAP_PRIVATE, fd, base_offset); if (mapbase == (caddr_t) -1) { - _rtld_error("mmap of entire address space failed: %s", - strerror(errno)); + _rtld_error("%s: mmap of entire address space failed: %s", + path, strerror(errno)); return NULL; } if (base_addr != NULL && mapbase != base_addr) { - _rtld_error("mmap returned wrong address: wanted %p, got %p", - base_addr, mapbase); + _rtld_error("%s: mmap returned wrong address: wanted %p, got %p", + path, base_addr, mapbase); munmap(mapbase, mapsize); return NULL; } @@ -190,7 +204,7 @@ map_object(int fd) data_addr = mapbase + (data_vaddr - base_vaddr); if (mmap(data_addr, data_vlimit - data_vaddr, protflags(segs[1]->p_flags), MAP_PRIVATE|MAP_FIXED, fd, data_offset) == (caddr_t) -1) { - _rtld_error("mmap of data failed: %s", strerror(errno)); + _rtld_error("%s: mmap of data failed: %s", path, strerror(errno)); return NULL; } @@ -207,7 +221,7 @@ map_object(int fd) if (bss_vlimit > bss_vaddr) { /* There is something to do */ if (mmap(bss_addr, bss_vlimit - bss_vaddr, protflags(segs[1]->p_flags), MAP_PRIVATE|MAP_FIXED|MAP_ANON, -1, 0) == (caddr_t) -1) { - _rtld_error("mmap of bss failed: %s", strerror(errno)); + _rtld_error("%s: mmap of bss failed: %s", path, strerror(errno)); return NULL; } } diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 313e8ef..796742a 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: rtld.c,v 1.27 1999/07/09 16:22:55 jdp Exp $ + * $Id: rtld.c,v 1.28 1999/07/14 04:09:11 jdp Exp $ */ /* @@ -73,7 +73,7 @@ static void call_fini_functions(Obj_Entry *); static void call_init_functions(Obj_Entry *); static void die(void); static void digest_dynamic(Obj_Entry *); -static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t); +static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); static Obj_Entry *dlcheck(void *); static char *find_library(const char *, const Obj_Entry *); static const char *gethints(void); @@ -170,6 +170,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) char **env; Elf_Auxinfo *aux; Elf_Auxinfo *auxp; + const char *argv0; /* * On entry, the dynamic linker itself has not been relocated yet. @@ -200,6 +201,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr); __progname = obj_rtld.path; + argv0 = argv[0] != NULL ? argv[0] : "(null)"; environ = env; trust = geteuid() == getuid() && getegid() == getgid(); @@ -226,7 +228,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); + obj_main = map_object(fd, argv0); close(fd); if (obj_main == NULL) die(); @@ -244,10 +246,11 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr)); assert(aux_info[AT_ENTRY] != NULL); entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr; - obj_main = digest_phdr(phdr, phnum, entry); + if ((obj_main = digest_phdr(phdr, phnum, entry, argv0)) == NULL) + die(); } - obj_main->path = xstrdup(argv[0] ? argv[0] : "(null)"); + obj_main->path = xstrdup(argv0); obj_main->mainprog = true; digest_dynamic(obj_main); @@ -543,7 +546,7 @@ digest_dynamic(Obj_Entry *obj) * returns an Obj_Entry structure. */ static Obj_Entry * -digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry) +digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) { Obj_Entry *obj = CNEW(Obj_Entry); const Elf_Phdr *phlimit = phdr + phnum; @@ -554,13 +557,19 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry) switch (ph->p_type) { case PT_PHDR: - assert((const Elf_Phdr *) ph->p_vaddr == phdr); + if ((const Elf_Phdr *)ph->p_vaddr != phdr) { + _rtld_error("%s: invalid PT_PHDR", path); + return NULL; + } obj->phdr = (const Elf_Phdr *) ph->p_vaddr; obj->phsize = ph->p_memsz; break; case PT_LOAD: - assert(nsegs < 2); + if (nsegs >= 2) { + _rtld_error("%s: too many PT_LOAD segments", path); + return NULL; + } if (nsegs == 0) { /* First load segment */ obj->vaddrbase = trunc_page(ph->p_vaddr); obj->mapbase = (caddr_t) obj->vaddrbase; @@ -579,7 +588,10 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry) break; } } - assert(nsegs == 2); + if (nsegs < 2) { + _rtld_error("%s: too few PT_LOAD segments", path); + return NULL; + } obj->entry = entry; return obj; @@ -944,7 +956,7 @@ load_object(char *path) return NULL; } dbg("loading \"%s\"", path); - obj = map_object(fd); + obj = map_object(fd, path); close(fd); if (obj == NULL) { free(path); @@ -1366,9 +1378,9 @@ symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj, const Elf_Sym *symp; const char *strp; - assert(symnum < obj->nchains); + if (symnum >= obj->nchains) + return NULL; /* Bad object */ symp = obj->symtab + symnum; - assert(symp->st_name != 0); strp = obj->strtab + symp->st_name; if (strcmp(name, strp) == 0) diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 1380e74..95a057a 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: rtld.h,v 1.5 1998/09/04 19:03:57 dfr Exp $ + * $Id: rtld.h,v 1.6 1999/04/09 00:28:31 jdp Exp $ */ #ifndef RTLD_H /* { */ @@ -123,8 +123,8 @@ typedef struct Struct_Obj_Entry { #define RTLD_MAGIC 0xd550b87a #define RTLD_VERSION 1 -extern void _rtld_error(const char *, ...); -extern Obj_Entry *map_object(int); +extern void _rtld_error(const char *, ...) __printflike(1, 2); +extern Obj_Entry *map_object(int, const char *); extern void *xcalloc(size_t); extern void *xmalloc(size_t); extern char *xstrdup(const char *); -- cgit v1.1