ldconfig: pointer validy checks patch
Andreas Jaeger
aj@suse.de
Fri May 26 03:20:00 GMT 2000
>>>>> 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
More information about the Libc-hacker
mailing list