2017-02-10 14:26:04 +00:00
|
|
|
// Copyright 2014 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2018-11-07 09:05:38 +00:00
|
|
|
#include <map>
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
#include <optional>
|
2017-02-10 14:26:04 +00:00
|
|
|
|
2018-11-07 09:05:38 +00:00
|
|
|
#include "src/base/region-allocator.h"
|
2019-05-22 07:55:37 +00:00
|
|
|
#include "src/execution/isolate.h"
|
2017-02-10 14:26:04 +00:00
|
|
|
#include "src/heap/heap-inl.h"
|
2020-05-15 19:14:08 +00:00
|
|
|
#include "src/heap/memory-allocator.h"
|
2017-02-10 14:26:04 +00:00
|
|
|
#include "src/heap/spaces-inl.h"
|
2019-05-23 13:27:57 +00:00
|
|
|
#include "src/utils/ostreams.h"
|
2017-02-10 14:26:04 +00:00
|
|
|
#include "test/unittests/test-utils.h"
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2018-11-07 09:05:38 +00:00
|
|
|
// This is a v8::PageAllocator implementation that decorates provided page
|
|
|
|
// allocator object with page tracking functionality.
|
|
|
|
class TrackingPageAllocator : public ::v8::PageAllocator {
|
|
|
|
public:
|
|
|
|
explicit TrackingPageAllocator(v8::PageAllocator* page_allocator)
|
|
|
|
: page_allocator_(page_allocator),
|
|
|
|
allocate_page_size_(page_allocator_->AllocatePageSize()),
|
|
|
|
commit_page_size_(page_allocator_->CommitPageSize()),
|
|
|
|
region_allocator_(kNullAddress, size_t{0} - commit_page_size_,
|
|
|
|
commit_page_size_) {
|
|
|
|
CHECK_NOT_NULL(page_allocator);
|
|
|
|
CHECK(IsAligned(allocate_page_size_, commit_page_size_));
|
|
|
|
}
|
|
|
|
~TrackingPageAllocator() override = default;
|
|
|
|
|
|
|
|
size_t AllocatePageSize() override { return allocate_page_size_; }
|
|
|
|
|
|
|
|
size_t CommitPageSize() override { return commit_page_size_; }
|
|
|
|
|
|
|
|
void SetRandomMmapSeed(int64_t seed) override {
|
|
|
|
return page_allocator_->SetRandomMmapSeed(seed);
|
|
|
|
}
|
|
|
|
|
|
|
|
void* GetRandomMmapAddr() override {
|
|
|
|
return page_allocator_->GetRandomMmapAddr();
|
|
|
|
}
|
|
|
|
|
|
|
|
void* AllocatePages(void* address, size_t size, size_t alignment,
|
|
|
|
PageAllocator::Permission access) override {
|
|
|
|
void* result =
|
|
|
|
page_allocator_->AllocatePages(address, size, alignment, access);
|
|
|
|
if (result) {
|
|
|
|
// Mark pages as used.
|
|
|
|
Address current_page = reinterpret_cast<Address>(result);
|
|
|
|
CHECK(IsAligned(current_page, allocate_page_size_));
|
|
|
|
CHECK(IsAligned(size, allocate_page_size_));
|
|
|
|
CHECK(region_allocator_.AllocateRegionAt(current_page, size));
|
|
|
|
Address end = current_page + size;
|
|
|
|
while (current_page < end) {
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
PageState state{access, access != kNoAccess};
|
|
|
|
page_permissions_.insert({current_page, state});
|
2018-11-07 09:05:38 +00:00
|
|
|
current_page += commit_page_size_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FreePages(void* address, size_t size) override {
|
|
|
|
bool result = page_allocator_->FreePages(address, size);
|
|
|
|
if (result) {
|
|
|
|
// Mark pages as free.
|
|
|
|
Address start = reinterpret_cast<Address>(address);
|
|
|
|
CHECK(IsAligned(start, allocate_page_size_));
|
|
|
|
CHECK(IsAligned(size, allocate_page_size_));
|
|
|
|
size_t freed_size = region_allocator_.FreeRegion(start);
|
|
|
|
CHECK(IsAligned(freed_size, commit_page_size_));
|
|
|
|
CHECK_EQ(RoundUp(freed_size, allocate_page_size_), size);
|
|
|
|
auto start_iter = page_permissions_.find(start);
|
|
|
|
CHECK_NE(start_iter, page_permissions_.end());
|
|
|
|
auto end_iter = page_permissions_.lower_bound(start + size);
|
|
|
|
page_permissions_.erase(start_iter, end_iter);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReleasePages(void* address, size_t size, size_t new_size) override {
|
|
|
|
bool result = page_allocator_->ReleasePages(address, size, new_size);
|
|
|
|
if (result) {
|
|
|
|
Address start = reinterpret_cast<Address>(address);
|
|
|
|
CHECK(IsAligned(start, allocate_page_size_));
|
|
|
|
CHECK(IsAligned(size, commit_page_size_));
|
|
|
|
CHECK(IsAligned(new_size, commit_page_size_));
|
|
|
|
CHECK_LT(new_size, size);
|
|
|
|
CHECK_EQ(region_allocator_.TrimRegion(start, new_size), size - new_size);
|
|
|
|
auto start_iter = page_permissions_.find(start + new_size);
|
|
|
|
CHECK_NE(start_iter, page_permissions_.end());
|
|
|
|
auto end_iter = page_permissions_.lower_bound(start + size);
|
|
|
|
page_permissions_.erase(start_iter, end_iter);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-04-26 13:01:46 +00:00
|
|
|
bool RecommitPages(void* address, size_t size,
|
|
|
|
PageAllocator::Permission access) override {
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
bool result = page_allocator_->RecommitPages(address, size, access);
|
|
|
|
if (result) {
|
|
|
|
// Check that given range had given access permissions.
|
|
|
|
CheckPagePermissions(reinterpret_cast<Address>(address), size, access,
|
|
|
|
{});
|
|
|
|
UpdatePagePermissions(reinterpret_cast<Address>(address), size, access,
|
|
|
|
true);
|
|
|
|
}
|
|
|
|
return result;
|
2022-04-26 13:01:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DiscardSystemPages(void* address, size_t size) override {
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
bool result = page_allocator_->DiscardSystemPages(address, size);
|
|
|
|
if (result) {
|
|
|
|
UpdatePagePermissions(reinterpret_cast<Address>(address), size, {},
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
return result;
|
2022-04-26 13:01:46 +00:00
|
|
|
}
|
|
|
|
|
2021-08-11 14:18:28 +00:00
|
|
|
bool DecommitPages(void* address, size_t size) override {
|
|
|
|
bool result = page_allocator_->DecommitPages(address, size);
|
|
|
|
if (result) {
|
|
|
|
// Mark pages as non-accessible.
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
UpdatePagePermissions(reinterpret_cast<Address>(address), size, kNoAccess,
|
|
|
|
false);
|
2021-08-11 14:18:28 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-11-07 09:05:38 +00:00
|
|
|
bool SetPermissions(void* address, size_t size,
|
|
|
|
PageAllocator::Permission access) override {
|
|
|
|
bool result = page_allocator_->SetPermissions(address, size, access);
|
|
|
|
if (result) {
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
bool committed = access != kNoAccess && access != kNoAccessWillJitLater;
|
|
|
|
UpdatePagePermissions(reinterpret_cast<Address>(address), size, access,
|
|
|
|
committed);
|
2018-11-07 09:05:38 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true if all the allocated pages were freed.
|
|
|
|
bool IsEmpty() { return page_permissions_.empty(); }
|
|
|
|
|
|
|
|
void CheckIsFree(Address address, size_t size) {
|
|
|
|
CHECK(IsAligned(address, allocate_page_size_));
|
|
|
|
CHECK(IsAligned(size, allocate_page_size_));
|
|
|
|
EXPECT_TRUE(region_allocator_.IsFree(address, size));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckPagePermissions(Address address, size_t size,
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
PageAllocator::Permission access,
|
|
|
|
std::optional<bool> committed = {true}) {
|
|
|
|
CHECK_IMPLIES(committed.has_value() && committed.value(),
|
|
|
|
access != PageAllocator::kNoAccess);
|
2018-11-07 09:05:38 +00:00
|
|
|
ForEachPage(address, size, [=](PagePermissionsMap::value_type* value) {
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
if (committed.has_value()) {
|
|
|
|
EXPECT_EQ(committed.value(), value->second.committed);
|
|
|
|
}
|
|
|
|
EXPECT_EQ(access, value->second.access);
|
2018-11-07 09:05:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void Print(const char* comment) const {
|
|
|
|
i::StdoutStream os;
|
|
|
|
os << "\n========================================="
|
|
|
|
<< "\nTracingPageAllocator state: ";
|
|
|
|
if (comment) os << comment;
|
|
|
|
os << "\n-----------------------------------------\n";
|
|
|
|
region_allocator_.Print(os);
|
|
|
|
os << "-----------------------------------------"
|
|
|
|
<< "\nPage permissions:";
|
|
|
|
if (page_permissions_.empty()) {
|
|
|
|
os << " empty\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
os << "\n" << std::hex << std::showbase;
|
|
|
|
|
|
|
|
Address contiguous_region_start = static_cast<Address>(-1);
|
|
|
|
Address contiguous_region_end = contiguous_region_start;
|
|
|
|
PageAllocator::Permission contiguous_region_access =
|
|
|
|
PageAllocator::kNoAccess;
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
bool contiguous_region_access_committed = false;
|
2018-11-07 09:05:38 +00:00
|
|
|
for (auto& pair : page_permissions_) {
|
|
|
|
if (contiguous_region_end == pair.first &&
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
pair.second.access == contiguous_region_access &&
|
|
|
|
pair.second.committed == contiguous_region_access_committed) {
|
2018-11-07 09:05:38 +00:00
|
|
|
contiguous_region_end += commit_page_size_;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (contiguous_region_start != contiguous_region_end) {
|
|
|
|
PrintRegion(os, contiguous_region_start, contiguous_region_end,
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
contiguous_region_access,
|
|
|
|
contiguous_region_access_committed);
|
2018-11-07 09:05:38 +00:00
|
|
|
}
|
|
|
|
contiguous_region_start = pair.first;
|
|
|
|
contiguous_region_end = pair.first + commit_page_size_;
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
contiguous_region_access = pair.second.access;
|
|
|
|
contiguous_region_access_committed = pair.second.committed;
|
2018-11-07 09:05:38 +00:00
|
|
|
}
|
|
|
|
if (contiguous_region_start != contiguous_region_end) {
|
|
|
|
PrintRegion(os, contiguous_region_start, contiguous_region_end,
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
contiguous_region_access, contiguous_region_access_committed);
|
2018-11-07 09:05:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
struct PageState {
|
|
|
|
PageAllocator::Permission access;
|
|
|
|
bool committed;
|
|
|
|
};
|
|
|
|
using PagePermissionsMap = std::map<Address, PageState>;
|
2019-03-29 09:47:48 +00:00
|
|
|
using ForEachFn = std::function<void(PagePermissionsMap::value_type*)>;
|
2018-11-07 09:05:38 +00:00
|
|
|
|
|
|
|
static void PrintRegion(std::ostream& os, Address start, Address end,
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
PageAllocator::Permission access, bool committed) {
|
2018-11-07 09:05:38 +00:00
|
|
|
os << " page: [" << start << ", " << end << "), access: ";
|
|
|
|
switch (access) {
|
|
|
|
case PageAllocator::kNoAccess:
|
2020-10-06 09:45:16 +00:00
|
|
|
case PageAllocator::kNoAccessWillJitLater:
|
2018-11-07 09:05:38 +00:00
|
|
|
os << "--";
|
|
|
|
break;
|
|
|
|
case PageAllocator::kRead:
|
|
|
|
os << "R";
|
|
|
|
break;
|
|
|
|
case PageAllocator::kReadWrite:
|
|
|
|
os << "RW";
|
|
|
|
break;
|
|
|
|
case PageAllocator::kReadWriteExecute:
|
|
|
|
os << "RWX";
|
|
|
|
break;
|
|
|
|
case PageAllocator::kReadExecute:
|
|
|
|
os << "RX";
|
|
|
|
break;
|
|
|
|
}
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
os << ", committed: " << static_cast<int>(committed) << "\n";
|
2018-11-07 09:05:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ForEachPage(Address address, size_t size, const ForEachFn& fn) {
|
|
|
|
CHECK(IsAligned(address, commit_page_size_));
|
|
|
|
CHECK(IsAligned(size, commit_page_size_));
|
|
|
|
auto start_iter = page_permissions_.find(address);
|
|
|
|
// Start page must exist in page_permissions_.
|
|
|
|
CHECK_NE(start_iter, page_permissions_.end());
|
|
|
|
auto end_iter = page_permissions_.find(address + size - commit_page_size_);
|
|
|
|
// Ensure the last but one page exists in page_permissions_.
|
|
|
|
CHECK_NE(end_iter, page_permissions_.end());
|
|
|
|
// Now make it point to the next element in order to also process is by the
|
|
|
|
// following for loop.
|
|
|
|
++end_iter;
|
|
|
|
for (auto iter = start_iter; iter != end_iter; ++iter) {
|
|
|
|
PagePermissionsMap::value_type& pair = *iter;
|
|
|
|
fn(&pair);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdatePagePermissions(Address address, size_t size,
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
std::optional<PageAllocator::Permission> access,
|
|
|
|
bool committed) {
|
2018-11-07 09:05:38 +00:00
|
|
|
ForEachPage(address, size, [=](PagePermissionsMap::value_type* value) {
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
if (access.has_value()) {
|
|
|
|
value->second.access = access.value();
|
|
|
|
}
|
|
|
|
value->second.committed = committed;
|
2018-11-07 09:05:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
v8::PageAllocator* const page_allocator_;
|
|
|
|
const size_t allocate_page_size_;
|
|
|
|
const size_t commit_page_size_;
|
|
|
|
// Region allocator tracks page allocation/deallocation requests.
|
|
|
|
base::RegionAllocator region_allocator_;
|
|
|
|
// This map keeps track of allocated pages' permissions.
|
|
|
|
PagePermissionsMap page_permissions_;
|
|
|
|
};
|
|
|
|
|
V8 Sandbox rebranding
This CL renames a number of things related to the V8 sandbox.
Mainly, what used to be under V8_HEAP_SANDBOX is now under
V8_SANDBOXED_EXTERNAL_POINTERS, while the previous V8 VirtualMemoryCage
is now simply the V8 Sandbox:
V8_VIRTUAL_MEMORY_CAGE => V8_SANDBOX
V8_HEAP_SANDBOX => V8_SANDBOXED_EXTERNAL_POINTERS
V8_CAGED_POINTERS => V8_SANDBOXED_POINTERS
V8VirtualMemoryCage => Sandbox
CagedPointer => SandboxedPointer
fake cage => partially reserved sandbox
src/security => src/sandbox
This naming scheme should simplify things: the sandbox is now the large
region of virtual address space inside which V8 mainly operates and
which should be considered untrusted. Mechanisms like sandboxed pointers
are then used to attempt to prevent escapes from the sandbox (i.e.
corruption of memory outside of it). Furthermore, the new naming scheme
avoids the confusion with the various other "cages" in V8, in
particular, the VirtualMemoryCage class, by dropping that name entirely.
Future sandbox features are developed under their own V8_SANDBOX_X flag,
and will, once final, be merged into V8_SANDBOX. Current future features
are sandboxed external pointers (using the external pointer table), and
sandboxed pointers (pointers guaranteed to point into the sandbox, e.g.
because they are encoded as offsets). This CL then also introduces a new
build flag, v8_enable_sandbox_future, which enables all future features.
Bug: v8:10391
Change-Id: I5174ea8f5ab40fb96a04af10853da735ad775c96
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3322981
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78384}
2021-12-15 13:39:15 +00:00
|
|
|
// This test is currently incompatible with the sandbox. Enable it
|
|
|
|
// once the VirtualAddressSpace interface is stable.
|
2022-05-13 11:10:04 +00:00
|
|
|
#if !V8_OS_FUCHSIA && !V8_ENABLE_SANDBOX
|
2022-04-06 11:56:49 +00:00
|
|
|
|
|
|
|
template <typename TMixin>
|
|
|
|
class SequentialUnmapperTestMixin : public TMixin {
|
|
|
|
public:
|
|
|
|
SequentialUnmapperTestMixin();
|
|
|
|
~SequentialUnmapperTestMixin() override;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SequentialUnmapperTest : public //
|
|
|
|
WithInternalIsolateMixin< //
|
|
|
|
WithIsolateScopeMixin< //
|
|
|
|
WithIsolateMixin< //
|
|
|
|
SequentialUnmapperTestMixin< //
|
|
|
|
WithDefaultPlatformMixin< //
|
|
|
|
::testing::Test>>>>> {
|
2017-02-10 14:26:04 +00:00
|
|
|
public:
|
|
|
|
SequentialUnmapperTest() = default;
|
|
|
|
~SequentialUnmapperTest() override = default;
|
2020-11-05 08:11:05 +00:00
|
|
|
SequentialUnmapperTest(const SequentialUnmapperTest&) = delete;
|
|
|
|
SequentialUnmapperTest& operator=(const SequentialUnmapperTest&) = delete;
|
2017-02-10 14:26:04 +00:00
|
|
|
|
2022-04-06 11:56:49 +00:00
|
|
|
static void FreeProcessWidePtrComprCageForTesting() {
|
|
|
|
IsolateAllocator::FreeProcessWidePtrComprCageForTesting();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DoMixinSetUp() {
|
2018-11-07 09:05:38 +00:00
|
|
|
CHECK_NULL(tracking_page_allocator_);
|
|
|
|
old_page_allocator_ = GetPlatformPageAllocator();
|
|
|
|
tracking_page_allocator_ = new TrackingPageAllocator(old_page_allocator_);
|
|
|
|
CHECK(tracking_page_allocator_->IsEmpty());
|
|
|
|
CHECK_EQ(old_page_allocator_,
|
|
|
|
SetPlatformPageAllocatorForTesting(tracking_page_allocator_));
|
2017-02-10 14:26:04 +00:00
|
|
|
old_flag_ = i::FLAG_concurrent_sweeping;
|
|
|
|
i::FLAG_concurrent_sweeping = false;
|
2021-09-16 13:56:38 +00:00
|
|
|
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
|
|
|
|
// Reinitialize the process-wide pointer cage so it can pick up the
|
|
|
|
// TrackingPageAllocator.
|
V8 Sandbox rebranding
This CL renames a number of things related to the V8 sandbox.
Mainly, what used to be under V8_HEAP_SANDBOX is now under
V8_SANDBOXED_EXTERNAL_POINTERS, while the previous V8 VirtualMemoryCage
is now simply the V8 Sandbox:
V8_VIRTUAL_MEMORY_CAGE => V8_SANDBOX
V8_HEAP_SANDBOX => V8_SANDBOXED_EXTERNAL_POINTERS
V8_CAGED_POINTERS => V8_SANDBOXED_POINTERS
V8VirtualMemoryCage => Sandbox
CagedPointer => SandboxedPointer
fake cage => partially reserved sandbox
src/security => src/sandbox
This naming scheme should simplify things: the sandbox is now the large
region of virtual address space inside which V8 mainly operates and
which should be considered untrusted. Mechanisms like sandboxed pointers
are then used to attempt to prevent escapes from the sandbox (i.e.
corruption of memory outside of it). Furthermore, the new naming scheme
avoids the confusion with the various other "cages" in V8, in
particular, the VirtualMemoryCage class, by dropping that name entirely.
Future sandbox features are developed under their own V8_SANDBOX_X flag,
and will, once final, be merged into V8_SANDBOX. Current future features
are sandboxed external pointers (using the external pointer table), and
sandboxed pointers (pointers guaranteed to point into the sandbox, e.g.
because they are encoded as offsets). This CL then also introduces a new
build flag, v8_enable_sandbox_future, which enables all future features.
Bug: v8:10391
Change-Id: I5174ea8f5ab40fb96a04af10853da735ad775c96
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3322981
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78384}
2021-12-15 13:39:15 +00:00
|
|
|
// The pointer cage must be destroyed before the sandbox.
|
2021-09-16 13:56:38 +00:00
|
|
|
IsolateAllocator::FreeProcessWidePtrComprCageForTesting();
|
2022-05-13 11:10:04 +00:00
|
|
|
#ifdef V8_ENABLE_SANDBOX
|
V8 Sandbox rebranding
This CL renames a number of things related to the V8 sandbox.
Mainly, what used to be under V8_HEAP_SANDBOX is now under
V8_SANDBOXED_EXTERNAL_POINTERS, while the previous V8 VirtualMemoryCage
is now simply the V8 Sandbox:
V8_VIRTUAL_MEMORY_CAGE => V8_SANDBOX
V8_HEAP_SANDBOX => V8_SANDBOXED_EXTERNAL_POINTERS
V8_CAGED_POINTERS => V8_SANDBOXED_POINTERS
V8VirtualMemoryCage => Sandbox
CagedPointer => SandboxedPointer
fake cage => partially reserved sandbox
src/security => src/sandbox
This naming scheme should simplify things: the sandbox is now the large
region of virtual address space inside which V8 mainly operates and
which should be considered untrusted. Mechanisms like sandboxed pointers
are then used to attempt to prevent escapes from the sandbox (i.e.
corruption of memory outside of it). Furthermore, the new naming scheme
avoids the confusion with the various other "cages" in V8, in
particular, the VirtualMemoryCage class, by dropping that name entirely.
Future sandbox features are developed under their own V8_SANDBOX_X flag,
and will, once final, be merged into V8_SANDBOX. Current future features
are sandboxed external pointers (using the external pointer table), and
sandboxed pointers (pointers guaranteed to point into the sandbox, e.g.
because they are encoded as offsets). This CL then also introduces a new
build flag, v8_enable_sandbox_future, which enables all future features.
Bug: v8:10391
Change-Id: I5174ea8f5ab40fb96a04af10853da735ad775c96
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3322981
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78384}
2021-12-15 13:39:15 +00:00
|
|
|
// Reinitialze the sandbox so it uses the TrackingPageAllocator.
|
|
|
|
GetProcessWideSandbox()->TearDown();
|
2021-08-11 14:18:28 +00:00
|
|
|
constexpr bool use_guard_regions = false;
|
V8 Sandbox rebranding
This CL renames a number of things related to the V8 sandbox.
Mainly, what used to be under V8_HEAP_SANDBOX is now under
V8_SANDBOXED_EXTERNAL_POINTERS, while the previous V8 VirtualMemoryCage
is now simply the V8 Sandbox:
V8_VIRTUAL_MEMORY_CAGE => V8_SANDBOX
V8_HEAP_SANDBOX => V8_SANDBOXED_EXTERNAL_POINTERS
V8_CAGED_POINTERS => V8_SANDBOXED_POINTERS
V8VirtualMemoryCage => Sandbox
CagedPointer => SandboxedPointer
fake cage => partially reserved sandbox
src/security => src/sandbox
This naming scheme should simplify things: the sandbox is now the large
region of virtual address space inside which V8 mainly operates and
which should be considered untrusted. Mechanisms like sandboxed pointers
are then used to attempt to prevent escapes from the sandbox (i.e.
corruption of memory outside of it). Furthermore, the new naming scheme
avoids the confusion with the various other "cages" in V8, in
particular, the VirtualMemoryCage class, by dropping that name entirely.
Future sandbox features are developed under their own V8_SANDBOX_X flag,
and will, once final, be merged into V8_SANDBOX. Current future features
are sandboxed external pointers (using the external pointer table), and
sandboxed pointers (pointers guaranteed to point into the sandbox, e.g.
because they are encoded as offsets). This CL then also introduces a new
build flag, v8_enable_sandbox_future, which enables all future features.
Bug: v8:10391
Change-Id: I5174ea8f5ab40fb96a04af10853da735ad775c96
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3322981
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78384}
2021-12-15 13:39:15 +00:00
|
|
|
CHECK(GetProcessWideSandbox()->Initialize(
|
|
|
|
tracking_page_allocator_, kSandboxMinimumSize, use_guard_regions));
|
2021-08-11 14:18:28 +00:00
|
|
|
#endif
|
2021-04-19 16:39:28 +00:00
|
|
|
IsolateAllocator::InitializeOncePerProcess();
|
2021-04-10 02:09:41 +00:00
|
|
|
#endif
|
2017-02-10 14:26:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-06 11:56:49 +00:00
|
|
|
static void DoMixinTearDown() {
|
2021-04-10 02:09:41 +00:00
|
|
|
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
|
|
|
|
// Free the process-wide cage reservation, otherwise the pages won't be
|
|
|
|
// freed until process teardown.
|
2021-04-19 16:39:28 +00:00
|
|
|
IsolateAllocator::FreeProcessWidePtrComprCageForTesting();
|
2021-08-11 14:18:28 +00:00
|
|
|
#endif
|
2022-05-13 11:10:04 +00:00
|
|
|
#ifdef V8_ENABLE_SANDBOX
|
V8 Sandbox rebranding
This CL renames a number of things related to the V8 sandbox.
Mainly, what used to be under V8_HEAP_SANDBOX is now under
V8_SANDBOXED_EXTERNAL_POINTERS, while the previous V8 VirtualMemoryCage
is now simply the V8 Sandbox:
V8_VIRTUAL_MEMORY_CAGE => V8_SANDBOX
V8_HEAP_SANDBOX => V8_SANDBOXED_EXTERNAL_POINTERS
V8_CAGED_POINTERS => V8_SANDBOXED_POINTERS
V8VirtualMemoryCage => Sandbox
CagedPointer => SandboxedPointer
fake cage => partially reserved sandbox
src/security => src/sandbox
This naming scheme should simplify things: the sandbox is now the large
region of virtual address space inside which V8 mainly operates and
which should be considered untrusted. Mechanisms like sandboxed pointers
are then used to attempt to prevent escapes from the sandbox (i.e.
corruption of memory outside of it). Furthermore, the new naming scheme
avoids the confusion with the various other "cages" in V8, in
particular, the VirtualMemoryCage class, by dropping that name entirely.
Future sandbox features are developed under their own V8_SANDBOX_X flag,
and will, once final, be merged into V8_SANDBOX. Current future features
are sandboxed external pointers (using the external pointer table), and
sandboxed pointers (pointers guaranteed to point into the sandbox, e.g.
because they are encoded as offsets). This CL then also introduces a new
build flag, v8_enable_sandbox_future, which enables all future features.
Bug: v8:10391
Change-Id: I5174ea8f5ab40fb96a04af10853da735ad775c96
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3322981
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78384}
2021-12-15 13:39:15 +00:00
|
|
|
GetProcessWideSandbox()->TearDown();
|
2021-04-10 02:09:41 +00:00
|
|
|
#endif
|
2017-02-10 14:26:04 +00:00
|
|
|
i::FLAG_concurrent_sweeping = old_flag_;
|
2018-11-07 09:05:38 +00:00
|
|
|
CHECK(tracking_page_allocator_->IsEmpty());
|
2020-01-20 18:53:45 +00:00
|
|
|
|
|
|
|
// Restore the original v8::PageAllocator and delete the tracking one.
|
|
|
|
CHECK_EQ(tracking_page_allocator_,
|
|
|
|
SetPlatformPageAllocatorForTesting(old_page_allocator_));
|
2018-11-07 09:05:38 +00:00
|
|
|
delete tracking_page_allocator_;
|
|
|
|
tracking_page_allocator_ = nullptr;
|
2017-02-10 14:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Heap* heap() { return isolate()->heap(); }
|
|
|
|
MemoryAllocator* allocator() { return heap()->memory_allocator(); }
|
|
|
|
MemoryAllocator::Unmapper* unmapper() { return allocator()->unmapper(); }
|
|
|
|
|
2018-11-07 09:05:38 +00:00
|
|
|
TrackingPageAllocator* tracking_page_allocator() {
|
|
|
|
return tracking_page_allocator_;
|
|
|
|
}
|
|
|
|
|
2017-02-10 14:26:04 +00:00
|
|
|
private:
|
2018-11-07 09:05:38 +00:00
|
|
|
static TrackingPageAllocator* tracking_page_allocator_;
|
|
|
|
static v8::PageAllocator* old_page_allocator_;
|
2017-02-10 14:26:04 +00:00
|
|
|
static bool old_flag_;
|
|
|
|
};
|
|
|
|
|
2018-11-07 09:05:38 +00:00
|
|
|
TrackingPageAllocator* SequentialUnmapperTest::tracking_page_allocator_ =
|
|
|
|
nullptr;
|
|
|
|
v8::PageAllocator* SequentialUnmapperTest::old_page_allocator_ = nullptr;
|
2017-02-10 14:26:04 +00:00
|
|
|
bool SequentialUnmapperTest::old_flag_;
|
|
|
|
|
2022-04-06 11:56:49 +00:00
|
|
|
template <typename TMixin>
|
|
|
|
SequentialUnmapperTestMixin<TMixin>::SequentialUnmapperTestMixin() {
|
|
|
|
SequentialUnmapperTest::DoMixinSetUp();
|
|
|
|
}
|
|
|
|
template <typename TMixin>
|
|
|
|
SequentialUnmapperTestMixin<TMixin>::~SequentialUnmapperTestMixin() {
|
|
|
|
SequentialUnmapperTest::DoMixinTearDown();
|
|
|
|
}
|
|
|
|
|
2017-02-10 14:26:04 +00:00
|
|
|
// See v8:5945.
|
|
|
|
TEST_F(SequentialUnmapperTest, UnmapOnTeardownAfterAlreadyFreeingPooled) {
|
2021-05-06 08:49:22 +00:00
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-03-28 08:18:20 +00:00
|
|
|
Page* page =
|
|
|
|
allocator()->AllocatePage(MemoryAllocator::AllocationMode::kRegular,
|
|
|
|
static_cast<PagedSpace*>(heap()->old_space()),
|
|
|
|
Executability::NOT_EXECUTABLE);
|
2017-02-10 14:26:04 +00:00
|
|
|
EXPECT_NE(nullptr, page);
|
2018-11-07 09:05:38 +00:00
|
|
|
const size_t page_size = tracking_page_allocator()->AllocatePageSize();
|
|
|
|
tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
|
|
|
|
PageAllocator::kReadWrite);
|
2022-03-28 08:18:20 +00:00
|
|
|
allocator()->Free(MemoryAllocator::FreeMode::kConcurrentlyAndPool, page);
|
2018-11-07 09:05:38 +00:00
|
|
|
tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
|
|
|
|
PageAllocator::kReadWrite);
|
2017-02-10 14:26:04 +00:00
|
|
|
unmapper()->FreeQueuedChunks();
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
tracking_page_allocator()->CheckPagePermissions(
|
|
|
|
page->address(), page_size, PageAllocator::kNoAccess, false);
|
2017-02-10 14:26:04 +00:00
|
|
|
unmapper()->TearDown();
|
2020-10-01 13:23:44 +00:00
|
|
|
#ifdef V8_COMPRESS_POINTERS
|
|
|
|
// In this mode Isolate uses bounded page allocator which allocates pages
|
|
|
|
// inside prereserved region. Thus these pages are kept reserved until
|
|
|
|
// the Isolate dies.
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
tracking_page_allocator()->CheckPagePermissions(
|
|
|
|
page->address(), page_size, PageAllocator::kNoAccess, false);
|
2020-10-01 13:23:44 +00:00
|
|
|
#else
|
|
|
|
tracking_page_allocator()->CheckIsFree(page->address(), page_size);
|
|
|
|
#endif // V8_COMPRESS_POINTERS
|
2017-02-10 14:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// See v8:5945.
|
|
|
|
TEST_F(SequentialUnmapperTest, UnmapOnTeardown) {
|
2021-05-06 08:49:22 +00:00
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-03-28 08:18:20 +00:00
|
|
|
Page* page =
|
|
|
|
allocator()->AllocatePage(MemoryAllocator::AllocationMode::kRegular,
|
|
|
|
static_cast<PagedSpace*>(heap()->old_space()),
|
|
|
|
Executability::NOT_EXECUTABLE);
|
2017-02-10 14:26:04 +00:00
|
|
|
EXPECT_NE(nullptr, page);
|
2018-11-07 09:05:38 +00:00
|
|
|
const size_t page_size = tracking_page_allocator()->AllocatePageSize();
|
|
|
|
tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
|
|
|
|
PageAllocator::kReadWrite);
|
|
|
|
|
2022-03-28 08:18:20 +00:00
|
|
|
allocator()->Free(MemoryAllocator::FreeMode::kConcurrentlyAndPool, page);
|
2018-11-07 09:05:38 +00:00
|
|
|
tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
|
|
|
|
PageAllocator::kReadWrite);
|
2017-02-10 14:26:04 +00:00
|
|
|
unmapper()->TearDown();
|
2020-10-01 13:23:44 +00:00
|
|
|
#ifdef V8_COMPRESS_POINTERS
|
|
|
|
// In this mode Isolate uses bounded page allocator which allocates pages
|
|
|
|
// inside prereserved region. Thus these pages are kept reserved until
|
|
|
|
// the Isolate dies.
|
Reland "[rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)"
This is a reland of commit 9d31f8663ad72fdf04d15a72d83b54a6ac33b640
There were issues with --future flag implications on M1.
Original change's description:
> [rwx][mac] Support fast W^X permission switching on Apple Silicon (M1)
>
> ... for V8 code space. The feature is currently disabled.
>
> In order to use fast W^X permission switching we must allocate
> executable pages with readable writable executable permissions (RWX).
> However, MacOS on ARM64 ("Apple M1"/Apple Silicon) prohibits further
> permission changing of RWX memory pages. This means that the code page
> headers must be allocated with RWX permissions too because otherwise
> it wouldn't be possible to allocate a large code page over the freed
> regular code page and vice versa.
>
> When enabled, the new machinery works as follows:
>
> 1) when memory region is reserved for allocating executable pages, the
> whole region is committed with RWX permissions and then decommitted,
> 2) since reconfiguration of RWX page permissions is not allowed on
> MacOS on ARM64 ("Apple M1"/Apple Silicon), there must be no attempts
> to change them,
> 3) the request to set RWX permissions in the executable page region
> just recommits the pages without changing permissions (see (1), they
> were already allocated as RWX and then discarded),
> 4) in order to make executable pages inaccessible one must use
> OS::DiscardSystemPages() instead of OS::DecommitPages() or
> setting permissions to kNoAccess because the latter two are not
> allowed by the MacOS (see (2)).
> 5) since code space page headers are allocated as RWX pages it's also
> necessary to switch between W^X modes when updating the data in the
> page headers (i.e. when marking, updating stats, wiring pages in
> lists, etc.). The new CodePageHeaderModificationScope class is used
> in the respective places. On unrelated configurations it's a no-op.
>
> The fast permission switching can't be used for V8 configuration with
> enabled pointer compression and disabled external code space because
> a) the pointer compression cage has to be reserved with MAP_JIT flag
> which is too expensive,
> b) in case of shared pointer compression cage if the code range will
> be deleted while the cage is still alive then attempt to configure
> permissions of pages that were previously set to RWX will fail.
>
> This also CL extends the unmapper unit tests with permissions tracking
> for discarded pages.
>
> Bug: v8:12797
> Change-Id: Idb28cbc481306477589eee9962d2e75167d87c61
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3579303
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Igor Sheludko <ishell@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#80238}
Bug: v8:12797
Change-Id: I0fe86666f31bad37d7074e217555c95900d2afba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610433
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80259}
2022-04-28 10:14:12 +00:00
|
|
|
tracking_page_allocator()->CheckPagePermissions(
|
|
|
|
page->address(), page_size, PageAllocator::kNoAccess, false);
|
2020-10-01 13:23:44 +00:00
|
|
|
#else
|
|
|
|
tracking_page_allocator()->CheckIsFree(page->address(), page_size);
|
|
|
|
#endif // V8_COMPRESS_POINTERS
|
2017-02-10 14:26:04 +00:00
|
|
|
}
|
2022-05-13 11:10:04 +00:00
|
|
|
#endif // !V8_OS_FUCHSIA && !V8_ENABLE_SANDBOX
|
2017-02-10 14:26:04 +00:00
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|