Messages in this thread Patch in this message | | | From | Azat Khuzhin <> | Subject | [PATCH] fs/binfmt_elf: use ELF_ET_DYN_BASE for PIE (ET_DYN with INTERP) binaries | Date | Mon, 31 Jan 2022 23:17:16 +0300 |
| |
Since 9630f0d60fec ELF_ET_DYN_BASE is not used as a load_bias anymore and this breaks PIE binaries, since after this change data segment became too nearby the stack:
Before 9630f0d60fec:
$ strace -febrk /tmp/test-stack |& head brk(NULL) = 0x555555559000 $ /tmp/test-stack bottom_of_stack = 0x7fffffffc5c0 recursion depth: 1 (stack diff: 32) ... recursion depth: 7690 (stack diff: 8365664) Segmentation fault (core dumped)
After 9630f0d60fec:
$ strace -ebrk /tmp/test-stack |& head brk(NULL) = 0x7ffff7fff000
$ /tmp/test-stack bottom_of_stack = 0x7fffffffc640 recursion depth: 1 (stack diff: 32) ... recursion depth: 146 (stack diff: 157792) Segmentation fault (core dumped)
Found this during compiling with clang, that started to randomly SIGSEGV when it eats some heap.
Reproducer:
#include <stdio.h> #include <stddef.h> #include <stdlib.h>
static int depth = 0; static void* bottom_of_stack;
int inner() { char buffer[1024]; ptrdiff_t diff; int ret;
++depth; diff = bottom_of_stack - __builtin_frame_address(0);
fprintf(stderr, "recursion depth: %i (stack diff: %zu)\n", depth, (size_t)diff);
for (size_t i = 0; i < 1024; ++i) ret += buffer[i];
ret += inner();
return ret; }
int main() { for (size_t size = 0; size < 128<<20; size += 16<<10) malloc(16<<10);
bottom_of_stack = __builtin_frame_address(0); fprintf(stderr, "bottom_of_stack = %p\n", bottom_of_stack); inner(); }
Fixes: 9630f0d60fec ("fs/binfmt_elf: use PT_LOAD p_align values for static PIE") Signed-off-by: Azat Khuzhin <a3at.mail@gmail.com> Cc: Chris Kennelly <ckennelly@google.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Song Liu <songliubraving@fb.com> Cc: David Rientjes <rientjes@google.com> Cc: Ian Rogers <irogers@google.com> Cc: Hugh Dickins <hughd@google.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Sandeep Patil <sspatil@google.com> Cc: Fangrui Song <maskray@google.com> Cc: Nick Desaulniers <ndesaulniers@google.com> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Mike Kravetz <mike.kravetz@oracle.com> Cc: Shuah Khan <shuah@kernel.org> Cc: H.J. Lu <hjl.tools@gmail.com> --- fs/binfmt_elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 605017eb9349..9e11e6f13e83 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1117,7 +1117,7 @@ static int load_elf_binary(struct linux_binprm *bprm) * without MAP_FIXED nor MAP_FIXED_NOREPLACE). */ alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); - if (alignment > ELF_MIN_ALIGN) { + if (interpreter || alignment > ELF_MIN_ALIGN) { load_bias = ELF_ET_DYN_BASE; if (current->flags & PF_RANDOMIZE) load_bias += arch_mmap_rnd(); -- 2.35.1
| |