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:
parent
63dffb48c5
commit
63e74a01d3
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user