"poor man's" pre-loaded DispVM for faster start

I hope one day Qubes OS will have the ability to hold a preloaded DispVM ready to use it immediately when requested instead of having to start it. Until then I’ve implemented a little workaround / hack that gives me an approximation.

  1. create named DispVMs

e.g. qvm-create --class DispVM --template offline-dvm --label purple offline and qvm-create --class DispVM --template online-dvm --label red online

  1. make sure they start automatically either by using the autostart property or by creating shortcuts in dom0’s ~/.config/autostart. I prefer the later as it takes effect after logging in. XFCE has a nice GUI under “Session and Startup | Application Autostart” in it’s preferences to help you create them.

  2. create a bash script qvm-run-in-focused-vm in dom0 with the following contents (e.g. in ~/bin):

#!/bin/bash

window_id=`xdotool getwindowfocus`
qube_name=`xprop _QUBES_VMNAME -id $window_id | cut -f2 -d\"`
command=$1

if [[ "$qube_name" == "_QUBES_VMNAME:  not found." ]]; then
         notify-send "qvm-run-in-focused-vm (dom0)" "$command"
         "$command" &

elif [[ ( "$qube_name" == "offline" || "$qube_name" == "online" ) && "$command" == "sudo poweroff" ]]; then

         notify-send "restarting $qube_name"
         qvm-shutdown --wait "$qube_name"
         qvm-start "$qube_name"

else
         notify-send "qvm-run-in-focused-vm ($qube_name)" "$command"
         qvm-run -a "$qube_name" "$command" &
fi

The above takes the first parameter given to the bash script and executes it in whatever qube had the focus (or dom0 if that had the focus). The ‘elif’ condition is what I specifically added for this workaround. It detects the names of my named DispVMs ‘offline’ or ‘online’ and if the command executed is sudo poweroff. If that’s the case it won’t execute the command but instead shutdown the respective qube (same effect) and wait. The when the qube is down, it will restart it.

  1. Add a keyboard shortcut in XFCE’s settings app under “Keyboard | Application Shortcuts”. I choose Shift+Ctrl+W and mapped it to qvm-run-in-focused-vm 'sudo poweroff'. [1]

  2. Add or edit your /etc/qubes/policy.d/30-user.policy to include these lines:

qubes.OpenInVM          *           @anyvm          @dispvm     allow target=offline
qubes.OpenInVM          *           @anyvm          @anyvm      ask
qubes.OpenURL           *           @anyvm          @dispvm     ask default_target=online
qubes.OpenURL           *           @anyvm          @anyvm      ask

The effect is that any call of qvm-open-in-dvm with a file as parameter will open said file in the ‘offline’ qube, while any URL given will result in dom0 asking the user which qube to open it in with the default option being the ‘online’ qube.

  1. train yourself to close windows by using Ctrl+Shift+W

Limitations:

  • repeated qvm-open-in-dvm calls without Ctrl+Shift+W between them will open in the same instance of the named disposable. This can be a security issue as one infected file can then infect others opened in the same instance, but it can also be a feature depending on what you are doing

  • if you just close the window using the normal ways (quit app, Ctrl+W or clicking on the respective window decoration) the workaround won’t work and the named disposable won’t restart (retain state)

Disclaimers:

  • use at your own risk!
  • know what you are doing!

  1. other unrelated nice shortcuts are: Shift+Ctrl+Return for qvm-run-in-focused-vm nautilus and Ctrl+Return for qvm-run-in-focused-vm xterm. I think you can see how this speeds things up a lot in daily use. ↩︎

5 Likes

This is indeed interesting. Anyway

  1. doesn’t this eat available RAM?
  2. and nevertheless is it possible to autostart dispVM, no-named (dispXXXX), on boot?

@enmus asked:

This is indeed interesting. Anyway

  1. doesn’t this eat available RAM?

Yes of course.

  1. and nevertheless is it possible to autostart dispVM, no-named (dispXXXX), on boot?

Kind of. A non-named dispVM is started executing a specific command and if that command terminates the dispVM will too.

e.g. qvm-run --dispvm=offline-dvm --service qubes.StartApp+debian-xterm starts XTerm in a dispXXX instance for me. However when XTerm terminates, so does the dispXXXX instance.

