Skip to content

chansrv leaves a CB_FORMAT_DATA_REQUEST unanswered when the X selection owner does not reply #3863

Description

@richardwellgood-byte

xrdp version

0.10.80

Detailed xrdp version, build options

xrdp 0.10.80
  A Remote Desktop Protocol Server.
  Copyright (C) 2004-2025 Jay Sorg, Neutrino Labs, and all contributors.
  See https://github.com/neutrinolabs/xrdp for more information.

  Configure options:
      --with-systemdsystemunitdir=/usr/lib/systemd/system
      --enable-ibus
      --enable-jpeg
      --enable-fuse
      --enable-mp3lame
      --enable-fdkaac
      --enable-opus
      --enable-rfxcodec
      --enable-painter
      --enable-pixman
      --enable-utmp
      -with-imlib2
      --with-freetype2
      --enable-vsock

  Compiled with OpenSSL 3.0.13 30 Jan 2024

Operating system & version

Ubuntu 24.04.4 LTS (Kubuntu). Also reproduced on Ubuntu 26.04.

Installation method

git clone & make install

Which backend do you use?

xorgxrdp

What desktop environment do you use?

KDE Plasma

Environment xrdp running on

Physical machine for the main setup; a VirtualBox VM for the second one

What's your client?

Remmina 1.4.43 with libfreerdp 3.30.0, on Manjaro

Area(s) with issue?

Clipboard

Steps to reproduce

  1. Connect to the session with a client that waits for a CB_FORMAT_DATA_RESPONSE and does not recover if it never arrives. Remmina 1.4.43 is one such client.
  2. Arrange for the X selection owner in the session not to answer a conversion. Any of these does it:
    • the owning application exits between the format list and the paste. On Plasma, Klipper takes over the selection and masks this, so a session without a clipboard manager is needed;
    • the owner is itself a remote desktop client fetching the data over its own connection, i.e. RDP inside RDP;
    • a process that still owns the selection but is stopped:
      echo test | xclip -selection clipboard
      sleep 1
      kill -STOP "$(pgrep -nx xclip)"
      
  3. Paste on the client. Nothing arrives, which is expected — the conversion genuinely failed.
  4. Restore a healthy clipboard: copy something in an ordinary application in the session, then paste on the client again.

✔️ Expected Behavior

Step 4 pastes the new text. A single failed conversion should cost one paste, not the whole direction.

❌ Actual Behavior

Step 4 pastes nothing, and neither does any later attempt. Server to client clipboard stays dead for the rest of the connection, while client to server keeps working. Reconnecting is the only recovery.

On the client side this shows up as one timeout followed by an unbounded run of "Cannot paste now":

14:10:07  Clipboard data from the server is not available in 6 seconds.
14:10:07  Cannot paste now, I'm already transferring clipboard data from server.
14:17:37  Cannot paste now, ...
...
22:50:26  Cannot paste now, ...

One timeout at 14:10, then 8.5 hours of a dead direction on the same connection and the same PID, with no further request ever being sent.

Anything else?

chansrv answers a client CB_FORMAT_DATA_REQUEST asynchronously: it calls XConvertSelection() on whoever owns the X CLIPBOARD selection, and the matching CB_FORMAT_DATA_RESPONSE is only sent later, from clipboard_event_selection_notify().

If that conversion never completes, no response is ever sent and the client is left waiting indefinitely. clipboard_send_data_response_failed() already exists and is used for an unknown format id, so answering a failure is clearly the intended behaviour — these paths just miss it.

Paths that produce no response

In sesman/chansrv/clipboard.c, clipboard_event_selection_notify():

Condition Result
property == None (owner refused) rv = 1, falls through, nothing sent
clipboard_get_window_property() fails early return 0
target XA_STRING, data_size == 0 inner guard skipped
target image/bmp, data_size <= 14 inner guard skipped
restrict_outbound_clipboard set logged, nothing sent
unhandled target "unknown target", nothing sent
unhandled selection "unknown selection", nothing sent

Plus: an owner that never answers at all produces no SelectionNotify, and there is no timeout anywhere in this path.

That last case is easy to hit in practice: the owning window has already gone away, or the owner is itself a remote-desktop client fetching the data over its own network connection (RDP inside RDP).

Impact

Clients do not necessarily recover. Remmina 1.4.43 gives up after 6 seconds but leaves rfClipboard.srv_clip_data_wait at SCDW_BUSY_WAIT; the reset to SCDW_NONE only happens when a CB_FORMAT_DATA_RESPONSE actually arrives (plugins/rdp/rdp_cliprdr.c:607). Every later paste then returns early at "Cannot paste now, I'm already transferring clipboard data from server", so server to client clipboard stays dead for the rest of the connection while client to server keeps working.

That is a Remmina bug too, and I intend to report it there. But xrdp is the side that stops replying, and fixing it in xrdp helps every client.

Suggested fix

Track the pending request and always answer it: fail it when the conversion cannot complete, and arm a timeout so an owner that never replies cannot leave the client waiting. The timeout has to be shorter than the client's own, so the client sees a real CB_RESPONSE_FAIL instead of hitting its own timeout.

I have a patch and will open a PR.

The symptom pattern reported in #2596 looks like the same thing, although that report is with mstsc and I have not checked what that client does with an unanswered request. #2763 is the same family on the X side.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions