Re: [RFC PATCH] elf: enforce MAP_FIXED on overlaying elf segments (was: Re: ppc elf_map breakage with MAP_FIXED_NOREPLACE)

2018-02-14 Thread Khalid Aziz
On Tue, 2018-02-13 at 11:04 +0100, Michal Hocko wrote:
> 
> From 97e7355a6dc31a73005fa806566a57eb5c38032b Mon Sep 17 00:00:00
> 2001
> From: Michal Hocko 
> Date: Tue, 13 Feb 2018 10:50:53 +0100
> Subject: [PATCH] elf: enforce MAP_FIXED on overlaying elf segments
> 
> Anshuman has reported that some ELF binaries in his environment fail
> to
> start with
>  [   23.423642] 9148 (sed): Uhuuh, elf segment at 1003
> requested but the memory is mapped already
>  [   23.423706] requested [1003, 1004] mapped [1003,
> 1004] 100073 anon
> 
> The reason is that the above binary has overlapping elf segments:
>   LOAD   0x 0x1000
> 0x1000
>  0x00013a8c 0x00013a8c  R E1
>   LOAD   0x0001fd40 0x1002fd40
> 0x1002fd40
>  0x02c0 0x05e8  RW 1
>   LOAD   0x00020328 0x10030328
> 0x10030328
>  0x0384 0x94a0  RW 1
> 
> That binary has two RW LOAD segments, the first crosses a page border
> into the second
> 
> 0x1002fd40 (LOAD2-vaddr) + 0x5e8 (LOAD2-memlen) == 0x10030328 (LOAD3-
> vaddr)
> 
> Handle this situation by enforcing MAP_FIXED when we establish a
> temporary brk VMA to handle overlapping segments. All other mappings
> will still use MAP_FIXED_NOREPLACE.
> 
> Fixes: fs, elf: drop MAP_FIXED usage from elf_map
> Reported-by: Anshuman Khandual 
> Signed-off-by: Michal Hocko 
> ---
> 

Looks reasonable to me.

Reviewed-by: Khalid Aziz 


[RFC PATCH] elf: enforce MAP_FIXED on overlaying elf segments (was: Re: ppc elf_map breakage with MAP_FIXED_NOREPLACE)

2018-02-13 Thread Michal Hocko
On Fri 02-02-18 07:55:14, Kees Cook wrote:
> On Fri, Feb 2, 2018 at 12:40 AM, Michal Hocko  wrote:
> > On Thu 01-02-18 14:10:07, Michal Hocko wrote:
> > Thanks a lot to Michael Matz for his background. He has pointed me to
> > the following two segments from your binary[1]
> >   LOAD   0x 0x1000 0x1000
> >  0x00013a8c 0x00013a8c  R E1
> >   LOAD   0x0001fd40 0x1002fd40 0x1002fd40
> >  0x02c0 0x05e8  RW 1
> >   LOAD   0x00020328 0x10030328 0x10030328
> >  0x0384 0x94a0  RW 1
> >
> > That binary has two RW LOAD segments, the first crosses a page border
> > into the second
> > 0x1002fd40 (LOAD2-vaddr) + 0x5e8 (LOAD2-memlen) == 0x10030328 (LOAD3-vaddr)
> >
> > He says
> > : This is actually an artifact of RELRO machinism.  The first RW mapping
> > : will be remapped as RO after relocations are applied (to increase
> > : security).
> > : Well, to be honest, normal relro binaries also don't have more than
> > : two LOAD segments, so whatever RHEL did to their compilation options,
> > : it's something in addition to just relro (which can be detected by
> > : having a GNU_RELRO program header)
> > : But it definitely has something to do with relro, it's just not the
> > : whole story yet.
> >
> > I am still trying to wrap my head around all this, but it smells rather
> > dubious to map different segments over the same page. Is this something
> > that might happen widely and therefore MAP_FIXED_NOREPLACE is a no-go
> > when loading ELF segments? Or is this a special case we can detect?
> 
> Eww. FWIW, I would expect that to be rare and detectable.

OK, so Anshuman has confirmed [1] that the patch below fixes the issue
for him. I am sending this as an RFC because this is not really my area
and load_elf_binary is obscure as hell. The changelog could see much
more clear wording than I am able to provide. Any help would be highly
appreciated.

[1] 
http://lkml.kernel.org/r/b0a751c4-9552-87b4-c768-3e1b02c18...@linux.vnet.ibm.com

>From 97e7355a6dc31a73005fa806566a57eb5c38032b Mon Sep 17 00:00:00 2001
From: Michal Hocko 
Date: Tue, 13 Feb 2018 10:50:53 +0100
Subject: [PATCH] elf: enforce MAP_FIXED on overlaying elf segments

Anshuman has reported that some ELF binaries in his environment fail to
start with
 [   23.423642] 9148 (sed): Uhuuh, elf segment at 1003 requested 
but the memory is mapped already
 [   23.423706] requested [1003, 1004] mapped [1003, 1004] 
100073 anon

The reason is that the above binary has overlapping elf segments:
  LOAD   0x 0x1000 0x1000
 0x00013a8c 0x00013a8c  R E1
  LOAD   0x0001fd40 0x1002fd40 0x1002fd40
 0x02c0 0x05e8  RW 1
  LOAD   0x00020328 0x10030328 0x10030328
 0x0384 0x94a0  RW 1

That binary has two RW LOAD segments, the first crosses a page border
into the second

0x1002fd40 (LOAD2-vaddr) + 0x5e8 (LOAD2-memlen) == 0x10030328 (LOAD3-vaddr)

Handle this situation by enforcing MAP_FIXED when we establish a
temporary brk VMA to handle overlapping segments. All other mappings
will still use MAP_FIXED_NOREPLACE.

Fixes: fs, elf: drop MAP_FIXED usage from elf_map
Reported-by: Anshuman Khandual 
Signed-off-by: Michal Hocko 
---
 fs/binfmt_elf.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 2f492dfcabde..4679d1d945f9 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -895,7 +895,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
   the correct location in memory. */
for(i = 0, elf_ppnt = elf_phdata;
i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
-   int elf_prot = 0, elf_flags;
+   int elf_prot = 0, elf_flags, elf_fixed = MAP_FIXED_NOREPLACE;
unsigned long k, vaddr;
unsigned long total_size = 0;
 
@@ -927,6 +927,13 @@ static int load_elf_binary(struct linux_binprm *bprm)
 */
}
}
+
+   /*
+* Some binaries have overlapping elf segments and then
+* we have to forcefully map over an existing mapping
+* e.g. over this newly established brk mapping.
+*/
+   elf_fixed = MAP_FIXED;
}
 
if (elf_ppnt->p_flags & PF_R)
@@ -944,7 +951,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
 * the ET_DYN load_addr calculations, proceed normally.