Merge branch 'master' of git://git.qubes-os.org/marmarek/core
This commit is contained in:
commit
3898b69ac1
11
Makefile
11
Makefile
@ -12,15 +12,20 @@ help:
|
||||
@echo "make update-repo-installer -- copy dom0 rpms to installer repo"
|
||||
@echo "make clean -- cleanup"
|
||||
|
||||
rpms:
|
||||
rpms: rpms-vm rpms-dom0
|
||||
|
||||
rpms-vm:
|
||||
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/core-vm.spec
|
||||
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/core-vm-kernel-placeholder.spec
|
||||
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/core-dom0.spec
|
||||
rpm --addsign \
|
||||
$(RPMS_DIR)/x86_64/qubes-core-dom0-$(VERSION_DOM0)*.rpm \
|
||||
$(RPMS_DIR)/x86_64/qubes-core-vm-*$(VERSION_VM)*.rpm \
|
||||
$(RPMS_DIR)/x86_64/qubes-core-vm-kernel-placeholder-*.rpm
|
||||
|
||||
rpms-dom0:
|
||||
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/core-dom0.spec
|
||||
rpm --addsign \
|
||||
$(RPMS_DIR)/x86_64/qubes-core-dom0-$(VERSION_DOM0)*.rpm
|
||||
|
||||
rpms-vaio-fixes:
|
||||
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/core-dom0-vaio-fixes.spec
|
||||
rpm --addsign $(RPMS_DIR)/x86_64/qubes-core-dom0-vaio-fixes-$(VERSION_VAIO_FIXES)*.rpm
|
||||
|
69
README.pvusb
Normal file
69
README.pvusb
Normal file
@ -0,0 +1,69 @@
|
||||
Dedicated usbvm (optional)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In dom0, once:
|
||||
qvm-create -l red usbvm
|
||||
|
||||
# FIXME: use your own PCI device IDs
|
||||
qvm-pci -a usbvm 00:1d.0
|
||||
qvm-pci -a usbvm 00:1d.1
|
||||
qvm-pci -a usbvm 00:1d.2
|
||||
qvm-pci -a usbvm 00:1d.7
|
||||
|
||||
After each dom0 reboot:
|
||||
qvm-start usbvm
|
||||
|
||||
List
|
||||
~~~~
|
||||
|
||||
In dom0:
|
||||
qvm-usb -l
|
||||
|
||||
Example output:
|
||||
dom0:7-4 0718:061a TDKMedia_Trans-It_Drive_070326AE8AF92D95 (attached to qdvp:0-1)
|
||||
dom0:7-5 0b05:1706 ASUS_802.11g_WLAN_Drive (attached to netvm:0-1)
|
||||
dom0:1-1 045e:0084 Microsoft_Basic_Optical_Mouse
|
||||
usbvm:4-6 05e3:0723 Generic_USB_Storage (attached to qdvp:1-1)
|
||||
|
||||
Attach
|
||||
~~~~~~
|
||||
|
||||
In dom0:
|
||||
qvm-usb -a [--no-auto-detach] <vm-name> <device-vm-name>:<backend-controller>-<backend-port>
|
||||
|
||||
Example:
|
||||
qvm-usb -a netvm usbvm:4-1
|
||||
|
||||
Detach
|
||||
~~~~~~
|
||||
|
||||
In dom0:
|
||||
qvm-usb -d <vm-name>:<vusb-controller>-<vusb-port>
|
||||
|
||||
Example:
|
||||
qvm-usb -d netvm:0-1
|
||||
|
||||
Known issues
|
||||
~~~~~~~~~~~~
|
||||
|
||||
List/attach/detach operations seem to work ok, devices are recognized by the target VM etc.
|
||||
But actual usage of the attached devices is unstable at best. In fact the only working device
|
||||
I saw was one USB stick (and this only after it took a minute to time out and reset the bus
|
||||
couple times). Kernel crashes are normal as well. I have not investigated these issues yet,
|
||||
I had similar experience with Marek's scripts.
|
||||
|
||||
* System keyboard / mouse are listed and can be detached away
|
||||
* Virtual USB devices (ones created by PVUSB frontend) may be listed
|
||||
* The installation/configuration is not persistent, not retained between reboots
|
||||
* No debugging / logging / audit trail
|
||||
* When an attached device is physically unplugged, USB port remains mapped but not displayed
|
||||
in the list. If device is plugged back it continues to work. Unlisted device cannot be detached.
|
||||
* We are not attaching actual devices, but USB ports (different behavior from VMWare, might be confusing)
|
||||
* After device is detached from the frontend and returned back to the backend it is not alwayws usable there
|
||||
* Code changing configuration of pvusb fe/be and vusb bind/unbind helper are located
|
||||
misc/xl-qvm-usb-attach.py misc/xl-qvm-usb-detach.py misc/vusb-ctl.py. These helpers are
|
||||
deployed into the backend domain. The initialization code is qubesutils.py in usb_setup(),
|
||||
should probably also be moved into an external helper. Perhaps the functionality of these
|
||||
external helpers should be merged into libxl? The is one catch is invokation of vusb helper
|
||||
in the backend domain -- now it relies on qubes-specific API.
|
||||
|
1
build-deps.list
Normal file
1
build-deps.list
Normal file
@ -0,0 +1 @@
|
||||
xen-devel-*DIST*
|
22238
dom0/misc/Fedora-13-comps.xml
Normal file
22238
dom0/misc/Fedora-13-comps.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -84,7 +84,7 @@ def handle_dom0updates(updatevm):
|
||||
if updates_error_file_handle is not None:
|
||||
updates_error_file_handle.close()
|
||||
# After updates received - create repo metadata
|
||||
subprocess.check_call(["/usr/bin/createrepo", "-q", updates_dir])
|
||||
subprocess.check_call(["/usr/bin/createrepo", "-g", "/usr/share/qubes/Fedora-13-comps.xml", "-q", updates_dir])
|
||||
os.chown(updates_repodata_dir, -1, qubes_gid)
|
||||
os.chmod(updates_repodata_dir, 0775)
|
||||
# Clean old cache
|
||||
|
@ -75,7 +75,7 @@ default_kernels_subdir = "kernels"
|
||||
default_firewall_conf_file = "firewall.xml"
|
||||
default_memory = 400
|
||||
default_kernelopts = ""
|
||||
default_kernelopts_pcidevs = "iommu=soft swiotlb=2048"
|
||||
default_kernelopts_pcidevs = "iommu=soft swiotlb=4096"
|
||||
|
||||
default_hvm_disk_size = 20*1024*1024*1024
|
||||
default_hvm_private_img_size = 2*1024*1024*1024
|
||||
@ -874,6 +874,10 @@ class QubesVm(object):
|
||||
"{0}/qubes-block-devices".format(domain_path),
|
||||
'')
|
||||
|
||||
xs.write('',
|
||||
"{0}/qubes-usb-devices".format(domain_path),
|
||||
'')
|
||||
|
||||
xs.write('', "{0}/qubes-debug-mode".format(domain_path),
|
||||
str(int(self.debug)))
|
||||
|
||||
@ -884,6 +888,8 @@ class QubesVm(object):
|
||||
[{ 'dom': xid }])
|
||||
xs.set_permissions('', '{0}/qubes-block-devices'.format(domain_path),
|
||||
[{ 'dom': xid }])
|
||||
xs.set_permissions('', '{0}/qubes-usb-devices'.format(domain_path),
|
||||
[{ 'dom': xid }])
|
||||
|
||||
def get_rootdev(self, source_template=None):
|
||||
if self.template:
|
||||
|
@ -293,12 +293,18 @@ def block_check_attached(backend_vm, device, backend_xid = None):
|
||||
return None
|
||||
|
||||
def block_attach(vm, backend_vm, device, frontend=None, mode="w", auto_detach=False, wait=True):
|
||||
device_attach_check(vm, backend_vm, device, frontend)
|
||||
do_block_attach(vm, backend_vm, device, frontend, mode, auto_detach, wait)
|
||||
|
||||
def device_attach_check(vm, backend_vm, device, frontend):
|
||||
""" Checks all the parameters, dies on errors """
|
||||
if not vm.is_running():
|
||||
raise QubesException("VM %s not running" % vm.name)
|
||||
|
||||
if not backend_vm.is_running():
|
||||
raise QubesException("VM %s not running" % backend_vm.name)
|
||||
|
||||
def do_block_attach(vm, backend_vm, device, frontend, mode, auto_detach, wait):
|
||||
if frontend is None:
|
||||
frontend = block_find_unused_frontend(vm)
|
||||
if frontend is None:
|
||||
@ -398,6 +404,268 @@ def block_detach_all(vm, vm_xid = None):
|
||||
xl_cmd = [ '/usr/sbin/xl', 'block-detach', str(vm_xid), devid]
|
||||
subprocess.check_call(xl_cmd)
|
||||
|
||||
####### USB devices ######
|
||||
|
||||
usb_ver_re = re.compile(r"^(1|2)$")
|
||||
usb_device_re = re.compile(r"^[0-9]+-[0-9]+(_[0-9]+)?$")
|
||||
usb_port_re = re.compile(r"^$|^[0-9]+-[0-9]+(\.[0-9]+)?$")
|
||||
|
||||
def usb_setup(backend_vm_xid, vm_xid, devid, usb_ver):
|
||||
"""
|
||||
Attach frontend to the backend.
|
||||
backend_vm_xid - id of the backend domain
|
||||
vm_xid - id of the frontend domain
|
||||
devid - id of the pvusb controller
|
||||
"""
|
||||
num_ports = 8
|
||||
trans = xs.transaction_start()
|
||||
|
||||
be_path = "/local/domain/%d/backend/vusb/%d/%d" % (backend_vm_xid, vm_xid, devid)
|
||||
fe_path = "/local/domain/%d/device/vusb/%d" % (vm_xid, devid)
|
||||
|
||||
be_perm = [{'dom': backend_vm_xid}, {'dom': vm_xid, 'read': True} ]
|
||||
fe_perm = [{'dom': vm_xid}, {'dom': backend_vm_xid, 'read': True} ]
|
||||
|
||||
# Create directories and set permissions
|
||||
xs.write(trans, be_path, "")
|
||||
xs.set_permissions(trans, be_path, be_perm)
|
||||
|
||||
xs.write(trans, fe_path, "")
|
||||
xs.set_permissions(trans, fe_path, fe_perm)
|
||||
|
||||
# Write backend information into the location that frontend looks for
|
||||
xs.write(trans, "%s/backend-id" % fe_path, str(backend_vm_xid))
|
||||
xs.write(trans, "%s/backend" % fe_path, be_path)
|
||||
|
||||
# Write frontend information into the location that backend looks for
|
||||
xs.write(trans, "%s/frontend-id" % be_path, str(vm_xid))
|
||||
xs.write(trans, "%s/frontend" % be_path, fe_path)
|
||||
|
||||
# Write USB Spec version field.
|
||||
xs.write(trans, "%s/usb-ver" % be_path, usb_ver)
|
||||
|
||||
# Write virtual root hub field.
|
||||
xs.write(trans, "%s/num-ports" % be_path, str(num_ports))
|
||||
for port in range(1, num_ports+1):
|
||||
# Set all port to disconnected state
|
||||
xs.write(trans, "%s/port/%d" % (be_path, port), "")
|
||||
|
||||
# Set state to XenbusStateInitialising
|
||||
xs.write(trans, "%s/state" % fe_path, "1")
|
||||
xs.write(trans, "%s/state" % be_path, "1")
|
||||
xs.write(trans, "%s/online" % be_path, "1")
|
||||
|
||||
xs.transaction_end(trans)
|
||||
|
||||
def usb_decode_device_from_xs(xs_encoded_device):
|
||||
""" recover actual device name (xenstore doesn't allow dot in key names, so it was translated to underscore) """
|
||||
return xs_encoded_device.replace('_', '.')
|
||||
|
||||
def usb_encode_device_for_xs(device):
|
||||
""" encode actual device name (xenstore doesn't allow dot in key names, so translated it into underscore) """
|
||||
return device.replace('.', '_')
|
||||
|
||||
def usb_list():
|
||||
"""
|
||||
Returns a dictionary of USB devices (for PVUSB backends running in all VM).
|
||||
The dictionary is keyed by 'name' (see below), each element is a dictionary itself:
|
||||
vm = name of the backend domain
|
||||
xid = xid of the backend domain
|
||||
device = <frontend device number>-<frontend port number>
|
||||
name = <name of backend domain>:<frontend device number>-<frontend port number>
|
||||
desc = description
|
||||
"""
|
||||
# FIXME: any better idea of desc_re?
|
||||
desc_re = re.compile(r"^.{1,255}$")
|
||||
|
||||
devices_list = {}
|
||||
|
||||
xs_trans = xs.transaction_start()
|
||||
vm_list = xs.ls(xs_trans, '/local/domain')
|
||||
|
||||
for xid in vm_list:
|
||||
vm_name = xs.read(xs_trans, '/local/domain/%s/name' % xid)
|
||||
vm_devices = xs.ls(xs_trans, '/local/domain/%s/qubes-usb-devices' % xid)
|
||||
if vm_devices is None:
|
||||
continue
|
||||
# when listing devices in xenstore we get encoded names
|
||||
for xs_encoded_device in vm_devices:
|
||||
# Sanitize device id
|
||||
if not usb_device_re.match(xs_encoded_device):
|
||||
print >> sys.stderr, "Invalid device id in backend VM '%s'" % vm_name
|
||||
continue
|
||||
device = usb_decode_device_from_xs(xs_encoded_device)
|
||||
device_desc = xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/desc' % (xid, xs_encoded_device))
|
||||
if not desc_re.match(device_desc):
|
||||
print >> sys.stderr, "Invalid %s device desc in VM '%s'" % (device, vm_name)
|
||||
continue
|
||||
visible_name = "%s:%s" % (vm_name, device)
|
||||
# grab version
|
||||
usb_ver = xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/usb-ver' % (xid, xs_encoded_device))
|
||||
if usb_ver is None or not usb_ver_re.match(usb_ver):
|
||||
print >> sys.stderr, "Invalid %s device USB version in VM '%s'" % (device, vm_name)
|
||||
continue
|
||||
devices_list[visible_name] = {"name": visible_name, "xid":int(xid),
|
||||
"vm": vm_name, "device":device,
|
||||
"desc":device_desc,
|
||||
"usb_ver":usb_ver}
|
||||
|
||||
xs.transaction_end(xs_trans)
|
||||
return devices_list
|
||||
|
||||
def usb_check_attached(xs_trans, backend_vm, device):
|
||||
"""
|
||||
Checks if the given device in the given backend attached to any frontend.
|
||||
Parameters:
|
||||
backend_vm - xid of the backend domain
|
||||
device - device name in the backend domain
|
||||
Returns None or a dictionary:
|
||||
vm - the name of the frontend domain
|
||||
xid - xid of the frontend domain
|
||||
frontend - frontend device number FIXME
|
||||
devid - frontend port number FIXME
|
||||
"""
|
||||
# sample xs content: /local/domain/0/backend/vusb/4/0/port/1 = "7-5"
|
||||
attached_dev = None
|
||||
vms = xs.ls(xs_trans, '/local/domain/%d/backend/vusb' % backend_vm)
|
||||
if vms is None:
|
||||
return None
|
||||
for vm in vms:
|
||||
if not vm.isdigit():
|
||||
print >> sys.stderr, "Invalid VM id"
|
||||
continue
|
||||
frontend_devs = xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%s' % (backend_vm, vm))
|
||||
if frontend_devs is None:
|
||||
continue
|
||||
for frontend_dev in frontend_devs:
|
||||
if not frontend_dev.isdigit():
|
||||
print >> sys.stderr, "Invalid frontend in VM %s" % vm
|
||||
continue
|
||||
ports = xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%s/%s/port' % (backend_vm, vm, frontend_dev))
|
||||
if ports is None:
|
||||
continue
|
||||
for port in ports:
|
||||
# FIXME: refactor, see similar loop in usb_find_unused_frontend(), use usb_list() instead?
|
||||
if not port.isdigit():
|
||||
print >> sys.stderr, "Invalid port in VM %s frontend %s" % (vm, frontend)
|
||||
continue
|
||||
dev = xs.read(xs_trans, '/local/domain/%d/backend/vusb/%s/%s/port/%s' % (backend_vm, vm, frontend_dev, port))
|
||||
if dev == "":
|
||||
continue
|
||||
# Sanitize device id
|
||||
if not usb_port_re.match(dev):
|
||||
print >> sys.stderr, "Invalid device id in backend VM %d @ %s/%s/port/%s" % \
|
||||
(backend_vm, vm, frontend_dev, port)
|
||||
continue
|
||||
if dev == device:
|
||||
frontend = "%s-%s" % (frontend_dev, port)
|
||||
vm_name = xl_ctx.domid_to_name(int(vm))
|
||||
if vm_name is None:
|
||||
# FIXME: should we wipe references to frontends running on nonexistent VMs?
|
||||
continue
|
||||
attached_dev = {"xid":int(vm), "frontend": frontend, "devid": device, "vm": vm_name}
|
||||
break
|
||||
return attached_dev
|
||||
|
||||
#def usb_check_frontend_busy(vm, front_dev, port):
|
||||
# devport = frontend.split("-")
|
||||
# if len(devport) != 2:
|
||||
# raise QubesException("Malformed frontend syntax, must be in device-port format")
|
||||
# # FIXME:
|
||||
# # return xs.read('', '/local/domain/%d/device/vusb/%d/state' % (vm.xid, frontend)) == '4'
|
||||
# return False
|
||||
|
||||
def usb_find_unused_frontend(xs_trans, backend_vm_xid, vm_xid, usb_ver):
|
||||
"""
|
||||
Find an unused frontend/port to link the given backend with the given frontend.
|
||||
Creates new frontend if needed.
|
||||
Returns frontend specification in <device>-<port> format.
|
||||
"""
|
||||
|
||||
# This variable holds an index of last frontend scanned by the loop below.
|
||||
# If nothing found, this value will be used to derive the index of a new frontend.
|
||||
last_frontend_dev = -1
|
||||
|
||||
frontend_devs = xs.ls(xs_trans, "/local/domain/%d/device/vusb" % vm_xid)
|
||||
if frontend_devs is not None:
|
||||
for frontend_dev in frontend_devs:
|
||||
if not frontend_dev.isdigit():
|
||||
print >> sys.stderr, "Invalid frontend_dev in VM %d" % vm_xid
|
||||
continue
|
||||
frontend_dev = int(frontend_dev)
|
||||
fe_path = "/local/domain/%d/device/vusb/%d" % (vm_xid, frontend_dev)
|
||||
if xs.read(xs_trans, "%s/backend-id" % fe_path) == str(backend_vm_xid):
|
||||
if xs.read(xs_trans, '/local/domain/%d/backend/vusb/%d/%d/usb-ver' % (backend_vm_xid, vm_xid, frontend_dev)) != usb_ver:
|
||||
last_frontend_dev = frontend_dev
|
||||
continue
|
||||
# here: found an existing frontend already connected to right backend using an appropriate USB version
|
||||
ports = xs.ls(xs_trans, '/local/domain/%d/backend/vusb/%d/%d/port' % (backend_vm_xid, vm_xid, frontend_dev))
|
||||
if ports is None:
|
||||
print >> sys.stderr, "No ports in VM %d frontend_dev %d?" % (vm_xid, frontend_dev)
|
||||
last_frontend_dev = frontend_dev
|
||||
continue
|
||||
for port in ports:
|
||||
# FIXME: refactor, see similar loop in usb_check_attached(), use usb_list() instead?
|
||||
if not port.isdigit():
|
||||
print >> sys.stderr, "Invalid port in VM %d frontend_dev %d" % (vm_xid, frontend_dev)
|
||||
continue
|
||||
port = int(port)
|
||||
dev = xs.read(xs_trans, '/local/domain/%d/backend/vusb/%s/%s/port/%s' % (backend_vm, vm, frontend_dev, port))
|
||||
# Sanitize device id
|
||||
if not usb_port_re.match(dev):
|
||||
print >> sys.stderr, "Invalid device id in backend VM %d @ %d/%d/port/%d" % \
|
||||
(backend_vm_xid, vm_xid, frontend_dev, port)
|
||||
continue
|
||||
if dev == "":
|
||||
return '%d-%d' % (frontend_dev, port)
|
||||
last_frontend_dev = frontend_dev
|
||||
|
||||
# create a new frontend_dev and link it to the backend
|
||||
frontend_dev = last_frontend_dev + 1
|
||||
usb_setup(backend_vm_xid, vm_xid, frontend_dev, usb_ver)
|
||||
return '%d-%d' % (frontend_dev, 1)
|
||||
|
||||
def usb_attach(vm, backend_vm, device, frontend=None, auto_detach=False, wait=True):
|
||||
device_attach_check(vm, backend_vm, device, frontend)
|
||||
|
||||
xs_trans = xs.transaction_start()
|
||||
|
||||
xs_encoded_device = usb_encode_device_for_xs(device)
|
||||
usb_ver = xs.read(xs_trans, '/local/domain/%s/qubes-usb-devices/%s/usb-ver' % (backend_vm.xid, xs_encoded_device))
|
||||
if usb_ver is None or not usb_ver_re.match(usb_ver):
|
||||
xs.transaction_end(xs_trans)
|
||||
raise QubesException("Invalid %s device USB version in VM '%s'" % (device, backend_vm.name))
|
||||
|
||||
if frontend is None:
|
||||
frontend = usb_find_unused_frontend(xs_trans, backend_vm.xid, vm.xid, usb_ver)
|
||||
else:
|
||||
# Check if any device attached at this frontend
|
||||
#if usb_check_frontend_busy(vm, frontend):
|
||||
# raise QubesException("Frontend %s busy in VM %s, detach it first" % (frontend, vm.name))
|
||||
xs.transaction_end(xs_trans)
|
||||
raise NotImplementedError("Explicit USB frontend specification is not implemented yet")
|
||||
|
||||
# Check if this device is attached to some domain
|
||||
attached_vm = usb_check_attached(xs_trans, backend_vm.xid, device)
|
||||
xs.transaction_end(xs_trans)
|
||||
|
||||
if attached_vm:
|
||||
if auto_detach:
|
||||
usb_detach(backend_vm, attached_vm)
|
||||
else:
|
||||
raise QubesException("Device %s from %s already connected to VM %s as %s" % (device, backend_vm.name, attached_vm['vm'], attached_vm['frontend']))
|
||||
|
||||
# Run helper script
|
||||
xl_cmd = [ '/usr/lib/qubes/xl-qvm-usb-attach.py', str(vm.xid), device, frontend, str(backend_vm.xid) ]
|
||||
subprocess.check_call(xl_cmd)
|
||||
|
||||
def usb_detach(backend_vm, attachment):
|
||||
xl_cmd = [ '/usr/lib/qubes/xl-qvm-usb-detach.py', str(attachment['xid']), attachment['devid'], attachment['frontend'], str(backend_vm.xid) ]
|
||||
subprocess.check_call(xl_cmd)
|
||||
|
||||
def usb_detach_all(vm):
|
||||
raise NotImplementedError("Detaching all devices from a given VM is not implemented yet")
|
||||
|
||||
####### QubesWatch ######
|
||||
|
||||
def only_in_first_list(l1, l2):
|
||||
|
157
dom0/qvm-tools/qvm-usb
Executable file
157
dom0/qvm-tools/qvm-usb
Executable file
@ -0,0 +1,157 @@
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Marek Marczykowski <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVmCollection, QubesException
|
||||
from qubes.qubesutils import usb_list,usb_attach,usb_detach,usb_detach_all,usb_check_attached
|
||||
from optparse import OptionParser
|
||||
import sys
|
||||
import os
|
||||
|
||||
pvusb_enable_flagfile = '/var/lib/qubes/pvusb-enable.flag'
|
||||
|
||||
def main():
|
||||
usage = "usage: %prog -l [options]\n"\
|
||||
"usage: %prog -a [options] <vm-name> <device-vm-name>:<device>\n"\
|
||||
"usage: %prog -d [options] <device-vm-name>:<device>\n"\
|
||||
"List/set VM USB devices."
|
||||
# "usage: %prog -d [options] <vm-name>\n"\
|
||||
|
||||
parser = OptionParser (usage)
|
||||
parser.add_option ("-l", "--list", action="store_true", dest="do_list", default=False)
|
||||
parser.add_option ("-a", "--attach", action="store_true", dest="do_attach", default=False)
|
||||
parser.add_option ("-d", "--detach", action="store_true", dest="do_detach", default=False)
|
||||
# parser.add_option ("-f", "--frontend", dest="frontend",
|
||||
# help="Specify device id at destination VM [default: first unused]")
|
||||
parser.add_option ("--no-auto-detach", dest="auto_detach", action="store_false", default=True,
|
||||
help="Fail when device already connected to other VM")
|
||||
parser.add_option ("--force-root", action="store_true", dest="force_root", default=False,
|
||||
help="Force to run, even with root privileges")
|
||||
|
||||
(options, args) = parser.parse_args ()
|
||||
|
||||
if not os.path.exists(pvusb_enable_flagfile):
|
||||
print >> sys.stderr, ""
|
||||
print >> sys.stderr, "******* WARNING *** WARNING *** WARNING *** WARNING *******"
|
||||
print >> sys.stderr, "*** ***"
|
||||
print >> sys.stderr, "*** PVUSB passthrough kernel support is still unstable. ***"
|
||||
print >> sys.stderr, "*** It can CRASH your VMs. ***"
|
||||
print >> sys.stderr, "*** ***"
|
||||
print >> sys.stderr, "***********************************************************"
|
||||
print >> sys.stderr, ""
|
||||
print >> sys.stderr, "To use it, you need install kernel from \"unstable\" repository"
|
||||
print >> sys.stderr, "If you still want to enable it, type capital YES"
|
||||
print >> sys.stderr, ""
|
||||
prompt = raw_input ("Do you want enable PV USB support? ")
|
||||
if prompt == "YES":
|
||||
open(pvusb_enable_flagfile, "w").close()
|
||||
else:
|
||||
exit(1)
|
||||
|
||||
if os.geteuid() == 0:
|
||||
if not options.force_root:
|
||||
print >> sys.stderr, "*** Running this tool as root is strongly discouraged, this will lead you in permissions problems."
|
||||
print >> sys.stderr, "Retry as unprivileged user."
|
||||
print >> sys.stderr, "... or use --force-root to continue anyway."
|
||||
exit(1)
|
||||
|
||||
if options.do_list + options.do_attach + options.do_detach > 1:
|
||||
print >> sys.stderr, "Only one of -l -a -d is allowed!"
|
||||
exit (1)
|
||||
|
||||
if options.do_attach or options.do_detach:
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
if options.do_attach:
|
||||
if (len (args) != 2):
|
||||
parser.error ("You must provide vm name and device!")
|
||||
vm = qvm_collection.get_vm_by_name(args[0])
|
||||
if vm is None:
|
||||
parser.error ("Invalid VM name: %s" % args[0])
|
||||
|
||||
# FIXME: here we assume that device is always in form "domain:dev", which can be changed in the future
|
||||
if args[1].find(":") < 0:
|
||||
parser.error ("Invalid device syntax: %s" % args[1])
|
||||
dev_list = usb_list()
|
||||
if not args[1] in dev_list.keys():
|
||||
parser.error ("Invalid device name: %s" % args[1])
|
||||
dev = dev_list[args[1]]
|
||||
backend_vm = qvm_collection.get_vm_by_name(dev['vm'])
|
||||
assert backend_vm is not None
|
||||
|
||||
kwargs = {}
|
||||
# if options.frontend:
|
||||
# kwargs['frontend'] = options.frontend
|
||||
kwargs['auto_detach'] = options.auto_detach
|
||||
try:
|
||||
usb_attach(vm, backend_vm, dev['device'], **kwargs)
|
||||
except QubesException as e:
|
||||
print >> sys.stderr, "ERROR: %s" % str(e)
|
||||
sys.exit(1)
|
||||
elif options.do_detach:
|
||||
if (len (args) < 1):
|
||||
parser.error ("You must provide device or vm name!")
|
||||
if len(args) > 1:
|
||||
parser.error ("Too many parameters")
|
||||
# Check if provided name is VM
|
||||
vm = qvm_collection.get_vm_by_name(args[0])
|
||||
if vm is not None:
|
||||
#kwargs = {}
|
||||
#if options.frontend:
|
||||
# kwargs['frontend'] = options.frontend
|
||||
# usb_detach(vm, **kwargs)
|
||||
#else:
|
||||
usb_detach_all(vm)
|
||||
else:
|
||||
# Maybe usbvm:device?
|
||||
|
||||
# FIXME: nasty copy-paste from attach code half a page above
|
||||
# FIXME: here we assume that device is always in form "domain:dev", which can be changed in the future
|
||||
if args[0].find(":") < 0:
|
||||
parser.error ("Invalid device syntax: %s" % args[0])
|
||||
dev_list = usb_list()
|
||||
if not args[0] in dev_list.keys():
|
||||
parser.error ("Invalid device name: %s" % args[0])
|
||||
dev = dev_list[args[0]]
|
||||
backend_vm = qvm_collection.get_vm_by_name(dev['vm'])
|
||||
assert backend_vm is not None
|
||||
|
||||
attached_to = usb_check_attached('', backend_vm.xid, dev['device'])
|
||||
if attached_to is None:
|
||||
print >> sys.stderr, "WARNING: Device not connected to any VM"
|
||||
exit(0)
|
||||
usb_detach(backend_vm, attached_to)
|
||||
else:
|
||||
if len(args) > 0:
|
||||
parser.error ("Too many parameters")
|
||||
# do_list
|
||||
for dev in usb_list().values():
|
||||
attached_to = usb_check_attached('', dev['xid'], dev['device'])
|
||||
attached_to_str = ""
|
||||
if attached_to:
|
||||
attached_to_str = " (attached to %s:%s)" % (attached_to['vm'], attached_to['frontend'])
|
||||
print "%s\t%s%s (USBv%s)" % (dev['name'], dev['desc'], attached_to_str, dev['usb_ver'])
|
||||
exit (0)
|
||||
|
||||
main()
|
@ -1,2 +1,3 @@
|
||||
modprobe evtchn 2>/dev/null || modprobe xen-evtchn
|
||||
modprobe xen-blkback 2> /dev/null || modprobe blkbk
|
||||
modprobe xen-usbfront 2> /dev/null
|
||||
|
10
misc/qubes_usb.rules
Normal file
10
misc/qubes_usb.rules
Normal file
@ -0,0 +1,10 @@
|
||||
# Expose all USB devices (except block) via xenstore
|
||||
|
||||
# Handle only USB devices
|
||||
SUBSYSTEM!="usb", GOTO="qubes_usb_end"
|
||||
|
||||
ACTION=="add", IMPORT{program}="/usr/lib/qubes/usb_add_change"
|
||||
ACTION=="change", IMPORT{program}="/usr/lib/qubes/usb_add_change"
|
||||
ACTION=="remove", RUN+="/usr/lib/qubes/usb_remove"
|
||||
|
||||
LABEL="qubes_usb_end"
|
40
misc/usb_add_change
Executable file
40
misc/usb_add_change
Executable file
@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
##
|
||||
## This script is invoked by udev rules whenever USB device appears or
|
||||
## changes. This happens in usbvm domain (or dom0 if USB controller
|
||||
## drivers are in dom0). The script records information about available
|
||||
## USB devices into XS directory, making it available to qvm-usb tool
|
||||
## running in dom0.
|
||||
##
|
||||
|
||||
# FIXME: Ignore USB hubs and other wierd devices (see also in usb_remove).
|
||||
[ "`echo $TYPE | cut -f1 -d/`" = "9" ] && exit 0
|
||||
[ "$DEVTYPE" != "usb_device" ] && exit 0
|
||||
|
||||
# xenstore doesn't allow dot in key name
|
||||
XSNAME=`basename ${DEVPATH} | tr . _`
|
||||
|
||||
# FIXME: For some devices (my Cherry keyboard) ID_SERIAL does not
|
||||
# contain proper human-readable name, should find better method to
|
||||
# build devide description.
|
||||
#DESC=`python -c "dev='%d-%d' % (int('${BUSNUM}'.lstrip('0')), (int('${DEVNUM}'.lstrip('0'))-1)); from xen.util import vusb_util; print vusb_util.get_usbdevice_info(dev);"`
|
||||
DESC="${ID_VENDOR_ID}:${ID_MODEL_ID} ${ID_SERIAL}"
|
||||
|
||||
VERSION=`cat /sys/$DEVPATH/version`
|
||||
if [ "${VERSION}" = " 1.00" -o "${VERSION}" = " 1.10" ] ; then
|
||||
VERSION=1
|
||||
elif [ "${VERSION}" = " 2.00" ] ; then
|
||||
VERSION=2
|
||||
else
|
||||
# FIXME: silently ignoring devices with unexpected USB version
|
||||
exit 0
|
||||
fi
|
||||
|
||||
XS_KEY="qubes-usb-devices/$XSNAME"
|
||||
|
||||
xenstore-write "$XS_KEY/desc" "$DESC"
|
||||
xenstore-write "$XS_KEY/usb-ver" "$VERSION"
|
||||
|
||||
# Make sure PVUSB backend driver is loaded.
|
||||
/sbin/modprobe xen-usbback 2> /dev/null || /sbin/modprobe usbbk
|
9
misc/usb_remove
Executable file
9
misc/usb_remove
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# FIXME: Ignore USB hubs.
|
||||
[ "`echo $TYPE | cut -f1 -d/`" = "9" ] && exit 0
|
||||
|
||||
NAME=`basename ${DEVPATH} | tr . _`
|
||||
XS_KEY="qubes-usb-devices/$NAME"
|
||||
|
||||
xenstore-rm "$XS_KEY"
|
24
misc/vusb-ctl.py
Executable file
24
misc/vusb-ctl.py
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
##
|
||||
## Python script wrapper around xen.util.vusb_util bind_usb_device() and unbind_usb_device() methods
|
||||
## Run as root in usbvm
|
||||
##
|
||||
|
||||
from xen.util import vusb_util
|
||||
import sys
|
||||
import os
|
||||
|
||||
if len(sys.argv)!=3:
|
||||
print 'usage: vusb-ctl <bind|unbind> device'
|
||||
sys.exit(1)
|
||||
|
||||
device=sys.argv[2]
|
||||
if sys.argv[1] == 'bind':
|
||||
vusb_util.bind_usb_device(device)
|
||||
elif sys.argv[1] == 'unbind':
|
||||
vusb_util.unbind_usb_device(device)
|
||||
else:
|
||||
print "Invalid command, must be 'bind' or 'unbind'"
|
||||
sys.exit(1)
|
||||
|
48
misc/xl-qvm-usb-attach.py
Executable file
48
misc/xl-qvm-usb-attach.py
Executable file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
##
|
||||
## This script is for dom0
|
||||
## The syntax is modelled after "xl block-attach"
|
||||
##
|
||||
|
||||
import sys
|
||||
import os
|
||||
import xen.lowlevel.xl
|
||||
|
||||
|
||||
# parse command line
|
||||
if (len(sys.argv)<4) or (len(sys.argv)>5):
|
||||
print 'usage: xl-qvm-usb-attach.py <frontendvm-xid> <backendvm-device> <frontendvm-device> [<backendvm-xid>]'
|
||||
sys.exit(1)
|
||||
|
||||
frontendvm_xid=sys.argv[1]
|
||||
backendvm_device=sys.argv[2]
|
||||
|
||||
frontend=sys.argv[3].split('-')
|
||||
if len(frontend)!=2:
|
||||
print 'Error: frontendvm-device must be in <controller>-<port> format'
|
||||
sys.exit(1)
|
||||
(controller, port)=frontend
|
||||
|
||||
if len(sys.argv)>4:
|
||||
backendvm_xid=int(sys.argv[4])
|
||||
backendvm_name=xen.lowlevel.xl.ctx().domid_to_name(backendvm_xid)
|
||||
else:
|
||||
backendvm_xid=0
|
||||
|
||||
# FIXME: command injection
|
||||
os.system("xenstore-write /local/domain/%s/backend/vusb/%s/%s/port/%s '%s'"
|
||||
% (backendvm_xid, frontendvm_xid, controller, port, backendvm_device))
|
||||
|
||||
cmd = "/usr/lib/qubes/vusb-ctl.py bind '%s'" % backendvm_device
|
||||
if backendvm_xid == 0:
|
||||
os.system("sudo %s" % cmd)
|
||||
else:
|
||||
from qubes.qubes import QubesVmCollection
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
# launch
|
||||
qvm_collection.get_vm_by_name(backendvm_name).run("root: %s" % cmd)
|
49
misc/xl-qvm-usb-detach.py
Executable file
49
misc/xl-qvm-usb-detach.py
Executable file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
##
|
||||
## This script is for dom0
|
||||
## The syntax is modelled after "xl block-attach"
|
||||
## FIXME: should be modelled after block-detach instead
|
||||
##
|
||||
|
||||
import sys
|
||||
import os
|
||||
import xen.lowlevel.xl
|
||||
|
||||
# parse command line
|
||||
if (len(sys.argv)<4) or (len(sys.argv)>5):
|
||||
print 'usage: xl-qvm-usb-detach.py <frontendvm-xid> <backendvm-device> <frontendvm-device> [<backendvm-xid>]'
|
||||
sys.exit(1)
|
||||
|
||||
frontendvm_xid=sys.argv[1]
|
||||
backendvm_device=sys.argv[2]
|
||||
|
||||
frontend=sys.argv[3].split('-')
|
||||
if len(frontend)!=2:
|
||||
print 'Error: frontendvm-device must be in <controller>-<port> format'
|
||||
sys.exit(1)
|
||||
(controller, port)=frontend
|
||||
|
||||
if len(sys.argv)>4:
|
||||
backendvm_xid=int(sys.argv[4])
|
||||
backendvm_name=xen.lowlevel.xl.ctx().domid_to_name(backendvm_xid)
|
||||
else:
|
||||
backendvm_xid=0
|
||||
|
||||
cmd = "/usr/lib/qubes/vusb-ctl.py unbind '%s'" % backendvm_device
|
||||
if backendvm_xid == 0:
|
||||
os.system("sudo %s" % cmd)
|
||||
else:
|
||||
from qubes.qubes import QubesVmCollection
|
||||
qvm_collection = QubesVmCollection()
|
||||
qvm_collection.lock_db_for_reading()
|
||||
qvm_collection.load()
|
||||
qvm_collection.unlock_db()
|
||||
|
||||
# launch
|
||||
qvm_collection.get_vm_by_name(backendvm_name).run("root: %s" % cmd)
|
||||
|
||||
# FIXME: command injection
|
||||
os.system("xenstore-write /local/domain/%s/backend/vusb/%s/%s/port/%s ''"
|
||||
% (backendvm_xid, frontendvm_xid, controller, port))
|
||||
|
@ -56,9 +56,10 @@ python -O -m compileall qvm-core qmemman
|
||||
make -C restore
|
||||
make -C qubes_rpc
|
||||
make -C ../qubes_rpc
|
||||
make -C ../vchan -f Makefile.linux
|
||||
make -C ../u2mfn
|
||||
make -C ../vchan -f Makefile.linux
|
||||
make -C ../qrexec
|
||||
make -C ../misc
|
||||
|
||||
%install
|
||||
|
||||
@ -80,6 +81,7 @@ ln -s block-snapshot $RPM_BUILD_ROOT/etc/xen/scripts/block-origin
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d
|
||||
cp ../misc/qubes_block.rules $RPM_BUILD_ROOT/etc/udev/rules.d/99-qubes_block.rules
|
||||
cp ../misc/qubes_usb.rules $RPM_BUILD_ROOT/etc/udev/rules.d/99-qubes_usb.rules
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT%{python_sitearch}/qubes
|
||||
cp qvm-core/qubes.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
|
||||
@ -117,6 +119,11 @@ cp qubes_rpc/qubes-receive-updates $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../misc/block_add_change $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../misc/block_remove $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../misc/block_cleanup $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../misc/usb_add_change $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../misc/usb_remove $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../misc/vusb-ctl.py $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../misc/xl-qvm-usb-attach.py $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp ../misc/xl-qvm-usb-detach.py $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp aux-tools/block_cleaner_daemon.py $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
cp aux-tools/fix_dir_perms.sh $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
|
||||
@ -168,6 +175,7 @@ cp misc/qubes-appmenu-select.desktop $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
cp misc/qubes-start.desktop $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
cp misc/vm-template.conf $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
cp misc/vm-template-hvm.conf $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
cp misc/Fedora-13-comps.xml $RPM_BUILD_ROOT/usr/share/qubes/
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
cp ../network/qubes_setup_dnat_to_ns $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
@ -367,16 +375,21 @@ fi
|
||||
/usr/lib/qubes/block_remove
|
||||
/usr/lib/qubes/block_cleanup
|
||||
/usr/lib/qubes/block_cleaner_daemon.py*
|
||||
/usr/lib/qubes/usb_add_change
|
||||
/usr/lib/qubes/usb_remove
|
||||
/usr/lib/qubes/vusb-ctl.py*
|
||||
/usr/lib/qubes/xl-qvm-usb-attach.py*
|
||||
/usr/lib/qubes/xl-qvm-usb-detach.py*
|
||||
/usr/lib/qubes/fix_dir_perms.sh
|
||||
%attr(4750,root,qubes) /usr/lib/qubes/qfile-dom0-unpacker
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/vm-templates
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/appvms
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/servicevms
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/backup
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/dvmdata
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/updates
|
||||
%attr(770,root,qubes) %dir /var/lib/qubes/vm-kernels
|
||||
%attr(0770,root,qubes) %dir /var/lib/qubes
|
||||
%attr(0770,root,qubes) %dir /var/lib/qubes/vm-templates
|
||||
%attr(0770,root,qubes) %dir /var/lib/qubes/appvms
|
||||
%attr(0770,root,qubes) %dir /var/lib/qubes/servicevms
|
||||
%attr(0770,root,qubes) %dir /var/lib/qubes/backup
|
||||
%attr(0770,root,qubes) %dir /var/lib/qubes/dvmdata
|
||||
%attr(0770,root,qubes) %dir /var/lib/qubes/updates
|
||||
%attr(0770,root,qubes) %dir /var/lib/qubes/vm-kernels
|
||||
/usr/share/qubes/icons/*.png
|
||||
/usr/share/qubes/qubes-vm.directory.template
|
||||
/usr/share/qubes/qubes-templatevm.directory.template
|
||||
@ -387,6 +400,7 @@ fi
|
||||
/usr/share/qubes/qubes-start.desktop
|
||||
/usr/share/qubes/vm-template.conf
|
||||
/usr/share/qubes/vm-template-hvm.conf
|
||||
/usr/share/qubes/Fedora-13-comps.xml
|
||||
/usr/lib/qubes/qubes_setup_dnat_to_ns
|
||||
/usr/lib/qubes/qubes_fix_nm_conf.sh
|
||||
/etc/dhclient.d/qubes_setup_dnat_to_ns.sh
|
||||
@ -421,7 +435,7 @@ fi
|
||||
/etc/qubes_rpc/qubes.ReceiveUpdates
|
||||
%attr(4750,root,qubes) /usr/lib/qubes/qrexec_daemon
|
||||
%attr(2770,root,qubes) %dir /var/log/qubes
|
||||
%attr(770,root,qubes) %dir /var/run/qubes
|
||||
%attr(0770,root,qubes) %dir /var/run/qubes
|
||||
%{_libdir}/libvchan.so
|
||||
%{_libdir}/libu2mfn.so
|
||||
/etc/yum.real.repos.d/qubes-cached.repo
|
||||
@ -429,8 +443,9 @@ fi
|
||||
/etc/xdg/autostart/qubes-guid.desktop
|
||||
/etc/security/limits.d/99-qubes.conf
|
||||
/etc/udev/rules.d/99-qubes_block.rules
|
||||
/etc/cron.daily/qubes-dom0-updates.cron
|
||||
/etc/cron.d/qubes-sync-clock.cron
|
||||
/etc/udev/rules.d/99-qubes_usb.rules
|
||||
%attr(0644,root,root) /etc/cron.daily/qubes-dom0-updates.cron
|
||||
%attr(0644,root,root) /etc/cron.d/qubes-sync-clock.cron
|
||||
/etc/dracut.conf.d/*
|
||||
%dir /usr/share/dracut/modules.d/90qubes-pciback
|
||||
/usr/share/dracut/modules.d/90qubes-pciback/*
|
||||
|
@ -113,9 +113,12 @@ install -D misc/xenstore-watch $RPM_BUILD_ROOT/usr/bin/xenstore-watch-qubes
|
||||
install -d $RPM_BUILD_ROOT/etc/udev/rules.d
|
||||
install -m 0644 misc/qubes_memory.rules $RPM_BUILD_ROOT/etc/udev/rules.d/50-qubes_memory.rules
|
||||
install -m 0644 misc/qubes_block.rules $RPM_BUILD_ROOT/etc/udev/rules.d/99-qubes_block.rules
|
||||
install -m 0644 misc/qubes_usb.rules $RPM_BUILD_ROOT/etc/udev/rules.d/99-qubes_usb.rules
|
||||
install -d $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
install misc/qubes_download_dom0_updates.sh $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
install misc/{block_add_change,block_remove,block_cleanup} $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
install misc/{usb_add_change,usb_remove} $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
install misc/vusb-ctl.py $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
install misc/qubes_trigger_sync_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||
install -D -m 0644 misc/qubes_trigger_sync_appmenus.action $RPM_BUILD_ROOT/etc/yum/post-actions/qubes_trigger_sync_appmenus.action
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes
|
||||
@ -209,7 +212,7 @@ remove_ShowIn () {
|
||||
for F in abrt-applet deja-dup-monitor imsettings-start krb5-auth-dialog pulseaudio restorecond sealertauto gnome-power-manager gnome-sound-applet gnome-screensaver orca-autostart; do
|
||||
if [ -e /etc/xdg/autostart/$F.desktop ]; then
|
||||
remove_ShowIn $F
|
||||
echo 'NotShowIn=QUBES' >> /etc/xdg/autostart/$F.desktop
|
||||
echo 'NotShowIn=QUBES;' >> /etc/xdg/autostart/$F.desktop
|
||||
fi
|
||||
done
|
||||
|
||||
@ -217,7 +220,7 @@ done
|
||||
for F in gcm-apply ; do
|
||||
if [ -e /etc/xdg/autostart/$F.desktop ]; then
|
||||
remove_ShowIn $F
|
||||
echo 'NotShowIn=DisposableVM' >> /etc/xdg/autostart/$F.desktop
|
||||
echo 'NotShowIn=DisposableVM;' >> /etc/xdg/autostart/$F.desktop
|
||||
fi
|
||||
done
|
||||
|
||||
@ -312,6 +315,10 @@ do
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ $(basename $f) == "99-qubes_usb.rules" ] ; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ $(basename $f) == "90-hal.rules" ] ; then
|
||||
continue
|
||||
fi
|
||||
@ -383,6 +390,7 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/etc/udev/rules.d/50-qubes_memory.rules
|
||||
/etc/udev/rules.d/99-qubes_block.rules
|
||||
/etc/udev/rules.d/99-qubes_network.rules
|
||||
/etc/udev/rules.d/99-qubes_usb.rules
|
||||
/etc/xen/scripts/vif-route-qubes
|
||||
/etc/yum.conf.d/qubes-proxy.conf
|
||||
/etc/yum.repos.d/qubes.repo
|
||||
@ -399,6 +407,9 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/usr/lib/qubes/block_add_change
|
||||
/usr/lib/qubes/block_cleanup
|
||||
/usr/lib/qubes/block_remove
|
||||
/usr/lib/qubes/usb_add_change
|
||||
/usr/lib/qubes/usb_remove
|
||||
/usr/lib/qubes/vusb-ctl.py*
|
||||
/usr/lib/qubes/dispvm-prerun.sh
|
||||
/usr/lib/qubes/sync-ntp-clock
|
||||
/usr/lib/qubes/prepare-suspend
|
||||
|
50
test/block-001-list-attach-use-detach
Executable file
50
test/block-001-list-attach-use-detach
Executable file
@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
|
||||
tmpf=`mktemp`
|
||||
|
||||
## === List
|
||||
echo 'qvm-block -l'
|
||||
qvm-block -l > $tmpf
|
||||
|
||||
cat <<'END' | diff -u - $tmpf
|
||||
netvm:sda STORAGE_DEVICE () 0 B
|
||||
dom0:sdb1 Cruzer () 3 GiB
|
||||
dom0:sdb Cruzer () 3 GiB
|
||||
END
|
||||
|
||||
## === Attach
|
||||
echo 'qvm-block -a'
|
||||
qvm-block -a work dom0:sdb | diff -u /dev/null -
|
||||
|
||||
## === List again
|
||||
echo 'qvm-block -l'
|
||||
qvm-block -l > $tmpf
|
||||
|
||||
cat <<'END' | diff -u - $tmpf
|
||||
netvm:sda STORAGE_DEVICE () 0 B
|
||||
dom0:sdb1 Cruzer () 3 GiB
|
||||
dom0:sdb Cruzer () 3 GiB (attached to 'work' as 'xvdi')
|
||||
END
|
||||
|
||||
## === Use
|
||||
echo 'qvm-run work fdisk'
|
||||
qvm-run -qp work 'su - root -c "fdisk -l /dev/xvdi"' > $tmpf
|
||||
|
||||
cat <<'END' | diff -u - $tmpf
|
||||
|
||||
Disk /dev/xvdi: 4022 MB, 4022337024 bytes
|
||||
124 heads, 62 sectors/track, 1021 cylinders, total 7856127 sectors
|
||||
Units = sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
Disk identifier: 0x3963a77b
|
||||
|
||||
Device Boot Start End Blocks Id System
|
||||
/dev/xvdi1 * 62 7849447 3924693 c W95 FAT32 (LBA)
|
||||
END
|
||||
|
||||
## === Detach
|
||||
echo 'qvm-block -d'
|
||||
qvm-block -d work dom0:sdb1 | diff -u /dev/null -
|
||||
|
||||
rm $tmpf
|
14
test/pvusb-001-mouse-kbd-attached
Executable file
14
test/pvusb-001-mouse-kbd-attached
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
tmpf=`mktemp`
|
||||
|
||||
sudo xenstore-ls -f qubes-usb-devices | sort > $tmpf
|
||||
|
||||
cat << 'END' | diff -u - $tmpf
|
||||
qubes-usb-devices/2-1 = ""
|
||||
qubes-usb-devices/2-1/desc = "046a:0021 046a_0021"
|
||||
qubes-usb-devices/2-2 = ""
|
||||
qubes-usb-devices/2-2/desc = "045e:0745 Microsoft_Microsoft\xc2\xae_Nano_Transceiver_v1.0"
|
||||
END
|
||||
|
||||
rm $tmpf
|
18
test/pvusb-002-mouse-kbd-usbstick-wlan-attached
Executable file
18
test/pvusb-002-mouse-kbd-usbstick-wlan-attached
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
tmpf=`mktemp`
|
||||
|
||||
sudo xenstore-ls -f qubes-usb-devices | sort > $tmpf
|
||||
|
||||
cat << 'END' | diff -u - $tmpf
|
||||
qubes-usb-devices/2-1 = ""
|
||||
qubes-usb-devices/2-1/desc = "046a:0021 046a_0021"
|
||||
qubes-usb-devices/2-2 = ""
|
||||
qubes-usb-devices/2-2/desc = "045e:0745 Microsoft_Microsoft\xc2\xae_Nano_Transceiver_v1.0"
|
||||
qubes-usb-devices/7-1 = ""
|
||||
qubes-usb-devices/7-1/desc = "07d1:3c0a Ralink_11n_Adapter_1.0"
|
||||
qubes-usb-devices/7-5 = ""
|
||||
qubes-usb-devices/7-5/desc = "0781:5530 SanDisk_Cruzer_1942531DB09038A6"
|
||||
END
|
||||
|
||||
rm $tmpf
|
67
test/pvusb-003-list-attach-use-detach
Executable file
67
test/pvusb-003-list-attach-use-detach
Executable file
@ -0,0 +1,67 @@
|
||||
#!/bin/sh
|
||||
|
||||
tmpf=`mktemp`
|
||||
domu='qdvp'
|
||||
|
||||
## === List
|
||||
echo 'qvm-usb -l'
|
||||
qvm-usb -l | sort > $tmpf
|
||||
|
||||
cat <<'END' | diff -bu - $tmpf
|
||||
dom0:2-1 046a:0021 046a_0021
|
||||
dom0:2-2 045e:0745 Microsoft_Microsoft®_Nano_Transceiver_v1.0
|
||||
dom0:7-1 07d1:3c0a Ralink_11n_Adapter_1.0
|
||||
dom0:7-5 0781:5530 SanDisk_Cruzer_1942531DB09038A6
|
||||
END
|
||||
|
||||
## === Attach
|
||||
echo 'qvm-usb -a'
|
||||
qvm-usb -a $domu dom0:7-5 | diff -bu /dev/null -
|
||||
#echo 'pvusb-script/usb-attach.py'
|
||||
#sudo /home/abb/pvusb-scripts/usb-attach.py 7-5 3 1
|
||||
|
||||
## === List again
|
||||
echo 'qvm-usb -l'
|
||||
qvm-usb -l | sort > $tmpf
|
||||
|
||||
# FIXME
|
||||
cat <<'END' | diff -bu - $tmpf
|
||||
dom0:2-1 046a:0021 046a_0021
|
||||
dom0:2-2 045e:0745 Microsoft_Microsoft®_Nano_Transceiver_v1.0
|
||||
dom0:7-1 07d1:3c0a Ralink_11n_Adapter_1.0
|
||||
dom0:7-5 0781:5530 SanDisk_Cruzer_1942531DB09038A6
|
||||
END
|
||||
|
||||
read -p 'Press ENTER to continue'
|
||||
|
||||
## === Use: try ls
|
||||
echo 'qvm-run $domu ls /dev/sda'
|
||||
qvm-run -p $domu 'ls /dev/sda' > $tmpf
|
||||
cat <<'END' | diff -bu - $tmpf
|
||||
/dev/sda
|
||||
END
|
||||
|
||||
## === Use: try fdisk
|
||||
echo 'qvm-run $domu fdisk'
|
||||
qvm-run -p $domu 'su - root -c "fdisk -l /dev/sda"' > $tmpf
|
||||
|
||||
cat <<'END' | diff -bu - $tmpf
|
||||
|
||||
Disk /dev/sda: 4022 MB, 4022337024 bytes
|
||||
124 heads, 62 sectors/track, 1021 cylinders, total 7856127 sectors
|
||||
Units = sectors of 1 * 512 = 512 bytes
|
||||
Sector size (logical/physical): 512 bytes / 512 bytes
|
||||
I/O size (minimum/optimal): 512 bytes / 512 bytes
|
||||
Disk identifier: 0x3963a77b
|
||||
|
||||
Device Boot Start End Blocks Id System
|
||||
/dev/sda1 * 62 7849447 3924693 c W95 FAT32 (LBA)
|
||||
END
|
||||
|
||||
## === Detach
|
||||
#echo 'qvm-usb -d'
|
||||
#qvm-usb -d $domu:7-5 | diff -bu /dev/null -
|
||||
echo 'pvusb-script/usb-detach.py'
|
||||
sudo /home/abb/pvusb-scripts/usb-detach.py 7-5 4 1
|
||||
|
||||
rm $tmpf
|
@ -31,11 +31,24 @@ static int u2mfn_fd = -1;
|
||||
|
||||
static int get_fd()
|
||||
{
|
||||
if (u2mfn_fd == -1) {
|
||||
u2mfn_fd = open("/proc/u2mfn", O_RDWR);
|
||||
if (u2mfn_fd < 0)
|
||||
return -1;
|
||||
}
|
||||
if (u2mfn_fd == -1)
|
||||
u2mfn_fd = u2mfn_get_fd();
|
||||
if (u2mfn_fd < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int u2mfn_get_fd()
|
||||
{
|
||||
return open("/proc/u2mfn", O_RDWR);
|
||||
}
|
||||
|
||||
int u2mfn_get_mfn_for_page_with_fd(int fd, long va, int *mfn)
|
||||
{
|
||||
*mfn = ioctl(fd, U2MFN_GET_MFN_FOR_PAGE, va);
|
||||
if (*mfn == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -43,7 +56,12 @@ int u2mfn_get_mfn_for_page(long va, int *mfn)
|
||||
{
|
||||
if (get_fd())
|
||||
return -1;
|
||||
*mfn = ioctl(u2mfn_fd, U2MFN_GET_MFN_FOR_PAGE, va);
|
||||
return u2mfn_get_mfn_for_page_with_fd(u2mfn_fd, va, mfn);
|
||||
}
|
||||
|
||||
int u2mfn_get_last_mfn_with_fd(int fd, int *mfn)
|
||||
{
|
||||
*mfn = ioctl(fd, U2MFN_GET_LAST_MFN, 0);
|
||||
if (*mfn == -1)
|
||||
return -1;
|
||||
|
||||
@ -54,22 +72,20 @@ int u2mfn_get_last_mfn(int *mfn)
|
||||
{
|
||||
if (get_fd())
|
||||
return -1;
|
||||
|
||||
*mfn = ioctl(u2mfn_fd, U2MFN_GET_LAST_MFN, 0);
|
||||
if (*mfn == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return u2mfn_get_last_mfn_with_fd(u2mfn_fd, mfn);
|
||||
}
|
||||
|
||||
|
||||
char *u2mfn_alloc_kpage_with_fd(int fd)
|
||||
{
|
||||
char *ret;
|
||||
ret =
|
||||
mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *u2mfn_alloc_kpage()
|
||||
{
|
||||
char *ret;
|
||||
if (get_fd())
|
||||
return MAP_FAILED;
|
||||
ret =
|
||||
mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, u2mfn_fd, 0);
|
||||
return ret;
|
||||
return u2mfn_alloc_kpage_with_fd(u2mfn_fd);
|
||||
}
|
||||
|
@ -19,6 +19,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
int u2mfn_get_fd();
|
||||
int u2mfn_get_mfn_for_page(long va, int *mfn) ;
|
||||
int u2mfn_get_mfn_for_page_with_fd(int fd, long va, int *mfn) ;
|
||||
int u2mfn_get_last_mfn(int *mfn) ;
|
||||
char *u2mfn_alloc_kpage(void) ;
|
||||
int u2mfn_get_last_mfn_with_fd(int fd, int *mfn) ;
|
||||
char *u2mfn_alloc_kpage(void);
|
||||
char *u2mfn_alloc_kpage_with_fd(int fd);
|
||||
|
@ -92,6 +92,7 @@ static int ring_init(struct libvchan *ctrl)
|
||||
static int ring_init(struct libvchan *ctrl)
|
||||
{
|
||||
int mfn;
|
||||
int u2mfn_fd;
|
||||
struct vchan_interface *ring;
|
||||
#ifdef CONFIG_STUBDOM
|
||||
ring = (struct vchan_interface *) memalign(XC_PAGE_SIZE, sizeof(*ring));
|
||||
@ -102,12 +103,15 @@ static int ring_init(struct libvchan *ctrl)
|
||||
|
||||
mfn = virtual_to_mfn(ring);
|
||||
#else
|
||||
ring = (struct vchan_interface *) u2mfn_alloc_kpage ();
|
||||
u2mfn_fd = u2mfn_get_fd();
|
||||
if (u2mfn_fd < 0)
|
||||
return -1;
|
||||
ring = (struct vchan_interface *) u2mfn_alloc_kpage_with_fd (u2mfn_fd);
|
||||
|
||||
if (ring == MAP_FAILED)
|
||||
return -1;
|
||||
|
||||
if (u2mfn_get_last_mfn (&mfn) < 0)
|
||||
if (u2mfn_get_last_mfn_with_fd (u2mfn_fd, &mfn) < 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
|
@ -129,7 +129,7 @@ int libvchan_wait(struct libvchan *ctrl)
|
||||
may write less data than requested;
|
||||
returns the amount of data processed, -1 on error or peer close
|
||||
*/
|
||||
int libvchan_write(struct libvchan *ctrl, char *data, int size)
|
||||
int libvchan_write(struct libvchan *ctrl, const char *data, int size)
|
||||
{
|
||||
int avail, avail_contig;
|
||||
int real_idx;
|
||||
|
@ -78,7 +78,7 @@ struct libvchan *libvchan_server_init(int devno);
|
||||
struct libvchan *libvchan_client_init(int domain, int devno);
|
||||
|
||||
int libvchan_server_handle_connected(struct libvchan *ctrl);
|
||||
int libvchan_write(struct libvchan *ctrl, char *data, int size);
|
||||
int libvchan_write(struct libvchan *ctrl, const char *data, int size);
|
||||
int libvchan_read(struct libvchan *ctrl, char *data, int size);
|
||||
int libvchan_wait(struct libvchan *ctrl);
|
||||
int libvchan_close(struct libvchan *ctrl);
|
||||
|
@ -1 +1 @@
|
||||
2.0.36
|
||||
2.1.1
|
||||
|
@ -1 +1 @@
|
||||
1.7.46
|
||||
2.1.1
|
||||
|
@ -17,6 +17,8 @@ start()
|
||||
|
||||
# Set permissions to /proc/xen/xenbus, so normal user can use xenstore-read
|
||||
chmod 666 /proc/xen/xenbus
|
||||
# Set permissions to files needed to listen at vchan
|
||||
chmod 666 /proc/u2mfn /dev/xen/evtchn
|
||||
|
||||
mkdir -p /var/run/xen-hotplug
|
||||
|
||||
|
@ -25,6 +25,8 @@ mkdir -p /var/run/xen-hotplug
|
||||
|
||||
# Set permissions to /proc/xen/xenbus, so normal user can use xenstore-read
|
||||
chmod 666 /proc/xen/xenbus
|
||||
# Set permissions to files needed to listen at vchan
|
||||
chmod 666 /proc/u2mfn /dev/xen/evtchn
|
||||
|
||||
# Set default services depending on VM type
|
||||
TYPE=`$XS_READ qubes_vm_type 2> /dev/null`
|
||||
|
Loading…
Reference in New Issue
Block a user