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

Kloak in dom0 #8541

Open
DemiMarie opened this issue Sep 21, 2023 · 8 comments
Open

Kloak in dom0 #8541

DemiMarie opened this issue Sep 21, 2023 · 8 comments
Labels
C: Whonix This issue impacts Qubes-Whonix P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. privacy This issue pertains to data or information privacy through technological means. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality.

Comments

@DemiMarie
Copy link

How to file a helpful issue

The problem you're addressing (if any)

#8534 is going to break with the Wayland agent, and likely has synchronization problems with the X11 agent.

Xorg has its own idea of what the window stacking order is. It is absolutely not wanted here, but getting rid of it requires changes to Xorg that nobody is interested in doing. The (partial) workaround is to raise a window before sending events to it. However, this requires that sending events to the X server is synchronized with manipulating the X11 window stacking order. This is only possible if event delivery is synchronous, not if it is asynchronous. Additionally, the X11 GUI agent is going to eventually be replaced by a Wayland compositor, currently at https://github.com/DemiMarie/qubes-compositor. The Wayland compositor does not kernel input events at all, and does not even have a driver to communicate with the kernel input subsystem.

More fundamentally, the GUI agent is the wrong place to solve this — if someone compromises the VM, they will still be able to get precise input events, compromising anonymity.

The solution you'd like

Run Kloak on the host, or in the GUI daemon. This ensures that anonymization is done before the (potentially compromised) guest gets access to the events. It also solves the event routing problem.

The value to a user, and who that user might be

Qubes-Whonix users will benefit from improved anonymity.

@DemiMarie DemiMarie added T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality. C: Whonix This issue impacts Qubes-Whonix P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. labels Sep 21, 2023
@andrewdavidwong
Copy link
Member

Is this a duplicate of #1850?

@andrewdavidwong andrewdavidwong added the privacy This issue pertains to data or information privacy through technological means. label Sep 22, 2023
@adrelanos
Copy link
Member

Run Kloak on the host, or in the GUI daemon.

This would be nice but I wouldn't have dared to suggest it. Because many users may not want this for non-Whonix VMs. Reasons:

  • Some websites (such as banks) use keystroke dynamics as part of user identification / automatic compromise detection.
  • If kloak breaks, non-users of Whonix would not want their non-Whonix VM input devices being broken.
  • Even Whonix users wouldn't want their non-Whonix VMs broken in case of kloak issues.
  • We'd need Fedora packaging (probably doable) and the package maintained in Qubes dom0 repository?

Could the GUI agent interface with kloak and only apply keystroke anonmyization on an opt-in base (using qvm-service)?

Is this a duplicate of #1850?

Perhaps a sub ticket? Depends how much related it can be before being a duplicate. This issue seems complicated enough to warrant a separate ticket. How the input device is (not) accessible from the VM / dom0 could be independently designed from #1850.

@DemiMarie
Copy link
Author

Run Kloak on the host, or in the GUI daemon.

This would be nice but I wouldn't have dared to suggest it. Because many users may not want this for non-Whonix VMs. Reasons:

  • Some websites (such as banks) use keystroke dynamics as part of user identification / automatic compromise detection.
  • If kloak breaks, non-users of Whonix would not want their non-Whonix VM input devices being broken.
  • Even Whonix users wouldn't want their non-Whonix VMs broken in case of kloak issues.
  • We'd need Fedora packaging (probably doable) and the package maintained in Qubes dom0 repository?

If my understanding is correct, the current implementation of kloak fundamentally assumes that input events are routed via the kernel’s input event system. Qubes OS does not (and, in the long term, cannot) use the kernel event system outside of dom0 and sys-gui. #8534 will break once Qubes OS switches to Wayland. Therefore, kloak as it is currently implemented can only be used system-wide or not at all, hence this issue.

Could the GUI agent interface with kloak and only apply keystroke anonmyization on an opt-in base (using qvm-service)?

Yes, but this would require kloak be changed to not rely on the kernel event subsystem. A much better approach would be for kloak to either a library that the GUI daemon communicated with via function calls, or a separate process that the GUI daemon communicated with via pipes, sockets, or other IPC.

Is this a duplicate of #1850?

Perhaps a sub ticket? Depends how much related it can be before being a duplicate. This issue seems complicated enough to warrant a separate ticket. How the input device is (not) accessible from the VM / dom0 could be independently designed from #1850.

Qubes VMs have no input devices. The GUI daemon directs events to specific windows, not to specific coordinates in a global coordinate space. This is made much more obvious by Wayland, where there is no global coordinate space, and instead the Wayland compositor dispatches events directly to applications. Wayland, not X11, is the future, so kloak needs to fit in to Wayland. That means operating as a plugin for the GUI agent and/or GUI daemon.

@skyzzuu
Copy link

