[libcxx-commits] [libcxx] 189ba3d - Fix CFI issues in <future>

Evgenii Stepanov via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 6 12:05:40 PDT 2020


Author: Evgenii Stepanov
Date: 2020-08-06T12:05:22-07:00
New Revision: 189ba3db8653eaefc191599dd60d9aa6b0127c44

URL: https://github.com/llvm/llvm-project/commit/189ba3db8653eaefc191599dd60d9aa6b0127c44
DIFF: https://github.com/llvm/llvm-project/commit/189ba3db8653eaefc191599dd60d9aa6b0127c44.diff

LOG: Fix CFI issues in <future>

This change fixes errors reported by Control Flow Integrity (CFI) checking when using `std::packaged_task`.  The errors mostly stem from casting the underlying storage (`__buf_`) to `__base*`, even if it is uninitialized.  The solution is to wrap `__base*` access to `__buf_` behind a getter marked with _LIBCPP_NO_CFI.

Differential Revision: https://reviews.llvm.org/D82627

Added: 
    

Modified: 
    libcxx/include/future

Removed: 
    


################################################################################
diff  --git a/libcxx/include/future b/libcxx/include/future
index bdf74e3055c0..6d437a489cad 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -1823,6 +1823,10 @@ template<class _Rp, class ..._ArgTypes>
 class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_function<_Rp(_ArgTypes...)>
 {
     typedef __packaged_task_base<_Rp(_ArgTypes...)> __base;
+
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_NO_CFI
+    __base* __get_buf() { return (__base*)&__buf_; }
+
     typename aligned_storage<3*sizeof(void*)>::type __buf_;
     __base* __f_;
 
@@ -1856,10 +1860,10 @@ __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(__packaged
 {
     if (__f.__f_ == nullptr)
         __f_ = nullptr;
-    else if (__f.__f_ == (__base*)&__f.__buf_)
+    else if (__f.__f_ == __f.__get_buf())
     {
+        __f.__f_->__move_to(__get_buf());
         __f_ = (__base*)&__buf_;
-        __f.__f_->__move_to(__f_);
     }
     else
     {
@@ -1877,8 +1881,8 @@ __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f)
     typedef __packaged_task_func<_FR, allocator<_FR>, _Rp(_ArgTypes...)> _FF;
     if (sizeof(_FF) <= sizeof(__buf_))
     {
+        ::new (&__buf_) _FF(_VSTD::forward<_Fp>(__f));
         __f_ = (__base*)&__buf_;
-        ::new (__f_) _FF(_VSTD::forward<_Fp>(__f));
     }
     else
     {
@@ -1920,17 +1924,17 @@ template<class _Rp, class ..._ArgTypes>
 __packaged_task_function<_Rp(_ArgTypes...)>&
 __packaged_task_function<_Rp(_ArgTypes...)>::operator=(__packaged_task_function&& __f) _NOEXCEPT
 {
-    if (__f_ == (__base*)&__buf_)
+    if (__f_ == __get_buf())
         __f_->destroy();
     else if (__f_)
         __f_->destroy_deallocate();
     __f_ = nullptr;
     if (__f.__f_ == nullptr)
         __f_ = nullptr;
-    else if (__f.__f_ == (__base*)&__f.__buf_)
+    else if (__f.__f_ == __f.__get_buf())
     {
-        __f_ = (__base*)&__buf_;
-        __f.__f_->__move_to(__f_);
+        __f.__f_->__move_to(__get_buf());
+        __f_ = __get_buf();
     }
     else
     {
@@ -1943,13 +1947,14 @@ __packaged_task_function<_Rp(_ArgTypes...)>::operator=(__packaged_task_function&
 template<class _Rp, class ..._ArgTypes>
 __packaged_task_function<_Rp(_ArgTypes...)>::~__packaged_task_function()
 {
-    if (__f_ == (__base*)&__buf_)
+    if (__f_ == __get_buf())
         __f_->destroy();
     else if (__f_)
         __f_->destroy_deallocate();
 }
 
 template<class _Rp, class ..._ArgTypes>
+_LIBCPP_NO_CFI
 void
 __packaged_task_function<_Rp(_ArgTypes...)>::swap(__packaged_task_function& __f) _NOEXCEPT
 {


        


More information about the libcxx-commits mailing list