[haiku-commits] BRANCH pdziepak-github.aslr - src/system/kernel/vm src/system/runtime_loader headers/private/kernel/arch/x86

  • From: pdziepak-github.aslr <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 9 Apr 2013 00:00:35 +0200 (CEST)

added 4 changesets to branch 'refs/remotes/pdziepak-github/aslr'
old head: a6ce073ae11c9dbf311b9654e4efd38e065165a5
new head: d57105534be7e294889fd20c4b1c9ad8768cebce
overview: https://github.com/pdziepak/Haiku/compare/a6ce073...d571055

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

65ed4fa: vm: implement B_RANDOMIZED_IMAGE_ADDRESS address specification
  
  On some 64 bit architectures program and library images have to be mapped in
  the lower 2 GB of the address space (due to instruction pointer relative
  addressing). Address specification B_RANDOMIZED_IMAGE_ADDRESS ensures that
  created area satisfies that requirement.

4cafc0a: runtime_loader: use long type for region delta

a8f8d2c: x86_64: put user stack and team data at top of user address space

d571055: vm: several improvements to VMUserAddressSpace::_InsertAreaSlot 
implementation
   * B_BASE_ADDRESS honors requested alignment
   * end of range is honored
   * B_BASE_ADDRESS reuses B_ANY_ADDRESS code

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

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

6 files changed, 76 insertions(+), 92 deletions(-)
headers/os/kernel/OS.h                        |   1 +
headers/private/kernel/arch/x86/arch_kernel.h |   4 +-
src/system/kernel/vm/VMUserAddressSpace.cpp   | 155 ++++++++++------------
src/system/kernel/vm/VMUserAddressSpace.h     |   1 +
src/system/kernel/vm/vm.cpp                   |   1 +
src/system/runtime_loader/images.cpp          |   6 +-

############################################################################

Commit:      65ed4fa908cce8864aee0905014bb802857d601d
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Apr  4 02:05:37 2013 UTC

vm: implement B_RANDOMIZED_IMAGE_ADDRESS address specification

On some 64 bit architectures program and library images have to be mapped in
the lower 2 GB of the address space (due to instruction pointer relative
addressing). Address specification B_RANDOMIZED_IMAGE_ADDRESS ensures that
created area satisfies that requirement.

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

diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h
index dc91207..820b534 100644
--- a/headers/os/kernel/OS.h
+++ b/headers/os/kernel/OS.h
@@ -81,6 +81,7 @@ typedef struct area_info {
 /* B_ANY_KERNEL_BLOCK_ADDRESS          5 */
 #define B_RANDOMIZED_ANY_ADDRESS       6
 #define B_RANDOMIZED_BASE_ADDRESS      7
+#define B_RANDOMIZED_IMAGE_ADDRESS     8
 
 /* area protection */
 #define B_READ_AREA                            1
diff --git a/src/system/kernel/vm/VMUserAddressSpace.cpp 
b/src/system/kernel/vm/VMUserAddressSpace.cpp
index 1933eb6..ffb8b62 100644
--- a/src/system/kernel/vm/VMUserAddressSpace.cpp
+++ b/src/system/kernel/vm/VMUserAddressSpace.cpp
@@ -36,6 +36,7 @@ const addr_t VMUserAddressSpace::kMaxInitialRandomize = 
0x20000000000ul;
 const addr_t VMUserAddressSpace::kMaxRandomize                 =  0x800000ul;
 const addr_t VMUserAddressSpace::kMaxInitialRandomize  = 0x2000000ul;
 #endif
+const addr_t VMUserAddressSpace::kImageEndAddress              = 0x7ffffffful;
 
 
 /*!    Verifies that an area with the given aligned base and size fits into
@@ -69,6 +70,15 @@ log2(uint32_t v)
 }
 
 
+static inline bool
+is_randomized(uint32 addressSpec)
+{
+       return addressSpec == B_RANDOMIZED_ANY_ADDRESS
+               || addressSpec == B_RANDOMIZED_BASE_ADDRESS
+               || addressSpec == B_RANDOMIZED_IMAGE_ADDRESS;
+}
+
+
 VMUserAddressSpace::VMUserAddressSpace(team_id id, addr_t base, size_t size)
        :
        VMAddressSpace(id, base, size, "address space"),
@@ -183,6 +193,11 @@ VMUserAddressSpace::InsertArea(VMArea* _area, size_t size,
                        searchEnd = fEndAddress;
                        break;
 
+               case B_RANDOMIZED_IMAGE_ADDRESS:
+                       searchBase = (addr_t)addressRestrictions->address;
+                       searchEnd = min_c(fEndAddress, kImageEndAddress);
+                       break;
+
                default:
                        return B_BAD_VALUE;
        }
@@ -561,7 +576,9 @@ VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t 
size, addr_t end,
 
        start = ROUNDUP(start, alignment);
 
-       if (addressSpec == B_RANDOMIZED_BASE_ADDRESS) {
+       if (addressSpec == B_RANDOMIZED_BASE_ADDRESS
+               || addressSpec == B_RANDOMIZED_IMAGE_ADDRESS) {
+
                originalStart = start;
                start = _RandomizeAddress(start, end - size, alignment, true);
        }
@@ -594,7 +611,7 @@ second_chance:
                                addr_t nextBase = next == NULL ? end : 
next->Base();
                                if (is_valid_spot(start, alignedBase, size, 
nextBase)) {
 
-                                       if (addressSpec == 
B_RANDOMIZED_ANY_ADDRESS) {
+                                       if (is_randomized(addressSpec)) {
                                                alignedBase = 
_RandomizeAddress(alignedBase,
                                                        nextBase - size, 
alignment);
                                        }
@@ -615,7 +632,7 @@ second_chance:
                                if (is_valid_spot(last->Base() + (last->Size() 
- 1),
                                                alignedBase, size, 
next->Base())) {
 
-                                       if (addressSpec == 
B_RANDOMIZED_ANY_ADDRESS) {
+                                       if (is_randomized(addressSpec)) {
                                                alignedBase = 
_RandomizeAddress(alignedBase,
                                                        next->Base() - size, 
alignment);
                                        }
@@ -637,7 +654,7 @@ second_chance:
                        if (is_valid_spot(last->Base() + (last->Size() - 1), 
alignedBase,
                                        size, end)) {
 
-                               if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) {
+                               if (is_randomized(addressSpec)) {
                                        alignedBase = 
_RandomizeAddress(alignedBase, end - size,
                                                alignment);
                                }
@@ -677,7 +694,7 @@ second_chance:
                                                &&  alignedBase == next->Base()
                                                && next->Size() >= size) {
 
-                                               if (addressSpec == 
B_RANDOMIZED_ANY_ADDRESS) {
+                                               if (is_randomized(addressSpec)) 
{
                                                        alignedBase = 
_RandomizeAddress(next->Base(),
                                                                next->Size() - 
size, alignment);
                                                }
@@ -699,7 +716,7 @@ second_chance:
                                                // reserved area, and the 
reserved area will be resized
                                                // to make space
 
-                                               if (addressSpec == 
B_RANDOMIZED_ANY_ADDRESS) {
+                                               if (is_randomized(addressSpec)) 
{
                                                        addr_t alignedNextBase 
= ROUNDUP(next->Base(),
                                                                alignment);
 
@@ -731,6 +748,7 @@ second_chance:
 
                case B_BASE_ADDRESS:
                case B_RANDOMIZED_BASE_ADDRESS:
+               case B_RANDOMIZED_IMAGE_ADDRESS:
                {
                        // find a hole big enough for a new area beginning with 
"start"
                        if (last == NULL) {
@@ -765,7 +783,7 @@ second_chance:
                                        area->SetBase(start);
                                else {
                                        start = lastEnd + 1;
-                                       if (addressSpec == 
B_RANDOMIZED_BASE_ADDRESS) {
+                                       if (is_randomized(addressSpec)) {
                                                addr_t spaceEnd = end;
                                                if (next != NULL)
                                                        spaceEnd = next->Base();
@@ -781,7 +799,7 @@ second_chance:
 
                        // we didn't find a free spot in the requested range, 
so we'll
                        // try again without any restrictions
-                       if (addressSpec != B_RANDOMIZED_BASE_ADDRESS) {
+                       if (!is_randomized(addressSpec)) {
                                start = fBase;
                                addressSpec = B_ANY_ADDRESS;
                        } else if (originalStart == 0) {
diff --git a/src/system/kernel/vm/VMUserAddressSpace.h 
b/src/system/kernel/vm/VMUserAddressSpace.h
index 0aa4261..8bd04bc 100644
--- a/src/system/kernel/vm/VMUserAddressSpace.h
+++ b/src/system/kernel/vm/VMUserAddressSpace.h
@@ -67,6 +67,7 @@ private:
 private:
        static  const addr_t            kMaxRandomize;
        static  const addr_t            kMaxInitialRandomize;
+       static  const addr_t            kImageEndAddress;
 
                        VMUserAreaList          fAreas;
        mutable VMUserArea*                     fAreaHint;
diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp
index f9a2f4d..a730c0e 100644
--- a/src/system/kernel/vm/vm.cpp
+++ b/src/system/kernel/vm/vm.cpp
@@ -1226,6 +1226,7 @@ vm_create_anonymous_area(team_id team, const char *name, 
addr_t size,
                case B_ANY_KERNEL_BLOCK_ADDRESS:
                case B_RANDOMIZED_ANY_ADDRESS:
                case B_RANDOMIZED_BASE_ADDRESS:
+               case B_RANDOMIZED_IMAGE_ADDRESS:
                        break;
 
                default:
diff --git a/src/system/runtime_loader/images.cpp 
b/src/system/runtime_loader/images.cpp
index d7323aa..21c3802 100644
--- a/src/system/runtime_loader/images.cpp
+++ b/src/system/runtime_loader/images.cpp
@@ -173,7 +173,7 @@ get_image_region_load_address(image_t* image, uint32 index, 
int32 lastDelta,
                if (index == 0) {
                        // but only the first segment gets a free ride
                        loadAddress = RLD_PROGRAM_BASE;
-                       addressSpecifier = B_RANDOMIZED_BASE_ADDRESS;
+                       addressSpecifier = B_RANDOMIZED_IMAGE_ADDRESS;
                } else {
                        loadAddress = image->regions[index].vmstart + lastDelta;
                        addressSpecifier = B_EXACT_ADDRESS;
@@ -298,7 +298,7 @@ map_image(int fd, char const* path, image_t* image, bool 
fixed)
        addr_t loadAddress;
        size_t reservedSize = 0;
        size_t length = 0;
-       uint32 addressSpecifier = B_RANDOMIZED_ANY_ADDRESS;
+       uint32 addressSpecifier = B_RANDOMIZED_IMAGE_ADDRESS;
 
        for (uint32 i = 0; i < image->num_regions; i++) {
                // for BeOS compatibility: if we load an old BeOS executable, we

############################################################################

Commit:      4cafc0acab0fecc88fa5eeafef25ca587aab59d9
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Apr  4 18:54:13 2013 UTC

runtime_loader: use long type for region delta

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

diff --git a/src/system/runtime_loader/images.cpp 
b/src/system/runtime_loader/images.cpp
index 21c3802..55dcdf0 100644
--- a/src/system/runtime_loader/images.cpp
+++ b/src/system/runtime_loader/images.cpp
@@ -165,7 +165,7 @@ topological_sort(image_t* image, uint32 slot, image_t** 
initList,
 /*!    Finds the load address and address specifier of the given image region.
 */
 static void
-get_image_region_load_address(image_t* image, uint32 index, int32 lastDelta,
+get_image_region_load_address(image_t* image, uint32 index, long lastDelta,
        bool fixed, addr_t& loadAddress, uint32& addressSpecifier)
 {
        if (image->dynamic_ptr != 0 && !fixed) {

############################################################################

Commit:      a8f8d2c057711ac2894f02e2b8704cd8b03c346f
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Apr  4 18:54:56 2013 UTC

x86_64: put user stack and team data at top of user address space

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

diff --git a/headers/private/kernel/arch/x86/arch_kernel.h 
b/headers/private/kernel/arch/x86/arch_kernel.h
index 9736e09..f5d6c4d 100644
--- a/headers/private/kernel/arch/x86/arch_kernel.h
+++ b/headers/private/kernel/arch/x86/arch_kernel.h
@@ -48,8 +48,8 @@
 #define USER_SIZE                              (0x800000000000 - 0x200000)
 #define USER_TOP                               (USER_BASE + (USER_SIZE - 1))
 
-#define KERNEL_USER_DATA_BASE  0x7fffe0000000
-#define USER_STACK_REGION              0x7ffff0000000
+#define KERNEL_USER_DATA_BASE  0x7f0000000000
+#define USER_STACK_REGION              0x7f0000000000
 #define USER_STACK_REGION_SIZE ((USER_TOP - USER_STACK_REGION) + 1)
 
 

############################################################################

Commit:      d57105534be7e294889fd20c4b1c9ad8768cebce
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Apr  4 18:56:41 2013 UTC

vm: several improvements to VMUserAddressSpace::_InsertAreaSlot implementation
 * B_BASE_ADDRESS honors requested alignment
 * end of range is honored
 * B_BASE_ADDRESS reuses B_ANY_ADDRESS code

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

diff --git a/src/system/kernel/vm/VMUserAddressSpace.cpp 
b/src/system/kernel/vm/VMUserAddressSpace.cpp
index ffb8b62..9315e97 100644
--- a/src/system/kernel/vm/VMUserAddressSpace.cpp
+++ b/src/system/kernel/vm/VMUserAddressSpace.cpp
@@ -186,10 +186,6 @@ VMUserAddressSpace::InsertArea(VMArea* _area, size_t size,
                case B_ANY_KERNEL_BLOCK_ADDRESS:
                case B_RANDOMIZED_ANY_ADDRESS:
                        searchBase = fBase;
-                       // TODO: remove this again when vm86 mode is moved into 
the kernel
-                       // completely (currently needs a userland address 
space!)
-                       if (searchBase == USER_BASE)
-                               searchBase = USER_BASE_ANY;
                        searchEnd = fEndAddress;
                        break;
 
@@ -202,6 +198,11 @@ VMUserAddressSpace::InsertArea(VMArea* _area, size_t size,
                        return B_BAD_VALUE;
        }
 
+       // TODO: remove this again when vm86 mode is moved into the kernel
+       // completely (currently needs a userland address space!)
+       if (addressRestrictions->address_specification != B_EXACT_ADDRESS)
+               searchBase = max_c(searchBase, USER_BASE_ANY);
+
        status = _InsertAreaSlot(searchBase, size, searchEnd,
                addressRestrictions->address_specification,
                addressRestrictions->alignment, area, allocationFlags);
@@ -603,17 +604,21 @@ second_chance:
                case B_ANY_KERNEL_ADDRESS:
                case B_ANY_KERNEL_BLOCK_ADDRESS:
                case B_RANDOMIZED_ANY_ADDRESS:
+               case B_BASE_ADDRESS:
+               case B_RANDOMIZED_BASE_ADDRESS:
+               case B_RANDOMIZED_IMAGE_ADDRESS:
                {
                        // find a hole big enough for a new area
                        if (last == NULL) {
                                // see if we can build it at the beginning of 
the virtual map
                                addr_t alignedBase = ROUNDUP(start, alignment);
-                               addr_t nextBase = next == NULL ? end : 
next->Base();
+                               addr_t nextBase = next == NULL ? end : 
min_c(next->Base(), end);
                                if (is_valid_spot(start, alignedBase, size, 
nextBase)) {
 
+                                       addr_t rangeEnd = min_c(nextBase - 
size, end);
                                        if (is_randomized(addressSpec)) {
-                                               alignedBase = 
_RandomizeAddress(alignedBase,
-                                                       nextBase - size, 
alignment);
+                                               alignedBase = 
_RandomizeAddress(alignedBase, rangeEnd,
+                                                       alignment);
                                        }
 
                                        foundSpot = true;
@@ -626,15 +631,17 @@ second_chance:
                        }
 
                        // keep walking
-                       while (next != NULL) {
+                       while (next != NULL && next->Base() + size - 1 <= end) {
                                addr_t alignedBase = ROUNDUP(last->Base() + 
last->Size(),
                                        alignment);
+                               addr_t nextBase = min_c(end, next->Base());
                                if (is_valid_spot(last->Base() + (last->Size() 
- 1),
-                                               alignedBase, size, 
next->Base())) {
+                                               alignedBase, size, nextBase)) {
 
+                                       addr_t rangeEnd = min_c(nextBase - 
size, end);
                                        if (is_randomized(addressSpec)) {
                                                alignedBase = 
_RandomizeAddress(alignedBase,
-                                                       next->Base() - size, 
alignment);
+                                                       rangeEnd, alignment);
                                        }
 
                                        foundSpot = true;
@@ -663,6 +670,24 @@ second_chance:
                                foundSpot = true;
                                area->SetBase(alignedBase);
                                break;
+                       } else if (addressSpec == B_BASE_ADDRESS
+                               || addressSpec == B_RANDOMIZED_BASE_ADDRESS
+                               || addressSpec == B_RANDOMIZED_IMAGE_ADDRESS) {
+
+                               // we didn't find a free spot in the requested 
range, so we'll
+                               // try again without any restrictions
+                               start = USER_BASE_ANY;
+                               if (!is_randomized(addressSpec))
+                                       addressSpec = B_ANY_ADDRESS;
+                               else if (start == originalStart)
+                                       addressSpec = B_RANDOMIZED_ANY_ADDRESS;
+                               else {
+                                       start = originalStart;
+                                       addressSpec = B_RANDOMIZED_BASE_ADDRESS;
+                               }
+
+                               last = NULL;
+                               goto second_chance;
                        } else if (area->id != RESERVED_AREA_ID) {
                                // We didn't find a free spot - if there are 
any reserved areas,
                                // we can now test those for free space
@@ -673,7 +698,8 @@ second_chance:
                                        if (next->id != RESERVED_AREA_ID) {
                                                last = next;
                                                continue;
-                                       }
+                                       } else if (next->Base() + size - 1 > 
end)
+                                               break;
 
                                        // TODO: take free space after the 
reserved area into
                                        // account!
@@ -694,9 +720,10 @@ second_chance:
                                                &&  alignedBase == next->Base()
                                                && next->Size() >= size) {
 
+                                               addr_t rangeEnd = 
min_c(next->Size() - size, end);
                                                if (is_randomized(addressSpec)) 
{
                                                        alignedBase = 
_RandomizeAddress(next->Base(),
-                                                               next->Size() - 
size, alignment);
+                                                               rangeEnd, 
alignment);
                                                }
                                                addr_t offset = alignedBase - 
next->Base();
 
@@ -711,7 +738,7 @@ second_chance:
                                        }
 
                                        if (is_valid_spot(next->Base(), 
alignedBase, size,
-                                                       next->Base() + 
(next->Size() - 1))) {
+                                                       min_c(next->Base() + 
next->Size() - 1, end))) {
                                                // The new area will be placed 
at the end of the
                                                // reserved area, and the 
reserved area will be resized
                                                // to make space
@@ -726,8 +753,11 @@ second_chance:
 
                                                        startRange = 
max_c(startRange, alignedNextBase);
 
+                                                       addr_t rangeEnd
+                                                               = 
min_c(next->Base() + next->Size() - size,
+                                                                       end);
                                                        alignedBase = 
_RandomizeAddress(startRange,
-                                                               next->Base() + 
next->Size() - size, alignment);
+                                                               rangeEnd, 
alignment);
                                                } else {
                                                        alignedBase = ROUNDDOWN(
                                                                next->Base() + 
next->Size() - size, alignment);
@@ -743,75 +773,8 @@ second_chance:
                                        last = next;
                                }
                        }
-                       break;
-               }
-
-               case B_BASE_ADDRESS:
-               case B_RANDOMIZED_BASE_ADDRESS:
-               case B_RANDOMIZED_IMAGE_ADDRESS:
-               {
-                       // find a hole big enough for a new area beginning with 
"start"
-                       if (last == NULL) {
-                               // see if we can build it at the beginning of 
the specified
-                               // start
-                               if (next == NULL || next->Base() > start + 
(size - 1)) {
-                                       foundSpot = true;
-                                       area->SetBase(start);
-                                       break;
-                               }
-
-                               last = next;
-                               next = it.Next();
-                       }
-
-                       // keep walking
-                       while (next != NULL) {
-                               if (next->Base() - (last->Base() + 
last->Size()) >= size) {
-                                       // we found a spot (it'll be filled up 
below)
-                                       break;
-                               }
-
-                               last = next;
-                               next = it.Next();
-                       }
-
-                       addr_t lastEnd = last->Base() + (last->Size() - 1);
-                       if (next != NULL || end - lastEnd >= size) {
-                               // got a spot
-                               foundSpot = true;
-                               if (lastEnd < start)
-                                       area->SetBase(start);
-                               else {
-                                       start = lastEnd + 1;
-                                       if (is_randomized(addressSpec)) {
-                                               addr_t spaceEnd = end;
-                                               if (next != NULL)
-                                                       spaceEnd = next->Base();
-
-                                               start = 
_RandomizeAddress(lastEnd + 1, spaceEnd - size,
-                                                       B_PAGE_SIZE);
-                                       }
-
-                                       area->SetBase(start);
-                               }
-                               break;
-                       }
 
-                       // we didn't find a free spot in the requested range, 
so we'll
-                       // try again without any restrictions
-                       if (!is_randomized(addressSpec)) {
-                               start = fBase;
-                               addressSpec = B_ANY_ADDRESS;
-                       } else if (originalStart == 0) {
-                               start = fBase;
-                               addressSpec = B_RANDOMIZED_ANY_ADDRESS;
-                       } else {
-                               start = originalStart;
-                               originalStart = 0;
-                       }
-
-                       last = NULL;
-                       goto second_chance;
+                       break;
                }
 
                case B_EXACT_ADDRESS:


Other related posts: