Messages in this thread | | | From | "H.J. Lu" <> | Date | Mon, 31 Jan 2022 13:30:38 -0800 | Subject | Re: [PATCH] fs/binfmt_elf: use ELF_ET_DYN_BASE for PIE (ET_DYN with INTERP) binaries |
| |
On Mon, Jan 31, 2022 at 12:17 PM Azat Khuzhin <a3at.mail@gmail.com> wrote: > > 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.
How do I reproduce it on x86-64?
> 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 >
-- H.J.
| |