aboutsummaryrefslogtreecommitdiff
path: root/libc/private/WriteProtected.h
diff options
context:
space:
mode:
Diffstat (limited to 'libc/private/WriteProtected.h')
-rw-r--r--libc/private/WriteProtected.h42
1 files changed, 18 insertions, 24 deletions
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 8f5b32d7a..746f72a4d 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -40,23 +40,11 @@ union WriteProtectedContents {
// explicitly.
template <typename T>
class WriteProtected {
+ public:
static_assert(sizeof(T) < PAGE_SIZE,
"WriteProtected only supports contents up to PAGE_SIZE");
static_assert(__is_pod(T), "WriteProtected only supports POD contents");
- WriteProtectedContents<T> contents;
-
- int set_protection(int prot) {
- auto addr = &contents;
-#if __has_feature(hwaddress_sanitizer)
- // The mprotect system call does not currently untag pointers, so do it
- // ourselves.
- addr = untag_address(addr);
-#endif
- return mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot);
- }
-
- public:
WriteProtected() = default;
BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtected);
@@ -64,10 +52,7 @@ class WriteProtected {
// Not strictly necessary, but this will hopefully segfault if we initialize
// multiple times by accident.
memset(&contents, 0, sizeof(contents));
-
- if (set_protection(PROT_READ)) {
- async_safe_fatal("failed to make WriteProtected nonwritable in initialize");
- }
+ set_protection(PROT_READ);
}
const T* operator->() {
@@ -80,14 +65,23 @@ class WriteProtected {
template <typename Mutator>
void mutate(Mutator mutator) {
- if (set_protection(PROT_READ | PROT_WRITE) != 0) {
- async_safe_fatal("failed to make WriteProtected writable in mutate: %s",
- strerror(errno));
- }
+ set_protection(PROT_READ | PROT_WRITE);
mutator(&contents.value);
- if (set_protection(PROT_READ) != 0) {
- async_safe_fatal("failed to make WriteProtected nonwritable in mutate: %s",
- strerror(errno));
+ set_protection(PROT_READ);
+ }
+
+ private:
+ WriteProtectedContents<T> contents;
+
+ void set_protection(int prot) {
+ auto addr = &contents;
+#if __has_feature(hwaddress_sanitizer)
+ // The mprotect system call does not currently untag pointers, so do it
+ // ourselves.
+ addr = untag_address(addr);
+#endif
+ if (mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot) == -1) {
+ async_safe_fatal("WriteProtected mprotect %x failed: %s", prot, strerror(errno));
}
}
};