This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
>>>>> Andreas Jaeger writes: > ldconfig crashed when one of the elf structures is broken and a > pointer points outside the mmapped region. I've added now checks to > prevent the most common cases. We can still segfault if e.g. the end > of file is in the middle of a string - but I don't think we should > test all those cases and concentrate on the common ones first. > I'll commit this patch later, > Andreas I've changed the library names in readlib a bit to use <gnu/lib-names.h> and commited this now. FYI I've appended the patch, Andreas 2000-05-26 Andreas Jaeger <aj@suse.de> * sysdeps/generic/readelflib.c (check_ptr): New. (process_elf_file): Use check_ptr to check all accesses to the mmapped file. * elf/readlib.c (known_libs): Use <gnu/lib-names.h> to specify library names. ============================================================ Index: elf/ldconfig.h --- elf/ldconfig.h 2000/05/07 21:20:01 1.3 +++ elf/ldconfig.h 2000/05/26 10:14:18 @@ -46,7 +46,8 @@ /* 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. */ ============================================================ Index: elf/readlib.c --- elf/readlib.c 2000/04/11 16:22:06 1.3 +++ elf/readlib.c 2000/05/26 10:14:18 @@ -35,6 +35,7 @@ #include <sys/mman.h> #include <sys/stat.h> +#include <gnu/lib-names.h> #include "ldconfig.h" @@ -49,23 +50,26 @@ 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 @@ 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: ============================================================ Index: sysdeps/generic/readelflib.c --- sysdeps/generic/readelflib.c 1999/12/04 07:56:05 1.1 +++ sysdeps/generic/readelflib.c 2000/05/26 10:14:18 @@ -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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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) { ============================================================ Index: sysdeps/unix/sysv/linux/sparc/readelflib.c --- sysdeps/unix/sysv/linux/sparc/readelflib.c 1999/12/04 07:55:35 1.1 +++ sysdeps/unix/sysv/linux/sparc/readelflib.c 2000/05/26 10:14:19 @@ -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 size) { 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; -- Andreas Jaeger SuSE Labs aj@suse.de private aj@arthur.rhein-neckar.de
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |