From 5546d679c0cd8e3d7a9ba94678e8b22be8525510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sun, 21 Feb 2016 12:41:13 +0100 Subject: [PATCH] dispvm: use try/finally to make sure that qubes.xml is unlocked Even in case of some exception (in which case theoretically it should be unlocked at qfile-daemon-dvm exit, but the script may wait for something). QubesOS/qubes-issues#1636 --- dispvm/qfile-daemon-dvm | 121 ++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 61 deletions(-) diff --git a/dispvm/qfile-daemon-dvm b/dispvm/qfile-daemon-dvm index c582f79b..423500b6 100755 --- a/dispvm/qfile-daemon-dvm +++ b/dispvm/qfile-daemon-dvm @@ -51,68 +51,67 @@ class QfileDaemonDvm: qvm_collection = QubesVmCollection() qvm_collection.lock_db_for_writing() - - tar_process = subprocess.Popen( - ['bsdtar', '-C', current_savefile_vmdir, - '-xSUf', os.path.join(current_savefile_vmdir, 'saved-cows.tar')]) - - qvm_collection.load() - print >>sys.stderr, "time=%s, collection loaded" % (str(time.time())) - - vm = qvm_collection.get_vm_by_name(self.name) - if vm is None: - sys.stderr.write('Domain ' + self.name + ' does not exist ?') - qvm_collection.unlock_db() - return None - label = vm.label - if len(sys.argv) > 4 and len(sys.argv[4]) > 0: - assert sys.argv[4] in QubesDispVmLabels.keys(), "Invalid label" - label = QubesDispVmLabels[sys.argv[4]] - disp_templ = self.get_disp_templ() - vm_disptempl = qvm_collection.get_vm_by_name(disp_templ) - if vm_disptempl is None: - sys.stderr.write('Domain ' + disp_templ + ' does not exist ?') - qvm_collection.unlock_db() - return None - dispvm = qvm_collection.add_new_vm('QubesDisposableVm', - disp_template=vm_disptempl, - label=label) - print >>sys.stderr, "time=%s, VM created" % (str(time.time())) - # By default inherit firewall rules from calling VM - disp_firewall_conf = '/var/run/qubes/%s-firewall.xml' % dispvm.name - dispvm.firewall_conf = disp_firewall_conf - if os.path.exists(vm.firewall_conf): - shutil.copy(vm.firewall_conf, disp_firewall_conf) - elif vm.qid == 0 and os.path.exists(vm_disptempl.firewall_conf): - # for DispVM called from dom0, copy use rules from DispVM template - shutil.copy(vm_disptempl.firewall_conf, disp_firewall_conf) - 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.uses_default_netvm = False - # netvm can be changed before restore, - # but cannot be enabled/disabled - if (dispvm.netvm is None) == (vm.dispvm_netvm is None): - dispvm.netvm = vm.dispvm_netvm - # Wait for tar to finish - if tar_process.wait() != 0: - sys.stderr.write('Failed to unpack saved-cows.tar') - qvm_collection.unlock_db() - return None - print >>sys.stderr, "time=%s, VM starting" % (str(time.time())) try: - dispvm.start() - except (MemoryError, QubesException) as e: - tray_notify_error(str(e)) - raise - if vm.qid != 0: - # if need to enable/disable netvm, do it while DispVM is alive - if (dispvm.netvm is None) != (vm.dispvm_netvm is None): - dispvm.netvm = vm.dispvm_netvm - print >>sys.stderr, "time=%s, VM started" % (str(time.time())) - qvm_collection.save() - qvm_collection.unlock_db() + + tar_process = subprocess.Popen( + ['bsdtar', '-C', current_savefile_vmdir, + '-xSUf', os.path.join(current_savefile_vmdir, 'saved-cows.tar')]) + + qvm_collection.load() + print >>sys.stderr, "time=%s, collection loaded" % (str(time.time())) + + vm = qvm_collection.get_vm_by_name(self.name) + if vm is None: + sys.stderr.write('Domain ' + self.name + ' does not exist ?') + return None + label = vm.label + if len(sys.argv) > 4 and len(sys.argv[4]) > 0: + assert sys.argv[4] in QubesDispVmLabels.keys(), "Invalid label" + label = QubesDispVmLabels[sys.argv[4]] + disp_templ = self.get_disp_templ() + vm_disptempl = qvm_collection.get_vm_by_name(disp_templ) + if vm_disptempl is None: + sys.stderr.write('Domain ' + disp_templ + ' does not exist ?') + return None + dispvm = qvm_collection.add_new_vm('QubesDisposableVm', + disp_template=vm_disptempl, + label=label) + print >>sys.stderr, "time=%s, VM created" % (str(time.time())) + # By default inherit firewall rules from calling VM + disp_firewall_conf = '/var/run/qubes/%s-firewall.xml' % dispvm.name + dispvm.firewall_conf = disp_firewall_conf + if os.path.exists(vm.firewall_conf): + shutil.copy(vm.firewall_conf, disp_firewall_conf) + elif vm.qid == 0 and os.path.exists(vm_disptempl.firewall_conf): + # for DispVM called from dom0, copy use rules from DispVM template + shutil.copy(vm_disptempl.firewall_conf, disp_firewall_conf) + 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.uses_default_netvm = False + # netvm can be changed before restore, + # but cannot be enabled/disabled + if (dispvm.netvm is None) == (vm.dispvm_netvm is None): + dispvm.netvm = vm.dispvm_netvm + # Wait for tar to finish + if tar_process.wait() != 0: + sys.stderr.write('Failed to unpack saved-cows.tar') + return None + print >>sys.stderr, "time=%s, VM starting" % (str(time.time())) + try: + dispvm.start() + except (MemoryError, QubesException) as e: + tray_notify_error(str(e)) + raise + if vm.qid != 0: + # if need to enable/disable netvm, do it while DispVM is alive + if (dispvm.netvm is None) != (vm.dispvm_netvm is None): + dispvm.netvm = vm.dispvm_netvm + print >>sys.stderr, "time=%s, VM started" % (str(time.time())) + qvm_collection.save() + finally: + qvm_collection.unlock_db() # Reload firewall rules print >>sys.stderr, "time=%s, reloading firewall" % (str(time.time())) for vm in qvm_collection.values():