From 95bda789ea62fe9ef2aeff10ab0aa4b81ed8e718 Mon Sep 17 00:00:00 2001 From: Daniel Cheng Date: Tue, 14 Jun 2022 19:11:17 +0000 Subject: [Backport] CVE-2022-2156: Use after free in Base Manual backport of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/3703779: [M102] Ensure raw_ptr and T* are treated identically in //base callback. There are safety checks associated with raw pointers (e.g. ensuring receiver pointers are not raw pointers). Make sure these checks are applied whether the input type is T* or raw_ptr. - Implement base::IsPointer and base::RemovePointer, which are similar to std::is_pointer and std::remove_pointer, except they also consider raw_ptr a raw pointer type. - Fix failures from the strengthened asserts: WebAppInstallFinalizer does not need a callback at all, while the privacy sandbox dialog tests can safely use base::Unretained(). - Add test cases to cover this in the //base callback nocompile test suite. - Fix the existing nocompile tests, which did not escape `||` and inadvertently matched any error text. (cherry picked from commit 00c072a2c7f24921af3bbf8441abb34ecb0551a6) Bug: 1335458 Change-Id: I470e3d5bc35ed52bf125136db738a868ef90b7e7 Reviewed-by: Lei Zhang Commit-Queue: Daniel Cheng Cr-Original-Commit-Position: refs/heads/main@{#1013266} Cr-Commit-Position: refs/branch-heads/5005@{#1173} Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738} Reviewed-by: Michal Klocek --- chromium/base/bind_internal.h | 16 +++++------ chromium/base/memory/raw_ptr.h | 32 ++++++++++++++++++++++ .../memory/raw_scoped_refptr_mismatch_checker.h | 5 ++-- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/chromium/base/bind_internal.h b/chromium/base/bind_internal.h index a7aba35bb6c..5315534e478 100644 --- a/chromium/base/bind_internal.h +++ b/chromium/base/bind_internal.h @@ -801,8 +801,8 @@ bool QueryCancellationTraits(const BindStateBase* base, template std::enable_if_t< !(MakeFunctorTraits::is_method && - std::is_pointer>::value && - IsRefCountedType>>::value)> + IsPointerV> && + IsRefCountedType>>::value)> BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {} template @@ -812,8 +812,8 @@ void BanUnconstructedRefCountedReceiver() {} template std::enable_if_t< MakeFunctorTraits::is_method && - std::is_pointer>::value && - IsRefCountedType>>::value> + IsPointerV> && + IsRefCountedType>>::value> BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) { DCHECK(receiver); @@ -946,8 +946,8 @@ struct MakeBindStateTypeImpl { static_assert(!std::is_array>::value, "First bound argument to a method cannot be an array."); static_assert( - !std::is_pointer::value || - IsRefCountedType>::value, + !IsPointerV || + IsRefCountedType>::value, "Receivers may not be raw pointers. If using a raw pointer here is safe" " and has no lifetime concerns, use base::Unretained() and document why" " it's safe."); @@ -957,8 +957,8 @@ struct MakeBindStateTypeImpl { public: using Type = BindState< std::decay_t, - std::conditional_t::value, - scoped_refptr>, + std::conditional_t, + scoped_refptr>, DecayedReceiver>, std::decay_t...>; }; diff --git a/chromium/base/memory/raw_ptr.h b/chromium/base/memory/raw_ptr.h index f22003573c7..56f0bd20d5a 100644 --- a/chromium/base/memory/raw_ptr.h +++ b/chromium/base/memory/raw_ptr.h @@ -579,6 +579,38 @@ class raw_ptr { friend class raw_ptr; }; + +// Template helpers for working with T* or raw_ptr. +template +struct IsPointer : std::false_type {}; + +template +struct IsPointer : std::true_type {}; + +template +struct IsPointer> : std::true_type {}; + +template +inline constexpr bool IsPointerV = IsPointer::value; + +template +struct RemovePointer { + using type = T; +}; + +template +struct RemovePointer { + using type = T; +}; + +template +struct RemovePointer> { + using type = T; +}; + +template +using RemovePointerT = typename RemovePointer::type; + } // namespace base using base::raw_ptr; diff --git a/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h b/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h index 9e50458ec98..7afae066fa3 100644 --- a/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h +++ b/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h @@ -7,6 +7,7 @@ #include +#include "base/memory/raw_ptr.h" #include "base/template_util.h" // It is dangerous to post a task with a T* argument where T is a subtype of @@ -35,8 +36,8 @@ struct IsRefCountedType struct NeedsScopedRefptrButGetsRawPtr - : conjunction, - IsRefCountedType>> { + : conjunction, + IsRefCountedType>> { static_assert(!std::is_reference::value, "NeedsScopedRefptrButGetsRawPtr requires non-reference type."); }; -- cgit v1.2.1