Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Tue, 19 Sep 2017 09:46:19 -0700
From: John Reiser <jreiser@...wagon.com>
To: musl@...ts.openwall.com
Subject: preventable SIGSEGV when bad AT_SYSINFO_EHDR

__dls3() and friends in musl/ldso/dynlink.c should check Elf headers more carefully.
I saw a SIGSEGV in decode_dyn() because vdso_base = ElfXX_auxv[{AT_SYSINFO_EHDR}].a_ptr
pointed to a region that was all zero, and thus vdso.dynv == 0.  The operating system
kernel is the only one who can perform a fork() or clone(), but other software can
perform execve().  In my case that other software had a bug.  However, the blame
for the SIGSEGV rests on __dls3() because it did not validate input data.  [This is
the stuff of exploits.]  Calling a_crash() is OK; but a preventable SIGSEGV must be
avoided, both directly and because it indicates a lack of secure implementation.

It is [mostly] reasonable that __dls3() should trust that a non-zero vdso_base points to
a region that is readable, is as big and as aligned as an ElfXX_Ehdr, and is const
(no other thread is writing it, neither is any other process via a shared memory mapping);
but after that ldso should check.

In particular, these should be checked:
   0 == memcmp(ELFMAG, &.e_ident[EI_MAG0], SELFMAG)
   .e_machine matches the executing ldso
   .e_ident[{EI_CLASS, EI_DATA}] match the executing ldso
   .e_phnum != 0
   .e_phentsize >= sizeof(ElfXX_Phdr);  and larger *IS ALLOWED*: derived classes, etc.
   .e_phnum * .e_phentsize is not too large  [loops that increment a pointer by .e_phentsize]
   .e_phoff >= sizeof(ElfXX_Ehdr);  overlap of Ehdr and Phdr is a logical error
   (.e_phoff + .e_phnum * .e_phentsize) < .st_size;  no access beyond EOF

-- 

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.