]> git.baikalelectronics.ru Git - kernel.git/commit
binfmt_elf: fix PT_INTERP bss handling
authorRoland McGrath <roland@redhat.com>
Wed, 9 Sep 2009 02:49:40 +0000 (19:49 -0700)
committerJames Morris <jmorris@namei.org>
Thu, 10 Sep 2009 10:11:12 +0000 (20:11 +1000)
commit531d37974fdc2ee2cb5e0cbf0db677ffe50b8fa0
tree513bd54b92aad6ba44173e11e85a3203c26583fb
parentaa64d7d0b85facc46faf7bfb11342ccf5c1baa4e
binfmt_elf: fix PT_INTERP bss handling

In fs/binfmt_elf.c, load_elf_interp() calls padzero() for .bss even if
the PT_LOAD has no PROT_WRITE and no .bss.  This generates EFAULT.

Here is a small test case.  (Yes, there are other, useful PT_INTERP
which have only .text and no .data/.bss.)

----- ptinterp.S
_start: .globl _start
 nop
 int3
-----
$ gcc -m32 -nostartfiles -nostdlib -o ptinterp ptinterp.S
$ gcc -m32 -Wl,--dynamic-linker=ptinterp -o hello hello.c
$ ./hello
Segmentation fault  # during execve() itself

After applying the patch:
$ ./hello
Trace trap  # user-mode execution after execve() finishes

If the ELF headers are actually self-inconsistent, then dying is fine.
But having no PROT_WRITE segment is perfectly normal and correct if
there is no segment with p_memsz > p_filesz (i.e. bss).  John Reiser
suggested checking for PROT_WRITE in the bss logic.  I think it makes
most sense to simply apply the bss logic only when there is bss.

This patch looks less trivial than it is due to some reindentation.
It just moves the "if (last_bss > elf_bss) {" test up to include the
partial-page bss logic as well as the more-pages bss logic.

Reported-by: John Reiser <jreiser@bitwagon.com>
Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
fs/binfmt_elf.c