Skip to content

Commit b162034

Browse files
Scott Violetmibrunin
authored andcommitted
[Backport] CVE-2021-30510: Race in Aura
Cherry-pick of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/2868317: views: handle deletion when toggling fullscreen This differs from the first in so far as needing to add more early outs in the windows side if destroyed. This was caught by the asan bot. Toggling fullscreen means the bounds change. There are some code paths that may delete the Widget when the bounds changes. This patch ensures the right thing happens if the Widget is deleted when this happens. BUG=1197436 TEST=DesktopWidgetTest.DestroyInSetFullscreen (cherry picked from commit 60fe7a686c0620855c28a60721f668a99e409ee4) Change-Id: I8ce8f2045878b6f6de530f58e386149189900498 Reviewed-by: Thomas Anderson <[email protected]> Commit-Queue: Scott Violet <[email protected]> Cr-Original-Commit-Position: refs/heads/master@{#877640} Auto-Submit: Scott Violet <[email protected]> Commit-Queue: Thomas Anderson <[email protected]> Cr-Commit-Position: refs/branch-heads/4430@{#1383} Cr-Branched-From: e5ce7dc4f7518237b3d9bb93cccca35d25216cbe-refs/heads/master@{#857950} Reviewed-by: Allan Sandfeld Jensen <[email protected]>
1 parent f5056d0 commit b162034

File tree

7 files changed

+60
-2
lines changed

7 files changed

+60
-2
lines changed

chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,10 @@ void DesktopWindowTreeHostPlatform::SetFullscreen(bool fullscreen) {
583583
if (IsFullscreen() == fullscreen)
584584
return;
585585

586+
auto weak_ptr = GetWeakPtr();
586587
platform_window()->ToggleFullscreen();
588+
if (!weak_ptr)
589+
return;
587590

588591
// The state must change synchronously to let media react on fullscreen
589592
// changes.

chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,10 @@ void DesktopWindowTreeHostWin::FrameTypeChanged() {
463463
}
464464

465465
void DesktopWindowTreeHostWin::SetFullscreen(bool fullscreen) {
466+
auto weak_ptr = GetWeakPtr();
466467
message_handler_->SetFullscreen(fullscreen);
468+
if (!weak_ptr)
469+
return;
467470
// TODO(sky): workaround for ScopedFullscreenVisibility showing window
468471
// directly. Instead of this should listen for visibility changes and then
469472
// update window.

chromium/ui/views/widget/widget.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,10 @@ void Widget::SetFullscreen(bool fullscreen) {
724724
if (IsFullscreen() == fullscreen)
725725
return;
726726

727+
auto weak_ptr = GetWeakPtr();
727728
native_widget_->SetFullscreen(fullscreen);
729+
if (!weak_ptr)
730+
return;
728731

729732
if (non_client_view_)
730733
non_client_view_->InvalidateLayout();

chromium/ui/views/widget/widget_unittest.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3084,6 +3084,41 @@ TEST_F(DesktopWidgetTest, FullscreenStatePropagated_DesktopWidget) {
30843084
IsNativeWindowVisible(top_level_widget->GetNativeWindow()));
30853085
}
30863086

3087+
// Used to delete the widget when the supplied bounds changes.
3088+
class DestroyingWidgetBoundsObserver : public WidgetObserver {
3089+
public:
3090+
explicit DestroyingWidgetBoundsObserver(std::unique_ptr<Widget> widget)
3091+
: widget_(std::move(widget)) {
3092+
widget_->AddObserver(this);
3093+
}
3094+
3095+
// There are no assertions here as not all platforms call
3096+
// OnWidgetBoundsChanged() when going fullscreen.
3097+
~DestroyingWidgetBoundsObserver() override = default;
3098+
3099+
// WidgetObserver:
3100+
void OnWidgetBoundsChanged(Widget* widget,
3101+
const gfx::Rect& new_bounds) override {
3102+
widget_->RemoveObserver(this);
3103+
widget_.reset();
3104+
}
3105+
3106+
private:
3107+
std::unique_ptr<Widget> widget_;
3108+
};
3109+
3110+
// Deletes a Widget when the bounds change as part of toggling fullscreen.
3111+
// This is a regression test for https://crbug.com/1197436 .
3112+
TEST_F(DesktopWidgetTest, DeleteInSetFullscreen) {
3113+
std::unique_ptr<Widget> widget = std::make_unique<Widget>();
3114+
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
3115+
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3116+
widget->Init(std::move(params));
3117+
Widget* w = widget.get();
3118+
DestroyingWidgetBoundsObserver destroyer(std::move(widget));
3119+
w->SetFullscreen(true);
3120+
}
3121+
30873122
namespace {
30883123

30893124
class FullscreenAwareFrame : public views::NonClientFrameView {

chromium/ui/views/win/fullscreen_handler.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ void FullscreenHandler::SetFullscreenImpl(bool fullscreen) {
7070

7171
fullscreen_ = fullscreen;
7272

73+
auto ref = weak_ptr_factory_.GetWeakPtr();
7374
if (fullscreen_) {
7475
// Set new window style and size.
7576
SetWindowLong(hwnd_, GWL_STYLE,
@@ -102,6 +103,8 @@ void FullscreenHandler::SetFullscreenImpl(bool fullscreen) {
102103
new_rect.height(),
103104
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
104105
}
106+
if (!ref)
107+
return;
105108

106109
MarkFullscreen(fullscreen);
107110
}

chromium/ui/views/win/fullscreen_handler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <map>
1212

1313
#include "base/macros.h"
14+
#include "base/memory/weak_ptr.h"
1415

1516
namespace gfx {
1617
class Rect;
@@ -54,6 +55,8 @@ class FullscreenHandler {
5455
// Used to mark a window as fullscreen.
5556
Microsoft::WRL::ComPtr<ITaskbarList2> task_bar_list_;
5657

58+
base::WeakPtrFactory<FullscreenHandler> weak_ptr_factory_{this};
59+
5760
DISALLOW_COPY_AND_ASSIGN(FullscreenHandler);
5861
};
5962

chromium/ui/views/win/hwnd_message_handler.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,10 @@ void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon,
895895

896896
void HWNDMessageHandler::SetFullscreen(bool fullscreen) {
897897
background_fullscreen_hack_ = false;
898+
auto ref = msg_handler_weak_factory_.GetWeakPtr();
898899
fullscreen_handler()->SetFullscreen(fullscreen);
900+
if (!ref)
901+
return;
899902

900903
// Add the fullscreen window to the fullscreen window map which is used to
901904
// handle window activations.
@@ -1392,8 +1395,10 @@ void HWNDMessageHandler::ClientAreaSizeChanged() {
13921395
// Ignore size changes due to fullscreen windows losing activation.
13931396
if (background_fullscreen_hack_ && !sent_window_size_changing_)
13941397
return;
1395-
gfx::Size s = GetClientAreaBounds().size();
1396-
delegate_->HandleClientSizeChanged(s);
1398+
auto ref = msg_handler_weak_factory_.GetWeakPtr();
1399+
delegate_->HandleClientSizeChanged(GetClientAreaBounds().size());
1400+
if (!ref)
1401+
return;
13971402

13981403
current_window_size_message_++;
13991404
sent_window_size_changing_ = false;
@@ -2918,8 +2923,11 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
29182923
void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) {
29192924
TRACE_EVENT0("ui", "HWNDMessageHandler::OnWindowPosChanged");
29202925

2926+
base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr());
29212927
if (DidClientAreaSizeChange(window_pos))
29222928
ClientAreaSizeChanged();
2929+
if (!ref)
2930+
return;
29232931
if (window_pos->flags & SWP_FRAMECHANGED)
29242932
SetDwmFrameExtension(DwmFrameState::kOn);
29252933
if (window_pos->flags & SWP_SHOWWINDOW) {

0 commit comments

Comments
 (0)