diff options
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | elf/ldconfig.h | 3 | ||||
-rw-r--r-- | elf/readlib.c | 17 | ||||
-rw-r--r-- | sysdeps/generic/readelflib.c | 26 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sparc/readelflib.c | 14 |
5 files changed, 64 insertions, 14 deletions
@@ -1,3 +1,21 @@ +2000-05-26 Andreas Jaeger <aj@suse.de> + + * elf/ldconfig.h: Update parameter list for process_elf_file. + + * sysdeps/unix/sysv/linux/sparc/readelflib.c (process_elf_file): + Add parameter file_length and pass it ot process_elf*file. + + * sysdeps/generic/readelflib.c (check_ptr): New. + (process_elf_file): Use check_ptr to check all accesses to the + mmapped file. Add parameter file_length. + + * elf/readlib.c (known_libs): Use <gnu/lib-names.h> to specify + library names. + + * sunrpc/xdr_intXX_t.c (xdr_uint8_t): Fix conversion. + Closes PR libc/1573, reported by Bradley White + <bww@laurelnetworks.com>. + 2000-05-25 Ulrich Drepper <drepper@redhat.com> * sysdeps/i386/fpu/bits/mathinline.h: Define expm1 inline only if diff --git a/elf/ldconfig.h b/elf/ldconfig.h index ecdbb14..a94df64 100644 --- a/elf/ldconfig.h +++ b/elf/ldconfig.h @@ -46,7 +46,8 @@ extern int process_file (const char *file_name, const char *lib, int *flag, /* Declared in readelflib.c. */ extern int process_elf_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents); + char **soname, void *file_contents, + size_t file_length); /* Declared in ldconfig.c. */ diff --git a/elf/readlib.c b/elf/readlib.c index 580d802..1914267 100644 --- a/elf/readlib.c +++ b/elf/readlib.c @@ -35,6 +35,7 @@ #include <sys/mman.h> #include <sys/stat.h> +#include <gnu/lib-names.h> #include "ldconfig.h" @@ -49,23 +50,26 @@ struct known_names static struct known_names interpreters [] = { - {"/lib/ld-linux.so.2", FLAG_ELF_LIBC6}, + {"/lib/" LD_LINUX_SO, FLAG_ELF_LIBC6}, {"/lib/ld-linux.so.1", FLAG_ELF_LIBC5} }; static struct known_names known_libs [] = { - {"libc.so.6", FLAG_ELF_LIBC6}, + /* Old names: */ {"libc.so.5", FLAG_ELF_LIBC5}, - {"libm.so.6", FLAG_ELF_LIBC6}, - {"libm.so.5", FLAG_ELF_LIBC5} + {"libm.so.5", FLAG_ELF_LIBC5}, + /* Current names: */ + {LIBC_SO, FLAG_ELF_LIBC6}, + {LIBM_SO, FLAG_ELF_LIBC6} }; /* Returns 0 if everything is ok, != 0 in case of error. */ int -process_file (const char *file_name, const char *lib, int *flag, char **soname, int is_link) +process_file (const char *file_name, const char *lib, int *flag, + char **soname, int is_link) { FILE *file; struct stat statbuf; @@ -156,7 +160,8 @@ process_file (const char *file_name, const char *lib, int *flag, char **soname, goto done; } - if (process_elf_file (file_name, lib, flag, soname, file_contents)) + if (process_elf_file (file_name, lib, flag, soname, file_contents, + statbuf.st_size)) ret = 1; done: diff --git a/sysdeps/generic/readelflib.c b/sysdeps/generic/readelflib.c index 645c912..270c9b0 100644 --- a/sysdeps/generic/readelflib.c +++ b/sysdeps/generic/readelflib.c @@ -23,10 +23,24 @@ which need to handle both 32bit and 64bit ELF libraries, this file is included twice for each arch size. */ +/* check_ptr checks that a pointer is in the mmaped file and doesn't + point outside it. */ +#define check_ptr(ptr) \ +do \ + { \ + if ((void *)(ptr) < file_contents \ + || (void *)(ptr) > (file_contents+file_length)) \ + { \ + error (0, 0, _("file %s is truncated\n"), file_name); \ + return 1; \ + } \ + } \ + while (0); + /* Returns 0 if everything is ok, != 0 in case of error. */ int -process_elf_file (const char *file_name, const char *lib, int *flag, char **soname, - void *file_contents) +process_elf_file (const char *file_name, const char *lib, int *flag, + char **soname, void *file_contents, size_t file_length) { int i; unsigned int j; @@ -65,6 +79,7 @@ process_elf_file (const char *file_name, const char *lib, int *flag, char **sona /* Get information from elf program header. */ elf_pheader = (ElfW(Phdr) *) (elf_header->e_phoff + file_contents); + check_ptr (elf_pheader); /* The library is an elf library, now search for soname and libc5/libc6. */ @@ -77,6 +92,8 @@ process_elf_file (const char *file_name, const char *lib, int *flag, char **sona for (i = 0, segment = elf_pheader; i < elf_header->e_phnum; i++, segment++) { + check_ptr (segment); + switch (segment->p_type) { case PT_LOAD: @@ -94,6 +111,7 @@ process_elf_file (const char *file_name, const char *lib, int *flag, char **sona break; case PT_INTERP: program_interpreter = (char *) (file_contents + segment->p_offset); + check_ptr (program_interpreter); /* Check if this is enough to classify the binary. */ for (j = 0; j < sizeof (interpreters) / sizeof (interpreters [0]); @@ -120,15 +138,18 @@ process_elf_file (const char *file_name, const char *lib, int *flag, char **sona return 1; dynamic_segment = (ElfW(Dyn) *) (file_contents + dynamic_addr); + check_ptr (dynamic_segment); /* Find the string table. */ dynamic_strings = NULL; for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; ++dyn_entry) { + check_ptr (dyn_entry); if (dyn_entry->d_tag == DT_STRTAB) { dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); + check_ptr (dynamic_strings); break; } } @@ -143,6 +164,7 @@ process_elf_file (const char *file_name, const char *lib, int *flag, char **sona if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME) { char *name = dynamic_strings + dyn_entry->d_un.d_val; + check_ptr (name); if (dyn_entry->d_tag == DT_NEEDED) { diff --git a/sysdeps/unix/sysv/linux/sparc/readelflib.c b/sysdeps/unix/sysv/linux/sparc/readelflib.c index d956ad9..f500627 100644 --- a/sysdeps/unix/sysv/linux/sparc/readelflib.c +++ b/sysdeps/unix/sysv/linux/sparc/readelflib.c @@ -20,23 +20,27 @@ int process_elf32_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents); + char **soname, void *file_contents, + size_t file_length); int process_elf64_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents); + char **soname, void *file_contents, + size_t file_length); /* Returns 0 if everything is ok, != 0 in case of error. */ int process_elf_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents) + char **soname, void *file_contents, size_t file_length) { ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents; int ret; if (elf_header->e_ident [EI_CLASS] == ELFCLASS32) - return process_elf32_file (file_name, lib, flag, soname, file_contents); + return process_elf32_file (file_name, lib, flag, soname, file_contents, + file_length); else { - ret = process_elf64_file (file_name, lib, flag, soname, file_contents); + ret = process_elf64_file (file_name, lib, flag, soname, file_contents, + file_length); /* Sparc 64bit libraries are always libc.so.6+. */ if (!ret) *flag = FLAG_SPARC_LIB64|FLAG_ELF_LIBC6; |