diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc index e5a7bd2fe36dc..5f8a9d30eff49 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc @@ -7,6 +7,7 @@ #include #include +#include "base/auto_reset.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/scoped_observation.h" @@ -131,6 +132,15 @@ DesktopDragDropClientOzone::~DesktopDragDropClientOzone() { &aura::client::DragDropClientObserver::OnDragDropClientDestroying); } +namespace { +// Process-global re-entrancy guard. DesktopDragDropClientOzone is per +// top-level window, so the per-instance drag_context_ check below does not +// catch a second window starting a drag while the first window's nested +// RunMoveLoop is pumping tasks. On X11 that lets a compromised renderer steal +// the global XdndSelection mid-drag. Mirrors desktop_drag_drop_client_win.cc. +bool g_is_dragging = false; +} // namespace + DragOperation DesktopDragDropClientOzone::StartDragAndDrop( std::unique_ptr data, aura::Window* root_window, @@ -142,6 +152,13 @@ DragOperation DesktopDragDropClientOzone::StartDragAndDrop( return DragOperation::kNone; } + // A renderer can send LocalFrameHost::StartDragging at any time, so reject + // (rather than CHECK) re-entrant drags from a second top-level window. + if (g_is_dragging) { + return DragOperation::kNone; + } + base::AutoReset drag_scoper(&g_is_dragging, true); + DCHECK(!drag_context_); drag_context_ = std::make_unique();