skyzzuu commented Sep 25, 2023

Would the following implementation be doable? I could be wrong, but it seems like it wouldn't require any changes to the gui daemon, and if kloak is kept separate from the gui daemon and new features are added, kloak could easily just be upgraded to the newest version instead of needing to change the gui daemon again to implement them.

kloak package that can be optionally installed in dom0
kloak package that can be optionally installed in the fedora templates that sys-usb is based off

qvm-service in sys-usb called kloak

In sys-usb some changes are needed as after qubes-input-sender has grabbed the input devices, kloak will then try to grab them and run into issues causing it to exit, but the output devices created by kloak still need qubes-input-sender.

I was thinking something like the following:

  1. If the kloak qvm-service is enabled and the kloak tag is not in udevreturn (original input device), start the new function that runs kloak
  2. else:
  3. run handle_service as usual to run qubes-input-sender

I haven't experimented with sys-gui yet so I'm not as familiar with how it works, but depending on whether it uses qubes-input-sender like sys-usb or not, I would think it could either just have kloak installed with no changes other than making sure the kloak qvm-service is enabled in it, or have the changes mentioned in the sys-usb section above.

@3hhh
Copy link

3hhh commented Jan 13, 2024

I don't understand the focus on kloak - it's a relatively simple application that randomizes the delay between input events.

With e.g. some plugin support for the Qubes OS keystroke handling code (wherever it may run) it should be fairly simple to replicate the kloak functionality.

Imho it's a bad idea to to force something to work with Qubes OS that was apparently not designed with Qubes OS in mind.

@3hhh
Copy link

3hhh commented Jan 13, 2024

On a side note: If qrexec is used to transport the keystrokes (I currently don't know), it may even be possible to use something like my https://github.com/3hhh/qubes-qrexec-proxy already.

@ArrayBolt3
Copy link

@DemiMarie

Yes, but this would require kloak be changed to not rely on the kernel event subsystem. A much better approach would be for kloak to either a library that the GUI daemon communicated with via function calls, or a separate process that the GUI daemon communicated with via pipes, sockets, or other IPC.

It sounds like what you're describing here is running kloak "as a service" in dom0 that provides one-way communication to individual qubes as needed?

The current architecture of kloak requires the use of evdev because there simply isn't any better spot to put an input device "mangler". The X server, to my awareness, lacks a way to put a process like kloak between the server and the applications, so you have to go underneath the server. The server communicates via evdev, so kloak has to be inserted there. The problem with that is that individual VMs won't have evdev anymore it sounds like, and so kloak can't be put there. Putting it straight on the host is all-or-nothing - you either obfuscate input everywhere or not at all. Trying to make kloak capture all input but then selectively deliver it to VMs sounds prohibitively difficult since then it has to "figure out" what VM the user is trying to communicate with, which is very difficult since it resides at the evdev layer and currently has no knowledge of what goes on above.

I think I have to agree with @3hhh here - the functionality offered by kloak should probably be replicated but in a way that works with Qubes OS's architecture. So, with that in mind, I did some digging, and found the following function in the GUI daemon:

// In qubes-gui-daemon/gui-daemon/xside.c
/* handle local Xserver event: XKeyEvent
 * send it to relevant window in VM
 */
static void process_xevent_keypress(Ghandles * g, const XKeyEvent * ev)
{
    struct msg_hdr hdr;
    struct msg_keypress k;
    CHECK_NONMANAGED_WINDOW(g, ev->window);
    update_wm_user_time(g, ev->window, ev->time);
    if (is_special_keypress(g, ev, vm_window->remote_winid))
        return;
    k.type = ev->type;
    k.x = ev->x;
    k.y = ev->y;
    k.state = ev->state;
    k.keycode = ev->keycode;
    hdr.type = MSG_KEYPRESS;
    hdr.window = vm_window->remote_winid;
    write_message(g->vchan, hdr, k);
//      fprintf(stderr, "win 0x%x(0x%x) type=%d keycode=%d\n",
//              (int) ev->window, hdr.window, k.type, k.keycode);
}

Similar handlers exist for motion and click events.

To me it seems like all that has to be done to add kloak functionality here is to just make a single master "send" function that the other event handlers call instead of write_message - this function would check a config key for the VM that specified whether it was "kloaked" or not, immediately write the event if not, and store it (with a scheduled release time) in a master event queue if so. Then some other function would periodically check the queue for events that were ready to be released and write them to their intended VMs if ready. This could be implemented entirely within the GUI daemon, which would probably be simpler than making it a library or separate process since the GUI daemon will need substantial modifications to work with kloak-like functionality anyway.

@adrelanos
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: Whonix This issue impacts Qubes-Whonix P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. privacy This issue pertains to data or information privacy through technological means. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality.
Projects
None yet
Development

No branches or pull requests

6 participants