Merge branch 'master' of git.qubes-os.org:/var/lib/qubes/git/marmarek/core

Conflicts:
	version_vm
This commit is contained in:
Joanna Rutkowska 2011-06-24 16:16:44 +02:00
commit b76ead2cb2
67 changed files with 1731 additions and 725 deletions

View File

@ -57,5 +57,6 @@ clean:
(cd dom0/restore && make clean)
(cd dom0/qmemman && make clean)
(cd common && make clean)
(cd u2mfn && make clean)
make -C qrexec clean
make -C vchan clean

View File

@ -5,9 +5,9 @@ dvm_file_editor: dvm_file_editor.o ../common/ioall.o
$(CC) -pie -g -o $@ $^
qfile-agent-dvm: qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o
$(CC) -pie -g -o $@ $^
qfile-agent: qfile-agent.o ../common/ioall.o ../common/gui-fatal.o copy_file.o crc32.o
qfile-agent: qfile-agent.o ../common/ioall.o ../common/gui-fatal.o ../common/copy_file.o ../common/crc32.o
$(CC) -pie -g -o $@ $^
qfile-unpacker: qfile-unpacker.o ../common/ioall.o ../common/gui-fatal.o copy_file.o unpack.o crc32.o
qfile-unpacker: qfile-unpacker.o ../common/ioall.o ../common/gui-fatal.o ../common/copy_file.o ../common/unpack.o ../common/crc32.o
$(CC) -pie -g -o $@ $^
clean:

View File

