Print this page
uts: Allow for address space randomisation.
Randomise the base addresses of shared objects, non-fixed mappings, the
stack and the heap. Introduce a service, svc:/system/process-security,
and a tool psecflags(1) to control and observe it
@@ -57,10 +57,11 @@
#include <sys/exechdr.h>
#include <sys/debug.h>
#include <sys/vmsystm.h>
#include <sys/swap.h>
#include <sys/dumphdr.h>
+#include <sys/random.h>
#include <vm/hat.h>
#include <vm/as.h>
#include <vm/seg.h>
#include <vm/seg_kp.h>
@@ -635,10 +636,17 @@
{
return (0);
}
/*
+ * The maximum amount a randomized mapping will be slewed. We should perhaps
+ * arrange things so these tunables can be separate for mmap, mmapobj, and
+ * ld.so
+ */
+volatile size_t aslr_max_map_skew = 256 * 1024 * 1024; /* 256MB */
+
+/*
* map_addr_proc() is the routine called when the system is to
* choose an address for the user. We will pick an address
* range which is the highest available below userlimit.
*
* Every mapping will have a redzone of a single page on either side of
@@ -750,10 +758,11 @@
ASSERT(ISP2(align_amount));
ASSERT(align_amount == 0 || align_amount >= PAGESIZE);
off = off & (align_amount - 1);
+
/*
* Look for a large enough hole starting below userlimit.
* After finding it, use the upper part.
*/
if (as_gap_aligned(as, len, &base, &slen, AH_HI, NULL, align_amount,
@@ -777,10 +786,27 @@
addr += (uintptr_t)off;
if (addr > as_addr) {
addr -= align_amount;
}
+ /*
+ * If randomization is requested, slew the allocation
+ * backwards, within the same gap, by a random amount.
+ *
+ * XXX: This will fall over in processes like Java, which
+ * commonly have a great many small mappings.
+ */
+ if (flags & _MAP_RANDOMIZE) {
+ uint32_t slew;
+
+ (void) random_get_pseudo_bytes((uint8_t *)&slew,
+ sizeof (slew));
+
+ slew = slew % MIN(aslr_max_map_skew, (addr - base));
+ addr -= P2ALIGN(slew, align_amount);
+ }
+
ASSERT(addr > base);
ASSERT(addr + len < base + slen);
ASSERT(((uintptr_t)addr & (align_amount - 1)) ==
((uintptr_t)(off)));
*addrp = addr;
@@ -3924,16 +3950,10 @@
*/
void
dcache_flushall()
{}
-size_t
-exec_get_spslew(void)
-{
- return (0);
-}
-
/*
* Allocate a memory page. The argument 'seed' can be any pseudo-random
* number to vary where the pages come from. This is quite a hacked up
* method -- it works for now, but really needs to be fixed up a bit.
*