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