Skip to content

Commit b359ac0

Browse files
sjindel-googlecommit-bot@chromium.org
authored andcommitted
[vm] Don't leave code pages unprotected when a free-list element's header straddles a page boundary.
The old code breaks in this situation. ^ indicates page boundary: | <allocated code> | <header> | <remainder> | <other code> | | ^ ^ ^ | It would have unprotected the start of <other code> without re-protecting it after updating the header. Fixes #38528 Change-Id: I989becc3ade434fac6ec0eba5b7f8130178f6f68 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122643 Commit-Queue: Samir Jindel <sjindel@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
1 parent e82fedc commit b359ac0

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

runtime/vm/heap/freelist.cc

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,24 @@ void FreeList::SplitElementAfterAndEnqueue(FreeListElement* element,
323323
intptr_t remainder_index = IndexForSize(remainder_size);
324324
EnqueueElement(element, remainder_index);
325325

326-
// Postcondition: when allocating in a protected page, the remainder
327-
// element is no longer writable unless it is in the same page as the
328-
// allocated element. (The allocated element is still writable, and the
329-
// remainder element will be protected when the allocated one is).
330-
if (is_protected &&
331-
!VirtualMemory::InSamePage(remainder_address - 1, remainder_address)) {
332-
VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address),
333-
remainder_size, VirtualMemory::kReadExecute);
326+
// Postcondition: when allocating in a protected page, the fraction of the
327+
// remainder element which does not share a page with the allocated element is
328+
// no longer writable. This means that if the remainder's header is not fully
329+
// contained in the last page of the allocation, we need to re-protect the
330+
// page it ends on.
331+
if (is_protected) {
332+
const uword remainder_header_size =
333+
FreeListElement::HeaderSizeFor(remainder_size);
334+
if (!VirtualMemory::InSamePage(
335+
remainder_address - 1,
336+
remainder_address + remainder_header_size - 1)) {
337+
VirtualMemory::Protect(
338+
reinterpret_cast<void*>(
339+
Utils::RoundUp(remainder_address, VirtualMemory::PageSize())),
340+
remainder_address + remainder_header_size -
341+
Utils::RoundUp(remainder_address, VirtualMemory::PageSize()),
342+
VirtualMemory::kReadExecute);
343+
}
334344
}
335345
}
336346

0 commit comments

Comments
 (0)