| From 9b2f72cc0aa4bb444541bb87581c35b7508b37d3 Mon Sep 17 00:00:00 2001 |
| From: Chen Jingwen <chenjingwen6@huawei.com> |
| Date: Tue, 28 Sep 2021 20:56:57 +0800 |
| Subject: elf: don't use MAP_FIXED_NOREPLACE for elf interpreter mappings |
| |
| From: Chen Jingwen <chenjingwen6@huawei.com> |
| |
| commit 9b2f72cc0aa4bb444541bb87581c35b7508b37d3 upstream. |
| |
| In commit b212921b13bd ("elf: don't use MAP_FIXED_NOREPLACE for elf |
| executable mappings") we still leave MAP_FIXED_NOREPLACE in place for |
| load_elf_interp. |
| |
| Unfortunately, this will cause kernel to fail to start with: |
| |
| 1 (init): Uhuuh, elf segment at 00003ffff7ffd000 requested but the memory is mapped already |
| Failed to execute /init (error -17) |
| |
| The reason is that the elf interpreter (ld.so) has overlapping segments. |
| |
| readelf -l ld-2.31.so |
| Program Headers: |
| Type Offset VirtAddr PhysAddr |
| FileSiz MemSiz Flags Align |
| LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 |
| 0x000000000002c94c 0x000000000002c94c R E 0x10000 |
| LOAD 0x000000000002dae0 0x000000000003dae0 0x000000000003dae0 |
| 0x00000000000021e8 0x0000000000002320 RW 0x10000 |
| LOAD 0x000000000002fe00 0x000000000003fe00 0x000000000003fe00 |
| 0x00000000000011ac 0x0000000000001328 RW 0x10000 |
| |
| The reason for this problem is the same as described in commit |
| ad55eac74f20 ("elf: enforce MAP_FIXED on overlaying elf segments"). |
| |
| Not only executable binaries, elf interpreters (e.g. ld.so) can have |
| overlapping elf segments, so we better drop MAP_FIXED_NOREPLACE and go |
| back to MAP_FIXED in load_elf_interp. |
| |
| Fixes: 4ed28639519c ("fs, elf: drop MAP_FIXED usage from elf_map") |
| Cc: <stable@vger.kernel.org> # v4.19 |
| Cc: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Michal Hocko <mhocko@suse.com> |
| Signed-off-by: Chen Jingwen <chenjingwen6@huawei.com> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/binfmt_elf.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/fs/binfmt_elf.c |
| +++ b/fs/binfmt_elf.c |
| @@ -627,7 +627,7 @@ static unsigned long load_elf_interp(str |
| |
| vaddr = eppnt->p_vaddr; |
| if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) |
| - elf_type |= MAP_FIXED_NOREPLACE; |
| + elf_type |= MAP_FIXED; |
| else if (no_base && interp_elf_ex->e_type == ET_DYN) |
| load_addr = -vaddr; |
| |