So in the context of this guide it is less useful since the instance won’t just exist in the background and you wouldn’t know it’s name… so how would you specify it as target in the policy file?

Loved the title, @Sven.

2 Likes

Great!

1 Like

Why it would be terminated?

A little hack to automatically send its Xterm to the nth workspace, and set-and-forgot?

Would I need to know?

What I was thinking is to create two adminVMs, named offline and online. Then to create dvm-template with each, then to start automatically dispxxx-offline and dispxxx-online, while in the policies should be enough to use:

tag:created-by-(dvm-?)offline
tag:created-by-(dvm-?)online

Do you think this is viable?

That way also all other qubes would be protected since no other qube can be managed by it.

No idea. Try and tell :wink:

OK, will do. Thanks.

1 Like

When one VM fires up an unnamed disposable VM…e.g., to open up a dodgy attachment you got in an e-mail…the starting VM has no idea what the name of the disposable VM is. The only way to know is for you (i.e., the meat being at the console) personally to note what it is, then YOU can, say. open a terminal on that disposable VM.

So far as I know, there is no way in software to open an unnamed disposable VM and send it commands to execute later on, even if it’s still running at that time, because the originating VM doesn’t know its name. You need a named disposable VM for this.

Edit:

If anyone knows of a way for the originating VM to know the name of an unnamed DVM it just started, I’d love to know it.

@SteveC one hacky way of doing it from dom0/bash of course would be to run qvm-ls --field=name | grep disp, then launch the unnamed dispVM, then run the same command again and look at the difference. I am more concerned with the question:

  • what process will anchor the dispVM (e.g. XTerm)?
  • how to detect that Qubes OS launched another process in it (e.g. evince)?
  • how to detect that that second process terminated and then terminate the first one?

At some point this will become so complex that it might be easier to actually implement the feature in Qubes OS proper. But this discussion might be a fun exercise that leads to new insights, let’s have it!

Exactly and indeed. While at the moment I’m trying to figure out how to try to call the vm with specific tag in RPC policy, it led me to a next thought (and this is for sure already brainstormed somewhere else already if not around infamous Qubes Air itself):
What if I’d create from each default (minimal) template (both fedora and debian) - adminvm templates (like those from @Sven’s debian-10-minimal topic but this time each would be actually AdminVM) and to start from there to create dvm templates, appvms and to start using Qubes. Would that increase security actually because qubes would be additionally isolated from each other due to additional grain layer created-by...
I cannot think through still if it would increase entropy even…

And/or - sys-net-eth from AdminVM1, and sys-net-wifi from AdminVM2, both adminVMs created by the same sys-net-template, or diferrent distros, whatever of these for example. Would that make sense and increase security, I’m trying to figure out, looking for a catch on RPC policy from the begining of a post…

And I hope it’ll stay like this forever in Qubes, otherwise…

I’m not sure what you mean by this…do you like the caller not being able to interact with the Disposable VM he just started?

@sven, I was envisioning starting a loop in the disposable VM that would cycle until told to “stop”, then it would exit and take the DVM with it. The disposable VM would exist to decrypt a secure container, and then the caller could take that container and pass it off to dom0 so he can qvmblock it to someone else. Once the “someone else” is done with that container, the disposable VM would be told to relock the container and then stop (exit).

I ended up using a named DVM for this purpose. THat bothers me because apparently some traces are left in dom0 of every disposable machine that runs, and someone could go “looking” for those machines since the name would be known after the fact. EDIT: wheras with a random named one, no one would know the name after the fact, once the creating VM shuts down.

Please look at @rustybird 's split-browser.

In fact, the originating VM does know the dispVM’s name, and can establish channels to interact with it.

1 Like

From casually looking at the description, it looks like the dispvm that actually runs the browser is “pulling” and “pushing” the data to the “main” vm, not the other way around. Of course it knows the name of the “main” vm.

Of course that’s a casual glance, not a deep read and certainly not an inspection of the package contents.

[Also of course, if the dispvm can send messages back to the main vm, one of those could be its own name. I actually tried to do something like that but it just hung. But that probably has more to do with the mechanism I was using for communication (I was going through a service call) than anything else. Still, I could maybe rethink things a bit and get it to work.]

The Split Browser approach for launching DisposableVMs is quite convoluted and I wouldn’t recommend doing it like that if you’re starting from scratch.