[PATCH] binfmt_elf: fix PIE load with randomization disabled

From: H.J. Lu
Date: Mon Dec 09 2013 - 10:50:38 EST


Normally, a PIE executable has zero virtual address on the first PT_LOAD
segment and kernel will load such executable at random address when
randomization is enabled. If randomization is disabled, kernel will load
it at a fixed address. But if a PIE executable has non-zero virtual
address on the first PT_LOAD segment, kernel will load such executable
at the non-zero virtual address when randomization is enabled. But when
randomization is disabled, kernel ignores the non-zero virtual address
at the non-zero virtual address when randomization is enabled. But when
randomization is disabled, kernel ignores the non-zero virtual address
on the first PT_LOAD segment and loads it at the fixed address. This
patch makes kernel consistent by loading PIE executable with non-zero
virtual address at the non-zero virtual address, regardless if
randomization is enabled or disabled.


--
H.J
From eee1f1f4f60eb1f1139ac311e787fac50accde30 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@xxxxxxxxx>
Date: Fri, 6 Dec 2013 12:44:41 -0800
Subject: [PATCH] binfmt_elf: fix PIE load with randomization disabled

Normally, a PIE executable has zero virtual address on the first PT_LOAD
segment and kernel will load such executable at random address when
randomization is enabled. If randomization is disabled, kernel will load
it at a fixed address. But if a PIE executable has non-zero virtual
address on the first PT_LOAD segment, kernel will load such executable
at the non-zero virtual address when randomization is enabled. But when
randomization is disabled, kernel ignores the non-zero virtual address
on the first PT_LOAD segment and loads it at the fixed address. This
patch makes kernel consistent by loading PIE executable with non-zero
virtual address at the non-zero virtual address, regardless if
randomization is enabled or disabled.

Signed-off-by: H.J. Lu <hjl.tools@xxxxxxxxx>
---
fs/binfmt_elf.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 4c94a79..a3fd4de 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -809,8 +809,13 @@ static int load_elf_binary(struct linux_binprm *bprm)
* If that is the case, retain the original non-zero
* load_bias value in order to establish proper
* non-randomized mappings.
+ * If the first PT_LOAD segment has non-zero p_vaddr,
+ * use the zero load_bias so that a PIE binary will be
+ * loaded at the specific address even if memory
+ * randomization is off.
*/
- if (current->flags & PF_RANDOMIZE)
+ if ((current->flags & PF_RANDOMIZE) ||
+ (!load_addr_set && vaddr))
load_bias = 0;
else
load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
--
1.8.3.1