summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/mmapobj.c
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2016-10-17 13:02:40 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2016-10-17 13:02:40 +0000
commit59a59b276f274cff7e883bcc3e10c162cfb3a263 (patch)
tree59b25df56be42eb7c8aae7cb02d6f1d39ec61b15 /usr/src/uts/common/os/mmapobj.c
parent8259b03da3b4ab815c3b6180f813fcfd57984470 (diff)
parentd2a70789f056fc6c9ce3ab047b52126d80b0e3da (diff)
downloadillumos-joyent-59a59b276f274cff7e883bcc3e10c162cfb3a263.tar.gz
[illumos-gate merge]
commit d2a70789f056fc6c9ce3ab047b52126d80b0e3da 7029 want per-process exploit mitigation features (secflags) 7030 want basic address space layout randomization (ASLR) 7031 noexec_user_stack should be a security-flag 7032 want a means to forbid mappings around NULL commit 8ab1c3f559468e655c4eb8acce993320403dd72b 7469 loader should use acpica provided by OS commit a1964bdd47804c37e09db1a79c23937c9aeac165 7470 acpi build sometimes doesn't descend into SUBDIRS commit abf99a006172ea5aab2246bda23f9d6d935bf1ad 7420 signalfd deadlock on pollwakeup 7421 panic in signalfd Conflicts: usr/src/cmd/sgs/libconv/common/corenote.c usr/src/cmd/zonecfg/zonecfg.c usr/src/cmd/zonecfg/zonecfg.h usr/src/cmd/zonecfg/zonecfg_grammar.y usr/src/cmd/zonecfg/zonecfg_lex.l usr/src/head/libzonecfg.h usr/src/lib/libzonecfg/common/libzonecfg.c usr/src/man/man1m/zonecfg.1m usr/src/man/man4/proc.4 usr/src/pkg/manifests/system-test-ostest.mf usr/src/test/os-tests/tests/Makefile usr/src/uts/common/exec/elf/elf.c usr/src/uts/common/io/signalfd.c usr/src/uts/common/os/sysent.c usr/src/uts/common/os/zone.c usr/src/uts/common/sys/proc.h usr/src/uts/common/sys/zone.h
Diffstat (limited to 'usr/src/uts/common/os/mmapobj.c')
-rw-r--r--usr/src/uts/common/os/mmapobj.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/usr/src/uts/common/os/mmapobj.c b/usr/src/uts/common/os/mmapobj.c
index 596c855a45..f6131f3e80 100644
--- a/usr/src/uts/common/os/mmapobj.c
+++ b/usr/src/uts/common/os/mmapobj.c
@@ -68,8 +68,9 @@
*
* Having mmapobj interpret and map objects will allow the kernel to make the
* best decision for where to place the mappings for said objects. Thus, we
- * can make optimizations inside of the kernel for specific platforms or
- * cache mapping information to make mapping objects faster.
+ * can make optimizations inside of the kernel for specific platforms or cache
+ * mapping information to make mapping objects faster. The cache is ignored
+ * if ASLR is enabled.
*
* The lib_va_hash will be one such optimization. For each ELF object that
* mmapobj is asked to interpret, we will attempt to cache the information
@@ -718,7 +719,7 @@ mmapobj_lookup_start_addr(struct lib_va *lvp)
*/
static caddr_t
mmapobj_alloc_start_addr(struct lib_va **lvpp, size_t len, int use_lib_va,
- size_t align, vattr_t *vap)
+ int randomize, size_t align, vattr_t *vap)
{
proc_t *p = curproc;
struct as *as = p->p_as;
@@ -733,6 +734,7 @@ mmapobj_alloc_start_addr(struct lib_va **lvpp, size_t len, int use_lib_va,
size_t lib_va_len;
ASSERT(lvpp != NULL);
+ ASSERT((randomize & use_lib_va) != 1);
MOBJ_STAT_ADD(alloc_start);
model = get_udatamodel();
@@ -748,6 +750,10 @@ mmapobj_alloc_start_addr(struct lib_va **lvpp, size_t len, int use_lib_va,
if (align > 1) {
ma_flags |= MAP_ALIGN;
}
+
+ if (randomize != 0)
+ ma_flags |= _MAP_RANDOMIZE;
+
if (use_lib_va) {
/*
* The first time through, we need to setup the lib_va arenas.
@@ -861,7 +867,14 @@ nolibva:
* If we don't have an expected base address, or the one that we want
* to use is not available or acceptable, go get an acceptable
* address range.
+ *
+ * If ASLR is enabled, we should never have used the cache, and should
+ * also start our real work here, in the consequent of the next
+ * condition.
*/
+ if (randomize != 0)
+ ASSERT(base == NULL);
+
if (base == NULL || as_gap(as, len, &base, &len, 0, NULL) ||
valid_usr_range(base, len, PROT_ALL, as, as->a_userlimit) !=
RANGE_OKAY || OVERLAPS_STACK(base + len, p)) {
@@ -1530,7 +1543,7 @@ check_exec_addrs(int loadable, mmapobj_result_t *mrp, caddr_t start_addr)
* Return 0 on success or error on failure.
*/
static int
-process_phdr(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
+process_phdrs(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
vnode_t *vp, uint_t *num_mapped, size_t padding, cred_t *fcred)
{
int i;
@@ -1586,7 +1599,7 @@ process_phdr(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
}
}
- if (padding != 0) {
+ if ((padding != 0) || secflag_enabled(curproc, PROC_SEC_ASLR)) {
use_lib_va = 0;
}
if (e_type == ET_DYN) {
@@ -1596,7 +1609,8 @@ process_phdr(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
return (error);
}
/* Check to see if we already have a description for this lib */
- lvp = lib_va_find(&vattr);
+ if (!secflag_enabled(curproc, PROC_SEC_ASLR))
+ lvp = lib_va_find(&vattr);
if (lvp != NULL) {
MOBJ_STAT_ADD(lvp_found);
@@ -1706,7 +1720,9 @@ process_phdr(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
*/
ASSERT(lvp ? use_lib_va == 0 : 1);
start_addr = mmapobj_alloc_start_addr(&lvp, len,
- use_lib_va, align, &vattr);
+ use_lib_va,
+ secflag_enabled(curproc, PROC_SEC_ASLR),
+ align, &vattr);
if (start_addr == NULL) {
if (lvp) {
lib_va_release(lvp);
@@ -2031,7 +2047,7 @@ doelfwork(Ehdr *ehdrp, vnode_t *vp, mmapobj_result_t *mrp,
}
/* Now process the phdr's */
- error = process_phdr(ehdrp, phbasep, nphdrs, mrp, vp, num_mapped,
+ error = process_phdrs(ehdrp, phbasep, nphdrs, mrp, vp, num_mapped,
padding, fcred);
kmem_free(phbasep, phsizep);
return (error);
@@ -2317,7 +2333,8 @@ mmapobj_map_interpret(vnode_t *vp, mmapobj_result_t *mrp,
* for this library. This is the fast path and only used for
* ET_DYN ELF files (dynamic libraries).
*/
- if (padding == 0 && (lvp = lib_va_find(&vattr)) != NULL) {
+ if (padding == 0 && !secflag_enabled(curproc, PROC_SEC_ASLR) &&
+ ((lvp = lib_va_find(&vattr)) != NULL)) {
int num_segs;
model = get_udatamodel();