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
This commit is contained in:
Marek Marczykowski-Górecki 2015-04-04 21:04:49 +02:00
parent a6448e073c
commit 7516737fae
4 changed files with 61 additions and 0 deletions

View File

@ -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

View File

@ -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')

View File

@ -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

View File

@ -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) <vmaname>"
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,