From b57e2113a9bff00052cad0a021e784d15c637226 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Tue, 19 Jan 2021 16:28:34 +0300 Subject: [PATCH 01/13] winusb: run qrexec daemon for stubdomain if the corresponding feature (stubdom_qrexec) is enabled --- qubes/vm/qubesvm.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 42789475a..6bb5b6163 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1211,6 +1211,9 @@ def start(self, start_guid=True, notify_function=None, self.libvirt_domain.resume() yield from self.start_qrexec_daemon() + if self.virt_mode == 'hvm' and \ + self.features.check_with_template('stubdom_qrexec', False): + yield from self.start_qrexec_daemon(stubdom=True) yield from self.fire_event_async('domain-start', start_guid=start_guid) @@ -1629,14 +1632,19 @@ def start_daemon(*command, input=None, **kwargs): output=stdout, stderr=stderr) @asyncio.coroutine - def start_qrexec_daemon(self): + def start_qrexec_daemon(self, stubdom=False): """Start qrexec daemon. :raises OSError: when starting fails. """ self.log.debug('Starting the qrexec daemon') - qrexec_args = [str(self.xid), self.name, self.default_user] + if stubdom: + qrexec_args = [str(self.stubdom_xid), self.name + '-dm', \ + self.default_user] + else: + qrexec_args = [str(self.xid), self.name, self.default_user] + if not self.debug: qrexec_args.insert(0, "-q") From ee42d7a9b2f9692e5ce6e8dc3621176f271a03d9 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Tue, 19 Jan 2021 16:29:56 +0300 Subject: [PATCH 02/13] winusb: Redirect rpc calls to stub domain --- qubes/vm/qubesvm.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 6bb5b6163..4612e62ca 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1418,7 +1418,7 @@ def unpause(self): return self - async def run_service(self, service, source=None, user=None, + async def run_service(self, service, source=None, user=None, stubdom=False, filter_esc=False, autostart=False, gui=False, **kwargs): """Run service on this VM @@ -1448,13 +1448,15 @@ async def run_service(self, service, source=None, user=None, source = 'dom0' if source is None else self.app.domains[source].name + name = self.name + '-dm' if stubdom else self.name + if user is None: user = self.default_user if self.is_paused(): # XXX what about autostart? raise qubes.exc.QubesVMNotRunningError( - self, 'Domain {!r} is paused'.format(self.name)) + self, 'Domain {!r} is paused'.format(name)) if not self.is_running(): if not autostart: raise qubes.exc.QubesVMNotRunningError(self) @@ -1462,14 +1464,14 @@ async def run_service(self, service, source=None, user=None, if not self.is_qrexec_running(): raise qubes.exc.QubesVMError( - self, 'Domain {!r}: qrexec not connected'.format(self.name)) + self, 'Domain {!r}: qrexec not connected'.format(name)) await self.fire_event_async('domain-cmd-pre-run', pre_event=True, start_guid=gui) return (await asyncio.create_subprocess_exec( qubes.config.system_path['qrexec_client_path'], - '-d', str(self.name), + '-d', str(name), *(('-t', '-T') if filter_esc else ()), '{}:QUBESRPC {} {}'.format(user, service, source), **kwargs)) From 1a695192f443be3df176ec4c256de78316a589f3 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Tue, 19 Jan 2021 16:30:47 +0300 Subject: [PATCH 03/13] winusb: Replace minimal stubomain' kernel and ramdisk in favor of alternative with extended functionality --- templates/libvirt/xen.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/templates/libvirt/xen.xml b/templates/libvirt/xen.xml index 30b642290..8ad672663 100644 --- a/templates/libvirt/xen.xml +++ b/templates/libvirt/xen.xml @@ -187,6 +187,11 @@ {% if vm.stubdom_mem %} memory="{{ vm.stubdom_mem * 1024 -}}" {% endif %} + {% if vm.features.check_with_template('audio-model', False) + or vm.features.check_with_template('stubdom_qrexec', False) %} + kernel="/usr/libexec/xen/boot/qemu-stubdom-linux-full-kernel" + ramdisk="/usr/libexec/xen/boot/qemu-stubdom-linux-full-rootfs" + {% endif %} /> {% if vm.features.check_with_template('audio-model', False) %} From 29daff1296e771d867fce2db785b06c1aef5a862 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Wed, 27 Jan 2021 17:46:01 +0300 Subject: [PATCH 04/13] winusb: fix naming --- templates/libvirt/xen.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/libvirt/xen.xml b/templates/libvirt/xen.xml index 8ad672663..02f235523 100644 --- a/templates/libvirt/xen.xml +++ b/templates/libvirt/xen.xml @@ -188,7 +188,7 @@ memory="{{ vm.stubdom_mem * 1024 -}}" {% endif %} {% if vm.features.check_with_template('audio-model', False) - or vm.features.check_with_template('stubdom_qrexec', False) %} + or vm.features.check_with_template('stubdom-qrexec', False) %} kernel="/usr/libexec/xen/boot/qemu-stubdom-linux-full-kernel" ramdisk="/usr/libexec/xen/boot/qemu-stubdom-linux-full-rootfs" {% endif %} From 8ebc7aa7869c1ec13c99f68fb67fb3d9140c8764 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Wed, 27 Jan 2021 17:49:04 +0300 Subject: [PATCH 05/13] winusb: run qrexec agent in stubdom before the main qrexec daemon --- qubes/vm/qubesvm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 4612e62ca..ac531b282 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1210,10 +1210,10 @@ def start(self, start_guid=True, notify_function=None, self.log.warning('Activating the {} VM'.format(self.name)) self.libvirt_domain.resume() - yield from self.start_qrexec_daemon() if self.virt_mode == 'hvm' and \ - self.features.check_with_template('stubdom_qrexec', False): + self.features.check_with_template('stubdom-qrexec', False): yield from self.start_qrexec_daemon(stubdom=True) + yield from self.start_qrexec_daemon() yield from self.fire_event_async('domain-start', start_guid=start_guid) From 6a8bfd426f32604df5ede5c3f0dfaa649dbcf0bf Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Wed, 27 Jan 2021 17:59:19 +0300 Subject: [PATCH 06/13] winusb: explicitly use root on starting qrexec daemon in stubdom --- qubes/vm/qubesvm.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index ac531b282..39b0bcec2 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1642,8 +1642,7 @@ def start_qrexec_daemon(self, stubdom=False): self.log.debug('Starting the qrexec daemon') if stubdom: - qrexec_args = [str(self.stubdom_xid), self.name + '-dm', \ - self.default_user] + qrexec_args = [str(self.stubdom_xid), self.name + '-dm', 'root'] else: qrexec_args = [str(self.xid), self.name, self.default_user] From 77ec0cf01433402c3ba9c5d5c1fe8aa638162409 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Thu, 28 Jan 2021 14:45:15 +0300 Subject: [PATCH 07/13] winusb: add test for run_service with stubdom arg --- qubes/tests/vm/qubesvm.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/qubes/tests/vm/qubesvm.py b/qubes/tests/vm/qubesvm.py index e0d2475b3..39333fd2b 100644 --- a/qubes/tests/vm/qubesvm.py +++ b/qubes/tests/vm/qubesvm.py @@ -2085,6 +2085,18 @@ def test_700_run_service(self, mock_subprocess): 'user:QUBESRPC test.service test-inst-vm') self.assertFalse(start_mock.called) + mock_subprocess.reset_mock() + start_mock.reset_mock() + with self.subTest('stubdom'): + vm.is_running = lambda: True + vm.is_qrexec_running = lambda: True + self.loop.run_until_complete(vm.run_service('test.service', + stubdom=True)) + mock_subprocess.assert_called_once_with( + '/usr/bin/qrexec-client', '-d', 'test-inst-vm-dm', + 'user:QUBESRPC test.service dom0') + self.assertFalse(start_mock.called) + @unittest.mock.patch('qubes.vm.qubesvm.QubesVM.run') def test_710_run_for_stdio(self, mock_run): vm = self.get_vm(cls=qubes.vm.standalonevm.StandaloneVM, From 21d67b2577df0657a40e94e8aeb4f4cfc7e2b0ab Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Tue, 16 Feb 2021 17:58:06 +0300 Subject: [PATCH 08/13] winusb: fix domain name for is_paused() message --- qubes/vm/qubesvm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 39b0bcec2..0f2d16843 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1456,7 +1456,7 @@ async def run_service(self, service, source=None, user=None, stubdom=False, if self.is_paused(): # XXX what about autostart? raise qubes.exc.QubesVMNotRunningError( - self, 'Domain {!r} is paused'.format(name)) + self, 'Domain {!r} is paused'.format(self.name)) if not self.is_running(): if not autostart: raise qubes.exc.QubesVMNotRunningError(self) From a2e4dbf127731c57c836272c2a9c6f93b2838e93 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Tue, 16 Feb 2021 18:00:04 +0300 Subject: [PATCH 09/13] winusb: check if qrexec running for the stubdom --- qubes/vm/qubesvm.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index 0f2d16843..533f9fe5f 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1462,7 +1462,7 @@ async def run_service(self, service, source=None, user=None, stubdom=False, raise qubes.exc.QubesVMNotRunningError(self) await self.start(start_guid=gui) - if not self.is_qrexec_running(): + if not self.is_qrexec_running(stubdom=stubdom): raise qubes.exc.QubesVMError( self, 'Domain {!r}: qrexec not connected'.format(name)) @@ -1974,7 +1974,7 @@ def is_paused(self): return self.libvirt_domain \ and self.libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PAUSED - def is_qrexec_running(self): + def is_qrexec_running(self, stubdom=False): """Check whether qrexec for this domain is available. :returns: :py:obj:`True` if qrexec is running, \ @@ -1983,7 +1983,8 @@ def is_qrexec_running(self): """ if self.xid < 0: # pylint: disable=comparison-with-callable return False - return os.path.exists('/var/run/qubes/qrexec.%s' % self.name) + name = self.name + '-dm' if stubdom else self.name + return os.path.exists('/var/run/qubes/qrexec.%s' % name) def is_fully_usable(self): return all(self.fire_event('domain-is-fully-usable')) From aa7ab3c45b6e6f0a9f6c5b284afdf4dc096aa5af Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Thu, 8 Apr 2021 20:20:27 +0300 Subject: [PATCH 10/13] winusb: remove whitespace --- qubes/vm/qubesvm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index abe25b850..46dbe5462 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -1228,7 +1228,7 @@ async def start(self, start_guid=True, notify_function=None, self.features.check_with_template('stubdom-qrexec', False): await self.start_qrexec_daemon(stubdom=True) await self.start_qrexec_daemon() - + await self.fire_event_async('domain-start', start_guid=start_guid) From 4d6eb898f02689bb080cf541fabadac84ef4762d Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Mon, 12 Apr 2021 16:45:09 +0300 Subject: [PATCH 11/13] winusb: add optional parameter to lambda function --- qubes/tests/vm/qubesvm.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qubes/tests/vm/qubesvm.py b/qubes/tests/vm/qubesvm.py index bcc7cd4ff..2b7c86efc 100644 --- a/qubes/tests/vm/qubesvm.py +++ b/qubes/tests/vm/qubesvm.py @@ -2021,7 +2021,7 @@ def test_700_run_service(self, mock_subprocess): vm = self.get_vm(cls=qubes.vm.standalonevm.StandaloneVM, name='vm') vm.is_running = lambda: True - vm.is_qrexec_running = lambda: True + vm.is_qrexec_running = lambda stubdom=False: True vm.start = start_mock with self.subTest('running'): self.loop.run_until_complete(vm.run_service('test.service')) @@ -2053,7 +2053,7 @@ def test_700_run_service(self, mock_subprocess): start_mock.reset_mock() with self.subTest('no_qrexec'): vm.is_running = lambda: True - vm.is_qrexec_running = lambda: False + vm.is_qrexec_running = lambda stubdom=False: False with self.assertRaises(qubes.exc.QubesVMError): self.loop.run_until_complete(vm.run_service('test.service')) self.assertFalse(start_mock.called) @@ -2063,7 +2063,7 @@ def test_700_run_service(self, mock_subprocess): start_mock.reset_mock() with self.subTest('other_user'): vm.is_running = lambda: True - vm.is_qrexec_running = lambda: True + vm.is_qrexec_running = lambda stubdom=False: True self.loop.run_until_complete(vm.run_service('test.service', user='other')) mock_subprocess.assert_called_once_with( @@ -2075,7 +2075,7 @@ def test_700_run_service(self, mock_subprocess): start_mock.reset_mock() with self.subTest('other_source'): vm.is_running = lambda: True - vm.is_qrexec_running = lambda: True + vm.is_qrexec_running = lambda stubdom=False: True self.loop.run_until_complete(vm.run_service('test.service', source='test-inst-vm')) mock_subprocess.assert_called_once_with( @@ -2087,7 +2087,7 @@ def test_700_run_service(self, mock_subprocess): start_mock.reset_mock() with self.subTest('stubdom'): vm.is_running = lambda: True - vm.is_qrexec_running = lambda: True + vm.is_qrexec_running = lambda stubdom=True: True self.loop.run_until_complete(vm.run_service('test.service', stubdom=True)) mock_subprocess.assert_called_once_with( From da5e9df0cd7ec94e4b873063d4b3e223c1f918e0 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Sun, 20 Jun 2021 17:02:04 +0300 Subject: [PATCH 12/13] winusb: fix requires --- rpm_spec/core-dom0.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm_spec/core-dom0.spec.in b/rpm_spec/core-dom0.spec.in index 76e7dcb42..15fdd4081 100644 --- a/rpm_spec/core-dom0.spec.in +++ b/rpm_spec/core-dom0.spec.in @@ -82,7 +82,7 @@ Conflicts: qubes-gui-dom0 < 1.1.13 %if "x%{?backend_vmm}" == "xxen" Requires: xen-runtime Requires: xen-hvm -Requires: xen-hvm-stubdom-linux >= 1.0.13 +Requires: xen-hvm-stubdom-linux-full >= 1.0.13 Requires: libvirt-daemon-xen >= 3.3.0-7 %endif Requires: cronie From c3f7cb2ecc4b75d8dfa976724075d3fc1e9e1577 Mon Sep 17 00:00:00 2001 From: Dmitry Fedorov Date: Sun, 20 Jun 2021 18:01:16 +0300 Subject: [PATCH 13/13] winusb: bring back xen-hvm-stubdom-linux --- rpm_spec/core-dom0.spec.in | 1 + 1 file changed, 1 insertion(+) diff --git a/rpm_spec/core-dom0.spec.in b/rpm_spec/core-dom0.spec.in index 15fdd4081..c1cc1c067 100644 --- a/rpm_spec/core-dom0.spec.in +++ b/rpm_spec/core-dom0.spec.in @@ -82,6 +82,7 @@ Conflicts: qubes-gui-dom0 < 1.1.13 %if "x%{?backend_vmm}" == "xxen" Requires: xen-runtime Requires: xen-hvm +Requires: xen-hvm-stubdom-linux >= 1.0.13 Requires: xen-hvm-stubdom-linux-full >= 1.0.13 Requires: libvirt-daemon-xen >= 3.3.0-7 %endif