diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index 93c1a2fd00..dc91207136 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -79,7 +79,7 @@ typedef struct area_info { #define B_CLONE_ADDRESS 3 #define B_ANY_KERNEL_ADDRESS 4 /* B_ANY_KERNEL_BLOCK_ADDRESS 5 */ -/* B_RANDOMIZED_ANY_ADDRESS 6 */ +#define B_RANDOMIZED_ANY_ADDRESS 6 #define B_RANDOMIZED_BASE_ADDRESS 7 /* area protection */ diff --git a/src/system/kernel/vm/VMUserAddressSpace.cpp b/src/system/kernel/vm/VMUserAddressSpace.cpp index 8e45bec99d..1933eb6f29 100644 --- a/src/system/kernel/vm/VMUserAddressSpace.cpp +++ b/src/system/kernel/vm/VMUserAddressSpace.cpp @@ -174,6 +174,7 @@ VMUserAddressSpace::InsertArea(VMArea* _area, size_t size, case B_ANY_ADDRESS: case B_ANY_KERNEL_ADDRESS: 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!) @@ -402,8 +403,11 @@ VMUserAddressSpace::Dump() const addr_t -VMUserAddressSpace::_RandomizeAddress(addr_t start, addr_t end, bool initial) +VMUserAddressSpace::_RandomizeAddress(addr_t start, addr_t end, + size_t alignment, bool initial) { + ASSERT((start & addr_t(alignment - 1)) == 0); + if (start == end) return start; @@ -430,7 +434,7 @@ VMUserAddressSpace::_RandomizeAddress(addr_t start, addr_t end, bool initial) range = min_c(range, kMaxRandomize); random %= range; - random &= ~addr_t(B_PAGE_SIZE - 1); + random &= ~addr_t(alignment - 1); return start + random; } @@ -555,13 +559,13 @@ VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end, alignment <<= 1; } - if (addressSpec == B_RANDOMIZED_BASE_ADDRESS) { - originalStart = start; - start = _RandomizeAddress(start, end - size, true); - } - start = ROUNDUP(start, alignment); + if (addressSpec == B_RANDOMIZED_BASE_ADDRESS) { + originalStart = start; + start = _RandomizeAddress(start, end - size, alignment, true); + } + // walk up to the spot where we should start searching second_chance: VMUserAreaList::Iterator it = fAreas.GetIterator(); @@ -581,13 +585,20 @@ second_chance: case B_ANY_ADDRESS: case B_ANY_KERNEL_ADDRESS: case B_ANY_KERNEL_BLOCK_ADDRESS: + case B_RANDOMIZED_ANY_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); - if (is_valid_spot(start, alignedBase, size, - next == NULL ? end : next->Base())) { + addr_t nextBase = next == NULL ? end : next->Base(); + if (is_valid_spot(start, alignedBase, size, nextBase)) { + + if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { + alignedBase = _RandomizeAddress(alignedBase, + nextBase - size, alignment); + } + foundSpot = true; area->SetBase(alignedBase); break; @@ -603,6 +614,12 @@ second_chance: alignment); if (is_valid_spot(last->Base() + (last->Size() - 1), alignedBase, size, next->Base())) { + + if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { + alignedBase = _RandomizeAddress(alignedBase, + next->Base() - size, alignment); + } + foundSpot = true; area->SetBase(alignedBase); break; @@ -619,6 +636,12 @@ second_chance: alignment); if (is_valid_spot(last->Base() + (last->Size() - 1), alignedBase, size, end)) { + + if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { + alignedBase = _RandomizeAddress(alignedBase, end - size, + alignment); + } + // got a spot foundSpot = true; area->SetBase(alignedBase); @@ -653,12 +676,19 @@ second_chance: if ((next->protection & RESERVED_AVOID_BASE) == 0 && alignedBase == next->Base() && next->Size() >= size) { + + if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { + alignedBase = _RandomizeAddress(next->Base(), + next->Size() - size, alignment); + } + addr_t offset = alignedBase - next->Base(); + // The new area will be placed at the beginning of the // reserved area and the reserved area will be offset // and resized foundSpot = true; - next->SetBase(next->Base() + size); - next->SetSize(next->Size() - size); + next->SetBase(next->Base() + offset + size); + next->SetSize(next->Size() - offset - size); area->SetBase(alignedBase); break; } @@ -668,8 +698,23 @@ second_chance: // The new area will be placed at the end of the // reserved area, and the reserved area will be resized // to make space - alignedBase = ROUNDDOWN( - next->Base() + next->Size() - size, alignment); + + if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { + addr_t alignedNextBase = ROUNDUP(next->Base(), + alignment); + + addr_t startRange = next->Base() + next->Size(); + startRange -= size + kMaxRandomize; + startRange = ROUNDDOWN(startRange, alignment); + + startRange = max_c(startRange, alignedNextBase); + + alignedBase = _RandomizeAddress(startRange, + next->Base() + next->Size() - size, alignment); + } else { + alignedBase = ROUNDDOWN( + next->Base() + next->Size() - size, alignment); + } foundSpot = true; next->SetSize(alignedBase - next->Base()); @@ -726,7 +771,7 @@ second_chance: spaceEnd = next->Base(); start = _RandomizeAddress(lastEnd + 1, spaceEnd - size, - false); + B_PAGE_SIZE); } area->SetBase(start); @@ -736,10 +781,12 @@ 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 - || originalStart == 0) { + if (addressSpec != B_RANDOMIZED_BASE_ADDRESS) { start = fBase; addressSpec = B_ANY_ADDRESS; + } else if (originalStart == 0) { + start = fBase; + addressSpec = B_RANDOMIZED_ANY_ADDRESS; } else { start = originalStart; originalStart = 0; diff --git a/src/system/kernel/vm/VMUserAddressSpace.h b/src/system/kernel/vm/VMUserAddressSpace.h index d24dc616f5..0aa42612b6 100644 --- a/src/system/kernel/vm/VMUserAddressSpace.h +++ b/src/system/kernel/vm/VMUserAddressSpace.h @@ -54,7 +54,7 @@ public: private: static addr_t _RandomizeAddress(addr_t start, addr_t end, - bool initial); + size_t alignment, bool initial = false); status_t _InsertAreaIntoReservedRegion(addr_t start, size_t size, VMUserArea* area, diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 3503b2bcf4..fb6c2464b5 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_RANDOMIZED_ANY_ADDRESS: case B_RANDOMIZED_BASE_ADDRESS: break;