Skip to content

Commit

Permalink
x86/vdso: Error out if the vDSO isn't a valid DSO
Browse files Browse the repository at this point in the history
Some distros has been playing with toolchain changes that can affect
the type of ELF objects built.  Occasionally, this goes wrong and
the vDSO ends up not being a DSO at all.  This causes the kernel to
end up broken in a surprisingly subtle way -- glibc apparently
silently ignores a vDSO that isn't a DSO, so everything works,
albeit slowly, until users try a different libc implementation.

Make the kernel build process a bit more robust: fail outright if
the vDSO isn't ET_DYN or is missing its PT_DYNAMIC segment.  I've
never seen this in an unmodified kernel.

See: https://github.com/docker/docker/issues/23378

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/8a30e0a07c3b47ff917a8daa2df5e407cc0c6698.1468878336.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Andy Lutomirski authored and Ingo Molnar committed Jul 19, 2016
1 parent be8a18e commit 57f90c3
Showing 1 changed file with 6 additions and 0 deletions.
6 changes: 6 additions & 0 deletions arch/x86/entry/vdso/vdso2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,

ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_LE(&hdr->e_phoff));

if (hdr->e_type != ET_DYN)
fail("input is not a shared object\n");

/* Walk the segment table. */
for (i = 0; i < GET_LE(&hdr->e_phnum); i++) {
if (GET_LE(&pt[i].p_type) == PT_LOAD) {
Expand Down Expand Up @@ -49,6 +52,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
if (stripped_len < load_size)
fail("stripped input is too short\n");

if (!dyn)
fail("input has no PT_DYNAMIC section -- your toolchain is buggy\n");

/* Walk the dynamic table */
for (i = 0; dyn + i < dyn_end &&
GET_LE(&dyn[i].d_tag) != DT_NULL; i++) {
Expand Down

0 comments on commit 57f90c3

Please sign in to comment.