Selaa lähdekoodia

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
Marek Marczykowski-Górecki 5 vuotta sitten
vanhempi
commit
9257a6d14f
2 muutettua tiedostoa jossa 20 lisäystä ja 6 poistoa
  1. 14 2
      qubes/api/internal.py
  2. 6 4
      qubes/vm/qubesvm.py

+ 14 - 2
qubes/api/internal.py

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

+ 6 - 4
qubes/vm/qubesvm.py

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