@ -20,15 +20,15 @@
#
#
if [ x"$1" = "x--with-progress" ] ; then
DO_PROGRESS=1
if [ x"$1" = "x--without-progress" ] ; then
DO_PROGRESS=0
shift
else
DO_PROGRESS=0
DO_PROGRESS=1
fi
if [ $# -lt 2 ] ; then
echo usage: $0 '[--with-progress] dest_vmname file [file]+'
echo usage: $0 '[--without-progress] dest_vmname file [file]+'
exit 1
fi

View File

@ -6,4 +6,4 @@ meminfo-writer: meminfo-writer.o
xenstore-watch: xenstore-watch.o
$(CC) -o xenstore-watch xenstore-watch.o -lxenstore
clean:
rm -f meminfo-writer *.o *~
rm -f meminfo-writer xenstore-watch *.o *~

View File

@ -5,7 +5,16 @@
# This creates dm-snapshot device on given arguments
dir=$(dirname "$0")
. "$dir/block-common.sh"
if [ "$1" = "prepare" ] || [ "$1" = "cleanup" ]; then
. "$dir/xen-hotplug-common.sh"
command=$1
else
. "$dir/block-common.sh"
fi
shopt -s nullglob
HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}"
get_dev() {
dev=$1
@ -89,7 +98,6 @@ create_dm_snapshot_origin() {
t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING')
case "$command" in
add)
case $t in
@ -117,24 +125,81 @@ case "$command" in
if [ "$t" == "snapshot" ]; then
#that's all for snapshot, store name of prepared device
xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname"
echo "/dev/mapper/$dm_devname" > "$HOTPLUG_STORE-node"
write_dev /dev/mapper/$dm_devname
elif [ "$t" == "origin" ]; then
# for origin - prepare snapshot-origin device and store its name
dm_devname=origin-$(stat -c '%D:%i' "$base")
create_dm_snapshot_origin $dm_devname "$base"
xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname"
echo "/dev/mapper/$dm_devname" > "$HOTPLUG_STORE-node"
write_dev /dev/mapper/$dm_devname
fi
# Save domain name for template commit on device remove
domain=$(xenstore_read_default "$XENBUS_PATH/domain" '')
if [ -z "$domain" ]; then
domid=$(xenstore_read "$XENBUS_PATH/frontend-id")
domain=$(xl domname $domid)
fi
echo $domain > "$HOTPLUG_STORE-domain"
release_lock "block"
exit 0
;;
esac
;;
prepare)
t=$2
case $t in
snapshot|origin)
p=$3
base=${p/:*/}
cow=${p/*:/}
if [ -L "$base" ]; then
base=$(readlink -f "$base") || fatal "$base link does not exist."
fi
if [ -L "$cow" ]; then
cow=$(readlink -f "$cow") || fatal "$cow link does not exist."
fi
# first ensure that snapshot device exists (to write somewhere changes from snapshot-origin)
dm_devname=$(get_dm_snapshot_name "$base" "$cow")
claim_lock "block"
# prepare snapshot device
create_dm_snapshot $dm_devname "$base" "$cow"
if [ "$t" == "snapshot" ]; then
#that's all for snapshot, store name of prepared device
echo "/dev/mapper/$dm_devname"
elif [ "$t" == "origin" ]; then
# for origin - prepare snapshot-origin device and store its name
dm_devname=origin-$(stat -c '%D:%i' "$base")
create_dm_snapshot_origin $dm_devname "$base"
echo "/dev/mapper/$dm_devname"
fi
release_lock "block"
exit 0
;;
esac
;;
remove)
remove|cleanup)
if [ "$command" = "cleanup" ]; then
t=$2
else
t=$(cat $HOTPLUG_STORE-type)
fi
case $t in
snapshot|origin)
node=$(xenstore_read "$XENBUS_PATH/node")
if [ "$command" = "cleanup" ]; then
node=$3
else
node=$(cat "$HOTPLUG_STORE-node")
fi
if [ -z "$node" ]; then
fatal "No device node to remove"
@ -174,14 +239,16 @@ case "$command" in
dmsetup remove $snap
fi
done
# Commit template changes
domain=$(xenstore_read "$XENBUS_PATH/domain")
if [ "$domain" ]; then
# Dont stop on errors
/usr/bin/qvm-template-commit "$domain" || true
if [ "$command" = "remove" ]; then
# Commit template changes
domain=$(cat "$HOTPLUG_STORE-domain")
if [ "$domain" ]; then
# Dont stop on errors
/usr/bin/qvm-template-commit "$domain" || true
fi
fi
fi
if [ -e $node ]; then
log debug "Removing $node"
dmsetup remove $node

View File

@ -0,0 +1,51 @@
#!/bin/bash
DOM0_UPDATES_DIR=/var/lib/qubes/dom0-updates
DOIT=0
GUI=1
while [ -n "$1" ]; do
if [ "x--doit" = "x$1" ]; then
DOIT=1
elif [ "x--nogui" = "x$1" ]; then
GUI=0
fi
shift
done
if ! [ -d "$DOM0_UPDATES_DIR" ]; then
echo "Dom0 updates dir does not exists: $DOM0_UPDATES_DIR"
exit 1
fi
mkdir -p $DOM0_UPDATES_DIR/etc
cp /etc/yum.conf $DOM0_UPDATES_DIR/etc/
echo "Checking for updates..."
PKGLIST=`yum --installroot $DOM0_UPDATES_DIR check-update -q | cut -f 1 -d ' '`
if [ -z $PKGLIST ]; then
# No new updates
exit 0
fi
if [ "$DOIT" != "1" ]; then
zenity --question --title="Qubes Dom0 updates" \
--text="Updates for dom0 available. Do you want to download its now?" || exit 0
fi
mkdir -p "$DOM0_UPDATES_DIR/packages"
set -e
if [ "$GUI" = 1 ]; then
( echo "1"
yumdownloader --destdir "$DOM0_UPDATES_DIR/packages" --installroot "$DOM0_UPDATES_DIR" $PKGLIST
echo 100 ) | zenity --progress --pulsate --auto-close --auto-kill \
--text="Downloading updates for Dom0, please wait..." --title="Qubes Dom0 updates"
else
yumdownloader --destdir "$DOM0_UPDATES_DIR/packages" --installroot "$DOM0_UPDATES_DIR" $PKGLIST
fi
# qvm-copy-to-vm works only from user
su -c "qvm-copy-to-vm @dom0updates $DOM0_UPDATES_DIR/packages/*.rpm" user

View File

@ -0,0 +1,2 @@
SUBSYSTEMS=="xen", KERNEL=="eth*", ACTION=="add", RUN+="/usr/lib/qubes/setup_ip"

View File

@ -0,0 +1 @@
*:any:/usr/lib/qubes/qubes_trigger_sync_appmenus.sh

View File

@ -0,0 +1,7 @@
#!/bin/sh
UPDATEABLE=`/usr/bin/xenstore-read qubes_vm_updateable`
if [ "$UPDATEABLE" = "True" ]; then
echo -n SYNC > /var/run/qubes/qrexec_agent
fi

13
common/setup_ip Executable file
View File

@ -0,0 +1,13 @@
#!/bin/sh
ip=`/usr/bin/xenstore-read qubes_ip`
netmask=`/usr/bin/xenstore-read qubes_netmask`
gateway=`/usr/bin/xenstore-read qubes_gateway`
secondary_dns=`/usr/bin/xenstore-read qubes_secondary_dns`
if [ x$ip != x ]; then
/sbin/ifconfig $INTERFACE $ip netmask 255.255.255.255
/sbin/ifconfig $INTERFACE up
/sbin/route add default dev $INTERFACE
echo "nameserver $gateway" > /etc/resolv.conf
echo "nameserver $secondary_dns" >> /etc/resolv.conf
fi

View File

@ -1,3 +1,4 @@
#define _GNU_SOURCE /* For O_NOFOLLOW. */
#include <errno.h>
#include <ioall.h>
#include <fcntl.h>

1
dom0/aux-tools/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
qfile-dom0-unpacker

4
dom0/aux-tools/Makefile Normal file
View File

@ -0,0 +1,4 @@
CC=gcc
CFLAGS=-g -Wall -I../../common -fPIC -pie
qfile-dom0-unpacker: qfile-dom0-unpacker.o ../../common/ioall.o ../../common/gui-fatal.o ../../common/copy_file.o ../../common/unpack.o ../../common/crc32.o
$(CC) -pie -g -o $@ $^

View File

@ -22,20 +22,29 @@
SRCDIR=$1
VMNAME=$2
VMDIR=/var/lib/qubes/appvms/$VMNAME
VMTYPE=$3
if [ -z "$VMTYPE" ]; then
VMTYPE=appvms
fi
VMDIR=/var/lib/qubes/$VMTYPE/$VMNAME
APPSDIR=$VMDIR/apps
if [ $# != 2 ]; then
echo "usage: $0 <apps_templates_dir> <vmname>"
if [ $# -lt 2 ]; then
echo "usage: $0 <apps_templates_dir> <vmname> [appvms|vm-templates|servicevms]"
exit
fi
mkdir -p $APPSDIR
if [ "$SRCDIR" != "none" ]; then
echo "--> Converting Appmenu Templates..."
find $SRCDIR -name "*.desktop" -exec /usr/lib/qubes/convert_apptemplate2vm.sh {} $APPSDIR $VMNAME $VMDIR \;
if [ -r "$VMDIR/whitelisted-appmenus.list" ]; then
cat $VMDIR/whitelisted-appmenus.list | xargs -I{} /usr/lib/qubes/convert_apptemplate2vm.sh $SRCDIR/{} $APPSDIR $VMNAME $VMDIR
else
find $SRCDIR -name "*.desktop" $CHECK_WHITELISTED -exec /usr/lib/qubes/convert_apptemplate2vm.sh {} $APPSDIR $VMNAME $VMDIR \;
fi
/usr/lib/qubes/convert_apptemplate2vm.sh /usr/share/qubes/qubes-appmenu-select.template $APPSDIR $VMNAME $VMDIR
/usr/lib/qubes/convert_dirtemplate2vm.sh $SRCDIR/qubes-vm.directory.template $APPSDIR/$VMNAME-vm.directory $VMNAME $VMDIR
/usr/lib/qubes/convert_dirtemplate2vm.sh $SRCDIR/qubes-*.directory.template $APPSDIR/$VMNAME-vm.directory $VMNAME $VMDIR
fi
echo "--> Adding Apps to the Menu..."

View File

@ -0,0 +1,86 @@
#define _GNU_SOURCE
#include <ioall.h>
#include <grp.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <sys/fsuid.h>
#include <gui-fatal.h>
#include <errno.h>
#include "filecopy.h"
int prepare_creds_return_uid(char *username)
{
struct passwd *pwd;
pwd = getpwnam(username);
if (!pwd) {
perror("getpwnam");
exit(1);
}
setenv("HOME", pwd->pw_dir, 1);
setenv("USER", username, 1);
setgid(pwd->pw_gid);
initgroups(username, pwd->pw_gid);
setfsuid(pwd->pw_uid);
return pwd->pw_uid;
}
void wait_for_child(int statusfd)
{
int status;
if (read(statusfd, &status, sizeof status)!=sizeof status)
gui_fatal("File copy error: Internal error reading status from unpacker");
errno = status;
switch (status) {
case LEGAL_EOF: break;
case 0: gui_fatal("File copy: Connection terminated unexpectedly"); break;
case EINVAL: gui_fatal("File copy: Corrupted data from packer"); break;
case EEXIST: gui_fatal("File copy: not overwriting existing file. Clean ~/incoming, and retry copy"); break;
default: gui_fatal("File copy");
}
}
extern void do_unpack(int);
int main(int argc, char ** argv)
{
char *incoming_dir;
int pipefds[2];
int uid;
if (argc < 3) {
fprintf(stderr, "Invalid parameters, usage: %s user dir\n", argv[0]);
exit(1);
}
pipe(pipefds);
uid = prepare_creds_return_uid(argv[1]);
incoming_dir = argv[2];
mkdir(incoming_dir, 0700);
if (chdir(incoming_dir))
gui_fatal("Error chdir to %s", incoming_dir);
switch (fork()) {
case -1:
perror("fork");
exit(1);
case 0:
if (chroot(incoming_dir)) //impossible
gui_fatal("Error chroot to %s", incoming_dir);
setuid(uid);
close(pipefds[0]);
do_unpack(pipefds[1]);
exit(0);
default:;
}
setuid(uid);
close(pipefds[1]);
wait_for_child(pipefds[0]);
return 0;
}

View File

@ -1,14 +1,19 @@
#!/bin/sh
VMNAME=$1
VMDIR=/var/lib/qubes/appvms/$VMNAME
VMTYPE=$2
if [ -z "$VMTYPE" ]; then
VMTYPE=appvms
fi
VMDIR=/var/lib/qubes/$VMTYPE/$VMNAME
APPSDIR=$VMDIR/apps
if [ $# != 1 ]; then
echo "usage: $0 <vmname>"
if [ $# -lt 1 ]; then
echo "usage: $0 <vmname> [appvms|vm-templates|servicevms]"
exit
fi
if ls $APPSDIR/*.directory $APPSDIR/*.desktop > /dev/null 2>&1; then
xdg-desktop-menu uninstall $APPSDIR/*.directory $APPSDIR/*.desktop
rm -f $APPSDIR/*.desktop $APPSDIR/*.directory
fi

View File

@ -0,0 +1,10 @@
#!/bin/sh
UPDATEVM=`qvm-get-updatevm`
if [ -n "$UPDATEVM" ]; then
qvm-run -u root --pass_io --localcmd='tar c /var/lib/rpm /etc/yum.repos.d' "$UPDATEVM" 'tar x -C /var/lib/qubes/dom0-updates'
fi
# Ignore errors (eg VM not running)
exit 0

View File

@ -20,6 +20,7 @@
start()
{
echo -n $"Executing Qubes Core scripts:"
modprobe evtchn
chgrp qubes /etc/xen
chmod 710 /etc/xen
chgrp qubes /var/run/xend
@ -28,7 +29,21 @@ start()
chmod 660 /var/run/xend/xen-api.sock /var/run/xend/xmlrpc.sock
chgrp qubes /var/run/xenstored/*
chmod 660 /var/run/xenstored/*
xm sched-credit -d 0 -w 65535
chgrp qubes /var/lib/xen
chmod 770 /var/lib/xen
chgrp qubes /var/log/xen
chmod 770 /var/log/xen
chgrp qubes /proc/xen/privcmd
chmod 660 /proc/xen/privcmd
chgrp qubes /dev/xen/evtchn
chmod 660 /dev/xen/evtchn
touch /var/run/qubes/xl-lock
chgrp qubes /var/run/qubes/xl-lock
chmod 660 /var/run/qubes/xl-lock
xenstore-write /local/domain/0/name Domain-0
xl sched-credit -d 0 -w 512
cp /var/lib/qubes/qubes.xml /var/lib/qubes/backup/qubes-$(date +%F-%T).xml
/usr/lib/qubes/qmemman_daemon.py >/var/log/qubes/qmemman.log 2>/var/log/qubes/qmemman.errs &

View File

@ -22,10 +22,10 @@ NETVM=$(qvm-get-default-netvm)
get_running_netvms() {
# Actually get running VMs with PCI devices attached
RUNNING_VMS=`xm list --state=Running | tail -n +3 | cut -f 1 -d " "`
RUNNING_VMS=`xl list | tail -n +3 | cut -f 1 -d " "`
RUNNING_NETVMS=""
for VM in $RUNNING_VMS; do
if [ -n "`xm pci-list $VM`" ]; then
if [ -n "`xl pci-list $VM`" ]; then
echo "$VM"
fi
done

View File

@ -0,0 +1,3 @@
# xl create needs to allocate and mlock all VM memory
@qubes soft memlock unlimited
@qubes hard memlock unlimited

View File

@ -0,0 +1,10 @@
[Desktop Entry]
Version=1.0
Type=Application
Exec=qubes-appmenu-select %VMNAME%
Icon=/usr/share/qubes/icons/qubes.png
Terminal=false
Name=%VMNAME%: Add more shortcuts...
GenericName=%VMNAME%: Add more shortcuts...
StartupNotify=false
Categories=System;

View File

@ -0,0 +1,5 @@
[Desktop Entry]
Encoding=UTF-8
Type=Directory
Name=Template: %VMNAME%
Icon=/usr/share/qubes/icons/template.png

View File

@ -0,0 +1,5 @@
[Desktop Entry]
Encoding=UTF-8
Type=Directory
Name=Domain: %VMNAME%
Icon=%VMDIR%/icon.png

View File

@ -0,0 +1 @@
*:any:/usr/lib/qubes/sync_rpmdb_updatevm.sh

View File

@ -0,0 +1,28 @@
#
# This is a Xen VM config file for Qubes VM
# DO NOT EDIT - autogenerated by qubes tools
#
kernel="{kerneldir}/vmlinuz"
ramdisk="{kerneldir}/initramfs"
extra="ro nomodeset xencons=hvc rd_NO_PLYMOUTH 3 {kernelopts}"
root="/dev/mapper/dmroot"
memory = {mem}
maxmem = {maxmem}
name = "{name}"
disk = [ {rootdev}
{privatedev}
{volatiledev}
]
vif = [ {netdev} ]
pci = [ {pcidev} ]
vcpus = {vcpus}
on_poweroff = 'destroy'
on_reboot = 'destroy'
on_crash = 'destroy'

View File

@ -4,10 +4,10 @@
get_running_netvms() {
# Actually get running VMs with PCI devices attached
RUNNING_VMS=`xm list --state=Running | tail -n +3 | cut -f 1 -d " "`
RUNNING_VMS=`xl list | tail -n +3 | cut -f 1 -d " "`
RUNNING_NETVMS=""
for VM in $RUNNING_VMS; do
if [ -n "`xm pci-list $VM`" ]; then
if [ -n "`xl pci-list $VM|tail -n +2`" ]; then
echo "$VM"
fi
done

View File

@ -9,6 +9,7 @@ class DomainState:
def __init__(self, id):
self.meminfo = None #dictionary of memory info read from client
self.memory_actual = None #the current memory size
self.memory_maximum = None #the maximum memory size
self.mem_used = None #used memory, computed based on meminfo
self.id = id #domain id
self.last_target = 0 #the last memset target
@ -27,6 +28,7 @@ class SystemState:
def del_domain(self, id):
self.domdict.pop(id)
self.do_balance()
def get_free_xen_memory(self):
return self.xc.physinfo()['free_memory']*1024
@ -42,6 +44,9 @@ class SystemState:
id = str(domain['domid'])
if self.domdict.has_key(id):
self.domdict[id].memory_actual = domain['mem_kb']*1024
self.domdict[id].memory_maximum = self.xs.read('', '/local/domain/%s/memory/static-max' % str(id))
if not self.domdict[id].memory_maximum:
self.domdict[id].memory_maximum = domain['maxmem_kb']*1024
#the below works (and is fast), but then 'xm list' shows unchanged memory value
def mem_set(self, id, val):
@ -51,6 +56,7 @@ class SystemState:
#can happen in the middle of domain shutdown
#apparently xc.lowlevel throws exceptions too
try:
self.xc.domain_setmaxmem(int(id), val/1024 + 1024) # LIBXL_MAXMEM_CONSTANT=1024
self.xc.domain_set_target_mem(int(id), val/1024)
except:
pass

View File

@ -60,8 +60,8 @@ def prefmem(domain):
CACHE_FACTOR = 1.3
#dom0 is special, as it must have large cache, for vbds. Thus, give it a special boost
if domain.id == '0':
return domain.mem_used*CACHE_FACTOR + 350*1024*1024
return domain.mem_used*CACHE_FACTOR
return min(domain.mem_used*CACHE_FACTOR + 350*1024*1024, domain.memory_maximum)
return min(domain.mem_used*CACHE_FACTOR, domain.memory_maximum)
def memory_needed(domain):
#do not change
@ -104,8 +104,11 @@ def balloon(memsize, domain_dictionary):
#redistribute positive "total_available_memory" of memory between domains, proportionally to prefmem
def balance_when_enough_memory(domain_dictionary, xen_free_memory, total_mem_pref, total_available_memory):
donors_rq = list()
acceptors_rq = list()
print 'balance_when_enough_memory(', xen_free_memory, total_mem_pref, total_available_memory, ')'
target_memory = {}
# memory not assigned because of static max
left_memory = 0
acceptors_count = 0
for i in domain_dictionary.keys():
if domain_dictionary[i].meminfo is None:
continue
@ -114,10 +117,43 @@ def balance_when_enough_memory(domain_dictionary, xen_free_memory, total_mem_pre
target_nonint = prefmem(domain_dictionary[i]) + scale*total_available_memory
#prevent rounding errors
target = int(0.999*target_nonint)
#do not try to give more memory than static max
if target > domain_dictionary[i].memory_maximum:
left_memory += target-domain_dictionary[i].memory_maximum
target = domain_dictionary[i].memory_maximum
else:
# count domains which can accept more memory
acceptors_count += 1
target_memory[i] = target
# distribute left memory across all acceptors
while left_memory > 0 and acceptors_count > 0:
print ' left_memory:', left_memory, 'acceptors_count:', acceptors_count
new_left_memory = 0
new_acceptors_count = acceptors_count
for i in target_memory.keys():
target = target_memory[i]
if target < domain_dictionary[i].memory_maximum:
memory_bonus = int(0.999*(left_memory/acceptors_count))
if target+memory_bonus >= domain_dictionary[i].memory_maximum:
new_left_memory += target+memory_bonus - domain_dictionary[i].memory_maximum
target = domain_dictionary[i].memory_maximum
new_acceptors_count -= 1
else:
target += memory_bonus
target_memory[i] = target
left_memory = new_left_memory
acceptors_count = new_acceptors_count
# split target_memory dictionary to donors and acceptors
# this is needed to first get memory from donors and only then give it to acceptors
donors_rq = list()
acceptors_rq = list()
for i in target_memory.keys():
target = target_memory[i]
if (target < domain_dictionary[i].memory_actual):
donors_rq.append((i, target))
else:
acceptors_rq.append((i, target))
# print 'balance(enough): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
return donors_rq + acceptors_rq
@ -140,7 +176,9 @@ def balance_when_low_on_memory(domain_dictionary, xen_free_memory, total_mem_pre
for i in acceptors:
scale = 1.0*prefmem(domain_dictionary[i])/total_mem_pref_acceptors
target_nonint = domain_dictionary[i].memory_actual + scale*squeezed_mem
acceptors_rq.append((i, int(target_nonint)))
#do not try to give more memory than static max
target = min(int(0.999*target_nonint), domain_dictionary[i].memory_maximum)
acceptors_rq.append((i, target))
# print 'balance(low): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
return donors_rq + acceptors_rq
@ -171,7 +209,7 @@ def balance(xen_free_memory, domain_dictionary):
continue
need = memory_needed(domain_dictionary[i])
# print 'domain' , i, 'act/pref', domain_dictionary[i].memory_actual, prefmem(domain_dictionary[i]), 'need=', need
if need < 0:
if need < 0 or domain_dictionary[i].memory_actual >= domain_dictionary[i].memory_maximum:
donors.append(i)
else:
acceptors.append(i)

View File

@ -29,10 +29,11 @@ class WatchType:
class XS_Watcher:
def __init__(self):
self.handle = xen.lowlevel.xs.xs()
self.handle.watch('/vm', WatchType(XS_Watcher.domain_list_changed, None))
self.handle.watch('/local/domain', WatchType(XS_Watcher.domain_list_changed, None))
self.watch_token_dict = {}
def domain_list_changed(self, param):
time.sleep(0.05)
curr = self.handle.ls('', '/local/domain')
if curr == None:
return

5
dom0/qubes-cached.repo Normal file
View File

@ -0,0 +1,5 @@
[qubes-dom0-cached]
name = Qubes OS Repository for Dom0
baseurl = file:///var/lib/qubes/updates
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-qubes-1-primary
gpgcheck = 1

File diff suppressed because it is too large Load Diff

View File

@ -64,14 +64,6 @@ def main():
qvm_collection.pop(vm.qid)
exit (1)
try:
vm.add_to_xen_storage()
except (IOError, OSError) as err:
print "ERROR: {0}".format(err)
qvm_collection.pop(vm.qid)
exit (1)
qvm_collection.save()
qvm_collection.unlock_db()

View File

@ -164,7 +164,6 @@ def main():
try:
vm.create_on_disk(verbose=options.verbose, source_template=template_vm)
vm.add_to_xen_storage()
except (IOError, OSError) as err:
print "ERROR: {0}".format(err)

20
dom0/qvm-tools/qvm-dom0-upgrade Executable file
View File

@ -0,0 +1,20 @@
#!/bin/bash
UPDATEVM=`qvm-get-updatevm`
if [ -z "$UPDATEVM" ]; then
echo "UpdateVM not set, exiting"
exit 1
fi
echo "Checking for dom0 updates"
# Start VM if not running already
qvm-run -a $UPDATEVM true || exit 1
/usr/lib/qubes/sync_rpmdb_updatevm.sh || exit 1
qvm-run -u root --pass_io $UPDATEVM "/usr/lib/qubes/qubes_download_dom0_updates.sh --doit $@" || exit 1
yum check-update
if [ $? -ne 100 ]; then
exit 0
fi
gpk-update-viewer

39
dom0/qvm-tools/qvm-get-updatevm Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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
from optparse import OptionParser;
def main():
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
updatevm = qvm_collection.get_updatevm_vm()
if updatevm is None:
print ""
else:
print updatevm.name
main()

View File

@ -21,6 +21,7 @@
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesHost
from qubes.qubes import QubesException
from optparse import OptionParser
@ -59,8 +60,8 @@ fields = {
"xid" : {"func" : "vm.get_xid() if vm.is_running() else '-'"},
"mem" : {"func" : "(str(vm.get_mem()/1024/1024) + ' MB') if vm.is_running() else '-'"},
"cpu" : {"func" : "round (vm.get_cpu_total_load(), 1) if vm.is_running() else '-'"},
"mem" : {"func" : "(str(vm.get_mem()/1024) + ' MB') if vm.is_running() else '-'"},
"cpu" : {"func" : "round (cpu_usages[vm.get_xid()]['cpu_usage'], 1) if vm.is_running() else '-'"},
"disk": {"func" : "str(vm.get_disk_utilization()/(1024*1024)) + ' MB'"},
"state": {"func" : "vm.get_power_state()"},
@ -114,10 +115,14 @@ def main():
fields_to_display = ["name", "on", "state", "updbl", "type", "template", "netvm", "label" ]
cpu_usages = None
if (options.ids):
fields_to_display += ["qid", "xid"]
if (options.cpu):
qhost = QubesHost()
(measure_time, cpu_usages) = qhost.measure_cpu_usage()
fields_to_display += ["cpu"]
if (options.mem):

View File

@ -32,7 +32,7 @@ def do_list(vm):
print fmt.format ("name", vm.name)
print fmt.format ("label", vm.label.name)
print fmt.format ("type", vm.type)
if vm.is_appvm():
if vm.template_vm is not None:
print fmt.format ("template", vm.template_vm.name)
if vm.netvm_vm is not None:
print fmt.format ("netvm", vm.netvm_vm.name)
@ -40,15 +40,18 @@ def do_list(vm):
print fmt.format ("installed by RPM?", vm.installed_by_rpm)
print fmt.format ("dir", vm.dir_path)
print fmt.format ("config", vm.conf_file)
print fmt.format ("pcidevs", vm.pcidevs)
if not vm.is_appvm():
print fmt.format ("root img", vm.root_img)
if vm.is_template():
print fmt.format ("root COW img", vm.rootcow_img)
if vm.is_appvm():
if vm.template_vm is not None:
print fmt.format ("root img", vm.template_vm.root_img)
print fmt.format ("root volatile img", vm.volatile_img)
print fmt.format ("root volatile img", vm.volatile_img)
print fmt.format ("private img", vm.private_img)
print fmt.format ("memory", vm.memory)
print fmt.format ("maxmem", vm.maxmem)
def set_label(vms, vm, args):
@ -65,6 +68,23 @@ def set_label(vms, vm, args):
vm.label = QubesVmLabels[label]
subprocess.check_call (["ln", "-sf", vm.label.icon_path, vm.icon_path])
def set_memory(vms, vm, args):
if len (args) != 1:
print "Missing memory argument!"
vm.memory = int(args[0])
def set_maxmem(vms, vm, args):
if len (args) != 1:
print "Missing maxmem argument!"
vm.maxmem = int(args[0])
def set_pcidevs(vms, vm, args):
if len (args) != 1:
print "Missing memory argument!"
vm.pcidevs = args[0]
def set_netvm(vms, vm, args):
if len (args) != 1:
@ -151,8 +171,11 @@ def set_nonupdateable(vms, vm, args):
properties = {
"updateable": set_updateable,
"nonupdateable": set_nonupdateable,
"pcidevs": set_pcidevs,
"label" : set_label,
"netvm" : set_netvm,
"maxmem" : set_maxmem,
"memory" : set_memory,
}

View File

@ -0,0 +1,140 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2011 Marek Marczykowski <marmarek@mimuw.edu.pl>
#
# 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
from qubes.qubes import QubesException
from optparse import OptionParser
import subprocess
import os
import time
import glob
def main():
usage = "usage: %prog [options] <template-name>"
parser = OptionParser (usage)
parser.add_option ("--force", action="store_true", dest="force", default=False,
help="Do not prompt for comfirmation")
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify TemplateVM name!")
vmname = args[0]
if os.geteuid() != 0:
print "ERROR: This tool must be run as root!"
exit(1)
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if not vm.is_template():
print "A VM '{0}' is not template.".format(vmname)
exit(1)
if vm.is_running():
print "You must stop VM first."
exit(1)
oldcow_img = vm.rootcow_img + '.old'
oldcow_stat = os.stat(oldcow_img)
oldcow_time_str = time.strftime("%F %T", time.gmtime(oldcow_stat.st_mtime))
root_stat = os.stat(vm.root_img)
old_dmdev = "/dev/mapper/snapshot-{0:x}:{1}-{2:x}:{3}".format(
root_stat[2], root_stat[1],
oldcow_stat[2], oldcow_stat[1])
snapshots = glob.glob('/dev/mapper/snapshot-{0:x}:{1}-*'.format(root_stat[2], root_stat[1]))
snapshot_present = False
for dev in snapshots:
if dev == old_dmdev:
snapshot_present = True
else:
print "ERROR: You must shutdown all VMs running system older/newer than last good one."
exit(1)
root_blocks = os.path.getsize(vm.root_img)/512
if not snapshot_present:
p = subprocess.Popen (["/etc/xen/scripts/block-snapshot", "prepare",
"snapshot", "{0}:{1}".format(vm.root_img, oldcow_img)],
stdout=subprocess.PIPE)
result = p.communicate()
if result[0].strip() != old_dmdev:
print "ERROR: Cannot create snapshot device ({0} != {1})".format(
result[0].strip(), old_dmdev)
exit(1)
print "INFO: Reverting template changes done at {0}".format(oldcow_time_str)
if not options.force:
prompt = raw_input ("Do you want to proceed? [y/N] ")
if not (prompt == "y" or prompt == "Y"):
exit (0)
p = subprocess.Popen(["/sbin/dmsetup", "table", old_dmdev], stdout=subprocess.PIPE)
result = p.communicate()
dm_table = result[0]
dm_table_elements = dm_table.split(' ')
if dm_table_elements[2] != 'snapshot':
print "ERROR: Unexpected device-mapper type ({0}). Template changes reverting already running".format(dm_table_elements[2])
exit(1)
dm_table_elements[2] = 'snapshot-merge'
dm_table = ' '.join(dm_table_elements)
subprocess.check_call(["/sbin/dmsetup", "reload", old_dmdev, "--table", dm_table])
# Reload new table into LIVE slot
subprocess.check_call(["/sbin/dmsetup", "suspend", old_dmdev])
subprocess.check_call(["/sbin/dmsetup", "resume", old_dmdev])
# Wait to snapshot merge completed
while True:
p = subprocess.Popen(["/sbin/dmsetup", "status", old_dmdev], stdout=subprocess.PIPE)
result = p.communicate()
status_details = result[0].split(' ')
blocks_used = status_details[3].split('/')[0]
if int(blocks_used) == int(status_details[4]):
break
print "\r-> Reverting template changes: {0} of {1} left".format(blocks_used, root_blocks),
time.sleep(1)
print "\r-> Reverting template changes: done ".format(blocks_used, root_blocks)
dm_table_elements[2] = 'snapshot'
dm_table = ' '.join(dm_table_elements)
subprocess.check_call(["/sbin/dmsetup", "reload", old_dmdev, "--table", dm_table])
# Reload new table into LIVE slot
subprocess.check_call(["/sbin/dmsetup", "suspend", old_dmdev])
subprocess.check_call(["/sbin/dmsetup", "resume", old_dmdev])
subprocess.check_call(["/etc/xen/scripts/block-snapshot", "cleanup",
"snapshot", old_dmdev])
os.rename(oldcow_img, vm.rootcow_img)
exit(0)
main()

View File

@ -79,19 +79,19 @@ def vm_run_cmd(vm, cmd, options):
if options.shutdown:
if options.verbose:
print "Shutting down VM: '{0}'...".format(vm.name)
subprocess.call (["/usr/sbin/xm", "shutdown", vm.name])
subprocess.call (["/usr/sbin/xl", "shutdown", vm.name])
return
if options.pause:
if options.verbose:
print "Pausing VM: '{0}'...".format(vm.name)
subprocess.call (["/usr/sbin/xm", "pause", vm.name])
subprocess.call (["/usr/sbin/xl", "pause", vm.name])
return
if options.unpause:
if options.verbose:
print "UnPausing VM: '{0}'...".format(vm.name)
subprocess.call (["/usr/sbin/xm", "unpause", vm.name])
subprocess.call (["/usr/sbin/xl", "unpause", vm.name])
return
if options.verbose:
@ -152,13 +152,13 @@ def main():
help="Wait for the VM(s) to shutdown")
parser.add_option ("--shutdown", action="store_true", dest="shutdown", default=False,
help="Do 'xm shutdown' for the VM(s) (can be combined this with --all and --wait)")
help="Do 'xl shutdown' for the VM(s) (can be combined this with --all and --wait)")
parser.add_option ("--pause", action="store_true", dest="pause", default=False,
help="Do 'xm pause' for the VM(s) (can be combined this with --all and --wait)")
help="Do 'xl pause' for the VM(s) (can be combined this with --all and --wait)")
parser.add_option ("--unpause", action="store_true", dest="unpause", default=False,
help="Do 'xm unpause' for the VM(s) (can be combined this with --all and --wait)")
help="Do 'xl unpause' for the VM(s) (can be combined this with --all and --wait)")
parser.add_option ("--pass_io", action="store_true", dest="passio", default=False,
help="Pass stdin/stdout/stderr from remote program")
@ -166,6 +166,9 @@ def main():
parser.add_option ("--localcmd", action="store", dest="localcmd", default=None,
help="With --pass_io, pass stdin/stdout/stderr to the given program")
parser.add_option ("--force", action="store_true", dest="force", default=False,
help="Force operation, even if may damage other VMs (eg shutdown of NetVM)")
(options, args) = parser.parse_args ()
@ -218,8 +221,12 @@ def main():
# If stopping NetVM - stop connected VMs too
if options.shutdown and vm.is_netvm():
vms_list += [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
vms_list.reverse()
connected_vms = [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
if connected_vms and not options.force:
print "ERROR: There are other VMs connected to this VM, "
print " shutdown them first or use --force option"
print "VMs list: " + str([vm.name for vm in connected_vms])
exit(1)
if takes_cmd_argument:
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)

46
dom0/qvm-tools/qvm-set-updatevm Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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
from optparse import OptionParser;
def main():
usage = "usage: %prog <vm-name>"
parser = OptionParser (usage)
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("Missing argument!")
vmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None or vm.qid not in qvm_collection:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
qvm_collection.set_updatevm_vm(vm)
qvm_collection.save()
qvm_collection.unlock_db()
main()

199
dom0/qvm-tools/qvm-sync-appmenus Executable file
View File

@ -0,0 +1,199 @@
#!/usr/bin/python
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2011 Marek Marczykowski <marmarek@mimuw.edu.pl>
#
# 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.
#
#
import subprocess
import re
import os
import sys
import fnmatch
import shutil
from optparse import OptionParser
from qubes.qubes import QubesVmCollection,QubesException
from qubes.qubes import qrexec_client_path
# fields required to be present (and verified) in retrieved desktop file
required_fields = [ "Name", "Exec" ]
# regexps for sanitization of retrieved values
std_re = re.compile(r"^[/a-zA-Z0-9.,&() -]*$")
fields_regexp = {
"Name": std_re,
"GenericName": std_re,
"Comment": std_re,
"Categories": re.compile(r"^[a-zA-Z0-9/.; -]*$"),
"Exec": re.compile(r"^[a-zA-Z0-9%>/:.= -]*$"),
}
def get_appmenus(xid):
untrusted_appmenulist = []
if xid == -1:
untrusted_appmenulist = sys.stdin.readlines()
else:
p = subprocess.Popen ([qrexec_client_path, '-d', str(xid),
'user:grep -H = /usr/share/applications/*.desktop'], stdout=subprocess.PIPE)
untrusted_appmenulist = p.communicate()[0].split('\n')
if p.returncode != 0:
raise QubesException("Error getting application list")
row_no = 0
appmenus = {}
line_rx = re.compile(r"([a-zA-Z0-9-.]+.desktop):([a-zA-Z0-9-]+(?:\[[a-zA-Z@_]+\])?)=(.*)")
ignore_rx = re.compile(r".*([a-zA-Z0-9-.]+.desktop):(#.*|\s+)$")
for untrusted_line in untrusted_appmenulist:
# Ignore blank lines and comments
if len(untrusted_line) == 0 or ignore_rx.match(untrusted_line):
continue
# use search instead of match to skip file path
untrusted_m = line_rx.search(untrusted_line)
if untrusted_m:
untrusted_key = untrusted_m.group(2)
untrusted_value = untrusted_m.group(3)
if fields_regexp.has_key(untrusted_key):
if fields_regexp[untrusted_key].match(untrusted_value):
# now values are sanitized
key = untrusted_key
value = untrusted_value
filename = untrusted_m.group(1)
if not appmenus.has_key(filename):
appmenus[filename] = {}
appmenus[filename][key]=value
else:
print >>sys.stderr, "Warning: ignoring key %s: %s" % (untrusted_key, untrusted_value)
# else: ignore this key
else:
print >>sys.stderr, "Warning: ignoring line: %s" % (untrusted_line);
return appmenus
def create_template(path, values):
# check if all required fields are present
for key in required_fields:
if not values.has_key(key):
print >>sys.stderr, "Warning: not creating/updating '%s' because of missing '%s' key" % (path, key)
return
desktop_file = open(path, "w")
desktop_file.write("[Desktop Entry]\n")
desktop_file.write("Version=1.0\n")
desktop_file.write("Type=Application\n")
desktop_file.write("Terminal=false\n")
desktop_file.write("X-Qubes-VmName=%VMNAME%\n")
desktop_file.write("Icon=%VMDIR%/icon.png\n")
for key in ["Name", "GenericName" ]:
if values.has_key(key):
desktop_file.write("{0}=%VMNAME%: {1}\n".format(key, values[key]))
for key in [ "Comment", "Categories" ]:
if values.has_key(key):
desktop_file.write("{0}={1}\n".format(key, values[key]))
desktop_file.write("Exec=qvm-run -q --tray -a %VMNAME% '{0}'\n".format(values['Exec']))
desktop_file.close()
def main():
env_vmname = os.environ.get("QREXEC_REMOTE_DOMAIN")
usage = "usage: %prog [options] <vm-name>\n"\
"Updates desktop file templates for given StandaloneVM or TemplateVM"
parser = OptionParser (usage)
parser.add_option ("-v", "--verbose", action="store_true", dest="verbose", default=False)
(options, args) = parser.parse_args ()
if (len (args) != 1) and env_vmname is None:
parser.error ("You must specify at least the VM name!")
if env_vmname:
vmname=env_vmname
else:
vmname=args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None:
print >>sys.stderr, "ERROR: A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if not vm.is_updateable():
print >>sys.stderr, "ERROR: To sync appmenus for non-updateable VM, do it on template instead"
exit(1)
if not vm.is_running():
print >>sys.stderr, "ERROR: Appmenus can be retrieved only from running VM - start it first"
exit(1)
new_appmenus = {}
if env_vmname is None:
# Get appmenus from VM
xid = vm.get_xid()
assert xid > 0
new_appmenus = get_appmenus(xid)
else:
options.verbose = False
new_appmenus = get_appmenus(-1)
if len(new_appmenus) == 0:
print >>sys.stderr, "ERROR: No appmenus received, terminating"
exit(1)
if not os.path.exists(vm.appmenus_templates_dir):
os.mkdir(vm.appmenus_templates_dir)
if vm.is_template():
shutil.copy('/usr/share/qubes/qubes-templatevm.directory.template', vm.appmenus_templates_dir)
else:
shutil.copy('/usr/share/qubes/qubes-vm.directory.template', vm.appmenus_templates_dir)
# Create new/update existing templates
if options.verbose:
print "--> Got {0} appmenus, storing to disk".format(str(len(new_appmenus)))
for appmenu_file in new_appmenus.keys():
if options.verbose:
if os.path.exists(vm.appmenus_templates_dir + '/' + appmenu_file):
print "---> Updating {0}".format(appmenu_file)
else:
print "---> Creating {0}".format(appmenu_file)
create_template(vm.appmenus_templates_dir + '/' + appmenu_file, new_appmenus[appmenu_file])
# Delete appmenus of remove applications
if options.verbose:
print "--> Cleaning old files"
for appmenu_file in os.listdir(vm.appmenus_templates_dir):
if not fnmatch.fnmatch(appmenu_file, '*.desktop'):
continue
if not new_appmenus.has_key(appmenu_file):
if options.verbose:
print "---> Removing {0}".format(appmenu_file)
os.unlink(vm.appmenus_templates_dir + '/' + appmenu_file)
main()

View File

@ -1,5 +1,7 @@
#!/bin/bash
HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}"
hd_arr[10]=a
hd_arr[11]=b
hd_arr[12]=c
@ -38,6 +40,8 @@ process()
xenstore-write "$XENBUS_PATH/node" "$dev" \
"$XENBUS_PATH/physical-device" "7:"$HEXNUMBER \
"$XENBUS_PATH/hotplug-status" connected
echo "$dev" > "$HOTPLUG_STORE-node"
echo "file" > "$HOTPLUG_STORE-type"
}
#exec 2>>/tmp/block.$$

View File

@ -22,8 +22,13 @@
import os
import sys
import subprocess
import shutil
import glob
from qubes.qubes import QubesVmCollection
updates_dir = "/var/lib/qubes/updates"
updates_rpm_dir = updates_dir + "/rpm"
def is_copy_allowed(vm):
# if vm.copy_allowed:
# return True
@ -33,6 +38,36 @@ def is_copy_allowed(vm):
retcode = subprocess.call(['/usr/bin/kdialog', '--yesno', q, '--title', 'File transfer confirmation'])
return retcode == 0
def dom0updates_fatal(msg):
print >> sys.stderr, msg
shutil.rmtree(updates_rpm_dir)
exit(1)
def handle_dom0updates(updatevm):
source=os.getenv("QREXEC_REMOTE_DOMAIN")
if source != updatevm.name:
print >> sys.stderr, 'Domain ' + source + ' not allowed to send dom0 updates'
exit(1)
# Clean old packages
if os.path.exists(updates_rpm_dir):
shutil.rmtree(updates_rpm_dir)
subprocess.check_call(["/usr/lib/qubes/qfile-dom0-unpacker", os.getlogin(), updates_rpm_dir])
# Verify received files
for f in os.listdir(updates_rpm_dir):
if glob.fnmatch.fnmatch(f, "*.rpm"):
p = subprocess.Popen (["/bin/rpm", "-K", updates_rpm_dir + "/" + f],
stdout=subprocess.PIPE)
output = p.communicate()[0]
if p.returncode != 0:
dom0updates_fatal('Error while verifing %s signature: %s' % (f, output))
if output.find("pgp") < 0:
dom0updates_fatal('Domain ' + source + ' sent not signed rpm: ' + f)
else:
dom0updates_fatal('Domain ' + source + ' sent unexpected file: ' + f)
# After updates received - create repo metadata
subprocess.check_call(["/usr/bin/createrepo", "-q", "/var/lib/qubes/updates"])
exit(0)
def main():
FILECOPY_VMNAME_SIZE = 32
blob=os.read(0, FILECOPY_VMNAME_SIZE)
@ -42,6 +77,11 @@ def main():
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
if vmname == '@dom0updates':
updatevm = qvm_collection.get_updatevm_vm()
handle_dom0updates(updatevm)
# handle_dom0updates never returns
vm = qvm_collection.get_vm_by_name(vmname)
# we do not want to flood dom0 with error windows; so just log to stderr

View File

@ -31,6 +31,7 @@ from qubes.qubes import QubesDaemonPidfile
from qubes.qmemman_client import QMemmanClient
current_savefile = '/var/run/qubes/current_savefile'
current_dvm_conf = '/var/run/qubes/current_dvm.conf'
notify_object = None
class QfileDaemonDvm:
@ -58,6 +59,7 @@ class QfileDaemonDvm:
return None
retcode = subprocess.call(['/usr/lib/qubes/qubes_restore',
current_savefile,
current_dvm_conf,
'-c', vm.label.color,
'-i', vm.label.icon,
'-l', str(vm.label.index)])
@ -130,8 +132,8 @@ def main():
lockf.close()
if dispname is not None:
subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', dispname, 'directly:user:/usr/lib/qubes/dvm_file_editor'])
subprocess.call(['/usr/sbin/xm', 'destroy', dispname])
subprocess.call(['/usr/sbin/xl', 'destroy', dispname])
qfile.remove_disposable_from_qdb(dispname)
main()

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
get_encoded_script()
{
if ! [ -f "$1" ] ; then
@ -42,22 +42,24 @@ if [ -n "$ENCODED_SCRIPT" ] ; then
fi
#set -x
xenstore-write /local/domain/$ID/qubes_save_request 1
xenstore-watch /local/domain/$ID/device/qubes_used_mem
xenstore-watch-qubes /local/domain/$ID/device/qubes_used_mem
xenstore-read /local/domain/$ID/qubes_gateway | \
cut -d . -f 2 | tr -d "\n" > $VMDIR/netvm_id.txt
xm block-detach $1 /dev/xvdb
cut -d . -f 3 | tr -d "\n" > $VMDIR/netvm_id.txt
xl block-detach $1 xvdb
MEM=$(xenstore-read /local/domain/$ID/device/qubes_used_mem)
echo "DVM boot complete, memory used=$MEM. Saving image..."
QMEMMAN_STOP=/var/run/qubes/do-not-membalance
touch $QMEMMAN_STOP
xm mem-set $1 $(($MEM/1000))
xl mem-set $1 $(($MEM/1000))
sleep 1
touch $2
if ! xm save $1 $2 ; then
if ! xl save $1 $2 ; then
rm -f $QMEMMAN_STOP
exit 1
fi
rm -f $QMEMMAN_STOP
cd $VMDIR
# Fix start memory
sed -i -e "s/^memory.*/memory = $((MEM/1000))/" dvm.conf
tar -Scvf saved_cows.tar volatile.img
echo "DVM savefile created successfully."

View File

@ -12,95 +12,73 @@
#include <syslog.h>
#include <xs.h>
char xmlrpc_header[] =
"POST /RPC2 HTTP/1.0\r\n"
"Host: \r\n"
"User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\n"
"Content-Type: text/xml\r\n" "Content-Length: %d\r\n" "\r\n";
char xmlrpc_body_restore[] =
"<?xml version='1.0'?>\n"
"<methodCall>\n"
"<methodName>xend.domain.restore</methodName>\n"
"<params>\n"
"<param>\n"
"<value><string>%s</string></value>\n"
"</param>\n"
"<param>\n"
"<value><boolean>0</boolean></value>\n"
"</param>\n" "</params>\n" "</methodCall>\n";
char xmlrpc_body_setmem[] =
"<?xml version='1.0'?>\n<methodCall>\n<methodName>xend.domain.setMemoryTarget</methodName>\n<params>\n<param>\n<value><string>%d</string></value>\n</param>\n<param>\n<value><int>%d</int></value>\n</param>\n</params>\n</methodCall>\n";
void send_raw(int fd, char *body)
{
char *header;
asprintf(&header, xmlrpc_header, strlen(body));
if (write(fd, header, strlen(header)) != strlen(header)) {
perror("write xend");
int restore_domain(char *restore_file, char *conf_file, char *name) {
int pid, status, domid;
int pipe_fd[2];
char buf[256];
char *endptr;
switch (pid = fork()) {
case -1:
perror("fork");
exit(1);
}
if (write(fd, body, strlen(body)) != strlen(body)) {
perror("write xend");
exit(1);
}
shutdown(fd, SHUT_WR);
}
void send_req_restore(int fd, char *name)
{
char *body;
asprintf(&body, xmlrpc_body_restore, name);
send_raw(fd, body);
}
void send_req_setmem(int fd, int domid, int mem)
{
char *body;
asprintf(&body, xmlrpc_body_setmem, domid, mem);
send_raw(fd, body);
}
char *recv_resp(int fd)
{
#define RESPSIZE 65536
static char buf[RESPSIZE];
int total = 0;
int n;
for (;;) {
n = read(fd, buf + total, RESPSIZE - total);
if (n == 0) {
buf[total] = 0;
close(fd);
return buf;
}
if (n < 0) {
perror("xend read");
case 0:
close(1);
if (dup2(open("/dev/null", O_RDWR), 1)==-1) {
perror("dup2 or open");
exit(1);
}
total += n;
execl("/usr/sbin/xl", "xl", "restore", conf_file, restore_file, NULL);
perror("execl");
exit(1);
default:;
}
if (waitpid(pid, &status, 0) < 0) {
perror("waitpid");
exit(1);
}
if (status != 0) {
fprintf(stderr, "Error starting VM\n");
exit(1);
}
// read domid
if (pipe(pipe_fd)==-1) {
perror("pipe");
exit(1);
}
switch (pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
close(1);
if (dup2(pipe_fd[1], 1) == -1) {
perror("dup2");
exit(1);
}
execl("/usr/sbin/xl", "xl", "domid", name, NULL);
perror("execl");
exit(1);
default:;
}
read(pipe_fd[0], buf, sizeof(buf)-1);
buf[sizeof(buf)-1] = 0;
domid = strtoul(buf, &endptr, 10);
if (domid <= 0 || *endptr != '\n') {
fprintf(stderr, "Cannot get DispVM xid\n");
exit(1);
}
if (waitpid(pid, &status, 0) < 0) {
perror("waitpid");
exit(1);
}
if (status != 0) {
fprintf(stderr, "Error getting DispVM xid\n");
exit(1);
}
return domid;
}
void bad_resp(char *resp)
{
fprintf(stderr, "Error; Xend response:\n%s\n", resp);
exit(1);
}
int parse_resp(char *resp)
{
char *domid;
if (strstr(resp, "<fault>"))
bad_resp(resp);
if (!strstr(resp, "domid"))
bad_resp(resp);
domid = strstr(resp, "<int>");
if (!domid)
bad_resp(resp);
return strtoul(domid + 5, NULL, 0);
}
char *gettime()
{
@ -161,27 +139,6 @@ void preload_cache(int fd)
}
}
int xend_connect()
{
struct sockaddr_un server;
int s;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
perror("socket af_unix");
exit(1);
}
server.sun_family = AF_UNIX;
strcpy(server.sun_path, "/var/run/xend/xmlrpc.sock");
if (connect
(s, (struct sockaddr *) &server,
strlen(server.sun_path) + sizeof(server.sun_family))) {
perror("connext xend");
exit(1);
}
return s;
}
void start_rexec(int domid)
{
int pid, status;
@ -214,40 +171,13 @@ void start_guid(int domid, int argc, char **argv)
guid_args[0] = "qubes_guid";
guid_args[1] = "-d";
guid_args[2] = dstr;
for (i = 2; i < argc; i++)
for (i = 3; i < argc; i++)
guid_args[i + 1] = argv[i];
guid_args[argc + 1] = NULL;
execv("/usr/bin/qubes_guid", guid_args);
perror("execv");
}
// modify the savefile. fd = fd to the open savefile,
// buf - already read 1st page of the savefile
// pattern - pattern to search for
// val - string to replace pattern with
void fix_savefile(int fd, char *buf, char *pattern, char *val)
{
int i, len = strlen(val), origlen;
char *bracket;
char *loc = strstr(buf + 20, pattern) + strlen(pattern);
if (!loc)
return;
bracket = index(loc, ')');
if (!bracket)
return;
origlen = (long) bracket - (long) loc;
if (origlen < len) {
fprintf(stderr, "too long string %s\n", val);
exit(1);
}
for (i = 0; i < origlen - len; i++)
loc[i] = ' ';
memcpy(loc + i, val, strlen(val));
lseek(fd, (long) loc - (long) buf, SEEK_SET);
write(fd, loc, origlen);
}
char *dispname_by_dispid(int dispid)
{
static char retbuf[16];
@ -258,8 +188,7 @@ char *dispname_by_dispid(int dispid)
char *build_dvm_ip(int netvm, int id)
{
static char buf[256];
snprintf(buf, sizeof(buf), "10.%d.%d.%d", netvm, id / 254 + 200,
(id % 254) + 1);
snprintf(buf, sizeof(buf), "10.138.%d.%d", netvm, (id % 254) + 1);
return buf;
}
@ -270,15 +199,17 @@ char *build_dvm_ip(int netvm, int id)
// normally, it should be "templatename-dvm"
char *get_vmname_from_savefile(int fd)
{
int buflen;
static char buf[4096];
char *name;
char *slash;
lseek(fd, 0, SEEK_SET);
if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
perror("read savefile");
buflen = read(fd, buf, sizeof(buf) - 1);
if (buflen < 0) {
perror("read vm conf");
exit(1);
}
buf[sizeof(buf) - 1] = 0;
buf[buflen] = 0;
name = strstr(buf + 20, NAME_PATTERN);
if (!name) {
fprintf(stderr,
@ -296,25 +227,69 @@ char *get_vmname_from_savefile(int fd)
return slash + 1;
}
void fix_savefile_all(int fd, int dispid, int netvm_id)
void fill_field(FILE *conf, char *field, int dispid, int netvm_id)
{
char val[256];
char buf[4096];
lseek(fd, 0, SEEK_SET);
if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
perror("read savefile");
if (!strcmp(field, "NAME")) {
fprintf(conf, "%s", dispname_by_dispid(dispid));
} else if (!strcmp(field, "MAC")) {
fprintf(conf, "00:16:3e:7c:8b:%02x", dispid);
} else if (!strcmp(field, "IP")) {
fprintf(conf, "%s", build_dvm_ip(netvm_id, dispid));
} else if (!strcmp(field, "UUID")) {
// currently not present in conf file
fprintf(conf, "064cd14c-95ad-4fc2-a4c9-cf9f522e5b%02x", dispid);
} else {
fprintf(stderr, "unknown field in vm conf: %s\n", field);
exit(1);
}
buf[sizeof(buf) - 1] = 0;
snprintf(val, sizeof(val),
"064cd14c-95ad-4fc2-a4c9-cf9f522e5b%02x", dispid);
fix_savefile(fd, buf, "(uuid ", val);
fix_savefile(fd, buf, "(name ", dispname_by_dispid(dispid));
snprintf(val, sizeof(val), "00:16:3e:7c:8b:%02x", dispid);
fix_savefile(fd, buf, "(mac ", val);
fix_savefile(fd, buf, "(ip ", build_dvm_ip(netvm_id, dispid));
}
// modify the config file. conf = FILE of the new config,
// conf_templ - fd of config template
// pattern - pattern to search for
// val - string to replace pattern with
void fix_conffile(FILE *conf, int conf_templ, int dispid, int netvm_id)
{
int buflen, cur_len = 0;
char buf[4096];
char *bufpos = buf;
char *pattern, *patternend;
/* read config template */
lseek(conf_templ, 0, SEEK_SET);
while ((cur_len = read(conf_templ, buf+cur_len, sizeof(buf)-cur_len)) > 0) {
buflen+=cur_len;
}
if (cur_len < 0) {
perror("read vm conf");
exit(1);
}
while ((pattern = index(bufpos, '%'))) {
fwrite(bufpos, 1, pattern-bufpos, conf);
if (ferror(conf)) {
perror("write vm conf");
exit(1);
}
patternend = index(pattern+1, '%');
if (!patternend) {
fprintf(stderr, "Unmatched '%%' in VM config\n");
exit(1);
}
*patternend = '\0';
fill_field(conf, pattern+1, dispid, netvm_id);
bufpos = patternend+1;
}
while ((cur_len = fwrite(bufpos, 1, buflen-(bufpos-buf), conf)) > 0) {
bufpos+=cur_len;
}
if (ferror(conf)) {
perror("write vm conf");
exit(1);
}
}
void unpack_cows(char *name)
{
char vmdir[4096];
@ -355,6 +330,17 @@ void write_xs_single(struct xs_handle *xs, int domid, char *name,
}
}
void perm_xs_single(struct xs_handle *xs, int domid, char *name,
struct xs_permissions *perms, int nperms)
{
char key[256];
snprintf(key, sizeof(key), "/local/domain/%d/%s", domid, name);
if (!xs_set_permissions(xs, XBT_NULL, key, perms, nperms)) {
fprintf(stderr, "xs_set_permissions");
exit(1);
}
}
int get_netvm_id_from_name(char *name)
{
int fd, n;
@ -377,6 +363,7 @@ void setup_xenstore(int netvm_id, int domid, int dvmid, char *name)
{
char val[256];
struct xs_handle *xs = xs_daemon_open();
struct xs_permissions perm[1];
if (!xs) {
perror("xs_daemon_open");
exit(1);
@ -385,12 +372,18 @@ void setup_xenstore(int netvm_id, int domid, int dvmid, char *name)
write_xs_single(xs, domid, "qubes_ip",
build_dvm_ip(netvm_id, dvmid));
write_xs_single(xs, domid, "qubes_netmask", "255.255.0.0");
snprintf(val, sizeof(val), "10.%d.0.1", netvm_id);
snprintf(val, sizeof(val), "10.137.%d.1", netvm_id);
write_xs_single(xs, domid, "qubes_gateway", val);
snprintf(val, sizeof(val), "10.%d.255.254", netvm_id);
snprintf(val, sizeof(val), "10.137.%d.254", netvm_id);
write_xs_single(xs, domid, "qubes_secondary_dns", val);
write_xs_single(xs, domid, "qubes_vm_type", "AppVM");
write_xs_single(xs, domid, "qubes_restore_complete", "True");
perm[0].id = domid;
perm[0].perms = XS_PERM_NONE;
perm_xs_single(xs, domid, "device", perm, 1);
perm_xs_single(xs, domid, "memory", perm, 1);
xs_daemon_close(xs);
}
@ -437,46 +430,45 @@ void redirect_stderr()
int main(int argc, char **argv)
{
int fd, domid, dispid, netvm_id;
char *resp;
int conf_templ, domid, dispid, netvm_id;
FILE *conf;
char *name;
if (argc < 2) {
char confname[256];
if (argc < 3) {
fprintf(stderr,
"usage: %s savefile [guid args] \n", argv[0]);
"usage: %s savefile conf_templ [guid args] \n", argv[0]);
exit(1);
}
redirect_stderr();
fprintf(stderr, "time=%s, starting\n", gettime());
set_fast_flag();
atexit(rm_fast_flag);
fd = open(argv[1], O_RDWR);
if (fd < 0) {
perror("open savefile");
conf_templ = open(argv[2], O_RDONLY);
if (conf_templ < 0) {
perror("fopen vm conf");
exit(1);
}
dispid = get_next_disposable_id();
name = get_vmname_from_savefile(fd);
name = get_vmname_from_savefile(conf_templ);
netvm_id = get_netvm_id_from_name(name);
fix_savefile_all(fd, dispid, netvm_id);
snprintf(confname, sizeof(confname), "/tmp/qubes-dvm-%d.xl", dispid);
conf = fopen(confname, "w");
if (!conf) {
perror("fopen new vm conf");
exit(1);
}
fix_conffile(conf, conf_templ, dispid, netvm_id);
close(conf_templ);
fclose(conf);
// printf("name=%s\n", name);
unpack_cows(name);
// no preloading for now, assume savefile in shm
// preload_cache(fd);
fd = xend_connect();
send_req_restore(fd, argv[1]);
resp = recv_resp(fd);
domid = parse_resp(resp);
domid=restore_domain(argv[1], confname, dispname_by_dispid(dispid));
write_varrun_domid(domid, dispname_by_dispid(dispid), name);
fprintf(stderr,
"time=%s, created domid=%d, creating xenstore entries\n",
gettime(), domid);
#if 0
fd = xend_connect();
send_req_setmem(fd, domid, 400);
resp = recv_resp(fd);
// printf("%s\n", resp);
fprintf(stderr, "time=%s, creating xenstore entries\n", gettime());
#endif
setup_xenstore(netvm_id, domid, dispid, name);
fprintf(stderr, "time=%s, starting qubes_guid\n", gettime());
rm_fast_flag();

View File

@ -40,12 +40,16 @@ if ! /usr/lib/qubes/qubes_prepare_saved_domain.sh \
fi
ROOT=/var/lib/qubes/dvmdata/savefile_root
DEFAULT=/var/lib/qubes/dvmdata/default_savefile
DEFAULTCONF=/var/lib/qubes/dvmdata/default_dvm.conf
CURRENT=/var/run/qubes/current_savefile
CURRENTCONF=/var/run/qubes/current_dvm.conf
SHMDIR=/dev/shm/qubes
SHMCOPY=$SHMDIR/current_savefile
rm -f $ROOT $DEFAULT $CURRENT
rm -f $ROOT $DEFAULT $CURRENT $DEFAULTCONF $CURRENTCONF
ln -s "/var/lib/qubes/appvms/$DVMTMPL/dvm-savefile" $DEFAULT
ln -s "/var/lib/qubes/vm-templates/$TEMPLATENAME/root.img" $ROOT
ln -s $DVMTMPLDIR/dvm.conf $DEFAULTCONF
ln -s $DVMTMPLDIR/dvm.conf $CURRENTCONF
if [ -f /var/lib/qubes/dvmdata/dont_use_shm ] ; then
ln -s $DEFAULT $CURRENT
else

View File

@ -4,8 +4,13 @@
struct xen_sysctl_physinfo xphysinfo;
main()
{
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_interface *handle = xc_interface_open(NULL, NULL, 0);
if (!handle) {
#else
int handle = xc_interface_open();
if (handle == -1) {
#endif
perror("xc_interface_open");
exit(1);
}

View File

@ -1,42 +0,0 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!--
WARNING: if running any D-Bus version prior to 1.2.6, you may be
vulnerable to information leakage via the NM D-Bus interface.
Previous D-Bus versions did not deny-by-default, and this permissions
config file assumes that D-Bus will deny rules by default unless
explicitly over-ridden with an <allow /> tag.
-->
<policy user="root">
<allow own="org.freedesktop.NetworkManagerUserSettings"/>
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
send_interface="org.freedesktop.NetworkManagerSettings"/>
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
send_interface="org.freedesktop.NetworkManagerSettings.Connection"/>
<!-- Only root can get secrets -->
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
send_interface="org.freedesktop.NetworkManagerSettings.Connection.Secrets"/>
</policy>
<policy user="user">
<allow own="org.freedesktop.NetworkManagerUserSettings"/>
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
send_interface="org.freedesktop.NetworkManagerSettings"/>
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
send_interface="org.freedesktop.NetworkManagerSettings.Connection"/>
</policy>
<policy context="default">
<allow send_destination="org.freedesktop.NetworkManagerUserSettings"
send_interface="org.freedesktop.DBus.Introspectable"/>
</policy>
<limit name="max_replies_per_connection">512</limit>
</busconfig>

View File

@ -19,6 +19,9 @@ while true; do
IPTABLES_SAVE=$(/sbin/iptables-save | sed '/^\*filter/,/^COMMIT/d')
OUT=`echo -e "$RULES\n$IPTABLES_SAVE" | /sbin/iptables-restore 2>&1 || :`
/usr/bin/xenstore-write $XENSTORE_ERROR "$OUT"
if [ "$OUT" ]; then
DISPLAY=:0 /usr/bin/notify-send -t 3000 "Firewall loading error ($HOSTNAME)" "$OUT" || :
fi
if [[ -z "$OUT" ]]; then
# If OK save it for later
@ -29,5 +32,5 @@ while true; do
fi
# Wait for changes in xenstore file
/usr/bin/xenstore-watch $XENSTORE_IPTABLES
/usr/bin/xenstore-watch-qubes $XENSTORE_IPTABLES
done

View File

@ -24,8 +24,8 @@ while true; do
/usr/bin/xenstore-write qubes_netvm_external_ip "$CURR_NETCFG"
fi
/usr/bin/xenstore-watch /local/domain/$NET_DOMID/qubes_netvm_external_ip
/usr/bin/xenstore-watch-qubes /local/domain/$NET_DOMID/qubes_netvm_external_ip
else
/usr/bin/xenstore-watch qubes_netvm_domid
/usr/bin/xenstore-watch-qubes qubes_netvm_domid
fi
done

View File

@ -51,7 +51,8 @@ enum {
enum {
QREXEC_EXECUTE_FILE_COPY=0x700,
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM,
QREXEC_EXECUTE_APPMENUS_SYNC
};
struct server_header {

View File

@ -482,6 +482,9 @@ void handle_trigger_io()
else if (!strcmp(buf, "DVMR"))
s_hdr.client_id =
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM;
else if (!strcmp(buf, "SYNC"))
s_hdr.client_id =
QREXEC_EXECUTE_APPMENUS_SYNC;
if (s_hdr.client_id) {
s_hdr.type = MSG_AGENT_TO_SERVER_TRIGGER_EXEC;
write_all_vchan_ext(&s_hdr, sizeof s_hdr);

View File

@ -361,6 +361,10 @@ void handle_execute_predefined_command(int req)
rcmd = "directly:user:/usr/lib/qubes/qfile-agent-dvm";
lcmd = "/usr/lib/qubes/qfile-daemon-dvm";
break;
case QREXEC_EXECUTE_APPMENUS_SYNC:
rcmd = "user:grep -H = /usr/share/applications/*.desktop";
lcmd = "/usr/bin/qvm-sync-appmenus";
break;
default: /* cannot happen, already sanitized */
fprintf(stderr, "got trigger exec no %d\n", req);
exit(1);
@ -402,7 +406,8 @@ void sanitize_message_from_agent(struct server_header *untrusted_header)
case MSG_AGENT_TO_SERVER_TRIGGER_EXEC:
untrusted_cmd = untrusted_header->client_id;
if (untrusted_cmd != QREXEC_EXECUTE_FILE_COPY &&
untrusted_cmd != QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM) {
untrusted_cmd != QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM &&
untrusted_cmd != QREXEC_EXECUTE_APPMENUS_SYNC) {
fprintf(stderr,
"received MSG_AGENT_TO_SERVER_TRIGGER_EXEC cmd %d ?\n",
untrusted_cmd);

View File

@ -83,7 +83,11 @@ int buffer_space_vchan_ext()
// if the remote domain is destroyed, we get no notification
// thus, we check for the status periodically
#ifdef XENCTRL_HAS_XC_INTERFACE
static xc_interface *xc_handle = NULL;
#else
static int xc_handle = -1;
#endif
void slow_check_for_libvchan_is_eof(struct libvchan *ctrl)
{
struct evtchn_status evst;
@ -198,8 +202,13 @@ char *peer_client_init(int dom, int port)
// now client init should succeed; "while" is redundant
while (!(ctrl = libvchan_client_init(dom, port)));
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_handle = xc_interface_open(NULL, 0, 0);
if (!xc_handle) {
#else
xc_handle = xc_interface_open();
if (xc_handle < 0) {
#endif
perror("xc_interface_open");
exit(1);
}

View File

@ -33,6 +33,7 @@ License: GPL
URL: http://www.qubes-os.org
Requires: /usr/bin/xenstore-read
Requires: fedora-release
Requires: yum-plugin-post-transaction-actions
BuildRequires: xen-devel
%define _builddir %(pwd)/common
@ -71,24 +72,76 @@ install -m 644 RPM-GPG-KEY-qubes* $RPM_BUILD_ROOT/etc/pki/rpm-gpg/
mkdir -p $RPM_BUILD_ROOT/sbin
cp qubes_serial_login $RPM_BUILD_ROOT/sbin
mkdir -p $RPM_BUILD_ROOT/usr/bin
cp xenstore-watch $RPM_BUILD_ROOT/usr/bin
cp xenstore-watch $RPM_BUILD_ROOT/usr/bin/xenstore-watch-qubes
mkdir -p $RPM_BUILD_ROOT/etc
cp serial.conf $RPM_BUILD_ROOT/var/lib/qubes/
mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d
cp qubes_network.rules $RPM_BUILD_ROOT/etc/udev/rules.d/
mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes/
cp setup_ip $RPM_BUILD_ROOT/usr/lib/qubes/
cp qubes_download_dom0_updates.sh $RPM_BUILD_ROOT/usr/lib/qubes/
mkdir -p $RPM_BUILD_ROOT/etc/yum/post-actions
cp qubes_trigger_sync_appmenus.action $RPM_BUILD_ROOT/etc/yum/post-actions/
mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes
cp qubes_trigger_sync_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes/
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/dom0-updates
%triggerin -- initscripts
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
%post
# Disable gpk-update-icon
sed 's/^NotShowIn=KDE;$/\0QUBES;/' -i /etc/xdg/autostart/gpk-update-icon.desktop
# disable some Upstart services
for F in plymouth-shutdown prefdm splash-manager start-ttys tty ; do
if [ -e /etc/init/$F.conf ]; then
mv -f /etc/init/$F.conf /etc/init/$F.conf.disabled
fi
done
remove_ShowIn () {
if [ -e /etc/xdg/autostart/$1.desktop ]; then
sed -i '/^\(Not\|Only\)ShowIn/d' /etc/xdg/autostart/$1.desktop
fi
}
# don't want it at all
for F in abrt-applet deja-dup-monitor imsettings-start krb5-auth-dialog pulseaudio restorecond sealertauto ; do
if [ -e /etc/xdg/autostart/$F.desktop ]; then
remove_ShowIn $F
echo 'NotShowIn=QUBES' >> /etc/xdg/autostart/$F.desktop
fi
done
# don't want it in DisposableVM
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
fi
done
# want it in AppVM only
for F in gnome-keyring-gpg gnome-keyring-pkcs11 gnome-keyring-secrets gnome-keyring-ssh gnome-settings-daemon user-dirs-update-gtk gsettings-data-convert ; do
if [ -e /etc/xdg/autostart/$F.desktop ]; then
remove_ShowIn $F
echo 'OnlyShowIn=GNOME;AppVM;' >> /etc/xdg/autostart/$F.desktop
fi
done
# remove existing rule to add own later
for F in gpk-update-icon nm-applet ; do
remove_ShowIn $F
done
echo 'OnlyShowIn=GNOME;UpdateableVM;' >> /etc/xdg/autostart/gpk-update-icon.desktop || :
echo 'OnlyShowIn=GNOME;NetVM;' >> /etc/xdg/autostart/nm-applet.desktop || :
usermod -p '' root
if [ "$1" != 1 ] ; then
# do this whole %post thing only when updating for the first time...
exit 0
fi
usermod -L root
if ! [ -f /var/lib/qubes/serial.orig ] ; then
cp /etc/init/serial.conf /var/lib/qubes/serial.orig
fi
@ -177,4 +230,9 @@ rm -rf $RPM_BUILD_ROOT
/etc/yum.repos.d/qubes%{dist}.repo
/etc/pki/rpm-gpg/RPM-GPG-KEY-qubes*
/sbin/qubes_serial_login
/usr/bin/xenstore-watch
/usr/bin/xenstore-watch-qubes
/etc/udev/rules.d/qubes_network.rules
/usr/lib/qubes/setup_ip
/etc/yum/post-actions/qubes_trigger_sync_appmenus.action
/usr/lib/qubes/qubes_trigger_sync_appmenus.sh
/usr/lib/qubes/qubes_download_dom0_updates.sh

View File

@ -39,8 +39,9 @@ URL: http://www.qubes-os.org
BuildRequires: xen-devel
Requires: python, xen-runtime, pciutils, python-inotify, python-daemon, kernel-qubes-dom0
Conflicts: qubes-gui-dom0 < 1.1.13
Requires: yum-plugin-post-transaction-actions
Requires: NetworkManager >= 0.8.1-1
Requires: xen >= 3.4.3-6
Requires: xen >= 4.1.0-2
%define _builddir %(pwd)/dom0
%description
@ -50,6 +51,7 @@ The Qubes core files for installation on Dom0.
python -m compileall qvm-core qmemman
python -O -m compileall qvm-core qmemman
make -C restore
make -C aux-tools
make -C ../common
make -C ../vchan
make -C ../u2mfn
@ -89,17 +91,26 @@ cp aux-tools/convert_dirtemplate2vm.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/create_apps_for_appvm.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/remove_appvm_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/reset_vm_configs.py $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/sync_rpmdb_updatevm.sh $RPM_BUILD_ROOT/usr/lib/qubes/
cp qmemman/server.py $RPM_BUILD_ROOT/usr/lib/qubes/qmemman_daemon.py
cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes/
cp ../qrexec/qrexec_daemon $RPM_BUILD_ROOT/usr/lib/qubes/
cp ../qrexec/qrexec_client $RPM_BUILD_ROOT/usr/lib/qubes/
cp aux-tools/qfile-dom0-unpacker $RPM_BUILD_ROOT/usr/lib/qubes/
cp restore/xenstore-watch restore/qvm-create-default-dvm $RPM_BUILD_ROOT/usr/bin
cp restore/qvm-create-default-dvm $RPM_BUILD_ROOT/usr/bin
cp restore/xenstore-watch $RPM_BUILD_ROOT/usr/bin/xenstore-watch-qubes
cp restore/qubes_restore restore/xenfreepages $RPM_BUILD_ROOT/usr/lib/qubes
cp restore/qubes_prepare_saved_domain.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp restore/qfile-daemon-dvm $RPM_BUILD_ROOT/usr/lib/qubes
cp restore/qfile-daemon $RPM_BUILD_ROOT/usr/lib/qubes
mkdir -p $RPM_BUILD_ROOT/etc/yum.real.repos.d
cp qubes-cached.repo $RPM_BUILD_ROOT/etc/yum.real.repos.d/
mkdir -p $RPM_BUILD_ROOT/etc/yum/post-actions
cp misc/qubes_sync_rpmdb_updatevm.action $RPM_BUILD_ROOT/etc/yum/post-actions/
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/vm-templates
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/appvms
@ -108,8 +119,14 @@ mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/servicevms
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/backup
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/dvmdata
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/updates
mkdir -p $RPM_BUILD_ROOT/usr/share/qubes/icons
cp icons/*.png $RPM_BUILD_ROOT/usr/share/qubes/icons
cp misc/qubes-vm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
cp misc/qubes-templatevm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
cp misc/qubes-appmenu-select.template $RPM_BUILD_ROOT/usr/share/qubes/
cp misc/vm-template.conf $RPM_BUILD_ROOT/usr/share/qubes/
mkdir -p $RPM_BUILD_ROOT/usr/bin
cp ../common/qubes_setup_dnat_to_ns $RPM_BUILD_ROOT/usr/lib/qubes
@ -120,6 +137,8 @@ mkdir -p $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/
cp ../common/qubes_nmhook $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
cp ../common/iptables $RPM_BUILD_ROOT/etc/sysconfig
mkdir -p $RPM_BUILD_ROOT/etc/security/limits.d
cp misc/limits-qubes.conf $RPM_BUILD_ROOT/etc/security/limits.d/99-qubes.conf
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/
@ -150,6 +169,13 @@ fi
sed 's/^net.ipv4.ip_forward.*/net.ipv4.ip_forward = 1/' -i /etc/sysctl.conf
sed '/^autoballoon=/d;/^lockfile=/d' -i /etc/xen/xl.conf
echo 'autoballoon=0' >> /etc/xen/xl.conf
echo 'lockfile="/var/run/qubes/xl-lock"' >> /etc/xen/xl.conf
sed '/^reposdir=/d' -i /etc/yum.conf
echo reposdir=/etc/yum.real.repos.d >> /etc/yum.conf
chkconfig --add qubes_core || echo "WARNING: Cannot add service qubes_core!"
chkconfig --add qubes_netvm || echo "WARNING: Cannot add service qubes_netvm!"
chkconfig --add qubes_setupdvm || echo "WARNING: Cannot add service qubes_setupdvm!"
@ -158,6 +184,10 @@ chkconfig --level 5 qubes_core on || echo "WARNING: Cannot enable service qubes_
chkconfig --level 5 qubes_netvm on || echo "WARNING: Cannot enable service qubes_netvm!"
chkconfig --level 5 qubes_setupdvm on || echo "WARNING: Cannot enable service qubes_setupdvm!"
# Conflicts with libxl stack, so disable it
service xend stop
chkconfig --level 5 xend off
HAD_SYSCONFIG_NETWORK=yes
if ! [ -e /etc/sysconfig/network ]; then
HAD_SYSCONFIG_NETWORK=no
@ -167,10 +197,7 @@ fi
# Load evtchn module - xenstored needs it
modprobe evtchn
# Now launch xend - we will need it for subsequent steps
service xenstored start
service xend start
if ! [ -e /var/lib/qubes/qubes.xml ]; then
# echo "Initializing Qubes DB..."
@ -259,13 +286,20 @@ fi
/usr/lib/qubes/meminfo-writer
/usr/lib/qubes/qfile-daemon-dvm*
/usr/lib/qubes/qfile-daemon
/usr/lib/qubes/sync_rpmdb_updatevm.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
%dir /usr/share/qubes/icons/*.png
/usr/share/qubes/qubes-vm.directory.template
/usr/share/qubes/qubes-templatevm.directory.template
/usr/share/qubes/qubes-appmenu-select.template
/usr/share/qubes/vm-template.conf
/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
@ -274,7 +308,7 @@ fi
/usr/lib64/pm-utils/sleep.d/01qubes-sync-vms-clock
/usr/lib64/pm-utils/sleep.d/01qubes-suspend-netvm
/usr/lib64/pm-utils/sleep.d/02qubes-pause-vms
/usr/bin/xenstore-watch
/usr/bin/xenstore-watch-qubes
/usr/lib/qubes/qubes_restore
/usr/lib/qubes/qubes_prepare_saved_domain.sh
/etc/xen/scripts/block.qubes
@ -288,5 +322,8 @@ fi
%attr(770,root,qubes) %dir /var/run/qubes
%{_libdir}/libvchan.so
%{_libdir}/libu2mfn.so
/etc/yum.real.repos.d/qubes-cached.repo
/etc/sudoers.d/qubes
/etc/xdg/autostart/qubes-guid.desktop
/etc/security/limits.d/99-qubes.conf
/etc/yum/post-actions/qubes_sync_rpmdb_updatevm.action

View File

@ -66,9 +66,6 @@ mkdir -p $RPM_BUILD_ROOT/var/run/qubes
mkdir -p $RPM_BUILD_ROOT/etc/xen/scripts
cp ../common/vif-route-qubes $RPM_BUILD_ROOT/etc/xen/scripts
mkdir -p $RPM_BUILD_ROOT/etc/dbus-1/system.d
cp ../netvm/dbus-nm-applet.conf $RPM_BUILD_ROOT/etc/dbus-1/system.d/qubes-nm-applet.conf
%post
# Create NetworkManager configuration if we do not have it
@ -91,11 +88,6 @@ if [ "$1" = 0 ] ; then
chkconfig qubes_core_netvm off
fi
%triggerin -- NetworkManager
# Fix PolicyKit settings to allow run as normal user not visible to ConsoleKit
sed 's#<defaults>$#\0<allow_any>yes</allow_any>#' -i /usr/share/polkit-1/actions/org.freedesktop.NetworkManager.policy
%clean
rm -rf $RPM_BUILD_ROOT
@ -108,4 +100,3 @@ rm -rf $RPM_BUILD_ROOT
/etc/NetworkManager/dispatcher.d/qubes_nmhook
/etc/NetworkManager/dispatcher.d/30-qubes_external_ip
/etc/xen/scripts/vif-route-qubes
/etc/dbus-1/system.d/qubes-nm-applet.conf

View File

@ -65,15 +65,25 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
struct xs_handle *xs;
char buf[64];
char ref[16];
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_evtchn *evfd;
#else
int evfd;
#endif
evtchn_port_or_error_t port;
xs = xs_domain_open();
if (!xs) {
return ret;
}
#ifdef XENCTRL_HAS_XC_INTERFACE
evfd = xc_evtchn_open(NULL, 0);
if (!evfd)
goto fail;
#else
evfd = xc_evtchn_open();
if (evfd < 0)
goto fail;
#endif
ctrl->evfd = evfd;
// the following hardcoded 0 is the peer domain id
port = xc_evtchn_bind_unbound_port(evfd, 0);
@ -98,7 +108,11 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
ret = 0;
fail2:
if (ret)
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_evtchn_close(evfd);
#else
close(evfd);
#endif
fail:
xs_daemon_close(xs);
return ret;
@ -152,10 +166,18 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno)
int ret = -1;
unsigned int len;
struct xs_handle *xs;
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_interface *xcfd;
#else
int xcfd;
#endif
char buf[64];
char *ref;
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_evtchn *evfd;
#else
int evfd;
#endif
int remote_port;
xs = xs_daemon_open();
if (!xs) {
@ -181,23 +203,43 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno)
if (!remote_port)
goto fail;
free(ref);
#ifdef XENCTRL_HAS_XC_INTERFACE
xcfd = xc_interface_open(NULL, NULL, 0);
if (!xcfd)
goto fail;
#else
xcfd = xc_interface_open();
if (xcfd < 0)
goto fail;
#endif
ctrl->ring = (struct vchan_interface *)
xc_map_foreign_range(xcfd, domain, 4096,
PROT_READ | PROT_WRITE, ctrl->ring_ref);
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_interface_close(xcfd);
#else
close(xcfd);
#endif
if (ctrl->ring == 0 || ctrl->ring == MAP_FAILED)
goto fail;
#ifdef XENCTRL_HAS_XC_INTERFACE
evfd = xc_evtchn_open(NULL, 0);
if (!evfd)
goto fail;
#else
evfd = xc_evtchn_open();
if (evfd < 0)
goto fail;
#endif
ctrl->evfd = evfd;
ctrl->evport =
xc_evtchn_bind_interdomain(evfd, domain, remote_port);
if (ctrl->evport < 0 || xc_evtchn_notify(evfd, ctrl->evport))
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_evtchn_close(evfd);
#else
close(evfd);
#endif
else
ret = 0;
fail:

View File

@ -149,7 +149,7 @@ int libvchan_close(struct libvchan *ctrl)
/// The fd to use for select() set
int libvchan_fd_for_select(struct libvchan *ctrl)
{
return ctrl->evfd;
return xc_evtchn_fd(ctrl->evfd);
}
/// Unmasks event channel; must be called before calling select(), and only then

View File

@ -20,6 +20,7 @@
*/
#include <stdint.h>
#include <xenctrl.h>
typedef uint32_t VCHAN_RING_IDX;
/// struct vchan_interface is placed in memory shared between domains
@ -37,7 +38,11 @@ struct libvchan {
struct vchan_interface *ring;
uint32_t ring_ref;
/// descriptor to event channel interface
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_evtchn *evfd;
#else
int evfd;
#endif
int evport;
VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod;
char *rd_ring, *wr_ring;

View File

@ -1 +1 @@
1.5.26
1.6.1

View File

@ -1 +1 @@
1.5.28
1.6.1