From: Hector Marco <hecmargi@upv.es>
To: linux-kernel@vger.kernel.org
Cc: akpm@linux-foundation.org, tglx@linutronix.de, mingo@redhat.com,
hpa@zytor.com, linux@arm.linux.org.uk, catalin.marinas@arm.com,
will.deacon@arm.com, oleg@redhat.com, luto@amacapital.net,
keescook@chromium.org
Subject: [PATCH] ASLRv3: randomize_va_space=3 preventing offset2lib attack
Date: Fri, 05 Dec 2014 01:07:50 +0100 [thread overview]
Message-ID: <5480F756.90106@upv.es> (raw)
[PATCH] ASLRv3: randomize_va_space=3 preventing offset2lib attack
The issue appears on PIE linked executables when all memory areas of
a process are randomized (randomize_va_space=2). In this case, the
attack "offset2lib" de-randomizes all library areas on 64 bit Linux
systems in less than one second.
Further details of the PoC attack at:
http://cybersecurity.upv.es/attacks/offset2lib/offset2lib.html
PIE linked applications are loaded side by side with the dynamic
libraries, which is exploited by the offset2lib attack. Moving away
the executable from the mmap_base area (libraries area) prevents the
attack.
This patch loads the PIE linked executable in a different area than
the libraries when randomize_va_space=3.
Patch implementation details:
- The ELF_ET_DYN_BASE address is used as the base to load randomly
the PIE executable.
- The executable image has the same entropy than
randomize_va_space=2.
If the randomize_va_space is set to 2 then this patch does not change
any behavior when loading new processes.
The patch has been tested on x86_64/32 and ARM/ARM64.
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 5e85ed3..6602f5e 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -10,6 +10,7 @@
#include <linux/personality.h>
#include <linux/random.h>
#include <asm/cachetype.h>
+#include <asm/elf.h>
#define COLOUR_ALIGN(addr,pgoff) \
((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \
@@ -19,6 +20,14 @@
#define MIN_GAP (128*1024*1024UL)
#define MAX_GAP ((TASK_SIZE)/6*5)
+#if ELF_EXEC_PAGESIZE > PAGE_SIZE
+#define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE
+#else
+#define ELF_MIN_ALIGN PAGE_SIZE
+#endif
+
+#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))
+
static int mmap_is_legacy(void)
{
if (current->personality & ADDR_COMPAT_LAYOUT)
@@ -184,6 +193,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
} else {
mm->mmap_base = mmap_base(random_factor);
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ if (randomize_va_space > 2)
+ mm->exec_base = ELF_PAGESTART(ELF_ET_DYN_BASE -
+ ((get_random_int() % (1 << 8)) << PAGE_SHIFT));
}
}
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 1d73662..32be3fd 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -28,6 +28,16 @@
#include <linux/random.h>
#include <asm/cputype.h>
+#include <asm/elf.h>
+
+
+#if ELF_EXEC_PAGESIZE > PAGE_SIZE
+#define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE
+#else
+#define ELF_MIN_ALIGN PAGE_SIZE
+#endif
+
+#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))
/*
* Leave enough space between the mmap area and the stack to honour
ulimit in
@@ -93,6 +103,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
} else {
mm->mmap_base = mmap_base();
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ if (randomize_va_space > 2)
+ mm->exec_base = ELF_PAGESTART(ELF_ET_DYN_BASE - mmap_rnd());
}
}
EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 919b912..8cb9855 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,14 @@
#include <linux/sched.h>
#include <asm/elf.h>
+#if ELF_EXEC_PAGESIZE > PAGE_SIZE
+#define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE
+#else
+#define ELF_MIN_ALIGN PAGE_SIZE
+#endif
+
+#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))
+
struct va_alignment __read_mostly va_align = {
.flags = -1,
};
@@ -120,5 +128,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
mm->get_unmapped_area = arch_get_unmapped_area;
} else {
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ if (randomize_va_space > 2)
+ mm->exec_base = ELF_PAGESTART(ELF_ET_DYN_BASE - mmap_rnd());
}
}
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d8fc060..6f319c1 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -804,8 +804,11 @@ static int load_elf_binary(struct linux_binprm *bprm)
* load_bias value in order to establish proper
* non-randomized mappings.
*/
- if (current->flags & PF_RANDOMIZE)
+ if (current->flags & PF_RANDOMIZE) {
load_bias = 0;
+ if (randomize_va_space > 2)
+ load_bias = current->mm->exec_base;
+ }
else
load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
#else
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 6e0b286..dd052ec 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -353,6 +353,7 @@ struct mm_struct {
#endif
unsigned long mmap_base; /* base of mmap area */
unsigned long mmap_legacy_base; /* base of mmap area in
bottom-up allocations */
+ unsigned long exec_base; /* base of exec area */
unsigned long task_size; /* size of task vm space */
unsigned long highest_vm_end; /* highest vma end address */
pgd_t * pgd;
diff --git a/kernel/fork.c b/kernel/fork.c
index 9b7d746..1fd4553 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -551,6 +551,7 @@ static void mm_init_owner(struct mm_struct *mm,
struct task_struct *p)
static struct mm_struct *mm_init(struct mm_struct *mm, struct
task_struct *p)
{
mm->mmap = NULL;
+ mm->exec_base = 0;
mm->mm_rb = RB_ROOT;
mm->vmacache_seqnum = 0;
atomic_set(&mm->mm_users, 1);
Signed-off-by: Hector Marco-Gisbert <hecmargi@upv.es>
Signed-off-by: Ismael Ripoll <iripoll@upv.es>
next reply other threads:[~2014-12-05 0:25 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-05 0:07 Hector Marco [this message]
2014-12-05 20:08 ` [PATCH] ASLRv3: randomize_va_space=3 preventing offset2lib attack Kees Cook
2014-12-08 22:15 ` Hector Marco Gisbert
2014-12-05 22:00 ` Andy Lutomirski
2014-12-08 20:09 ` Christian Borntraeger
2014-12-09 17:37 ` Kees Cook
[not found] <5489E6D2.2060200@upv.es>
2014-12-11 20:12 ` Hector Marco
2014-12-11 22:11 ` Kees Cook
2014-12-12 16:32 ` Hector Marco
2014-12-12 17:17 ` Andy Lutomirski
2014-12-19 22:04 ` Hector Marco
2014-12-19 22:11 ` Andy Lutomirski
2014-12-19 22:19 ` Cyrill Gorcunov
2014-12-19 23:53 ` Andy Lutomirski
2014-12-22 17:36 ` Hector Marco Gisbert
2014-12-22 17:56 ` Andy Lutomirski
2014-12-22 19:49 ` Jiri Kosina
2014-12-22 20:00 ` Andy Lutomirski
2014-12-22 20:03 ` Jiri Kosina
2014-12-22 20:13 ` Andy Lutomirski
2014-12-22 23:23 ` Hector Marco Gisbert
2014-12-22 23:38 ` Andy Lutomirski
[not found] ` <CAH4rwTKeN0P84FJnocoKV4t9rc2Ox_EYc+LEibD+Y83n7C8aVA@mail.gmail.com>
2014-12-23 8:15 ` Andy Lutomirski
2014-12-23 20:06 ` Hector Marco Gisbert
2014-12-23 20:53 ` Andy Lutomirski
2015-01-07 17:26 ` Hector Marco Gisbert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5480F756.90106@upv.es \
--to=hecmargi@upv.es \
--cc=akpm@linux-foundation.org \
--cc=catalin.marinas@arm.com \
--cc=hpa@zytor.com \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=luto@amacapital.net \
--cc=mingo@redhat.com \
--cc=oleg@redhat.com \
--cc=tglx@linutronix.de \
--cc=will.deacon@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.