diff options
author | Steven Laver <lavers@google.com> | 2019-12-12 15:29:36 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-12-12 15:29:36 +0000 |
commit | a239544c7b06814b70fd970de7eaac234682fa52 (patch) | |
tree | a4298d61f9b73642f350799b1157e49b65f4e1e8 /libutils/include/utils/StrongPointer.h | |
parent | 63de1e1c8d7824c241f22de67edf54f4f1eaeea5 (diff) | |
parent | 5319412e5305a3b4bcecf251a2955c09a6e9837e (diff) |
Merge "Merge RP1A.191203.001" into r-keystone-qcom-dev
Diffstat (limited to 'libutils/include/utils/StrongPointer.h')
-rw-r--r-- | libutils/include/utils/StrongPointer.h | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h index 9cd7c75fd..07dd3f1cd 100644 --- a/libutils/include/utils/StrongPointer.h +++ b/libutils/include/utils/StrongPointer.h @@ -122,26 +122,54 @@ public: return o != *this; } -private: +private: template<typename Y> friend class sp; template<typename Y> friend class wp; void set_pointer(T* ptr); + static inline void check_not_on_stack(const void* ptr); T* m_ptr; }; -// For code size reasons, we do not want this inlined or templated. +// For code size reasons, we do not want these inlined or templated. void sp_report_race(); +void sp_report_stack_pointer(); #undef COMPARE // --------------------------------------------------------------------------- // No user serviceable parts below here. +// Check whether address is definitely on the calling stack. We actually check whether it is on +// the same 4K page as the frame pointer. +// +// Assumptions: +// - Pages are never smaller than 4K (MIN_PAGE_SIZE) +// - Malloced memory never shares a page with a stack. +// +// It does not appear safe to broaden this check to include adjacent pages; apparently this code +// is used in environments where there may not be a guard page below (at higher addresses than) +// the bottom of the stack. +// +// TODO: Consider adding make_sp<T>() to allocate an object and wrap the resulting pointer safely +// without checking overhead. +template <typename T> +void sp<T>::check_not_on_stack(const void* ptr) { + static constexpr int MIN_PAGE_SIZE = 0x1000; // 4K. Safer than including sys/user.h. + static constexpr uintptr_t MIN_PAGE_MASK = ~static_cast<uintptr_t>(MIN_PAGE_SIZE - 1); + uintptr_t my_frame_address = + reinterpret_cast<uintptr_t>(__builtin_frame_address(0 /* this frame */)); + if (((reinterpret_cast<uintptr_t>(ptr) ^ my_frame_address) & MIN_PAGE_MASK) == 0) { + sp_report_stack_pointer(); + } +} + template<typename T> sp<T>::sp(T* other) : m_ptr(other) { - if (other) + if (other) { + check_not_on_stack(other); other->incStrong(this); + } } template<typename T> @@ -159,8 +187,10 @@ sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) { template<typename T> template<typename U> sp<T>::sp(U* other) : m_ptr(other) { - if (other) + if (other) { + check_not_on_stack(other); (static_cast<T*>(other))->incStrong(this); + } } template<typename T> template<typename U> @@ -207,7 +237,10 @@ sp<T>& sp<T>::operator=(sp<T>&& other) noexcept { template<typename T> sp<T>& sp<T>::operator =(T* other) { T* oldPtr(*const_cast<T* volatile*>(&m_ptr)); - if (other) other->incStrong(this); + if (other) { + check_not_on_stack(other); + other->incStrong(this); + } if (oldPtr) oldPtr->decStrong(this); if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race(); m_ptr = other; |