qrexec: fix handling autostarting RPC target VM

Do not reimplement manual VM state checking in qrexec-policy.
`qubes.xml` is loaded anyway, so just use QubesVM object to check if
domain is running.

Fixes QubesOS/qubes-issues#1283
This commit is contained in:
Marek Marczykowski-Górecki 2015-10-11 01:52:40 +02:00
parent 63dffb48c5
commit 63e74a01d3
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -4,7 +4,9 @@ import os
import os.path import os.path
import subprocess import subprocess
from qubes.qubes import vmm from qubes.qubes import vmm
from qubes.qubes import QubesVmCollection
import qubes.guihelpers import qubes.guihelpers
import libvirt
from optparse import OptionParser from optparse import OptionParser
import fcntl import fcntl
@ -82,45 +84,36 @@ def find_policy(policy, domain, target):
return iter return iter
return get_default_policy() return get_default_policy()
def is_domain_running(target):
if target == "dom0":
return True
libvirt_dom = vmm.libvirt_conn.lookupByName(target)
if libvirt_dom:
return libvirt_dom.isActive()
else:
return False
def validate_target(target): def validate_target(target):
# special targets # special targets
if target in ['$dispvm', 'dom0']: if target in ['$dispvm']:
return True return True
from qubes.qubes import QubesVmCollection
qc = QubesVmCollection() qc = QubesVmCollection()
qc.lock_db_for_reading() qc.lock_db_for_reading()
qc.load() qc.load()
qc.unlock_db() qc.unlock_db()
return qc.get_vm_by_name(target) is not None return qc.get_vm_by_name(target)
def spawn_target_if_necessary(target): def spawn_target_if_necessary(vm):
if is_domain_running(target): if vm.is_running():
return return
null=open("/dev/null", "r+") # use qvm-run instead of vm.start() to make sure that nothing is written
subprocess.call(["qvm-run", "-a", "-q", target, "true"], stdin=null, stdout=null) # to stdout and nothing is read from stdin
null = open("/dev/null", "r+")
subprocess.call(["qvm-run", "-a", "-q", vm.name, "true"],
stdin=null, stdout=null)
null.close() null.close()
def do_execute(domain, target, user, service_name, process_ident): def do_execute(domain, target, user, service_name, process_ident, vm=None):
if target == "$dispvm": if target == "$dispvm":
cmd = "/usr/lib/qubes/qfile-daemon-dvm " + service_name + " " + domain + " " +user cmd = "/usr/lib/qubes/qfile-daemon-dvm " + service_name + " " + domain + " " +user
os.execl(QREXEC_CLIENT, "qrexec-client", os.execl(QREXEC_CLIENT, "qrexec-client",
"-d", "dom0", "-c", process_ident, cmd) "-d", "dom0", "-c", process_ident, cmd)
else: else:
# see the previous commit why "qvm-run -a" is broken and dangerous if isinstance(vm, qubes.qubes.QubesVm):
# also, dangling "xl" would keep stderr open and may prevent closing connection spawn_target_if_necessary(vm)
spawn_target_if_necessary(target)
if target == "dom0": if target == "dom0":
cmd = QUBES_RPC_MULTIPLEXER_PATH + " " + service_name + " " + domain cmd = QUBES_RPC_MULTIPLEXER_PATH + " " + service_name + " " + domain
else: else:
@ -175,7 +168,8 @@ def main():
# connection # connection
process_ident+=","+domain+","+domain_id process_ident+=","+domain+","+domain_id
if not validate_target(target): vm = validate_target(target)
if vm is None:
print >> sys.stderr, "Rpc failed (unknown domain):", domain, target, service_name print >> sys.stderr, "Rpc failed (unknown domain):", domain, target, service_name
text = "Domain '%s' doesn't exist (service %s called by domain %s)." % ( text = "Domain '%s' doesn't exist (service %s called by domain %s)." % (
target, service_name, domain) target, service_name, domain)
@ -218,7 +212,7 @@ def main():
else: else:
user="DEFAULT" user="DEFAULT"
print >> sys.stderr, "Rpc allowed:", domain, target, service_name print >> sys.stderr, "Rpc allowed:", domain, target, service_name
do_execute(domain, target, user, service_name, process_ident) do_execute(domain, target, user, service_name, process_ident, vm=vm)
print >> sys.stderr, "Rpc denied:", domain, target, service_name print >> sys.stderr, "Rpc denied:", domain, target, service_name
exit(1) exit(1)