From e2c43d22929dd1baf76755210f885fa37944d0b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Mon, 28 Oct 2013 05:09:54 +0100 Subject: [PATCH] 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. --- core-modules/01QubesHVm.py | 20 +++++++ qubes-rpc-policy/qubes.NotifyTools.policy | 6 ++ qubes-rpc/qubes-notify-tools | 70 +++++++++++++++++++++++ qubes-rpc/qubes.NotifyTools | 1 + rpm_spec/core-dom0.spec | 6 ++ 5 files changed, 103 insertions(+) create mode 100644 qubes-rpc-policy/qubes.NotifyTools.policy create mode 100755 qubes-rpc/qubes-notify-tools create mode 100644 qubes-rpc/qubes.NotifyTools diff --git a/core-modules/01QubesHVm.py b/core-modules/01QubesHVm.py index 93233e6c..53cce267 100644 --- a/core-modules/01QubesHVm.py +++ b/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 diff --git a/qubes-rpc-policy/qubes.NotifyTools.policy b/qubes-rpc-policy/qubes.NotifyTools.policy new file mode 100644 index 00000000..0f00b0b6 --- /dev/null +++ b/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 diff --git a/qubes-rpc/qubes-notify-tools b/qubes-rpc/qubes-notify-tools new file mode 100755 index 00000000..e9109e73 --- /dev/null +++ b/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() diff --git a/qubes-rpc/qubes.NotifyTools b/qubes-rpc/qubes.NotifyTools new file mode 100644 index 00000000..5c7e590a --- /dev/null +++ b/qubes-rpc/qubes.NotifyTools @@ -0,0 +1 @@ +/usr/lib/qubes/qubes-notify-tools diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index f12d2cec..a31aaac1 100644 --- a/rpm_spec/core-dom0.spec +++ b/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