Browse Source

Allow HVM to notify dom0 about tools installation

HVM can set some xenstore entries (in qubes-tools/ subtree) to pass
informations about installed tools to dom0. qubes.NotifyTools service
triggers update of VM properties (like qrexec_installed).
This way, after installation of Qubes Windows Tools, the user doesn't need
to change any VM settings to use the tools.
Marek Marczykowski-Górecki 10 years ago
parent
commit
e2c43d2292

+ 20 - 0
core-modules/01QubesHVm.py

@@ -280,6 +280,26 @@ class QubesHVm(QubesVm):
 
                 self.wait_for_session(notify_function=kwargs.get('notify_function', None))
 
+    def create_xenstore_entries(self, xid = None):
+        if dry_run:
+            return
+
+        super(QubesHVm, self).create_xenstore_entries(xid)
+
+        if xid is None:
+            xid = self.xid
+
+        domain_path = xs.get_domain_path(xid)
+
+        # Prepare xenstore directory for tools advertise
+        xs.write('',
+                "{0}/qubes-tools".format(domain_path),
+                '')
+
+        # Allow VM writes there
+        xs.set_permissions('', '{0}/qubes-tools'.format(domain_path),
+                [{ 'dom': xid }])
+
     def suspend(self):
         if dry_run:
             return

+ 6 - 0
qubes-rpc-policy/qubes.NotifyTools.policy

@@ -0,0 +1,6 @@
+## Note that policy parsing stops at the first match,
+## so adding anything below "$anyvm $anyvm action" line will have no effect
+
+## Please use a single # to start your custom comments
+
+$anyvm	dom0	allow

+ 70 - 0
qubes-rpc/qubes-notify-tools

@@ -0,0 +1,70 @@
+#!/usr/bin/python2
+
+import os
+import sys
+from qubes.qubes import QubesVmCollection,QubesException,QubesHVm
+from qubes.qubes import xs
+
+def main():
+
+    source = os.getenv("QREXEC_REMOTE_DOMAIN")
+
+    if source is None:
+        print >> sys.stderr, 'This script must be called as qrexec service!'
+        exit(1)
+
+    qvm_collection = QubesVmCollection()
+    qvm_collection.lock_db_for_writing()
+    try:
+        qvm_collection.load()
+
+        source_vm = qvm_collection.get_vm_by_name(source)
+        if source_vm is None:
+            raise QubesException('Domain ' + source + ' does not exists (?!)')
+
+        if not isinstance(source_vm, QubesHVm):
+            raise QubesException('Service qubes.ToolsNotify is designed only for HVM domains')
+
+        xs_path = "/local/domain/{0}/qubes-tools".format(source_vm.get_xid())
+
+        # for now used only to check for the tools presence
+        untrusted_version = xs.read('', '{0}/version'.format(xs_path))
+        # reserved for future use
+        untrusted_os = xs.read('', '{0}/os'.format(xs_path))
+        # qrexec agent presence (0 or 1)
+        untrusted_qrexec = xs.read('', '{0}/qrexec'.format(xs_path))
+        # gui agent presence (0 or 1)
+        untrusted_gui = xs.read('', '{0}/gui'.format(xs_path))
+
+        if untrusted_version is None:
+            # tools didn't advertised its features; it's strange that this
+            # service is called, but ignore it
+            return
+
+        # any suspicious string will raise exception here
+        version = int(untrusted_version)
+
+        # untrusted_os - ignore for now
+
+        if untrusted_qrexec is None:
+            qrexec = 0
+        else:
+            qrexec = int(untrusted_qrexec)
+
+        if untrusted_gui is None:
+            gui = 0
+        else:
+            gui = int(untrusted_gui)
+        
+        # Let the tools to be able to enable *or disable* each particular component
+        source_vm.qrexec_installed = qrexec > 0
+        source_vm.guiagent_installed = gui > 0
+
+        qvm_collection.save()
+    except Exception as e:
+        print >> sys.stderr, e.message
+        exit(1)
+    finally:
+        qvm_collection.unlock_db()
+
+main()

