mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
POSIX: ScopedMmap length refinement
9d26012e9c73 relaxed the requirement on ScopedMmap such that the length of the region supervised no longer needed to be provided as a round number of pages. This was accomplished by internally rounding up the provided length to a page length. Unfortunately, this made ScopedMmap::len() return something other than the passed-in length, which is undesirable. This change makes ScopedMmap store the passed-in length internally, making it available unmodified via the accessor, and rounding it up to page length at internal points of use. Change-Id: I827925af68e38f33bfa3cee535db0f098884fc6b Reviewed-on: https://chromium-review.googlesource.com/c/1492774 Commit-Queue: Mark Mentovai <mark@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
3332ae3546
commit
708367f5ba
@ -33,6 +33,11 @@ bool Munmap(uintptr_t addr, size_t len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t RoundPage(size_t size) {
|
||||
const size_t kPageMask = base::checked_cast<size_t>(getpagesize()) - 1;
|
||||
return (size + kPageMask) & ~kPageMask;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace crashpad {
|
||||
@ -41,7 +46,7 @@ ScopedMmap::ScopedMmap() {}
|
||||
|
||||
ScopedMmap::~ScopedMmap() {
|
||||
if (is_valid()) {
|
||||
Munmap(reinterpret_cast<uintptr_t>(addr_), len_);
|
||||
Munmap(reinterpret_cast<uintptr_t>(addr_), RoundPage(len_));
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,29 +56,28 @@ bool ScopedMmap::Reset() {
|
||||
|
||||
bool ScopedMmap::ResetAddrLen(void* addr, size_t len) {
|
||||
const uintptr_t new_addr = reinterpret_cast<uintptr_t>(addr);
|
||||
const size_t new_len_round = RoundPage(len);
|
||||
|
||||
if (addr == MAP_FAILED) {
|
||||
DCHECK_EQ(len, 0u);
|
||||
} else {
|
||||
// Round |len| up to the next page.
|
||||
const size_t kPageMask = base::checked_cast<size_t>(getpagesize()) - 1;
|
||||
len = (len + kPageMask) & ~kPageMask;
|
||||
|
||||
DCHECK_NE(len, 0u);
|
||||
DCHECK_EQ(new_addr % getpagesize(), 0u);
|
||||
DCHECK((base::CheckedNumeric<uintptr_t>(new_addr) + (len - 1)).IsValid());
|
||||
DCHECK((base::CheckedNumeric<uintptr_t>(new_addr) + (new_len_round - 1))
|
||||
.IsValid());
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
if (is_valid()) {
|
||||
const uintptr_t old_addr = reinterpret_cast<uintptr_t>(addr_);
|
||||
const size_t old_len_round = RoundPage(len_);
|
||||
if (old_addr < new_addr) {
|
||||
result &= Munmap(old_addr, std::min(len_, new_addr - old_addr));
|
||||
result &= Munmap(old_addr, std::min(old_len_round, new_addr - old_addr));
|
||||
}
|
||||
if (old_addr + len_ > new_addr + len) {
|
||||
uintptr_t unmap_start = std::max(old_addr, new_addr + len);
|
||||
result &= Munmap(unmap_start, old_addr + len_ - unmap_start);
|
||||
if (old_addr + old_len_round > new_addr + new_len_round) {
|
||||
uintptr_t unmap_start = std::max(old_addr, new_addr + new_len_round);
|
||||
result &= Munmap(unmap_start, old_addr + old_len_round - unmap_start);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +112,7 @@ bool ScopedMmap::ResetMmap(void* addr,
|
||||
}
|
||||
|
||||
bool ScopedMmap::Mprotect(int prot) {
|
||||
if (mprotect(addr_, len_, prot) < 0) {
|
||||
if (mprotect(addr_, RoundPage(len_), prot) < 0) {
|
||||
PLOG(ERROR) << "mprotect";
|
||||
return false;
|
||||
}
|
||||
|
@ -91,6 +91,11 @@ class ScopedMmap {
|
||||
}
|
||||
|
||||
//! \brief Returns the size of the memory-mapped region.
|
||||
//!
|
||||
//! This is the value originally passed to ResetAddrLen() or ResetMmap(), or
|
||||
//! after Reset(), `0`. It may not be a round number of pages. Providing the
|
||||
//! passed-in value is intended to ease tracking the intended lengths of
|
||||
//! memory-mapped regions backed by files whose sizes are not whole pages.
|
||||
size_t len() const { return len_; }
|
||||
|
||||
private:
|
||||
|
@ -309,7 +309,7 @@ TEST(ScopedMmapDeathTest, NotIntegralNumberOfPages) {
|
||||
ASSERT_TRUE(ScopedMmapResetMmap(&mapping, kHalfPageSize));
|
||||
EXPECT_TRUE(mapping.is_valid());
|
||||
EXPECT_NE(mapping.addr(), MAP_FAILED);
|
||||
EXPECT_EQ(mapping.len(), kPageSize);
|
||||
EXPECT_EQ(mapping.len(), kHalfPageSize);
|
||||
|
||||
TestCookie cookie;
|
||||
cookie.SetUp(mapping.addr_as<uint64_t*>());
|
||||
@ -319,7 +319,7 @@ TEST(ScopedMmapDeathTest, NotIntegralNumberOfPages) {
|
||||
ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kHalfPageSize));
|
||||
EXPECT_TRUE(mapping.is_valid());
|
||||
EXPECT_EQ(mapping.addr(), orig_addr);
|
||||
EXPECT_EQ(mapping.len(), kPageSize);
|
||||
EXPECT_EQ(mapping.len(), kHalfPageSize);
|
||||
|
||||
EXPECT_EQ(cookie.Observed(), cookie.Expected());
|
||||
|
||||
@ -328,14 +328,14 @@ TEST(ScopedMmapDeathTest, NotIntegralNumberOfPages) {
|
||||
ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, 1));
|
||||
EXPECT_TRUE(mapping.is_valid());
|
||||
EXPECT_EQ(mapping.addr(), orig_addr);
|
||||
EXPECT_EQ(mapping.len(), kPageSize);
|
||||
EXPECT_EQ(mapping.len(), 1u);
|
||||
|
||||
EXPECT_EQ(cookie.Observed(), cookie.Expected());
|
||||
|
||||
ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kPageSize - 1));
|
||||
EXPECT_TRUE(mapping.is_valid());
|
||||
EXPECT_EQ(mapping.addr(), orig_addr);
|
||||
EXPECT_EQ(mapping.len(), kPageSize);
|
||||
EXPECT_EQ(mapping.len(), kPageSize - 1);
|
||||
|
||||
EXPECT_EQ(cookie.Observed(), cookie.Expected());
|
||||
|
||||
@ -356,7 +356,7 @@ TEST(ScopedMmapDeathTest, NotIntegralNumberOfPages) {
|
||||
ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kHalfPageSize));
|
||||
EXPECT_TRUE(mapping.is_valid());
|
||||
EXPECT_EQ(mapping.addr(), orig_addr);
|
||||
EXPECT_EQ(mapping.len(), kPageSize);
|
||||
EXPECT_EQ(mapping.len(), kHalfPageSize);
|
||||
|
||||
EXPECT_EQ(two_cookies[0].Observed(), two_cookies[0].Expected());
|
||||
EXPECT_DEATH_CRASH(two_cookies[1].Check(), "");
|
||||
@ -376,7 +376,7 @@ TEST(ScopedMmapDeathTest, NotIntegralNumberOfPages) {
|
||||
ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kPageSize + kHalfPageSize));
|
||||
EXPECT_TRUE(mapping.is_valid());
|
||||
EXPECT_EQ(mapping.addr(), orig_addr);
|
||||
EXPECT_EQ(mapping.len(), 2 * kPageSize);
|
||||
EXPECT_EQ(mapping.len(), kPageSize + kHalfPageSize);
|
||||
|
||||
EXPECT_EQ(two_cookies[0].Observed(), two_cookies[0].Expected());
|
||||
EXPECT_EQ(two_cookies[1].Observed(), two_cookies[1].Expected());
|
||||
|
Loading…
x
Reference in New Issue
Block a user