diff --git a/qubes/ext/gui.py b/qubes/ext/gui.py index 82de66cd..68a65ba9 100644 --- a/qubes/ext/gui.py +++ b/qubes/ext/gui.py @@ -183,7 +183,7 @@ class GUI(qubes.ext.Extension): guid_cmd += self.kde_guid_args(vm) try: - subprocess.check_call(guid_cmd) + vm.start_daemon(guid_cmd) except subprocess.CalledProcessError: raise qubes.exc.QubesVMError(vm, 'Cannot start qubes-guid for domain {!r}'.format(vm.name)) @@ -246,7 +246,7 @@ class GUI(qubes.ext.Extension): guid_cmd += self.kde_guid_args(vm) try: - subprocess.check_call(guid_cmd) + vm.start_daemon(guid_cmd) except subprocess.CalledProcessError: raise qubes.exc.QubesVMError(vm, 'Cannot start gui daemon') diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index b893aa24..6b22b56a 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -39,6 +39,7 @@ import time import uuid import warnings +import grp import lxml import libvirt # pylint: disable=import-error @@ -926,6 +927,27 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): return qmemman_client + @staticmethod + def start_daemon(command, **kwargs): + '''Start a daemon for the VM + + This function take care to run it as appropriate user. + + :param command: command to run (array for + :py:meth:`subprocess.check_call`) + :param kwargs: args for :py:meth:`subprocess.check_call` + :return: None + ''' + + prefix_cmd = [] + if os.getuid() == 0: + # try to always have VM daemons running as normal user, otherwise + # some files (like clipboard) may be created as root and cause + # permission problems + qubes_group = grp.getgrnam('qubes') + prefix_cmd = ['runuser', '-u', qubes_group.gr_mem[0], '--'] + subprocess.check_call(prefix_cmd + command, **kwargs) + def start_qrexec_daemon(self): '''Start qrexec daemon. @@ -946,7 +968,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): qrexec_env['QREXEC_STARTUP_TIMEOUT'] = str(self.qrexec_timeout) try: - subprocess.check_call( + self.start_daemon( [qubes.config.system_path["qrexec_daemon_path"]] + qrexec_args, env=qrexec_env) except subprocess.CalledProcessError: @@ -961,11 +983,12 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): self.log.info('Starting Qubes DB') # FIXME #1694 #1241 - retcode = subprocess.call([ - qubes.config.system_path["qubesdb_daemon_path"], - str(self.xid), - self.name]) - if retcode != 0: + try: + self.start_daemon([ + qubes.config.system_path["qubesdb_daemon_path"], + str(self.xid), + self.name]) + except subprocess.CalledProcessError: raise qubes.exc.QubesException('Cannot execute qubesdb-daemon') def wait_for_session(self):