+ 1 - 0
qubes-rpc/qubes.NotifyTools

@@ -0,0 +1 @@
+/usr/lib/qubes/qubes-notify-tools

+ 6 - 0
rpm_spec/core-dom0.spec

@@ -130,6 +130,7 @@ cp linux/aux-tools/startup-misc.sh $RPM_BUILD_ROOT/usr/lib/qubes
 cp linux/aux-tools/prepare-volatile-img.sh $RPM_BUILD_ROOT/usr/lib/qubes
 cp qmemman/server.py $RPM_BUILD_ROOT/usr/lib/qubes/qmemman_daemon.py
 cp qmemman/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes/
+cp qubes-rpc/qubes-notify-tools $RPM_BUILD_ROOT/usr/lib/qubes/
 cp qubes-rpc/qubes-notify-updates $RPM_BUILD_ROOT/usr/lib/qubes/
 cp linux/aux-tools/vusb-ctl.py $RPM_BUILD_ROOT/usr/lib/qubes/
 cp linux/aux-tools/xl-qvm-usb-attach.py $RPM_BUILD_ROOT/usr/lib/qubes/
@@ -141,6 +142,8 @@ mkdir -p $RPM_BUILD_ROOT/etc/qubes-rpc/policy
 cp qubes-rpc-policy/qubes.Filecopy.policy $RPM_BUILD_ROOT/etc/qubes-rpc/policy/qubes.Filecopy
 cp qubes-rpc-policy/qubes.OpenInVM.policy $RPM_BUILD_ROOT/etc/qubes-rpc/policy/qubes.OpenInVM
 cp qubes-rpc-policy/qubes.VMShell.policy $RPM_BUILD_ROOT/etc/qubes-rpc/policy/qubes.VMShell
+cp qubes-rpc-policy/qubes.NotifyTools.policy $RPM_BUILD_ROOT/etc/qubes-rpc/policy/qubes.NotifyTools
+cp qubes-rpc/qubes.NotifyTools $RPM_BUILD_ROOT/etc/qubes-rpc/
 cp qubes-rpc-policy/qubes.NotifyUpdates.policy $RPM_BUILD_ROOT/etc/qubes-rpc/policy/qubes.NotifyUpdates
 cp qubes-rpc/qubes.NotifyUpdates $RPM_BUILD_ROOT/etc/qubes-rpc/
 
@@ -280,6 +283,7 @@ fi
 /usr/lib/qubes/qmemman_daemon.py*
 /usr/lib/qubes/meminfo-writer
 /usr/lib/qubes/qfile-daemon-dvm*
+/usr/lib/qubes/qubes-notify-tools
 /usr/lib/qubes/qubes-notify-updates
 /usr/lib/qubes/block-cleaner-daemon.py*
 /usr/lib/qubes/vusb-ctl.py*
@@ -314,8 +318,10 @@ fi
 /etc/xen/scripts/vif-route-qubes
 %attr(0664,root,qubes) %config(noreplace) /etc/qubes-rpc/policy/qubes.Filecopy
 %attr(0664,root,qubes) %config(noreplace) /etc/qubes-rpc/policy/qubes.OpenInVM
+%attr(0664,root,qubes) %config(noreplace) /etc/qubes-rpc/policy/qubes.NotifyTools
 %attr(0664,root,qubes) %config(noreplace) /etc/qubes-rpc/policy/qubes.NotifyUpdates
 %attr(0664,root,qubes) %config(noreplace) /etc/qubes-rpc/policy/qubes.VMShell
+/etc/qubes-rpc/qubes.NotifyTools
 /etc/qubes-rpc/qubes.NotifyUpdates
 %attr(2770,root,qubes) %dir /var/log/qubes
 %attr(0770,root,qubes) %dir /var/run/qubes