From 7516737fae3222e5d64acaad83cd26948a618025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 4 Apr 2015 21:04:49 +0200 Subject: [PATCH] core: Add "dispvm_netvm" property - NetVM for DispVMs started from a VM This allows to specify tight network isolation for a VM, and finally close one remaining way for leaking traffic around TorVM. Now when VM is connected to for example TorVM, its DispVMs will be also connected there. The new property can be set to: - default (uses_default_dispvm_netvm=True) - use the same NetVM/ProxyVM as the calling VM itself - including none it that's the case - None - DispVMs will be network-isolated - some NetVM/ProxyVM - will be used, even if calling VM is network-isolated Closes qubesos/qubes-issues#862 --- core-modules/000QubesVm.py | 21 +++++++++++++++++++++ dispvm/qfile-daemon-dvm | 2 ++ doc/qvm-tools/qvm-prefs.rst | 5 +++++ qvm-tools/qvm-prefs | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/core-modules/000QubesVm.py b/core-modules/000QubesVm.py index 14b76aa5..1960f352 100644 --- a/core-modules/000QubesVm.py +++ b/core-modules/000QubesVm.py @@ -156,6 +156,8 @@ class QubesVm(object): "default_user": { "default": "user", "attr": "_default_user" }, "qrexec_timeout": { "default": 60 }, "autostart": { "default": False, "attr": "_autostart" }, + "uses_default_dispvm_netvm": {"default": True, "order": 30}, + "dispvm_netvm": {"attr": "_dispvm_netvm", "default": None}, "backup_content" : { 'default': False }, "backup_size" : { "default": 0, @@ -218,6 +220,11 @@ class QubesVm(object): attrs['netvm']['save'] = \ lambda: str(self.netvm.qid) if self.netvm is not None else "none" attrs['netvm']['save_attr'] = "netvm_qid" + attrs['dispvm_netvm']['save'] = \ + lambda: str(self.dispvm_netvm.qid) \ + if self.dispvm_netvm is not None \ + else "none" + attrs['dispvm_netvm']['save_attr'] = "dispvm_netvm_qid" attrs['template']['save'] = \ lambda: str(self.template.qid) if self.template else "none" attrs['template']['save_attr'] = "template_qid" @@ -602,6 +609,20 @@ class QubesVm(object): self._internal = value self.post_set_attr('internal', value, oldvalue) + @property + def dispvm_netvm(self): + if self.uses_default_dispvm_netvm: + return self.netvm + else: + if isinstance(self._dispvm_netvm, int): + return self._collection[self._dispvm_netvm] + else: + return self._dispvm_netvm + + @dispvm_netvm.setter + def dispvm_netvm(self, value): + self._dispvm_netvm = value + @property def autostart(self): return self._autostart diff --git a/dispvm/qfile-daemon-dvm b/dispvm/qfile-daemon-dvm index 426945fb..bb77cced 100755 --- a/dispvm/qfile-daemon-dvm +++ b/dispvm/qfile-daemon-dvm @@ -81,6 +81,8 @@ class QfileDaemonDvm: if len(sys.argv) > 5 and len(sys.argv[5]) > 0: assert os.path.exists(sys.argv[5]), "Invalid firewall.conf location" dispvm.firewall_conf = sys.argv[5] + if vm.qid != 0: + dispvm.netvm = vm.dispvm_netvm # Wait for tar to finish if tar_process.wait() != 0: sys.stderr.write('Failed to unpack saved-cows.tar') diff --git a/doc/qvm-tools/qvm-prefs.rst b/doc/qvm-tools/qvm-prefs.rst index ea82bee1..f5f9c115 100644 --- a/doc/qvm-tools/qvm-prefs.rst +++ b/doc/qvm-tools/qvm-prefs.rst @@ -46,6 +46,11 @@ netvm *Notice:* when setting to ``none``, firewall will be set to block all traffic - it will be used by DispVM started from this VM. Setting back to some NetVM will _NOT_ restore previous firewall settings. +dispvm_netvm + Accepted values: netvm name, ``default``, ``none`` + + Which NetVM should be used for Disposable VMs started by this one. ``default`` is to use the same NetVM as the VM itself. + maxmem Accepted values: memory size in MB diff --git a/qvm-tools/qvm-prefs b/qvm-tools/qvm-prefs index 78e6c819..10c8947f 100755 --- a/qvm-tools/qvm-prefs +++ b/qvm-tools/qvm-prefs @@ -42,6 +42,11 @@ def do_list(vm): print fmt.format ("template", vm.template.name) if vm.netvm is not None: print fmt.format ("netvm", vm.netvm.name) + if vm.qid != 0: + print fmt.format("dispvm_netvm", "%s%s" % ( + vm.dispvm_netvm.name if vm.dispvm_netvm + else "none", + " (default)" if vm.uses_default_dispvm_netvm else "")) print fmt.format ("updateable", vm.updateable) print fmt.format ("autostart", vm.autostart) print fmt.format ("installed_by_rpm", vm.installed_by_rpm) @@ -219,6 +224,33 @@ def set_netvm(vms, vm, args): vm.netvm = netvm return True +def set_dispvm_netvm(vms, vm, args): + if len (args) != 1: + print >> sys.stderr, "Missing netvm name argument!" + print >> sys.stderr, "Possible values:" + print >> sys.stderr, "1) default (the same as VM own netvm)" + print >> sys.stderr, "2) none" + print >> sys.stderr, "3) " + return + + netvm = args[0] + if netvm == "none": + vm.netvm = None + vm.uses_default_dispvm_netvm = False + elif netvm == "default": + vm.uses_default_dispvm_netvm = True + else: + netvm = vms.get_vm_by_name (netvm) + if netvm is None: + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(netvm) + return False + if not netvm.is_netvm(): + print >> sys.stderr, "VM '{0}' is not a NetVM".format(netvm) + return False + vm.dispvm_netvm = netvm + vm.uses_default_dispvm_netvm = False + return True + def set_kernel(vms, vm, args): if len (args) != 1: print >> sys.stderr, "Missing kernel version argument!" @@ -423,6 +455,7 @@ properties = { "pcidevs": set_pcidevs, "label" : set_label, "netvm" : set_netvm, + "dispvm_netvm" : set_dispvm_netvm, "maxmem" : set_maxmem, "memory" : set_memory, "kernel" : set_kernel,