Do not abort suspend hooks if any qubes.Suspend* service fails to run

First of all, do not try to call those services in VMs not having qrexec
installed - for example Windows VMs without qubes tools.
Then, even if service call fails for any other reason, only log it but
do not prevent other services from being called. A single uncooperative
VM should generally be able only to hurt itself, not break other VMs
during suspend.

Fixes QubesOS/qubes-issues#3489
This commit is contained in:
Marek Marczykowski-Górecki 2019-02-24 16:08:49 +01:00
parent eeec2e0ddd
commit 9257a6d14f
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 20 additions and 6 deletions

View File

@ -95,13 +95,19 @@ class QubesInternalAPI(qubes.api.AbstractQubesAPI):
for vm in self.app.domains:
if isinstance(vm, qubes.vm.adminvm.AdminVM):
continue
if vm.is_running():
if not vm.is_running():
continue
if not vm.features.check_with_template('qrexec', False):
continue
try:
proc = yield from vm.run_service(
'qubes.SuspendPreAll', user='root',
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
processes.append(proc)
except qubes.exc.QubesException as e:
vm.log.warning('Failed to run qubes.SuspendPreAll: %s', str(e))
# FIXME: some timeout?
if processes:
@ -141,13 +147,19 @@ class QubesInternalAPI(qubes.api.AbstractQubesAPI):
for vm in self.app.domains:
if isinstance(vm, qubes.vm.adminvm.AdminVM):
continue
if vm.is_running():
if not vm.is_running():
continue
if not vm.features.check_with_template('qrexec', False):
continue
try:
proc = yield from vm.run_service(
'qubes.SuspendPostAll', user='root',
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
processes.append(proc)
except qubes.exc.QubesException as e:
vm.log.warning('Failed to run qubes.SuspendPostAll: %s', str(e))
# FIXME: some timeout?
if processes:

View File

@ -1213,8 +1213,9 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
raise qubes.exc.QubesVMNotRunningError(self)
if list(self.devices['pci'].attached()):
yield from self.run_service_for_stdio('qubes.SuspendPre',
user='root')
if self.features.check_with_template('qrexec', False):
yield from self.run_service_for_stdio('qubes.SuspendPre',
user='root')
self.libvirt_domain.pMSuspendForDuration(
libvirt.VIR_NODE_SUSPEND_TARGET_MEM, 0, 0)
else:
@ -1244,8 +1245,9 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
# pylint: disable=not-an-iterable
if self.get_power_state() == "Suspended":
self.libvirt_domain.pMWakeup()
yield from self.run_service_for_stdio('qubes.SuspendPost',
user='root')
if self.features.check_with_template('qrexec', False):
yield from self.run_service_for_stdio('qubes.SuspendPost',
user='root')
else:
yield from self.unpause()