Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wlctrl object id: not a static UID? #1

Open
jonleivent opened this issue Jul 31, 2023 · 7 comments
Open

wlctrl object id: not a static UID? #1

jonleivent opened this issue Jul 31, 2023 · 7 comments

Comments

@jonleivent
Copy link

@Consolatis

I've been examining your wl_framework code for ideas (I'm thinking of writing a secure clipboard manager). In wlctrl, I thought the idea behind the object ids is that they were static UIDs per window. But they are not. What seems to happen is that the numbering acts like a stack, with the lowest number always referring to the newest window, but with each new window incrementing the object ids of all of the older ones.

Is there something more like a static window UID in the protocol?

@Consolatis
Copy link
Owner

Consolatis commented Jul 31, 2023

Is there something more like a static window UID in the protocol?

In the wlr-foreign-toplevel protocol: sadly not. In the new incarnation of the protocol there is indeed a unique ID per window handle but in the existing wlr variant of the protocol there is not. The new "official" protocol does not yet allow any actions on those handles so its rather useless for now until its corresponding extension protocols are merged as well.

Keep in mind that the foreign toplevel protocol is only used to reference abstract "toplevels", while they may indeed refer to existing wayland xdg_toplevel objects they technically don't have to (e.g. some might also refer to xwayland windows or similar which don't have have a wayland object id at all).

The foreign-toplevel handle object ids are static for the lifetime of the connection though.

I guess what could be done is something along the lines of

  • implement own offers in the wl_framework implementation of the data-control protocol
  • at the send handler check which of the toplevels is currently focused / active
  • decide based on the toplevel app_id / title if we actually want to send some content
    • if no: just close the supplied fd
    • if yes: send the data and close the fd when done

Security wise, this is not bullet proof though:

  • clients may lie about their app_id / title
  • there is a race condition when matching a clipboard requester with the currently active window

If you still want to play around with that option I could add the ability to set own selections to the protocol implementation. That might take a few days though.

@jonleivent
Copy link
Author

The security issues are deal breakers for me.

However, consider the multi-socket version of labwc. Is there a way to identify which windows are attached to which sockets? Because security could be attained by allowing cut-and-paste freely among windows on the same socket, but have some other mechanism that can transfer clipboard entries between sockets. That other mechanism would require the more privileged protocol, so it would be disabled on the unprivileged sockets. It works because a client can't lie about what socket it's talking on. There shouldn't be a race condition because the transfer of entries between socket-specific clipboard histories would be out-of-band of window focusing.

Unless you mean the race condition is that the clipboard manager sees only the entry data and not where it came from, and has to assume it came from whatever window is currently active (which might not be the right one if a different window was activated quickly enough). Well that would not be nice. Could each socket can have a separate data sharing interface somehow?

This is beginning to sound almost like it's a tree of compositors. Which is what I was considering with using labwc in kiosk mode: one top-level labwc and many nested kiosk ones. Then they'd have their own separate clipboards. But this gets ugly in the UI: the top-level taskbar shows a bunch of title-less labwcs.

@Consolatis
Copy link
Owner

Unless you mean the race condition is that the clipboard manager sees only the entry data and not where it came from, and has to assume it came from whatever window is currently active (which might not be the right one if a different window was activated quickly enough). Well that would not be nice.

Yes, this. The data-control protocol used for clipboard manager implementations doesn't have any clue from which wayland client / surface a request came from (at least not that I am aware of). It only receives the requested mime type and a file descriptor to write to.

However, consider the multi-socket version of labwc. Is there a way to identify which windows are attached to which sockets?

Via external tools: no. Only the compositor has that knowledge. And even there, wlroots handles all the clipboard AFAIR.
What could be done though is to block clipboard sharing for all clients on some unprivileged socket by simply blocking the usual clipboard sharing protocols (wl_data_device_manager, zwp_primary_selection_device_manager_v1).

This is beginning to sound almost like it's a tree of compositors. Which is what I was considering with using labwc in kiosk mode: one top-level labwc and many nested kiosk ones. Then they'd have their own separate clipboards.

Yes, with nested compositors the clipboard issue would mostly be gone. But only because its not implemented for the wayland backend of wlroots, that could change in the future and you'd be back to square one. Although in that case the clipboard sharing protocols could simply be blocked for the nested instance.

But this gets ugly in the UI: the top-level taskbar shows a bunch of title-less labwcs.

I am not sure if there is a wlroots API to control the app_id / title of the compositor when running nested, I'd assume there is so that could potentially be overcome by adding some env var or command line arguments to labwc. Or potentially even set it automatically based on the client that currently has focus within the nested compositor. I didn't verify if this is actually possible though.

@jonleivent
Copy link
Author

Suppose the clipboard manager tracks all focus changes. Then it can be given a minimum time threshold such that it will only keep the data if the delays between the data management request and the surrounding focuses are at least that threshold. Else it will pop-up a "Please slow down! message. This mitigates the race condition, although imperfectly.

A much more elaborate idea is to have a nested compositor that is frameless - it passes its windows one-for-one to its backend parent compositor (maybe doing something like tagging their titles or app-ids in a reliable way). But it has its own data protocol and others (screencopy, etc.) to prevent potential secret leakage such that users of those protocols on the nested compositor only see events/data for the windows of the nested compositor's clients.

@Consolatis
Copy link
Owner

A much more elaborate idea is to have a nested compositor that is frameless - it passes its windows one-for-one to its backend parent compositor

That indeed sounds interesting. Basically xpra for native wayland. It is definitely out of scope for labwc though. Maybe waypipe could get modified to fill this role?

@jonleivent
Copy link
Author

That indeed sounds interesting. Basically xpra for native wayland. It is definitely out of scope for labwc though. Maybe waypipe could get modified to fill this role?

Should be easier than those. No serialization or network transparency. But hopefully no extra latency. It should only intervene between its clients and the backend compositor when dealing with those parts of the protocol that would allow data transfer to its clients. Call it "oneway".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants