From dbe96938517798c543803a1f4c8565b79354da85 Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Sat, 16 Mar 2013 19:52:16 +0100 Subject: [PATCH] Other Linux-specific files --- .gitignore | 1 + .../luks-aesni-missing-drivers.conf | 4 ++ dracut/dracut.conf.d/qubes-pciback.conf | 5 ++ dracut/modules.d/90qubes-pciback/install | 5 ++ .../modules.d/90qubes-pciback/installkernel | 3 + .../modules.d/90qubes-pciback/module-setup.sh | 13 ++++ .../90qubes-pciback/qubes-pciback.sh | 8 +++ pm-utils/01qubes-sync-vms-clock | 24 +++++++ pm-utils/51qubes-suspend-netvm | 39 +++++++++++ pm-utils/52qubes-pause-vms | 23 +++++++ rpm_spec/core-dom0-linux.spec | 68 +++++++++++++++++++ system-config/cpufreq-xen.modules | 12 ++++ system-config/ip6tables | 8 +++ system-config/iptables | 30 ++++++++ system-config/limits-qubes.conf | 3 + system-config/polkit-1-qubes-allow-all.rules | 2 + system-config/qubes-dom0.modules | 1 + system-config/qubes-sync-clock.cron | 1 + system-config/qubes.sudoers | 31 +++++++++ udev/udev-block-add-change | 61 +++++++++++++++++ udev/udev-block-cleanup | 8 +++ udev/udev-block-remove | 32 +++++++++ udev/udev-qubes-block.rules | 20 ++++++ udev/udev-qubes-usb.rules | 10 +++ udev/udev-usb-add-change | 40 +++++++++++ udev/udev-usb-remove | 9 +++ 26 files changed, 461 insertions(+) create mode 100644 .gitignore create mode 100644 dracut/dracut.conf.d/luks-aesni-missing-drivers.conf create mode 100644 dracut/dracut.conf.d/qubes-pciback.conf create mode 100755 dracut/modules.d/90qubes-pciback/install create mode 100755 dracut/modules.d/90qubes-pciback/installkernel create mode 100755 dracut/modules.d/90qubes-pciback/module-setup.sh create mode 100755 dracut/modules.d/90qubes-pciback/qubes-pciback.sh create mode 100755 pm-utils/01qubes-sync-vms-clock create mode 100755 pm-utils/51qubes-suspend-netvm create mode 100755 pm-utils/52qubes-pause-vms create mode 100755 system-config/cpufreq-xen.modules create mode 100644 system-config/ip6tables create mode 100644 system-config/iptables create mode 100644 system-config/limits-qubes.conf create mode 100644 system-config/polkit-1-qubes-allow-all.rules create mode 100755 system-config/qubes-dom0.modules create mode 100755 system-config/qubes-sync-clock.cron create mode 100644 system-config/qubes.sudoers create mode 100755 udev/udev-block-add-change create mode 100755 udev/udev-block-cleanup create mode 100755 udev/udev-block-remove create mode 100644 udev/udev-qubes-block.rules create mode 100644 udev/udev-qubes-usb.rules create mode 100755 udev/udev-usb-add-change create mode 100755 udev/udev-usb-remove diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c1f1f79 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +rpm/ diff --git a/dracut/dracut.conf.d/luks-aesni-missing-drivers.conf b/dracut/dracut.conf.d/luks-aesni-missing-drivers.conf new file mode 100644 index 0000000..6cb4ab8 --- /dev/null +++ b/dracut/dracut.conf.d/luks-aesni-missing-drivers.conf @@ -0,0 +1,4 @@ +# Apprently some of the drivers required when using a processor with AESNI for LUKS +# are missing in the initramfs, so lets include them manually here: + +add_drivers+=" xts aesni-intel aes-x86_64 crc32c-intel fpu ghash-clmulni-intel salsa20-x86_64 twofish-x86_64 " diff --git a/dracut/dracut.conf.d/qubes-pciback.conf b/dracut/dracut.conf.d/qubes-pciback.conf new file mode 100644 index 0000000..f96604b --- /dev/null +++ b/dracut/dracut.conf.d/qubes-pciback.conf @@ -0,0 +1,5 @@ +# This is to include Qubes-specific dracut module that takes care of +# detecting and hiding all networking devices at boot time +# so that Dom0 doesn't load drivers for them... + +add_dracutmodules+=" qubes-pciback " diff --git a/dracut/modules.d/90qubes-pciback/install b/dracut/modules.d/90qubes-pciback/install new file mode 100755 index 0000000..686910b --- /dev/null +++ b/dracut/modules.d/90qubes-pciback/install @@ -0,0 +1,5 @@ +#!/bin/bash +inst_hook cmdline 02 "$moddir/qubes-pciback.sh" +inst lspci +inst grep +inst awk diff --git a/dracut/modules.d/90qubes-pciback/installkernel b/dracut/modules.d/90qubes-pciback/installkernel new file mode 100755 index 0000000..427e99d --- /dev/null +++ b/dracut/modules.d/90qubes-pciback/installkernel @@ -0,0 +1,3 @@ +#!/bin/bash +modinfo -k $kernel pciback > /dev/null 2>&1 && instmods pciback +modinfo -k $kernel xen-pciback > /dev/null 2>&1 && instmods xen-pciback diff --git a/dracut/modules.d/90qubes-pciback/module-setup.sh b/dracut/modules.d/90qubes-pciback/module-setup.sh new file mode 100755 index 0000000..9118a14 --- /dev/null +++ b/dracut/modules.d/90qubes-pciback/module-setup.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +install() { + inst_hook cmdline 02 "$moddir/qubes-pciback.sh" + inst lspci + inst grep + inst awk +} + +installkernel() { + modinfo -k $kernel pciback > /dev/null 2>&1 && instmods pciback + modinfo -k $kernel xen-pciback > /dev/null 2>&1 && instmods xen-pciback +} diff --git a/dracut/modules.d/90qubes-pciback/qubes-pciback.sh b/dracut/modules.d/90qubes-pciback/qubes-pciback.sh new file mode 100755 index 0000000..2ba649b --- /dev/null +++ b/dracut/modules.d/90qubes-pciback/qubes-pciback.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# Find all networking devices currenly installed... +HIDE_PCI=`lspci -mm -n | grep '^[^ ]* "02'|awk '{ ORS="";print "(" $1 ")";}'` + +# ... and hide them so that Dom0 doesn't load drivers for them +modprobe pciback hide=$HIDE_PCI 2> /dev/null || modprobe xen-pciback hide=$HIDE_PCI + diff --git a/pm-utils/01qubes-sync-vms-clock b/pm-utils/01qubes-sync-vms-clock new file mode 100755 index 0000000..ccc7eea --- /dev/null +++ b/pm-utils/01qubes-sync-vms-clock @@ -0,0 +1,24 @@ +#!/bin/sh + +. "${PM_FUNCTIONS}" + +sync_qubes_vms_wallclock() +{ + # Sync all VMs based on dom0 clock + DATE=$(date) + echo + echo "Syncing VMs clock to: $DATE" + qvm-run --all -u root "date -s \"$DATE\"" + # Then try to sync from the network + /usr/bin/qvm-sync-clock & +} + +case "$1" in + thaw|resume) sync_qubes_vms_wallclock ;; + # Kill qvm-sync-clock (if running) to not desync time after resume + suspend|hibernate) + killall qvm-sync-clock 2> /dev/null + exit 0 + ;; + *) exit 0 ;; +esac diff --git a/pm-utils/51qubes-suspend-netvm b/pm-utils/51qubes-suspend-netvm new file mode 100755 index 0000000..21839cc --- /dev/null +++ b/pm-utils/51qubes-suspend-netvm @@ -0,0 +1,39 @@ +#!/bin/sh + +. "${PM_FUNCTIONS}" + +get_running_netvms() { + # Actually get running VMs with PCI devices attached + RUNNING_VMS=`xl list | tail -n +3 | cut -f 1 -d " "` + RUNNING_NETVMS="" + for VM in $RUNNING_VMS; do + if [ -n "`xl pci-list $VM|tail -n +2`" ]; then + echo "$VM" + fi + done +} + +suspend_net() +{ + for VM in `get_running_netvms`; do + qvm-run -u root --pass-io $VM 'QUBESRPC qubes.SuspendPre dom0' + done + # Ignore exit status from netvm... + return 0 +} + +resume_net() +{ + for VM in `get_running_netvms`; do + qvm-run -u root --pass-io $VM 'QUBESRPC qubes.SuspendPost dom0' + done + # Ignore exit status from netvm... + return 0 +} + + +case "$1" in + resume) resume_net ;; + suspend) suspend_net ;; + *) exit 0 ;; +esac diff --git a/pm-utils/52qubes-pause-vms b/pm-utils/52qubes-pause-vms new file mode 100755 index 0000000..5da1be8 --- /dev/null +++ b/pm-utils/52qubes-pause-vms @@ -0,0 +1,23 @@ +#!/bin/sh + +. "${PM_FUNCTIONS}" + +pause_vms() +{ +echo +qvm-run --all --pause +} + + +unpause_vms() +{ +echo +qvm-run --all --unpause +} + + +case "$1" in + thaw|resume) unpause_vms ;; + suspend|hibernate) pause_vms ;; + *) exit 0 ;; +esac diff --git a/rpm_spec/core-dom0-linux.spec b/rpm_spec/core-dom0-linux.spec index 524dae3..2b18622 100644 --- a/rpm_spec/core-dom0-linux.spec +++ b/rpm_spec/core-dom0-linux.spec @@ -98,6 +98,42 @@ install -m 0664 -D dom0-updates/qubes.ReceiveUpdates.policy $RPM_BUILD_ROOT/etc/ install -d $RPM_BUILD_ROOT/var/lib/qubes/updates +### Udev config +mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d +cp udev/udev-qubes-block.rules $RPM_BUILD_ROOT/etc/udev/rules.d/99-qubes-block.rules +cp udev/udev-qubes-usb.rules $RPM_BUILD_ROOT/etc/udev/rules.d/99-qubes-usb.rules + +mkdir -p $RPM_BUILD_ROOT/usr/libexec/qubes +cp udev/udev-block-add-change $RPM_BUILD_ROOT/usr/libexec/qubes/ +cp udev/udev-block-remove $RPM_BUILD_ROOT/usr/libexec/qubes/ +cp udev/udev-block-cleanup $RPM_BUILD_ROOT/usr/libexec/qubes/ +cp udev/udev-usb-add-change $RPM_BUILD_ROOT/usr/libexec/qubes/ +cp udev/udev-usb-remove $RPM_BUILD_ROOT/usr/libexec/qubes/ + +### pm-utils +mkdir -p $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d +cp pm-utils/01qubes-sync-vms-clock $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/ +cp pm-utils/51qubes-suspend-netvm $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/ +cp pm-utils/52qubes-pause-vms $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/ + +### Dracut module +mkdir -p $RPM_BUILD_ROOT/etc/dracut.conf.d +cp dracut/dracut.conf.d/* $RPM_BUILD_ROOT/etc/dracut.conf.d/ + +mkdir -p $RPM_BUILD_ROOT%{_dracutmoddir} +cp -r dracut/modules.d/* $RPM_BUILD_ROOT%{_dracutmoddir}/ + +### Others +mkdir -p $RPM_BUILD_ROOT/etc/sysconfig +install -m 0644 -D system-config/limits-qubes.conf $RPM_BUILD_ROOT/etc/security/limits.d/99-qubes.conf +install -D system-config/cpufreq-xen.modules $RPM_BUILD_ROOT/etc/sysconfig/modules/cpufreq-xen.modules +cp system-config/iptables $RPM_BUILD_ROOT/etc/sysconfig +cp system-config/ip6tables $RPM_BUILD_ROOT/etc/sysconfig +install -m 0440 -D system-config/qubes.sudoers $RPM_BUILD_ROOT/etc/sudoers.d/qubes +install -D system-config/polkit-1-qubes-allow-all.rules $RPM_BUILD_ROOT/etc/polkit-1/rules.d/00-qubes-allow-all.rules +install -D system-config/qubes-dom0.modules $RPM_BUILD_ROOT/etc/sysconfig/modules/qubes-dom0.modules +install -D system-config/qubes-sync-clock.cron $RPM_BUILD_ROOT/etc/cron.d/qubes-sync-clock.cron + ### Icons mkdir -p $RPM_BUILD_ROOT/usr/share/qubes/icons for icon in icons/*.png; do @@ -121,6 +157,10 @@ echo reposdir=/etc/yum.real.repos.d >> /etc/yum.conf sed '/^installonlypkgs\s*=/d' -i /etc/yum.conf echo 'installonlypkgs = kernel, kernel-qubes-vm' >> /etc/yum.conf +# Remove unnecessary udev rules that causes problems in dom0 (#605) +mkdir -p /var/lib/qubes/removed-udev-scripts +mv -f /lib/udev/rules.d/69-xorg-vmmouse.rules /var/lib/qubes/removed-udev-scripts/ 2> /dev/null || : + %preun if [ "$1" = 0 ] ; then # no more packages left @@ -136,6 +176,9 @@ fi # dom0 have no network, but still can receive updates (qubes-dom0-update) sed -i 's/^UseNetworkHeuristic=.*/UseNetworkHeuristic=false/' /etc/PackageKit/PackageKit.conf +%triggerin -- xorg-x11-drv-vmmouse +mv -f /lib/udev/rules.d/69-xorg-vmmouse.rules /var/lib/qubes/removed-udev-scripts/ 2> /dev/null || : + %files /etc/qubes-rpc/policy/qubes.SyncAppMenus.policy /etc/qubes-rpc/qubes.SyncAppMenus @@ -165,6 +208,31 @@ sed -i 's/^UseNetworkHeuristic=.*/UseNetworkHeuristic=false/' /etc/PackageKit/Pa /etc/qubes-rpc/qubes.ReceiveUpdates %attr(0664,root,qubes) %config(noreplace) /etc/qubes-rpc/policy/qubes.ReceiveUpdates %attr(0770,root,qubes) %dir /var/lib/qubes/updates +# Dracut module +/etc/dracut.conf.d/* +%dir %{_dracutmoddir}/90qubes-pciback +%{_dracutmoddir}/90qubes-pciback/* +# Udev +/usr/libexec/qubes/udev-block-add-change +/usr/libexec/qubes/udev-block-cleanup +/usr/libexec/qubes/udev-block-remove +/usr/libexec/qubes/udev-usb-add-change +/usr/libexec/qubes/udev-usb-remove +/etc/udev/rules.d/99-qubes-block.rules +/etc/udev/rules.d/99-qubes-usb.rules +# pm-utils +/usr/lib64/pm-utils/sleep.d/01qubes-sync-vms-clock +/usr/lib64/pm-utils/sleep.d/51qubes-suspend-netvm +/usr/lib64/pm-utils/sleep.d/52qubes-pause-vms +# Others +/etc/sysconfig/iptables +/etc/sysconfig/ip6tables +/etc/sysconfig/modules/qubes-dom0.modules +/etc/sysconfig/modules/cpufreq-xen.modules +/etc/sudoers.d/qubes +/etc/polkit-1/rules.d/00-qubes-allow-all.rules +/etc/security/limits.d/99-qubes.conf +%attr(0644,root,root) /etc/cron.d/qubes-sync-clock.cron # Man %{_mandir}/man1/qvm-*.1* %{_mandir}/man1/qubes-*.1* diff --git a/system-config/cpufreq-xen.modules b/system-config/cpufreq-xen.modules new file mode 100755 index 0000000..defac8c --- /dev/null +++ b/system-config/cpufreq-xen.modules @@ -0,0 +1,12 @@ +#!/bin/sh + +if modinfo cpufreq-xen > /dev/null 2>&1; then + modprobe acpi-cpufreq || exit 1 + modprobe cpufreq-xen + + for f in /sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_governor; do + echo xen > $f + done + +fi + diff --git a/system-config/ip6tables b/system-config/ip6tables new file mode 100644 index 0000000..8a906f5 --- /dev/null +++ b/system-config/ip6tables @@ -0,0 +1,8 @@ +# Generated by ip6tables-save v1.4.14 on Tue Sep 25 16:00:20 2012 +*filter +:INPUT DROP [1:72] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -i lo -j ACCEPT +COMMIT +# Completed on Tue Sep 25 16:00:20 2012 diff --git a/system-config/iptables b/system-config/iptables new file mode 100644 index 0000000..5977ff2 --- /dev/null +++ b/system-config/iptables @@ -0,0 +1,30 @@ +# Generated by iptables-save v1.4.5 on Mon Sep 6 08:57:46 2010 +*nat +:PREROUTING ACCEPT [85:5912] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:PR-QBS - [0:0] +:PR-QBS-SERVICES - [0:0] +-A PREROUTING -j PR-QBS +-A PREROUTING -j PR-QBS-SERVICES +-A POSTROUTING -o vif+ -j ACCEPT +-A POSTROUTING -o lo -j ACCEPT +-A POSTROUTING -j MASQUERADE +COMMIT +# Completed on Mon Sep 6 08:57:46 2010 +# Generated by iptables-save v1.4.5 on Mon Sep 6 08:57:46 2010 +*filter +:INPUT ACCEPT [168:11399] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [128:12536] +-A INPUT -i vif+ -p udp -m udp --dport 68 -j DROP +-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p icmp -j ACCEPT +-A INPUT -i lo -j ACCEPT +-A INPUT -j REJECT --reject-with icmp-host-prohibited +-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -i vif+ -o vif+ -j DROP +-A FORWARD -i vif+ -j ACCEPT +-A FORWARD -j DROP +COMMIT +# Completed on Mon Sep 6 08:57:46 2010 diff --git a/system-config/limits-qubes.conf b/system-config/limits-qubes.conf new file mode 100644 index 0000000..88198a6 --- /dev/null +++ b/system-config/limits-qubes.conf @@ -0,0 +1,3 @@ +# xl create needs to allocate and mlock all VM memory +@qubes soft memlock unlimited +@qubes hard memlock unlimited diff --git a/system-config/polkit-1-qubes-allow-all.rules b/system-config/polkit-1-qubes-allow-all.rules new file mode 100644 index 0000000..723d6d6 --- /dev/null +++ b/system-config/polkit-1-qubes-allow-all.rules @@ -0,0 +1,2 @@ +//allow any action, detailed reasoning in sudoers.d/qubes +polkit.addRule(function(action,subject) { return polkit.Result.YES; }); diff --git a/system-config/qubes-dom0.modules b/system-config/qubes-dom0.modules new file mode 100755 index 0000000..31431c6 --- /dev/null +++ b/system-config/qubes-dom0.modules @@ -0,0 +1 @@ +modprobe pciback 2> /dev/null || modprobe xen-pciback diff --git a/system-config/qubes-sync-clock.cron b/system-config/qubes-sync-clock.cron new file mode 100755 index 0000000..95c9d33 --- /dev/null +++ b/system-config/qubes-sync-clock.cron @@ -0,0 +1 @@ +*/6 * * * * root /usr/bin/qvm-sync-clock > /dev/null 2>&1 || true diff --git a/system-config/qubes.sudoers b/system-config/qubes.sudoers new file mode 100644 index 0000000..23086ed --- /dev/null +++ b/system-config/qubes.sudoers @@ -0,0 +1,31 @@ +%qubes ALL=(ALL) NOPASSWD: ALL + +# +# What we're saying above basically means: if the attacker got user access in +# Dom0, then you're screwed already, as there are dozens of ways for the +# attacker to escalate to root from user (e.g. via xend). +# +# Even that is not necessary, in fact! As all the VM control actions can be +# done by user -- after all this is why you can easily start/create VMs and +# apps in VMs from GUI -- all that the attacker needs is user access in Dom0. +# +# So, because in Qubes OS, in Dom0, user account is just as sensitive as root +# account, we don't pretend otherwise, and try to make life a bit easier for +# the user allowing for easy escalation (no need to choose and remember a root +# password in Dom0). +# +# This is also why we don't pretend that Qubes OS is a multiuser system -- it +# is not! (for the reasons given above). The assumption is that there is only +# one user that logs into GUI manager: YOU. This is hardly a limiting factor +# these days, when it's not uncommon for a single person to own not one, but +# several computers, which are not shared with others (phone, tablet, laptops). +# We live in a PC-era! :) +# +# This means that the user password you choose during installation servers only +# one purpose: it allows you to lock your screen while you're away via the +# screen saver. Nothing more! +# +# joanna. +# + +Defaults !requiretty diff --git a/udev/udev-block-add-change b/udev/udev-block-add-change new file mode 100755 index 0000000..7b65a2d --- /dev/null +++ b/udev/udev-block-add-change @@ -0,0 +1,61 @@ +#!/bin/bash + +NAME=${DEVNAME#/dev/} +DESC="${ID_MODEL} (${ID_FS_LABEL})" +SIZE=$[ $(cat /sys/$DEVPATH/size) * 512 ] +MODE=w +XS_KEY="qubes-block-devices/$NAME" + +xs_remove() { + if [ "$QUBES_EXPOSED" == "1" ]; then + xenstore-rm "$XS_KEY" + fi + echo QUBES_EXPOSED=0 +} + +# Ignore mounted... +if fgrep -q $DEVNAME /proc/mounts; then + xs_remove + exit 0 +fi +# ... and used by device-mapper +if [ -n "`ls -A /sys/$DEVPATH/holders 2> /dev/null`" ]; then + xs_remove + exit 0 +fi +# ... and "empty" loop devices +if [ "$MAJOR" -eq 7 -a ! -d /sys/$DEVPATH/loop ]; then + xs_remove + exit 0 +fi + +# Special case for CD +if [ "$ID_TYPE" = "cd" ]; then + if [ "$ID_CDROM_MEDIA" != "1" ]; then + # Hide empty cdrom drive + xs_remove + exit 0 + fi + MODE=r +fi + +# Special description for loop devices +if [ -d /sys/$DEVPATH/loop ]; then + DESC=$(cat /sys/$DEVPATH/loop/backing_file) +fi + +# Get lock only in dom0 - there are so many block devices so it causes xenstore +# deadlocks sometimes. +if [ -f /etc/qubes-release ]; then + # Skip xenstore-write if cannot obtain lock. This can mean very early system startup + # stage without /run mounted (or populated). Devices will be rediscovered later + # by qubes-core startup script. + exec 9>>/var/run/qubes/block-xenstore.lock || exit 0 + flock 9 +fi + +xenstore-write "$XS_KEY/desc" "$DESC" "$XS_KEY/size" "$SIZE" "$XS_KEY/mode" "$MODE" +echo QUBES_EXPOSED=1 + +# Make sure that block backend is loaded +/sbin/modprobe xen-blkback 2> /dev/null || /sbin/modprobe blkbk diff --git a/udev/udev-block-cleanup b/udev/udev-block-cleanup new file mode 100755 index 0000000..bc4535f --- /dev/null +++ b/udev/udev-block-cleanup @@ -0,0 +1,8 @@ +#!/bin/sh + +DEVID=$[ $MAJOR * 256 + $MINOR ] + +XS_PATH="device/vbd/$DEVID" + +# Double check that DEVID is not empty +[ -n "$DEVID" ] && xenstore-rm $XS_PATH diff --git a/udev/udev-block-remove b/udev/udev-block-remove new file mode 100755 index 0000000..21502c3 --- /dev/null +++ b/udev/udev-block-remove @@ -0,0 +1,32 @@ +#!/bin/sh + +NAME=${DEVNAME#/dev/} +XS_KEY="qubes-block-devices/$NAME" +xenstore-rm "$XS_KEY" + +# If device was connected to some VM - detach it +# Notice: this can be run also in VM, so we cannot use xl... + +device_detach() { + xs_path=$1 + + xenstore-write $xs_path/online 0 $xs_path/state 5 + + # Wait for backend to finish dev shutdown + try=30 + # -lt will break loop also when 'state' will be empty + while [ "`xenstore-read $xs_path/state 2> /dev/null`" -lt 6 ]; do + try=$[ $try - 1 ] + [ "$try" -le 0 ] && break + sleep 0.1 + done + xenstore-rm $xs_path +} + +for XS_DEV_PATH in `xenstore-ls -f backend/vbd | grep 'backend/vbd/[0-9]*/[0-9]* ' | cut -f 1 -d ' '`; do + CUR_DEVICE=`xenstore-read "$XS_DEV_PATH/params"` + if [ "$CUR_DEVICE" == "$DEVNAME" ]; then + device_detach "$XS_DEV_PATH" + exit 0 + fi +done diff --git a/udev/udev-qubes-block.rules b/udev/udev-qubes-block.rules new file mode 100644 index 0000000..364f5b2 --- /dev/null +++ b/udev/udev-qubes-block.rules @@ -0,0 +1,20 @@ +# Expose all (except xen-frontend) block devices via xenstore + +# Only block devices are interesting +SUBSYSTEM!="block", GOTO="qubes_block_end" + +# Skip xen-blkfront devices +ENV{MAJOR}=="202", GOTO="qubes_block_end" + +# Skip device-mapper devices +ENV{MAJOR}=="253", GOTO="qubes_block_end" + +IMPORT{db}="QUBES_EXPOSED" +ACTION=="add", IMPORT{program}="/usr/lib/qubes/udev-block-add-change" +ACTION=="change", IMPORT{program}="/usr/lib/qubes/udev-block-add-change" +ACTION=="remove", RUN+="/usr/lib/qubes/udev-block-remove" + +LABEL="qubes_block_end" + +# Cleanup disconnected frontend from xenstore +ACTION=="remove", SUBSYSTEM=="block", ENV{MAJOR}=="202", RUN+="/usr/lib/qubes/udev-block-cleanup" diff --git a/udev/udev-qubes-usb.rules b/udev/udev-qubes-usb.rules new file mode 100644 index 0000000..e5e24a0 --- /dev/null +++ b/udev/udev-qubes-usb.rules @@ -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/udev-usb-add-change" +ACTION=="change", IMPORT{program}="/usr/lib/qubes/udev-usb-add-change" +ACTION=="remove", RUN+="/usr/lib/qubes/udev-usb-remove" + +LABEL="qubes_usb_end" diff --git a/udev/udev-usb-add-change b/udev/udev-usb-add-change new file mode 100755 index 0000000..fe966e0 --- /dev/null +++ b/udev/udev-usb-add-change @@ -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 udev-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 diff --git a/udev/udev-usb-remove b/udev/udev-usb-remove new file mode 100755 index 0000000..aa562fa --- /dev/null +++ b/udev/udev-usb-remove @@ -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"