This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] Add Prefer_MAP_32BIT_EXEC for Silvermont
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: Jeff Law <law at redhat dot com>
- Cc: Zack Weinberg <zackw at panix dot com>, Andi Kleen <andi at firstfloor dot org>, Adhemerval Zanella <adhemerval dot zanella at linaro dot org>, GNU C Library <libc-alpha at sourceware dot org>
- Date: Sat, 12 Dec 2015 09:36:15 -0800
- Subject: Re: [PATCH] Add Prefer_MAP_32BIT_EXEC for Silvermont
- Authentication-results: sourceware.org; auth=none
- References: <CAKCAbMhMArQ9wsXhw2y+Fvv+_3O5i4g8pdDQdWo6_1YxqfVxkQ at mail dot gmail dot com> <CAMe9rOrVjSnhp-EzmAnVBg10wbqk9U4n+hL-3xF5=DPZP5co1A at mail dot gmail dot com> <CAKCAbMhk69hUBbrQ=0j0NDYjRT6R-EK1+F43+Mmi9FwS7epexQ at mail dot gmail dot com> <CAKCAbMhA6x4r6Bhw8cnAavoWzjWsm6WM8JPzrnCsrqxbEswS_g at mail dot gmail dot com> <87egeszoq3 dot fsf at tassilo dot jf dot intel dot com> <CAKCAbMibxh54DGJ6p59ah6jQK=oFkH9LCZo0UDBefQeh1y-5eg at mail dot gmail dot com> <CAMe9rOoyc4MXVz74GmjViora-iCEKitQXbpX9EB+Ln1Q_DAD_A at mail dot gmail dot com> <CAKCAbMi_noBivP+ksLaotNtfEhGrtUuUacbnZgjMg5m0PfEniw at mail dot gmail dot com> <20151211222913 dot GT15533 at two dot firstfloor dot org> <566B55DF dot 2040200 at redhat dot com> <20151212001449 dot GU15533 at two dot firstfloor dot org> <CAKCAbMgcZKr8-i2XuhHAnk4nKpJnpWEqj1XNuygkNhYzXPb8hA at mail dot gmail dot com> <566B8008 dot 6010106 at redhat dot com>
On Fri, Dec 11, 2015 at 6:01 PM, Jeff Law <law@redhat.com> wrote:
> On 12/11/2015 05:31 PM, Zack Weinberg wrote:
>>
>> On Fri, Dec 11, 2015 at 7:14 PM, Andi Kleen <andi@firstfloor.org> wrote:
>>>>
>>>> And I'd argue that this is killing ASLR at a level that it should be
>>>> an opt-out rather than opt-in. Crippling ASLR is, IMHO,
>>>> unacceptable.
>>>
>>>
>>> You're arguing then that running 32bit code is unacceptable.
>>
>>
>> I don't see that that follows.
>>
>> Right now, 32-bit code has security margin X and 64-bit code has
>> security margin Y > X. The proposed patch *reduces* the security
>> margin of 64-bit code from Y to X (give or take). That may be, and
>> IMHO is, an unacceptable change *even if* X is agreed to be adequate,
>> or anyway the best that can be done for 32-bit.
>
> Exactly. For a 64 bit application, this change will essentially cripple
> ASLR if I understand the patch correctly. That is unacceptable to me and
> likely to Red Hat as a whole.
>
>>
>> Fundamentally, my issue here is that there are people right now
>> depending on this security margin to be Y, so a glibc upgrade should
>> not silently remove that. It is a compatibility break of the worst
>> kind: completely invisible in normal operation, but the system no
>> longer has a property you were counting on to protect you under
>> abnormal (adversarial) conditions.
>
> Right. And in fact, ASLR is the margin by which some currently known
> vulnerabilities have not been turned into proof of concept exploits.
>
> ASLR, while not perfect, while bypassable via various information leaks, is
> still a vital component in the overall security profile for Linux,
> particularly for 64 bit OSs & applications.
>
Here is the updated patch to make it opt-in. OK for master?
--
H.J.
From 55a5e6278f86cecba8515804a7a2859a109920ba Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 21 Oct 2015 14:44:23 -0700
Subject: [PATCH] Add Prefer_MAP_32BIT_EXEC for Silvermont
According to Silvermont software optimization guide, for 64-bit
applications, branch prediction performance can be negatively impacted
when the target of a branch is more than 4GB away from the branch. Set
the Prefer_MAP_32BIT_EXEC bit for Silvermont so that mmap will try to
map executable pages with MAP_32BIT first. Also enable Silvermont
optimizations for Knights Landing.
Prefer_MAP_32BIT_EXEC reduces bits available for address space
layout randomization (ASLR), which is always disabled for SUID
programs and can only be enabled by setting environment variable,
LD_ENABLE_PREFER_MAP_32BIT_EXEC.
On Fedora 23, this patch speeds up GCC 5 testsuite by 3% on Silvermont.
* sysdeps/unix/sysv/linux/wordsize-64/mmap.c: New file.
* sysdeps/unix/sysv/linux/x86_64/64/mmap.c: Likewise.
* sysdeps/x86/cpu-features.c (get_prefer_map_32bit_exec): New
function.
(init_cpu_features): Call get_prefer_map_32bit_exec for
Silvermont. Enable Silvermont optimizations for Knights Landing.
* sysdeps/x86/cpu-features.h (bit_Prefer_MAP_32BIT_EXEC): New.
(index_Prefer_MAP_32BIT_EXEC): Likewise.
---
sysdeps/unix/sysv/linux/wordsize-64/mmap.c | 40 +++++++++++++++++++++++++
sysdeps/unix/sysv/linux/x86_64/64/mmap.c | 37 +++++++++++++++++++++++
sysdeps/x86/cpu-features.c | 48 ++++++++++++++++++++++++++++--
sysdeps/x86/cpu-features.h | 3 ++
4 files changed, 126 insertions(+), 2 deletions(-)
create mode 100644 sysdeps/unix/sysv/linux/wordsize-64/mmap.c
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/mmap.c
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/mmap.c b/sysdeps/unix/sysv/linux/wordsize-64/mmap.c
new file mode 100644
index 0000000..e098976
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/wordsize-64/mmap.c
@@ -0,0 +1,40 @@
+/* Linux mmap system call. 64-bit version.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sysdep.h>
+
+/* An architecture may override this. */
+#ifndef MMAP_PREPARE
+# define MMAP_PREPARE(addr, len, prot, flags, fd, offset)
+#endif
+
+__ptr_t
+__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+ MMAP_PREPARE (addr, len, prot, flags, fd, offset);
+ return (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags,
+ fd, offset);
+}
+
+weak_alias (__mmap, mmap)
+weak_alias (__mmap, mmap64)
+weak_alias (__mmap, __mmap64)
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/mmap.c b/sysdeps/unix/sysv/linux/x86_64/64/mmap.c
new file mode 100644
index 0000000..031316c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/mmap.c
@@ -0,0 +1,37 @@
+/* Linux mmap system call. x86-64 version.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+
+/* If the Prefer_MAP_32BIT_EXEC bit is set, try to map executable pages
+ with MAP_32BIT first. */
+#define MMAP_PREPARE(addr, len, prot, flags, fd, offset) \
+ if ((addr) == NULL \
+ && ((prot) & PROT_EXEC) != 0 \
+ && HAS_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC)) \
+ { \
+ __ptr_t ret = (__ptr_t) INLINE_SYSCALL (mmap, 6, (addr), (len), \
+ (prot), \
+ (flags) | MAP_32BIT, \
+ (fd), (offset)); \
+ if (ret != MAP_FAILED) \
+ return ret; \
+ }
+
+#include <sysdeps/unix/sysv/linux/wordsize-64/mmap.c>
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index fba3ef0..33e0e73 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -39,6 +39,37 @@ get_common_indeces (struct cpu_features *cpu_features,
}
}
+/* Prefer_MAP_32BIT_EXEC reduces bits available for address space layout
+ randomization (ASLR). Prefer_MAP_32BIT_EXEC is always disabled for
+ SUID programs and can be enabled by setting environment variable,
+ LD_ENABLE_PREFER_MAP_32BIT_EXEC. */
+
+static inline unsigned int
+get_prefer_map_32bit_exec (void)
+{
+#if defined __LP64__ && IS_IN (rtld)
+ extern char **__environ attribute_hidden;
+ extern int __libc_enable_secure;
+ if (__builtin_expect (__libc_enable_secure, 0))
+ return 0;
+ for (char **current = __environ; *current != NULL; ++current)
+ {
+ /* Check LD_ENABLE_PREFER_MAP_32BIT_EXEC=. */
+ static const char *enable = "LD_ENABLE_PREFER_MAP_32BIT_EXEC=";
+ for (size_t i = 0; ; i++)
+ {
+ if (enable[i] != (*current)[i])
+ break;
+ if ((*current)[i] == '=')
+ return bit_Prefer_MAP_32BIT_EXEC;
+ }
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
static inline void
init_cpu_features (struct cpu_features *cpu_features)
{
@@ -78,22 +109,35 @@ init_cpu_features (struct cpu_features *cpu_features)
cpu_features->feature[index_Slow_BSF] |= bit_Slow_BSF;
break;
+ case 0x57:
+ /* Knights Landing. Enable Silvermont optimizations. */
+
case 0x37:
case 0x4a:
case 0x4d:
case 0x5a:
case 0x5d:
- /* Unaligned load versions are faster than SSSE3
- on Silvermont. */
+ /* Unaligned load versions are faster than SSSE3 on
+ Silvermont. For 64-bit applications, branch
+ prediction performance can be negatively impacted
+ when the target of a branch is more than 4GB away
+ from the branch. Set the Prefer_MAP_32BIT_EXEC bit
+ so that mmap will try to map executable pages with
+ MAP_32BIT first. NB: MAP_32BIT will map to lower
+ 2GB, not lower 4GB, address. */
#if index_Fast_Unaligned_Load != index_Prefer_PMINUB_for_stringop
# error index_Fast_Unaligned_Load != index_Prefer_PMINUB_for_stringop
#endif
+#if index_Fast_Unaligned_Load != index_Prefer_MAP_32BIT_EXEC
+# error index_Fast_Unaligned_Load != index_Prefer_MAP_32BIT_EXEC
+#endif
#if index_Fast_Unaligned_Load != index_Slow_SSE4_2
# error index_Fast_Unaligned_Load != index_Slow_SSE4_2
#endif
cpu_features->feature[index_Fast_Unaligned_Load]
|= (bit_Fast_Unaligned_Load
| bit_Prefer_PMINUB_for_stringop
+ | get_prefer_map_32bit_exec ()
| bit_Slow_SSE4_2);
break;
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
index 80edbee..93bee69 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/cpu-features.h
@@ -33,6 +33,7 @@
#define bit_AVX512DQ_Usable (1 << 13)
#define bit_I586 (1 << 14)
#define bit_I686 (1 << 15)
+#define bit_Prefer_MAP_32BIT_EXEC (1 << 16)
/* CPUID Feature flags. */
@@ -97,6 +98,7 @@
# define index_AVX512DQ_Usable FEATURE_INDEX_1*FEATURE_SIZE
# define index_I586 FEATURE_INDEX_1*FEATURE_SIZE
# define index_I686 FEATURE_INDEX_1*FEATURE_SIZE
+# define index_Prefer_MAP_32BIT_EXEC FEATURE_INDEX_1*FEATURE_SIZE
# if defined (_LIBC) && !IS_IN (nonlib)
# ifdef __x86_64__
@@ -248,6 +250,7 @@ extern const struct cpu_features *__get_cpu_features (void)
# define index_AVX512DQ_Usable FEATURE_INDEX_1
# define index_I586 FEATURE_INDEX_1
# define index_I686 FEATURE_INDEX_1
+# define index_Prefer_MAP_32BIT_EXEC FEATURE_INDEX_1
#endif /* !__ASSEMBLER__ */
--
2.5.0