Subject: Re: ppc elf_map breakage with MAP_FIXED_NOREPLACE

From: Michal Hocko <[email-masked]>
Date: Thu, 1 Feb 2018 14:48:29 +0100

On Thu 01-02-18 08:43:34, Anshuman Khandual wrote:
[...]
> $dmesg | grep elf_brk
> [    9.571192] elf_brk 10030328 elf_bss 10030000
> 
> static int load_elf_binary(struct linux_binprm *bprm)
> ---------------------
> 
> 	if (unlikely (elf_brk > elf_bss)) {
> 			unsigned long nbyte;
> 	            
> 			/* There was a PT_LOAD segment with p_memsz > p_filesz
> 			   before this one. Map anonymous pages, if needed,
> 			   and clear the area.  */
> 			retval = set_brk(elf_bss + load_bias,
> 					 elf_brk + load_bias,
> 					 bss_prot);
> 
> 
> ---------------------

Just a blind shot... Does the following make any difference?
---
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 021fe78998ea..04b24d00c911 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,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
 					 */
 				}
 			}
+			elf_fixed = MAP_FIXED;
 		}
 
 		if (elf_ppnt->p_flags & PF_R)
@@ -944,7 +945,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
 		 * the ET_DYN load_addr calculations, proceed normally.
 		 */
 		if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
-			elf_flags |= MAP_FIXED_NOREPLACE;
+			elf_flags |= elf_fixed;
 		} else if (loc->elf_ex.e_type == ET_DYN) {
 			/*
 			 * This logic is run once for the first LOAD Program
@@ -980,7 +981,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
 				load_bias = ELF_ET_DYN_BASE;
 				if (current->flags & PF_RANDOMIZE)
 					load_bias += arch_mmap_rnd();
-				elf_flags |= MAP_FIXED_NOREPLACE;
+				elf_flags |= elf_fixed;
 			} else
 				load_bias = 0;

-- 
Michal Hocko
SUSE Labs