diff options
Diffstat (limited to 'libc/private/WriteProtected.h')
-rw-r--r-- | libc/private/WriteProtected.h | 42 |
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)); } } }; |