[haiku-commits] BRANCH pdziepak-github.aslr - src/system/kernel/vm headers/os/kernel

  • From: pdziepak-github.aslr <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 25 Feb 2013 23:00:38 +0100 (CET)

added 1 changeset to branch 'refs/remotes/pdziepak-github/aslr'
old head: fe9b18223abc0c92e2bbf3d80df8dfaf22e680a8
new head: ff6d12fc57686c163088393ed8d9ca5d5a366086
overview: https://github.com/pdziepak/Haiku/compare/fe9b182...ff6d12f

----------------------------------------------------------------------------

ff6d12f: vm: implement B_RAND_BASE_ADDRESS address spec
  
  B_RAND_BASE_ADDRESS is basically B_BASE_ADDRESS with non-deterministic created
  area's base address.
  
  Initial start address is randomized and then the algorithm looks for a large
  enough free space in the interval [randomized start, end]. If it fails then
  the search is repeated in the interval [original start, randomized start]. In
  case it also fails the algorithm falls back to B_ANY_ADDRESS
  (B_RAND_ANY_ADDRESS when it is implemented) just like B_BASE_ADDRESS does.
  
  Randomization range is limited by kMaxRandomize and kMaxInitialRandomize.

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit:      ff6d12fc57686c163088393ed8d9ca5d5a366086
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Mon Feb 25 21:40:05 2013 UTC

----------------------------------------------------------------------------

4 files changed, 106 insertions(+), 4 deletions(-)
headers/os/kernel/OS.h                      |   3 +
src/system/kernel/vm/VMUserAddressSpace.cpp | 100 +++++++++++++++++++++++-
src/system/kernel/vm/VMUserAddressSpace.h   |   6 ++
src/system/kernel/vm/vm.cpp                 |   1 +

----------------------------------------------------------------------------

diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h
index d5441da..1398451 100644
--- a/headers/os/kernel/OS.h
+++ b/headers/os/kernel/OS.h
@@ -78,6 +78,9 @@ typedef struct area_info {
 #define B_BASE_ADDRESS                 2
 #define B_CLONE_ADDRESS                        3
 #define        B_ANY_KERNEL_ADDRESS    4
+/* B_ANY_KERNEL_BLOCK_ADDRESS  5 */
+/* B_RAND_ANY_ADDRESS                  6 */
+#define B_RAND_BASE_ADDRESS            7
 
 /* area protection */
 #define B_READ_AREA                            1
diff --git a/src/system/kernel/vm/VMUserAddressSpace.cpp 
b/src/system/kernel/vm/VMUserAddressSpace.cpp
index 32730a4..3d014a1 100644
--- a/src/system/kernel/vm/VMUserAddressSpace.cpp
+++ b/src/system/kernel/vm/VMUserAddressSpace.cpp
@@ -137,6 +137,7 @@ VMUserAddressSpace::InsertArea(VMArea* _area, size_t size,
                        break;
 
                case B_BASE_ADDRESS:
+               case B_RAND_BASE_ADDRESS:
                        searchBase = (addr_t)addressRestrictions->address;
                        searchEnd = fEndAddress;
                        break;
@@ -450,6 +451,73 @@ VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t 
start, size_t size,
 }
 
 
+/* http://graphics.stanford.edu/~seander/bithacks.html */
+static int
+log2(uint32_t v)
+{
+       static const int multiply_debruijn_bit_position[32] =
+       {
+               0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
+               8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
+       };
+
+       v |= v >> 1;
+       v |= v >> 2;
+       v |= v >> 4;
+       v |= v >> 8;
+       v |= v >> 16;
+
+       return multiply_debruijn_bit_position[(uint32_t)(v * 0x07c4acddu) >> 
27];
+}
+
+
+#ifdef B_HAIKU_64_BIT
+const addr_t VMUserAddressSpace::kMaxRandomize                 =  
0x8000000000ul;
+const addr_t VMUserAddressSpace::kMaxInitialRandomize  = 0x20000000000ul;
+#else
+const addr_t VMUserAddressSpace::kMaxRandomize                 =  0x800000ul;
+const addr_t VMUserAddressSpace::kMaxInitialRandomize  = 0x2000000ul;
+#endif
+
+
+addr_t
+VMUserAddressSpace::_RandomizeAddress(addr_t start, addr_t end, bool initial)
+{
+       const int rand_shift = log2(RAND_MAX) + 1;
+       int shift = 0;
+
+       if (start == end)
+               return start;
+
+#ifdef B_HAIKU_64_BIT
+       uint64_t random = 0;
+
+       while (shift < 64) {
+               random |= (uint64_t)rand() << shift;
+               shift += rand_shift;
+       }
+#else
+       uint32_t random = 0;
+
+       while (shift < 32) {
+               random |= (uint32_t)rand() << shift;
+               shift += rand_shift;
+       }
+#endif
+
+       addr_t range = end - start;
+       if (initial)
+               range = min_c(range, kMaxInitialRandomize);
+       else
+               range = min_c(range, kMaxRandomize);
+
+       random %= range;
+       random &= ~0xffful;
+
+       return start + random;
+}
+
+
 /*!    Must be called with this address space's write lock held */
 status_t
 VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
@@ -459,6 +527,7 @@ VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t 
size, addr_t end,
        VMUserArea* last = NULL;
        VMUserArea* next;
        bool foundSpot = false;
+       addr_t originalStart = 0;
 
        TRACE(("VMUserAddressSpace::_InsertAreaSlot: address space %p, start "
                "0x%lx, size %ld, end 0x%lx, addressSpec %" B_PRIu32 ", area 
%p\n",
@@ -489,6 +558,11 @@ VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t 
size, addr_t end,
                        alignment <<= 1;
        }
 
+       if (addressSpec == B_RAND_BASE_ADDRESS) {
+               originalStart = start;
+               start = _RandomizeAddress(start, end - size, true);
+       }
+
        start = ROUNDUP(start, alignment);
 
        // walk up to the spot where we should start searching
@@ -614,6 +688,7 @@ second_chance:
                }
 
                case B_BASE_ADDRESS:
+               case B_RAND_BASE_ADDRESS:
                {
                        // find a hole big enough for a new area beginning with 
"start"
                        if (last == NULL) {
@@ -646,15 +721,32 @@ second_chance:
                                foundSpot = true;
                                if (lastEnd < start)
                                        area->SetBase(start);
-                               else
-                                       area->SetBase(lastEnd + 1);
+                               else {
+                                       start = lastEnd + 1;
+                                       if (addressSpec == B_RAND_BASE_ADDRESS) 
{
+                                               addr_t spaceEnd = end;
+                                               if (next != NULL)
+                                                       spaceEnd = next->Base();
+
+                                               start = 
_RandomizeAddress(lastEnd + 1, spaceEnd - size,
+                                                       false);
+                                       }
+
+                                       area->SetBase(start);
+                               }
                                break;
                        }
 
                        // we didn't find a free spot in the requested range, 
so we'll
                        // try again without any restrictions
-                       start = fBase;
-                       addressSpec = B_ANY_ADDRESS;
+                       if (addressSpec == B_RAND_BASE_ADDRESS && originalStart 
!= 0) {
+                               start = fBase;
+                               addressSpec = B_ANY_ADDRESS;
+                       } else {
+                               start = originalStart;
+                               originalStart = 0;
+                       }
+
                        last = NULL;
                        goto second_chance;
                }
diff --git a/src/system/kernel/vm/VMUserAddressSpace.h 
b/src/system/kernel/vm/VMUserAddressSpace.h
index fe5d37c..d24dc61 100644
--- a/src/system/kernel/vm/VMUserAddressSpace.h
+++ b/src/system/kernel/vm/VMUserAddressSpace.h
@@ -53,6 +53,9 @@ public:
        virtual void                            Dump() const;
 
 private:
+       static  addr_t                          _RandomizeAddress(addr_t start, 
addr_t end,
+                                                                       bool 
initial);
+
                        status_t                        
_InsertAreaIntoReservedRegion(addr_t start,
                                                                        size_t 
size, VMUserArea* area,
                                                                        uint32 
allocationFlags);
@@ -62,6 +65,9 @@ private:
                                                                        uint32 
allocationFlags);
 
 private:
+       static  const addr_t            kMaxRandomize;
+       static  const addr_t            kMaxInitialRandomize;
+
                        VMUserAreaList          fAreas;
        mutable VMUserArea*                     fAreaHint;
 };
diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp
index 6e809b6..d2e77c2 100644
--- a/src/system/kernel/vm/vm.cpp
+++ b/src/system/kernel/vm/vm.cpp
@@ -1219,6 +1219,7 @@ vm_create_anonymous_area(team_id team, const char *name, 
addr_t size,
                case B_BASE_ADDRESS:
                case B_ANY_KERNEL_ADDRESS:
                case B_ANY_KERNEL_BLOCK_ADDRESS:
+               case B_RAND_BASE_ADDRESS:
                        break;
 
                default:


Other related posts: