Merge branch 'master' of git.qubes-os.org:/var/lib/qubes/git/marmarek/core
Conflicts: version_vm
This commit is contained in:
commit
b76ead2cb2
1
Makefile
1
Makefile
@ -57,5 +57,6 @@ clean:
|
|||||||
(cd dom0/restore && make clean)
|
(cd dom0/restore && make clean)
|
||||||
(cd dom0/qmemman && make clean)
|
(cd dom0/qmemman && make clean)
|
||||||
(cd common && make clean)
|
(cd common && make clean)
|
||||||
|
(cd u2mfn && make clean)
|
||||||
make -C qrexec clean
|
make -C qrexec clean
|
||||||
make -C vchan clean
|
make -C vchan clean
|
||||||
|
@ -5,9 +5,9 @@ dvm_file_editor: dvm_file_editor.o ../common/ioall.o
|
|||||||
$(CC) -pie -g -o $@ $^
|
$(CC) -pie -g -o $@ $^
|
||||||
qfile-agent-dvm: qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o
|
qfile-agent-dvm: qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o
|
||||||
$(CC) -pie -g -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 $@ $^
|
$(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 $@ $^
|
$(CC) -pie -g -o $@ $^
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@ -20,15 +20,15 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
if [ x"$1" = "x--with-progress" ] ; then
|
if [ x"$1" = "x--without-progress" ] ; then
|
||||||
DO_PROGRESS=1
|
DO_PROGRESS=0
|
||||||
shift
|
shift
|
||||||
else
|
else
|
||||||
DO_PROGRESS=0
|
DO_PROGRESS=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $# -lt 2 ] ; then
|
if [ $# -lt 2 ] ; then
|
||||||
echo usage: $0 '[--with-progress] dest_vmname file [file]+'
|
echo usage: $0 '[--without-progress] dest_vmname file [file]+'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -6,4 +6,4 @@ meminfo-writer: meminfo-writer.o
|
|||||||
xenstore-watch: xenstore-watch.o
|
xenstore-watch: xenstore-watch.o
|
||||||
$(CC) -o xenstore-watch xenstore-watch.o -lxenstore
|
$(CC) -o xenstore-watch xenstore-watch.o -lxenstore
|
||||||
clean:
|
clean:
|
||||||
rm -f meminfo-writer *.o *~
|
rm -f meminfo-writer xenstore-watch *.o *~
|
||||||
|
@ -5,7 +5,16 @@
|
|||||||
# This creates dm-snapshot device on given arguments
|
# This creates dm-snapshot device on given arguments
|
||||||
|
|
||||||
dir=$(dirname "$0")
|
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() {
|
get_dev() {
|
||||||
dev=$1
|
dev=$1
|
||||||
@ -89,7 +98,6 @@ create_dm_snapshot_origin() {
|
|||||||
|
|
||||||
t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING')
|
t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING')
|
||||||
|
|
||||||
|
|
||||||
case "$command" in
|
case "$command" in
|
||||||
add)
|
add)
|
||||||
case $t in
|
case $t in
|
||||||
@ -117,24 +125,81 @@ case "$command" in
|
|||||||
if [ "$t" == "snapshot" ]; then
|
if [ "$t" == "snapshot" ]; then
|
||||||
#that's all for snapshot, store name of prepared device
|
#that's all for snapshot, store name of prepared device
|
||||||
xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname"
|
xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname"
|
||||||
|
echo "/dev/mapper/$dm_devname" > "$HOTPLUG_STORE-node"
|
||||||
write_dev /dev/mapper/$dm_devname
|
write_dev /dev/mapper/$dm_devname
|
||||||
elif [ "$t" == "origin" ]; then
|
elif [ "$t" == "origin" ]; then
|
||||||
# for origin - prepare snapshot-origin device and store its name
|
# for origin - prepare snapshot-origin device and store its name
|
||||||
dm_devname=origin-$(stat -c '%D:%i' "$base")
|
dm_devname=origin-$(stat -c '%D:%i' "$base")
|
||||||
create_dm_snapshot_origin $dm_devname "$base"
|
create_dm_snapshot_origin $dm_devname "$base"
|
||||||
xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname"
|
xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname"
|
||||||
|
echo "/dev/mapper/$dm_devname" > "$HOTPLUG_STORE-node"
|
||||||
write_dev /dev/mapper/$dm_devname
|
write_dev /dev/mapper/$dm_devname
|
||||||
fi
|
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"
|
release_lock "block"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
remove)
|
remove|cleanup)
|
||||||
|
if [ "$command" = "cleanup" ]; then
|
||||||
|
t=$2
|
||||||
|
else
|
||||||
|
t=$(cat $HOTPLUG_STORE-type)
|
||||||
|
fi
|
||||||
case $t in
|
case $t in
|
||||||
snapshot|origin)
|
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
|
if [ -z "$node" ]; then
|
||||||
fatal "No device node to remove"
|
fatal "No device node to remove"
|
||||||
@ -174,14 +239,16 @@ case "$command" in
|
|||||||
dmsetup remove $snap
|
dmsetup remove $snap
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
# Commit template changes
|
if [ "$command" = "remove" ]; then
|
||||||
domain=$(xenstore_read "$XENBUS_PATH/domain")
|
# Commit template changes
|
||||||
if [ "$domain" ]; then
|
domain=$(cat "$HOTPLUG_STORE-domain")
|
||||||
# Dont stop on errors
|
if [ "$domain" ]; then
|
||||||
/usr/bin/qvm-template-commit "$domain" || true
|
# Dont stop on errors
|
||||||
|
/usr/bin/qvm-template-commit "$domain" || true
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -e $node ]; then
|
if [ -e $node ]; then
|
||||||
log debug "Removing $node"
|
log debug "Removing $node"
|
||||||
dmsetup remove $node
|
dmsetup remove $node
|
||||||
|
51
common/qubes_download_dom0_updates.sh
Executable file
51
common/qubes_download_dom0_updates.sh
Executable 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
|
2
common/qubes_network.rules
Normal file
2
common/qubes_network.rules
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
SUBSYSTEMS=="xen", KERNEL=="eth*", ACTION=="add", RUN+="/usr/lib/qubes/setup_ip"
|
1
common/qubes_trigger_sync_appmenus.action
Normal file
1
common/qubes_trigger_sync_appmenus.action
Normal file
@ -0,0 +1 @@
|
|||||||
|
*:any:/usr/lib/qubes/qubes_trigger_sync_appmenus.sh
|
7
common/qubes_trigger_sync_appmenus.sh
Executable file
7
common/qubes_trigger_sync_appmenus.sh
Executable 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
13
common/setup_ip
Executable 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
|
@ -1,3 +1,4 @@
|
|||||||
|
#define _GNU_SOURCE /* For O_NOFOLLOW. */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ioall.h>
|
#include <ioall.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
1
dom0/aux-tools/.gitignore
vendored
Normal file
1
dom0/aux-tools/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
qfile-dom0-unpacker
|
4
dom0/aux-tools/Makefile
Normal file
4
dom0/aux-tools/Makefile
Normal 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 $@ $^
|
@ -22,20 +22,29 @@
|
|||||||
|
|
||||||
SRCDIR=$1
|
SRCDIR=$1
|
||||||
VMNAME=$2
|
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
|
APPSDIR=$VMDIR/apps
|
||||||
|
|
||||||
if [ $# != 2 ]; then
|
if [ $# -lt 2 ]; then
|
||||||
echo "usage: $0 <apps_templates_dir> <vmname>"
|
echo "usage: $0 <apps_templates_dir> <vmname> [appvms|vm-templates|servicevms]"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
mkdir -p $APPSDIR
|
mkdir -p $APPSDIR
|
||||||
|
|
||||||
if [ "$SRCDIR" != "none" ]; then
|
if [ "$SRCDIR" != "none" ]; then
|
||||||
echo "--> Converting Appmenu Templates..."
|
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
|
fi
|
||||||
|
|
||||||
echo "--> Adding Apps to the Menu..."
|
echo "--> Adding Apps to the Menu..."
|
||||||
|
86
dom0/aux-tools/qfile-dom0-unpacker.c
Normal file
86
dom0/aux-tools/qfile-dom0-unpacker.c
Normal 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;
|
||||||
|
}
|
@ -1,14 +1,19 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
VMNAME=$1
|
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
|
APPSDIR=$VMDIR/apps
|
||||||
|
|
||||||
if [ $# != 1 ]; then
|
if [ $# -lt 1 ]; then
|
||||||
echo "usage: $0 <vmname>"
|
echo "usage: $0 <vmname> [appvms|vm-templates|servicevms]"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ls $APPSDIR/*.directory $APPSDIR/*.desktop > /dev/null 2>&1; then
|
if ls $APPSDIR/*.directory $APPSDIR/*.desktop > /dev/null 2>&1; then
|
||||||
xdg-desktop-menu uninstall $APPSDIR/*.directory $APPSDIR/*.desktop
|
xdg-desktop-menu uninstall $APPSDIR/*.directory $APPSDIR/*.desktop
|
||||||
|
rm -f $APPSDIR/*.desktop $APPSDIR/*.directory
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
10
dom0/aux-tools/sync_rpmdb_updatevm.sh
Executable file
10
dom0/aux-tools/sync_rpmdb_updatevm.sh
Executable 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
|
@ -20,6 +20,7 @@
|
|||||||
start()
|
start()
|
||||||
{
|
{
|
||||||
echo -n $"Executing Qubes Core scripts:"
|
echo -n $"Executing Qubes Core scripts:"
|
||||||
|
modprobe evtchn
|
||||||
chgrp qubes /etc/xen
|
chgrp qubes /etc/xen
|
||||||
chmod 710 /etc/xen
|
chmod 710 /etc/xen
|
||||||
chgrp qubes /var/run/xend
|
chgrp qubes /var/run/xend
|
||||||
@ -28,7 +29,21 @@ start()
|
|||||||
chmod 660 /var/run/xend/xen-api.sock /var/run/xend/xmlrpc.sock
|
chmod 660 /var/run/xend/xen-api.sock /var/run/xend/xmlrpc.sock
|
||||||
chgrp qubes /var/run/xenstored/*
|
chgrp qubes /var/run/xenstored/*
|
||||||
chmod 660 /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
|
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 &
|
/usr/lib/qubes/qmemman_daemon.py >/var/log/qubes/qmemman.log 2>/var/log/qubes/qmemman.errs &
|
||||||
|
@ -22,10 +22,10 @@ NETVM=$(qvm-get-default-netvm)
|
|||||||
|
|
||||||
get_running_netvms() {
|
get_running_netvms() {
|
||||||
# Actually get running VMs with PCI devices attached
|
# 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=""
|
RUNNING_NETVMS=""
|
||||||
for VM in $RUNNING_VMS; do
|
for VM in $RUNNING_VMS; do
|
||||||
if [ -n "`xm pci-list $VM`" ]; then
|
if [ -n "`xl pci-list $VM`" ]; then
|
||||||
echo "$VM"
|
echo "$VM"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
3
dom0/misc/limits-qubes.conf
Normal file
3
dom0/misc/limits-qubes.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# xl create needs to allocate and mlock all VM memory
|
||||||
|
@qubes soft memlock unlimited
|
||||||
|
@qubes hard memlock unlimited
|
10
dom0/misc/qubes-appmenu-select.template
Normal file
10
dom0/misc/qubes-appmenu-select.template
Normal 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;
|
5
dom0/misc/qubes-templatevm.directory.template
Normal file
5
dom0/misc/qubes-templatevm.directory.template
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Encoding=UTF-8
|
||||||
|
Type=Directory
|
||||||
|
Name=Template: %VMNAME%
|
||||||
|
Icon=/usr/share/qubes/icons/template.png
|
5
dom0/misc/qubes-vm.directory.template
Normal file
5
dom0/misc/qubes-vm.directory.template
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Encoding=UTF-8
|
||||||
|
Type=Directory
|
||||||
|
Name=Domain: %VMNAME%
|
||||||
|
Icon=%VMDIR%/icon.png
|
1
dom0/misc/qubes_sync_rpmdb_updatevm.action
Normal file
1
dom0/misc/qubes_sync_rpmdb_updatevm.action
Normal file
@ -0,0 +1 @@
|
|||||||
|
*:any:/usr/lib/qubes/sync_rpmdb_updatevm.sh
|
28
dom0/misc/vm-template.conf
Normal file
28
dom0/misc/vm-template.conf
Normal 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'
|
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
get_running_netvms() {
|
get_running_netvms() {
|
||||||
# Actually get running VMs with PCI devices attached
|
# 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=""
|
RUNNING_NETVMS=""
|
||||||
for VM in $RUNNING_VMS; do
|
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"
|
echo "$VM"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
@ -9,6 +9,7 @@ class DomainState:
|
|||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
self.meminfo = None #dictionary of memory info read from client
|
self.meminfo = None #dictionary of memory info read from client
|
||||||
self.memory_actual = None #the current memory size
|
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.mem_used = None #used memory, computed based on meminfo
|
||||||
self.id = id #domain id
|
self.id = id #domain id
|
||||||
self.last_target = 0 #the last memset target
|
self.last_target = 0 #the last memset target
|
||||||
@ -27,6 +28,7 @@ class SystemState:
|
|||||||
|
|
||||||
def del_domain(self, id):
|
def del_domain(self, id):
|
||||||
self.domdict.pop(id)
|
self.domdict.pop(id)
|
||||||
|
self.do_balance()
|
||||||
|
|
||||||
def get_free_xen_memory(self):
|
def get_free_xen_memory(self):
|
||||||
return self.xc.physinfo()['free_memory']*1024
|
return self.xc.physinfo()['free_memory']*1024
|
||||||
@ -42,6 +44,9 @@ class SystemState:
|
|||||||
id = str(domain['domid'])
|
id = str(domain['domid'])
|
||||||
if self.domdict.has_key(id):
|
if self.domdict.has_key(id):
|
||||||
self.domdict[id].memory_actual = domain['mem_kb']*1024
|
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
|
#the below works (and is fast), but then 'xm list' shows unchanged memory value
|
||||||
def mem_set(self, id, val):
|
def mem_set(self, id, val):
|
||||||
@ -51,6 +56,7 @@ class SystemState:
|
|||||||
#can happen in the middle of domain shutdown
|
#can happen in the middle of domain shutdown
|
||||||
#apparently xc.lowlevel throws exceptions too
|
#apparently xc.lowlevel throws exceptions too
|
||||||
try:
|
try:
|
||||||
|
self.xc.domain_setmaxmem(int(id), val/1024 + 1024) # LIBXL_MAXMEM_CONSTANT=1024
|
||||||
self.xc.domain_set_target_mem(int(id), val/1024)
|
self.xc.domain_set_target_mem(int(id), val/1024)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -60,8 +60,8 @@ def prefmem(domain):
|
|||||||
CACHE_FACTOR = 1.3
|
CACHE_FACTOR = 1.3
|
||||||
#dom0 is special, as it must have large cache, for vbds. Thus, give it a special boost
|
#dom0 is special, as it must have large cache, for vbds. Thus, give it a special boost
|
||||||
if domain.id == '0':
|
if domain.id == '0':
|
||||||
return domain.mem_used*CACHE_FACTOR + 350*1024*1024
|
return min(domain.mem_used*CACHE_FACTOR + 350*1024*1024, domain.memory_maximum)
|
||||||
return domain.mem_used*CACHE_FACTOR
|
return min(domain.mem_used*CACHE_FACTOR, domain.memory_maximum)
|
||||||
|
|
||||||
def memory_needed(domain):
|
def memory_needed(domain):
|
||||||
#do not change
|
#do not change
|
||||||
@ -104,8 +104,11 @@ def balloon(memsize, domain_dictionary):
|
|||||||
|
|
||||||
#redistribute positive "total_available_memory" of memory between domains, proportionally to prefmem
|
#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):
|
def balance_when_enough_memory(domain_dictionary, xen_free_memory, total_mem_pref, total_available_memory):
|
||||||
donors_rq = list()
|
print 'balance_when_enough_memory(', xen_free_memory, total_mem_pref, total_available_memory, ')'
|
||||||
acceptors_rq = list()
|
target_memory = {}
|
||||||
|
# memory not assigned because of static max
|
||||||
|
left_memory = 0
|
||||||
|
acceptors_count = 0
|
||||||
for i in domain_dictionary.keys():
|
for i in domain_dictionary.keys():
|
||||||
if domain_dictionary[i].meminfo is None:
|
if domain_dictionary[i].meminfo is None:
|
||||||
continue
|
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
|
target_nonint = prefmem(domain_dictionary[i]) + scale*total_available_memory
|
||||||
#prevent rounding errors
|
#prevent rounding errors
|
||||||
target = int(0.999*target_nonint)
|
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):
|
if (target < domain_dictionary[i].memory_actual):
|
||||||
donors_rq.append((i, target))
|
donors_rq.append((i, target))
|
||||||
else:
|
else:
|
||||||
acceptors_rq.append((i, target))
|
acceptors_rq.append((i, target))
|
||||||
|
|
||||||
# print 'balance(enough): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
|
# print 'balance(enough): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
|
||||||
return 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:
|
for i in acceptors:
|
||||||
scale = 1.0*prefmem(domain_dictionary[i])/total_mem_pref_acceptors
|
scale = 1.0*prefmem(domain_dictionary[i])/total_mem_pref_acceptors
|
||||||
target_nonint = domain_dictionary[i].memory_actual + scale*squeezed_mem
|
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
|
# print 'balance(low): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
|
||||||
return donors_rq + acceptors_rq
|
return donors_rq + acceptors_rq
|
||||||
|
|
||||||
@ -171,7 +209,7 @@ def balance(xen_free_memory, domain_dictionary):
|
|||||||
continue
|
continue
|
||||||
need = memory_needed(domain_dictionary[i])
|
need = memory_needed(domain_dictionary[i])
|
||||||
# print 'domain' , i, 'act/pref', domain_dictionary[i].memory_actual, prefmem(domain_dictionary[i]), 'need=', need
|
# 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)
|
donors.append(i)
|
||||||
else:
|
else:
|
||||||
acceptors.append(i)
|
acceptors.append(i)
|
||||||
|
@ -29,10 +29,11 @@ class WatchType:
|
|||||||
class XS_Watcher:
|
class XS_Watcher:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.handle = xen.lowlevel.xs.xs()
|
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 = {}
|
self.watch_token_dict = {}
|
||||||
|
|
||||||
def domain_list_changed(self, param):
|
def domain_list_changed(self, param):
|
||||||
|
time.sleep(0.05)
|
||||||
curr = self.handle.ls('', '/local/domain')
|
curr = self.handle.ls('', '/local/domain')
|
||||||
if curr == None:
|
if curr == None:
|
||||||
return
|
return
|
||||||
|
5
dom0/qubes-cached.repo
Normal file
5
dom0/qubes-cached.repo
Normal 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
@ -64,14 +64,6 @@ def main():
|
|||||||
qvm_collection.pop(vm.qid)
|
qvm_collection.pop(vm.qid)
|
||||||
exit (1)
|
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.save()
|
||||||
qvm_collection.unlock_db()
|
qvm_collection.unlock_db()
|
||||||
|
|
||||||
|
@ -164,7 +164,6 @@ def main():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
vm.create_on_disk(verbose=options.verbose, source_template=template_vm)
|
vm.create_on_disk(verbose=options.verbose, source_template=template_vm)
|
||||||
vm.add_to_xen_storage()
|
|
||||||
|
|
||||||
except (IOError, OSError) as err:
|
except (IOError, OSError) as err:
|
||||||
print "ERROR: {0}".format(err)
|
print "ERROR: {0}".format(err)
|
||||||
|
20
dom0/qvm-tools/qvm-dom0-upgrade
Executable file
20
dom0/qvm-tools/qvm-dom0-upgrade
Executable 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
39
dom0/qvm-tools/qvm-get-updatevm
Executable 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()
|
@ -21,6 +21,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
from qubes.qubes import QubesVmCollection
|
from qubes.qubes import QubesVmCollection
|
||||||
|
from qubes.qubes import QubesHost
|
||||||
from qubes.qubes import QubesException
|
from qubes.qubes import QubesException
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
@ -59,8 +60,8 @@ fields = {
|
|||||||
|
|
||||||
"xid" : {"func" : "vm.get_xid() if vm.is_running() else '-'"},
|
"xid" : {"func" : "vm.get_xid() if vm.is_running() else '-'"},
|
||||||
|
|
||||||
"mem" : {"func" : "(str(vm.get_mem()/1024/1024) + ' MB') if vm.is_running() else '-'"},
|
"mem" : {"func" : "(str(vm.get_mem()/1024) + ' MB') if vm.is_running() else '-'"},
|
||||||
"cpu" : {"func" : "round (vm.get_cpu_total_load(), 1) 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'"},
|
"disk": {"func" : "str(vm.get_disk_utilization()/(1024*1024)) + ' MB'"},
|
||||||
"state": {"func" : "vm.get_power_state()"},
|
"state": {"func" : "vm.get_power_state()"},
|
||||||
|
|
||||||
@ -114,10 +115,14 @@ def main():
|
|||||||
|
|
||||||
fields_to_display = ["name", "on", "state", "updbl", "type", "template", "netvm", "label" ]
|
fields_to_display = ["name", "on", "state", "updbl", "type", "template", "netvm", "label" ]
|
||||||
|
|
||||||
|
cpu_usages = None
|
||||||
|
|
||||||
if (options.ids):
|
if (options.ids):
|
||||||
fields_to_display += ["qid", "xid"]
|
fields_to_display += ["qid", "xid"]
|
||||||
|
|
||||||
if (options.cpu):
|
if (options.cpu):
|
||||||
|
qhost = QubesHost()
|
||||||
|
(measure_time, cpu_usages) = qhost.measure_cpu_usage()
|
||||||
fields_to_display += ["cpu"]
|
fields_to_display += ["cpu"]
|
||||||
|
|
||||||
if (options.mem):
|
if (options.mem):
|
||||||
|
@ -32,7 +32,7 @@ def do_list(vm):
|
|||||||
print fmt.format ("name", vm.name)
|
print fmt.format ("name", vm.name)
|
||||||
print fmt.format ("label", vm.label.name)
|
print fmt.format ("label", vm.label.name)
|
||||||
print fmt.format ("type", vm.type)
|
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)
|
print fmt.format ("template", vm.template_vm.name)
|
||||||
if vm.netvm_vm is not None:
|
if vm.netvm_vm is not None:
|
||||||
print fmt.format ("netvm", vm.netvm_vm.name)
|
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 ("installed by RPM?", vm.installed_by_rpm)
|
||||||
print fmt.format ("dir", vm.dir_path)
|
print fmt.format ("dir", vm.dir_path)
|
||||||
print fmt.format ("config", vm.conf_file)
|
print fmt.format ("config", vm.conf_file)
|
||||||
|
print fmt.format ("pcidevs", vm.pcidevs)
|
||||||
if not vm.is_appvm():
|
if not vm.is_appvm():
|
||||||
print fmt.format ("root img", vm.root_img)
|
print fmt.format ("root img", vm.root_img)
|
||||||
if vm.is_template():
|
if vm.is_template():
|
||||||
print fmt.format ("root COW img", vm.rootcow_img)
|
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 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 ("private img", vm.private_img)
|
||||||
|
print fmt.format ("memory", vm.memory)
|
||||||
|
print fmt.format ("maxmem", vm.maxmem)
|
||||||
|
|
||||||
|
|
||||||
def set_label(vms, vm, args):
|
def set_label(vms, vm, args):
|
||||||
@ -65,6 +68,23 @@ def set_label(vms, vm, args):
|
|||||||
vm.label = QubesVmLabels[label]
|
vm.label = QubesVmLabels[label]
|
||||||
subprocess.check_call (["ln", "-sf", vm.label.icon_path, vm.icon_path])
|
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):
|
def set_netvm(vms, vm, args):
|
||||||
if len (args) != 1:
|
if len (args) != 1:
|
||||||
@ -151,8 +171,11 @@ def set_nonupdateable(vms, vm, args):
|
|||||||
properties = {
|
properties = {
|
||||||
"updateable": set_updateable,
|
"updateable": set_updateable,
|
||||||
"nonupdateable": set_nonupdateable,
|
"nonupdateable": set_nonupdateable,
|
||||||
|
"pcidevs": set_pcidevs,
|
||||||
"label" : set_label,
|
"label" : set_label,
|
||||||
"netvm" : set_netvm,
|
"netvm" : set_netvm,
|
||||||
|
"maxmem" : set_maxmem,
|
||||||
|
"memory" : set_memory,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
140
dom0/qvm-tools/qvm-revert-template-changes
Executable file
140
dom0/qvm-tools/qvm-revert-template-changes
Executable 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()
|
@ -79,19 +79,19 @@ def vm_run_cmd(vm, cmd, options):
|
|||||||
if options.shutdown:
|
if options.shutdown:
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
print "Shutting down VM: '{0}'...".format(vm.name)
|
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
|
return
|
||||||
|
|
||||||
if options.pause:
|
if options.pause:
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
print "Pausing VM: '{0}'...".format(vm.name)
|
print "Pausing VM: '{0}'...".format(vm.name)
|
||||||
subprocess.call (["/usr/sbin/xm", "pause", vm.name])
|
subprocess.call (["/usr/sbin/xl", "pause", vm.name])
|
||||||
return
|
return
|
||||||
|
|
||||||
if options.unpause:
|
if options.unpause:
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
print "UnPausing VM: '{0}'...".format(vm.name)
|
print "UnPausing VM: '{0}'...".format(vm.name)
|
||||||
subprocess.call (["/usr/sbin/xm", "unpause", vm.name])
|
subprocess.call (["/usr/sbin/xl", "unpause", vm.name])
|
||||||
return
|
return
|
||||||
|
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
@ -152,13 +152,13 @@ def main():
|
|||||||
help="Wait for the VM(s) to shutdown")
|
help="Wait for the VM(s) to shutdown")
|
||||||
|
|
||||||
parser.add_option ("--shutdown", action="store_true", dest="shutdown", default=False,
|
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,
|
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,
|
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,
|
parser.add_option ("--pass_io", action="store_true", dest="passio", default=False,
|
||||||
help="Pass stdin/stdout/stderr from remote program")
|
help="Pass stdin/stdout/stderr from remote program")
|
||||||
@ -166,6 +166,9 @@ def main():
|
|||||||
parser.add_option ("--localcmd", action="store", dest="localcmd", default=None,
|
parser.add_option ("--localcmd", action="store", dest="localcmd", default=None,
|
||||||
help="With --pass_io, pass stdin/stdout/stderr to the given program")
|
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 ()
|
(options, args) = parser.parse_args ()
|
||||||
|
|
||||||
|
|
||||||
@ -218,8 +221,12 @@ def main():
|
|||||||
|
|
||||||
# If stopping NetVM - stop connected VMs too
|
# If stopping NetVM - stop connected VMs too
|
||||||
if options.shutdown and vm.is_netvm():
|
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()]
|
connected_vms = [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
|
||||||
vms_list.reverse()
|
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:
|
if takes_cmd_argument:
|
||||||
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)
|
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)
|
||||||
|
46
dom0/qvm-tools/qvm-set-updatevm
Executable file
46
dom0/qvm-tools/qvm-set-updatevm
Executable 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
199
dom0/qvm-tools/qvm-sync-appmenus
Executable 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()
|
@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}"
|
||||||
|
|
||||||
hd_arr[10]=a
|
hd_arr[10]=a
|
||||||
hd_arr[11]=b
|
hd_arr[11]=b
|
||||||
hd_arr[12]=c
|
hd_arr[12]=c
|
||||||
@ -38,6 +40,8 @@ process()
|
|||||||
xenstore-write "$XENBUS_PATH/node" "$dev" \
|
xenstore-write "$XENBUS_PATH/node" "$dev" \
|
||||||
"$XENBUS_PATH/physical-device" "7:"$HEXNUMBER \
|
"$XENBUS_PATH/physical-device" "7:"$HEXNUMBER \
|
||||||
"$XENBUS_PATH/hotplug-status" connected
|
"$XENBUS_PATH/hotplug-status" connected
|
||||||
|
echo "$dev" > "$HOTPLUG_STORE-node"
|
||||||
|
echo "file" > "$HOTPLUG_STORE-type"
|
||||||
}
|
}
|
||||||
|
|
||||||
#exec 2>>/tmp/block.$$
|
#exec 2>>/tmp/block.$$
|
||||||
|
@ -22,8 +22,13 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
import glob
|
||||||
from qubes.qubes import QubesVmCollection
|
from qubes.qubes import QubesVmCollection
|
||||||
|
|
||||||
|
updates_dir = "/var/lib/qubes/updates"
|
||||||
|
updates_rpm_dir = updates_dir + "/rpm"
|
||||||
|
|
||||||
def is_copy_allowed(vm):
|
def is_copy_allowed(vm):
|
||||||
# if vm.copy_allowed:
|
# if vm.copy_allowed:
|
||||||
# return True
|
# return True
|
||||||
@ -33,6 +38,36 @@ def is_copy_allowed(vm):
|
|||||||
retcode = subprocess.call(['/usr/bin/kdialog', '--yesno', q, '--title', 'File transfer confirmation'])
|
retcode = subprocess.call(['/usr/bin/kdialog', '--yesno', q, '--title', 'File transfer confirmation'])
|
||||||
return retcode == 0
|
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():
|
def main():
|
||||||
FILECOPY_VMNAME_SIZE = 32
|
FILECOPY_VMNAME_SIZE = 32
|
||||||
blob=os.read(0, FILECOPY_VMNAME_SIZE)
|
blob=os.read(0, FILECOPY_VMNAME_SIZE)
|
||||||
@ -42,6 +77,11 @@ def main():
|
|||||||
qvm_collection.lock_db_for_reading()
|
qvm_collection.lock_db_for_reading()
|
||||||
qvm_collection.load()
|
qvm_collection.load()
|
||||||
qvm_collection.unlock_db()
|
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)
|
vm = qvm_collection.get_vm_by_name(vmname)
|
||||||
# we do not want to flood dom0 with error windows; so just log to stderr
|
# we do not want to flood dom0 with error windows; so just log to stderr
|
||||||
|
@ -31,6 +31,7 @@ from qubes.qubes import QubesDaemonPidfile
|
|||||||
from qubes.qmemman_client import QMemmanClient
|
from qubes.qmemman_client import QMemmanClient
|
||||||
|
|
||||||
current_savefile = '/var/run/qubes/current_savefile'
|
current_savefile = '/var/run/qubes/current_savefile'
|
||||||
|
current_dvm_conf = '/var/run/qubes/current_dvm.conf'
|
||||||
notify_object = None
|
notify_object = None
|
||||||
|
|
||||||
class QfileDaemonDvm:
|
class QfileDaemonDvm:
|
||||||
@ -58,6 +59,7 @@ class QfileDaemonDvm:
|
|||||||
return None
|
return None
|
||||||
retcode = subprocess.call(['/usr/lib/qubes/qubes_restore',
|
retcode = subprocess.call(['/usr/lib/qubes/qubes_restore',
|
||||||
current_savefile,
|
current_savefile,
|
||||||
|
current_dvm_conf,
|
||||||
'-c', vm.label.color,
|
'-c', vm.label.color,
|
||||||
'-i', vm.label.icon,
|
'-i', vm.label.icon,
|
||||||
'-l', str(vm.label.index)])
|
'-l', str(vm.label.index)])
|
||||||
@ -130,8 +132,8 @@ def main():
|
|||||||
lockf.close()
|
lockf.close()
|
||||||
if dispname is not None:
|
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/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)
|
qfile.remove_disposable_from_qdb(dispname)
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
get_encoded_script()
|
get_encoded_script()
|
||||||
{
|
{
|
||||||
if ! [ -f "$1" ] ; then
|
if ! [ -f "$1" ] ; then
|
||||||
@ -42,22 +42,24 @@ if [ -n "$ENCODED_SCRIPT" ] ; then
|
|||||||
fi
|
fi
|
||||||
#set -x
|
#set -x
|
||||||
xenstore-write /local/domain/$ID/qubes_save_request 1
|
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 | \
|
xenstore-read /local/domain/$ID/qubes_gateway | \
|
||||||
cut -d . -f 2 | tr -d "\n" > $VMDIR/netvm_id.txt
|
cut -d . -f 3 | tr -d "\n" > $VMDIR/netvm_id.txt
|
||||||
xm block-detach $1 /dev/xvdb
|
xl block-detach $1 xvdb
|
||||||
MEM=$(xenstore-read /local/domain/$ID/device/qubes_used_mem)
|
MEM=$(xenstore-read /local/domain/$ID/device/qubes_used_mem)
|
||||||
echo "DVM boot complete, memory used=$MEM. Saving image..."
|
echo "DVM boot complete, memory used=$MEM. Saving image..."
|
||||||
QMEMMAN_STOP=/var/run/qubes/do-not-membalance
|
QMEMMAN_STOP=/var/run/qubes/do-not-membalance
|
||||||
touch $QMEMMAN_STOP
|
touch $QMEMMAN_STOP
|
||||||
xm mem-set $1 $(($MEM/1000))
|
xl mem-set $1 $(($MEM/1000))
|
||||||
sleep 1
|
sleep 1
|
||||||
touch $2
|
touch $2
|
||||||
if ! xm save $1 $2 ; then
|
if ! xl save $1 $2 ; then
|
||||||
rm -f $QMEMMAN_STOP
|
rm -f $QMEMMAN_STOP
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rm -f $QMEMMAN_STOP
|
rm -f $QMEMMAN_STOP
|
||||||
cd $VMDIR
|
cd $VMDIR
|
||||||
|
# Fix start memory
|
||||||
|
sed -i -e "s/^memory.*/memory = $((MEM/1000))/" dvm.conf
|
||||||
tar -Scvf saved_cows.tar volatile.img
|
tar -Scvf saved_cows.tar volatile.img
|
||||||
echo "DVM savefile created successfully."
|
echo "DVM savefile created successfully."
|
||||||
|
@ -12,95 +12,73 @@
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <xs.h>
|
#include <xs.h>
|
||||||
|
|
||||||
char xmlrpc_header[] =
|
int restore_domain(char *restore_file, char *conf_file, char *name) {
|
||||||
"POST /RPC2 HTTP/1.0\r\n"
|
int pid, status, domid;
|
||||||
"Host: \r\n"
|
int pipe_fd[2];
|
||||||
"User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\n"
|
char buf[256];
|
||||||
"Content-Type: text/xml\r\n" "Content-Length: %d\r\n" "\r\n";
|
char *endptr;
|
||||||
char xmlrpc_body_restore[] =
|
switch (pid = fork()) {
|
||||||
"<?xml version='1.0'?>\n"
|
case -1:
|
||||||
"<methodCall>\n"
|
perror("fork");
|
||||||
"<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");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
case 0:
|
||||||
if (write(fd, body, strlen(body)) != strlen(body)) {
|
close(1);
|
||||||
perror("write xend");
|
if (dup2(open("/dev/null", O_RDWR), 1)==-1) {
|
||||||
exit(1);
|
perror("dup2 or open");
|
||||||
}
|
|
||||||
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");
|
|
||||||
exit(1);
|
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()
|
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)
|
void start_rexec(int domid)
|
||||||
{
|
{
|
||||||
int pid, status;
|
int pid, status;
|
||||||
@ -214,40 +171,13 @@ void start_guid(int domid, int argc, char **argv)
|
|||||||
guid_args[0] = "qubes_guid";
|
guid_args[0] = "qubes_guid";
|
||||||
guid_args[1] = "-d";
|
guid_args[1] = "-d";
|
||||||
guid_args[2] = dstr;
|
guid_args[2] = dstr;
|
||||||
for (i = 2; i < argc; i++)
|
for (i = 3; i < argc; i++)
|
||||||
guid_args[i + 1] = argv[i];
|
guid_args[i + 1] = argv[i];
|
||||||
guid_args[argc + 1] = NULL;
|
guid_args[argc + 1] = NULL;
|
||||||
execv("/usr/bin/qubes_guid", guid_args);
|
execv("/usr/bin/qubes_guid", guid_args);
|
||||||
perror("execv");
|
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)
|
char *dispname_by_dispid(int dispid)
|
||||||
{
|
{
|
||||||
static char retbuf[16];
|
static char retbuf[16];
|
||||||
@ -258,8 +188,7 @@ char *dispname_by_dispid(int dispid)
|
|||||||
char *build_dvm_ip(int netvm, int id)
|
char *build_dvm_ip(int netvm, int id)
|
||||||
{
|
{
|
||||||
static char buf[256];
|
static char buf[256];
|
||||||
snprintf(buf, sizeof(buf), "10.%d.%d.%d", netvm, id / 254 + 200,
|
snprintf(buf, sizeof(buf), "10.138.%d.%d", netvm, (id % 254) + 1);
|
||||||
(id % 254) + 1);
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,15 +199,17 @@ char *build_dvm_ip(int netvm, int id)
|
|||||||
// normally, it should be "templatename-dvm"
|
// normally, it should be "templatename-dvm"
|
||||||
char *get_vmname_from_savefile(int fd)
|
char *get_vmname_from_savefile(int fd)
|
||||||
{
|
{
|
||||||
|
int buflen;
|
||||||
static char buf[4096];
|
static char buf[4096];
|
||||||
char *name;
|
char *name;
|
||||||
char *slash;
|
char *slash;
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
|
buflen = read(fd, buf, sizeof(buf) - 1);
|
||||||
perror("read savefile");
|
if (buflen < 0) {
|
||||||
|
perror("read vm conf");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
buf[sizeof(buf) - 1] = 0;
|
buf[buflen] = 0;
|
||||||
name = strstr(buf + 20, NAME_PATTERN);
|
name = strstr(buf + 20, NAME_PATTERN);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -296,25 +227,69 @@ char *get_vmname_from_savefile(int fd)
|
|||||||
return slash + 1;
|
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];
|
if (!strcmp(field, "NAME")) {
|
||||||
char buf[4096];
|
fprintf(conf, "%s", dispname_by_dispid(dispid));
|
||||||
lseek(fd, 0, SEEK_SET);
|
} else if (!strcmp(field, "MAC")) {
|
||||||
if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
|
fprintf(conf, "00:16:3e:7c:8b:%02x", dispid);
|
||||||
perror("read savefile");
|
} 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);
|
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)
|
void unpack_cows(char *name)
|
||||||
{
|
{
|
||||||
char vmdir[4096];
|
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 get_netvm_id_from_name(char *name)
|
||||||
{
|
{
|
||||||
int fd, n;
|
int fd, n;
|
||||||
@ -377,6 +363,7 @@ void setup_xenstore(int netvm_id, int domid, int dvmid, char *name)
|
|||||||
{
|
{
|
||||||
char val[256];
|
char val[256];
|
||||||
struct xs_handle *xs = xs_daemon_open();
|
struct xs_handle *xs = xs_daemon_open();
|
||||||
|
struct xs_permissions perm[1];
|
||||||
if (!xs) {
|
if (!xs) {
|
||||||
perror("xs_daemon_open");
|
perror("xs_daemon_open");
|
||||||
exit(1);
|
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",
|
write_xs_single(xs, domid, "qubes_ip",
|
||||||
build_dvm_ip(netvm_id, dvmid));
|
build_dvm_ip(netvm_id, dvmid));
|
||||||
write_xs_single(xs, domid, "qubes_netmask", "255.255.0.0");
|
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);
|
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_secondary_dns", val);
|
||||||
write_xs_single(xs, domid, "qubes_vm_type", "AppVM");
|
write_xs_single(xs, domid, "qubes_vm_type", "AppVM");
|
||||||
write_xs_single(xs, domid, "qubes_restore_complete", "True");
|
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);
|
xs_daemon_close(xs);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -437,46 +430,45 @@ void redirect_stderr()
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int fd, domid, dispid, netvm_id;
|
int conf_templ, domid, dispid, netvm_id;
|
||||||
char *resp;
|
FILE *conf;
|
||||||
char *name;
|
char *name;
|
||||||
if (argc < 2) {
|
char confname[256];
|
||||||
|
if (argc < 3) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: %s savefile [guid args] \n", argv[0]);
|
"usage: %s savefile conf_templ [guid args] \n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
redirect_stderr();
|
redirect_stderr();
|
||||||
fprintf(stderr, "time=%s, starting\n", gettime());
|
fprintf(stderr, "time=%s, starting\n", gettime());
|
||||||
set_fast_flag();
|
set_fast_flag();
|
||||||
atexit(rm_fast_flag);
|
atexit(rm_fast_flag);
|
||||||
fd = open(argv[1], O_RDWR);
|
conf_templ = open(argv[2], O_RDONLY);
|
||||||
if (fd < 0) {
|
if (conf_templ < 0) {
|
||||||
perror("open savefile");
|
perror("fopen vm conf");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
dispid = get_next_disposable_id();
|
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);
|
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);
|
// printf("name=%s\n", name);
|
||||||
unpack_cows(name);
|
unpack_cows(name);
|
||||||
// no preloading for now, assume savefile in shm
|
// no preloading for now, assume savefile in shm
|
||||||
// preload_cache(fd);
|
// preload_cache(fd);
|
||||||
fd = xend_connect();
|
domid=restore_domain(argv[1], confname, dispname_by_dispid(dispid));
|
||||||
send_req_restore(fd, argv[1]);
|
|
||||||
resp = recv_resp(fd);
|
|
||||||
domid = parse_resp(resp);
|
|
||||||
write_varrun_domid(domid, dispname_by_dispid(dispid), name);
|
write_varrun_domid(domid, dispname_by_dispid(dispid), name);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"time=%s, created domid=%d, creating xenstore entries\n",
|
"time=%s, created domid=%d, creating xenstore entries\n",
|
||||||
gettime(), domid);
|
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);
|
setup_xenstore(netvm_id, domid, dispid, name);
|
||||||
fprintf(stderr, "time=%s, starting qubes_guid\n", gettime());
|
fprintf(stderr, "time=%s, starting qubes_guid\n", gettime());
|
||||||
rm_fast_flag();
|
rm_fast_flag();
|
||||||
|
@ -40,12 +40,16 @@ if ! /usr/lib/qubes/qubes_prepare_saved_domain.sh \
|
|||||||
fi
|
fi
|
||||||
ROOT=/var/lib/qubes/dvmdata/savefile_root
|
ROOT=/var/lib/qubes/dvmdata/savefile_root
|
||||||
DEFAULT=/var/lib/qubes/dvmdata/default_savefile
|
DEFAULT=/var/lib/qubes/dvmdata/default_savefile
|
||||||
|
DEFAULTCONF=/var/lib/qubes/dvmdata/default_dvm.conf
|
||||||
CURRENT=/var/run/qubes/current_savefile
|
CURRENT=/var/run/qubes/current_savefile
|
||||||
|
CURRENTCONF=/var/run/qubes/current_dvm.conf
|
||||||
SHMDIR=/dev/shm/qubes
|
SHMDIR=/dev/shm/qubes
|
||||||
SHMCOPY=$SHMDIR/current_savefile
|
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/appvms/$DVMTMPL/dvm-savefile" $DEFAULT
|
||||||
ln -s "/var/lib/qubes/vm-templates/$TEMPLATENAME/root.img" $ROOT
|
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
|
if [ -f /var/lib/qubes/dvmdata/dont_use_shm ] ; then
|
||||||
ln -s $DEFAULT $CURRENT
|
ln -s $DEFAULT $CURRENT
|
||||||
else
|
else
|
||||||
|
@ -4,8 +4,13 @@
|
|||||||
struct xen_sysctl_physinfo xphysinfo;
|
struct xen_sysctl_physinfo xphysinfo;
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_interface *handle = xc_interface_open(NULL, NULL, 0);
|
||||||
|
if (!handle) {
|
||||||
|
#else
|
||||||
int handle = xc_interface_open();
|
int handle = xc_interface_open();
|
||||||
if (handle == -1) {
|
if (handle == -1) {
|
||||||
|
#endif
|
||||||
perror("xc_interface_open");
|
perror("xc_interface_open");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -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>
|
|
||||||
|
|
@ -19,6 +19,9 @@ while true; do
|
|||||||
IPTABLES_SAVE=$(/sbin/iptables-save | sed '/^\*filter/,/^COMMIT/d')
|
IPTABLES_SAVE=$(/sbin/iptables-save | sed '/^\*filter/,/^COMMIT/d')
|
||||||
OUT=`echo -e "$RULES\n$IPTABLES_SAVE" | /sbin/iptables-restore 2>&1 || :`
|
OUT=`echo -e "$RULES\n$IPTABLES_SAVE" | /sbin/iptables-restore 2>&1 || :`
|
||||||
/usr/bin/xenstore-write $XENSTORE_ERROR "$OUT"
|
/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 [[ -z "$OUT" ]]; then
|
||||||
# If OK save it for later
|
# If OK save it for later
|
||||||
@ -29,5 +32,5 @@ while true; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Wait for changes in xenstore file
|
# Wait for changes in xenstore file
|
||||||
/usr/bin/xenstore-watch $XENSTORE_IPTABLES
|
/usr/bin/xenstore-watch-qubes $XENSTORE_IPTABLES
|
||||||
done
|
done
|
||||||
|
@ -24,8 +24,8 @@ while true; do
|
|||||||
/usr/bin/xenstore-write qubes_netvm_external_ip "$CURR_NETCFG"
|
/usr/bin/xenstore-write qubes_netvm_external_ip "$CURR_NETCFG"
|
||||||
fi
|
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
|
else
|
||||||
/usr/bin/xenstore-watch qubes_netvm_domid
|
/usr/bin/xenstore-watch-qubes qubes_netvm_domid
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
@ -51,7 +51,8 @@ enum {
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
QREXEC_EXECUTE_FILE_COPY=0x700,
|
QREXEC_EXECUTE_FILE_COPY=0x700,
|
||||||
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM
|
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM,
|
||||||
|
QREXEC_EXECUTE_APPMENUS_SYNC
|
||||||
};
|
};
|
||||||
|
|
||||||
struct server_header {
|
struct server_header {
|
||||||
|
@ -482,6 +482,9 @@ void handle_trigger_io()
|
|||||||
else if (!strcmp(buf, "DVMR"))
|
else if (!strcmp(buf, "DVMR"))
|
||||||
s_hdr.client_id =
|
s_hdr.client_id =
|
||||||
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM;
|
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM;
|
||||||
|
else if (!strcmp(buf, "SYNC"))
|
||||||
|
s_hdr.client_id =
|
||||||
|
QREXEC_EXECUTE_APPMENUS_SYNC;
|
||||||
if (s_hdr.client_id) {
|
if (s_hdr.client_id) {
|
||||||
s_hdr.type = MSG_AGENT_TO_SERVER_TRIGGER_EXEC;
|
s_hdr.type = MSG_AGENT_TO_SERVER_TRIGGER_EXEC;
|
||||||
write_all_vchan_ext(&s_hdr, sizeof s_hdr);
|
write_all_vchan_ext(&s_hdr, sizeof s_hdr);
|
||||||
|
@ -361,6 +361,10 @@ void handle_execute_predefined_command(int req)
|
|||||||
rcmd = "directly:user:/usr/lib/qubes/qfile-agent-dvm";
|
rcmd = "directly:user:/usr/lib/qubes/qfile-agent-dvm";
|
||||||
lcmd = "/usr/lib/qubes/qfile-daemon-dvm";
|
lcmd = "/usr/lib/qubes/qfile-daemon-dvm";
|
||||||
break;
|
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 */
|
default: /* cannot happen, already sanitized */
|
||||||
fprintf(stderr, "got trigger exec no %d\n", req);
|
fprintf(stderr, "got trigger exec no %d\n", req);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -402,7 +406,8 @@ void sanitize_message_from_agent(struct server_header *untrusted_header)
|
|||||||
case MSG_AGENT_TO_SERVER_TRIGGER_EXEC:
|
case MSG_AGENT_TO_SERVER_TRIGGER_EXEC:
|
||||||
untrusted_cmd = untrusted_header->client_id;
|
untrusted_cmd = untrusted_header->client_id;
|
||||||
if (untrusted_cmd != QREXEC_EXECUTE_FILE_COPY &&
|
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,
|
fprintf(stderr,
|
||||||
"received MSG_AGENT_TO_SERVER_TRIGGER_EXEC cmd %d ?\n",
|
"received MSG_AGENT_TO_SERVER_TRIGGER_EXEC cmd %d ?\n",
|
||||||
untrusted_cmd);
|
untrusted_cmd);
|
||||||
|
@ -83,7 +83,11 @@ int buffer_space_vchan_ext()
|
|||||||
// if the remote domain is destroyed, we get no notification
|
// if the remote domain is destroyed, we get no notification
|
||||||
// thus, we check for the status periodically
|
// thus, we check for the status periodically
|
||||||
|
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
static xc_interface *xc_handle = NULL;
|
||||||
|
#else
|
||||||
static int xc_handle = -1;
|
static int xc_handle = -1;
|
||||||
|
#endif
|
||||||
void slow_check_for_libvchan_is_eof(struct libvchan *ctrl)
|
void slow_check_for_libvchan_is_eof(struct libvchan *ctrl)
|
||||||
{
|
{
|
||||||
struct evtchn_status evst;
|
struct evtchn_status evst;
|
||||||
@ -198,8 +202,13 @@ char *peer_client_init(int dom, int port)
|
|||||||
// now client init should succeed; "while" is redundant
|
// now client init should succeed; "while" is redundant
|
||||||
while (!(ctrl = libvchan_client_init(dom, port)));
|
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();
|
xc_handle = xc_interface_open();
|
||||||
if (xc_handle < 0) {
|
if (xc_handle < 0) {
|
||||||
|
#endif
|
||||||
perror("xc_interface_open");
|
perror("xc_interface_open");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ License: GPL
|
|||||||
URL: http://www.qubes-os.org
|
URL: http://www.qubes-os.org
|
||||||
Requires: /usr/bin/xenstore-read
|
Requires: /usr/bin/xenstore-read
|
||||||
Requires: fedora-release
|
Requires: fedora-release
|
||||||
|
Requires: yum-plugin-post-transaction-actions
|
||||||
BuildRequires: xen-devel
|
BuildRequires: xen-devel
|
||||||
|
|
||||||
%define _builddir %(pwd)/common
|
%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
|
mkdir -p $RPM_BUILD_ROOT/sbin
|
||||||
cp qubes_serial_login $RPM_BUILD_ROOT/sbin
|
cp qubes_serial_login $RPM_BUILD_ROOT/sbin
|
||||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
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
|
mkdir -p $RPM_BUILD_ROOT/etc
|
||||||
cp serial.conf $RPM_BUILD_ROOT/var/lib/qubes/
|
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
|
%triggerin -- initscripts
|
||||||
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
|
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
|
||||||
|
|
||||||
%post
|
%post
|
||||||
|
|
||||||
# Disable gpk-update-icon
|
# disable some Upstart services
|
||||||
sed 's/^NotShowIn=KDE;$/\0QUBES;/' -i /etc/xdg/autostart/gpk-update-icon.desktop
|
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
|
if [ "$1" != 1 ] ; then
|
||||||
# do this whole %post thing only when updating for the first time...
|
# do this whole %post thing only when updating for the first time...
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
usermod -L root
|
|
||||||
if ! [ -f /var/lib/qubes/serial.orig ] ; then
|
if ! [ -f /var/lib/qubes/serial.orig ] ; then
|
||||||
cp /etc/init/serial.conf /var/lib/qubes/serial.orig
|
cp /etc/init/serial.conf /var/lib/qubes/serial.orig
|
||||||
fi
|
fi
|
||||||
@ -177,4 +230,9 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
/etc/yum.repos.d/qubes%{dist}.repo
|
/etc/yum.repos.d/qubes%{dist}.repo
|
||||||
/etc/pki/rpm-gpg/RPM-GPG-KEY-qubes*
|
/etc/pki/rpm-gpg/RPM-GPG-KEY-qubes*
|
||||||
/sbin/qubes_serial_login
|
/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
|
||||||
|
@ -39,8 +39,9 @@ URL: http://www.qubes-os.org
|
|||||||
BuildRequires: xen-devel
|
BuildRequires: xen-devel
|
||||||
Requires: python, xen-runtime, pciutils, python-inotify, python-daemon, kernel-qubes-dom0
|
Requires: python, xen-runtime, pciutils, python-inotify, python-daemon, kernel-qubes-dom0
|
||||||
Conflicts: qubes-gui-dom0 < 1.1.13
|
Conflicts: qubes-gui-dom0 < 1.1.13
|
||||||
|
Requires: yum-plugin-post-transaction-actions
|
||||||
Requires: NetworkManager >= 0.8.1-1
|
Requires: NetworkManager >= 0.8.1-1
|
||||||
Requires: xen >= 3.4.3-6
|
Requires: xen >= 4.1.0-2
|
||||||
%define _builddir %(pwd)/dom0
|
%define _builddir %(pwd)/dom0
|
||||||
|
|
||||||
%description
|
%description
|
||||||
@ -50,6 +51,7 @@ The Qubes core files for installation on Dom0.
|
|||||||
python -m compileall qvm-core qmemman
|
python -m compileall qvm-core qmemman
|
||||||
python -O -m compileall qvm-core qmemman
|
python -O -m compileall qvm-core qmemman
|
||||||
make -C restore
|
make -C restore
|
||||||
|
make -C aux-tools
|
||||||
make -C ../common
|
make -C ../common
|
||||||
make -C ../vchan
|
make -C ../vchan
|
||||||
make -C ../u2mfn
|
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/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/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/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 qmemman/server.py $RPM_BUILD_ROOT/usr/lib/qubes/qmemman_daemon.py
|
||||||
cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes/
|
cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes/
|
||||||
cp ../qrexec/qrexec_daemon $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 ../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_restore restore/xenfreepages $RPM_BUILD_ROOT/usr/lib/qubes
|
||||||
cp restore/qubes_prepare_saved_domain.sh $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-dvm $RPM_BUILD_ROOT/usr/lib/qubes
|
||||||
cp restore/qfile-daemon $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
|
||||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/vm-templates
|
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/vm-templates
|
||||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/appvms
|
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/backup
|
||||||
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/dvmdata
|
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
|
mkdir -p $RPM_BUILD_ROOT/usr/share/qubes/icons
|
||||||
cp icons/*.png $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
|
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||||
cp ../common/qubes_setup_dnat_to_ns $RPM_BUILD_ROOT/usr/lib/qubes
|
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/
|
cp ../common/qubes_nmhook $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/
|
||||||
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
||||||
cp ../common/iptables $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
|
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/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 '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_core || echo "WARNING: Cannot add service qubes_core!"
|
||||||
chkconfig --add qubes_netvm || echo "WARNING: Cannot add service qubes_netvm!"
|
chkconfig --add qubes_netvm || echo "WARNING: Cannot add service qubes_netvm!"
|
||||||
chkconfig --add qubes_setupdvm || echo "WARNING: Cannot add service qubes_setupdvm!"
|
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_netvm on || echo "WARNING: Cannot enable service qubes_netvm!"
|
||||||
chkconfig --level 5 qubes_setupdvm on || echo "WARNING: Cannot enable service qubes_setupdvm!"
|
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
|
HAD_SYSCONFIG_NETWORK=yes
|
||||||
if ! [ -e /etc/sysconfig/network ]; then
|
if ! [ -e /etc/sysconfig/network ]; then
|
||||||
HAD_SYSCONFIG_NETWORK=no
|
HAD_SYSCONFIG_NETWORK=no
|
||||||
@ -167,10 +197,7 @@ fi
|
|||||||
|
|
||||||
# Load evtchn module - xenstored needs it
|
# Load evtchn module - xenstored needs it
|
||||||
modprobe evtchn
|
modprobe evtchn
|
||||||
|
|
||||||
# Now launch xend - we will need it for subsequent steps
|
|
||||||
service xenstored start
|
service xenstored start
|
||||||
service xend start
|
|
||||||
|
|
||||||
if ! [ -e /var/lib/qubes/qubes.xml ]; then
|
if ! [ -e /var/lib/qubes/qubes.xml ]; then
|
||||||
# echo "Initializing Qubes DB..."
|
# echo "Initializing Qubes DB..."
|
||||||
@ -259,13 +286,20 @@ fi
|
|||||||
/usr/lib/qubes/meminfo-writer
|
/usr/lib/qubes/meminfo-writer
|
||||||
/usr/lib/qubes/qfile-daemon-dvm*
|
/usr/lib/qubes/qfile-daemon-dvm*
|
||||||
/usr/lib/qubes/qfile-daemon
|
/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
|
||||||
%attr(770,root,qubes) %dir /var/lib/qubes/vm-templates
|
%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/appvms
|
||||||
%attr(770,root,qubes) %dir /var/lib/qubes/servicevms
|
%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/backup
|
||||||
%attr(770,root,qubes) %dir /var/lib/qubes/dvmdata
|
%attr(770,root,qubes) %dir /var/lib/qubes/dvmdata
|
||||||
|
%attr(770,root,qubes) %dir /var/lib/qubes/updates
|
||||||
%dir /usr/share/qubes/icons/*.png
|
%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_setup_dnat_to_ns
|
||||||
/usr/lib/qubes/qubes_fix_nm_conf.sh
|
/usr/lib/qubes/qubes_fix_nm_conf.sh
|
||||||
/etc/dhclient.d/qubes_setup_dnat_to_ns.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-sync-vms-clock
|
||||||
/usr/lib64/pm-utils/sleep.d/01qubes-suspend-netvm
|
/usr/lib64/pm-utils/sleep.d/01qubes-suspend-netvm
|
||||||
/usr/lib64/pm-utils/sleep.d/02qubes-pause-vms
|
/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_restore
|
||||||
/usr/lib/qubes/qubes_prepare_saved_domain.sh
|
/usr/lib/qubes/qubes_prepare_saved_domain.sh
|
||||||
/etc/xen/scripts/block.qubes
|
/etc/xen/scripts/block.qubes
|
||||||
@ -288,5 +322,8 @@ fi
|
|||||||
%attr(770,root,qubes) %dir /var/run/qubes
|
%attr(770,root,qubes) %dir /var/run/qubes
|
||||||
%{_libdir}/libvchan.so
|
%{_libdir}/libvchan.so
|
||||||
%{_libdir}/libu2mfn.so
|
%{_libdir}/libu2mfn.so
|
||||||
|
/etc/yum.real.repos.d/qubes-cached.repo
|
||||||
/etc/sudoers.d/qubes
|
/etc/sudoers.d/qubes
|
||||||
/etc/xdg/autostart/qubes-guid.desktop
|
/etc/xdg/autostart/qubes-guid.desktop
|
||||||
|
/etc/security/limits.d/99-qubes.conf
|
||||||
|
/etc/yum/post-actions/qubes_sync_rpmdb_updatevm.action
|
||||||
|
@ -66,9 +66,6 @@ mkdir -p $RPM_BUILD_ROOT/var/run/qubes
|
|||||||
mkdir -p $RPM_BUILD_ROOT/etc/xen/scripts
|
mkdir -p $RPM_BUILD_ROOT/etc/xen/scripts
|
||||||
cp ../common/vif-route-qubes $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
|
%post
|
||||||
|
|
||||||
# Create NetworkManager configuration if we do not have it
|
# Create NetworkManager configuration if we do not have it
|
||||||
@ -91,11 +88,6 @@ if [ "$1" = 0 ] ; then
|
|||||||
chkconfig qubes_core_netvm off
|
chkconfig qubes_core_netvm off
|
||||||
fi
|
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
|
%clean
|
||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
@ -108,4 +100,3 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
/etc/NetworkManager/dispatcher.d/qubes_nmhook
|
/etc/NetworkManager/dispatcher.d/qubes_nmhook
|
||||||
/etc/NetworkManager/dispatcher.d/30-qubes_external_ip
|
/etc/NetworkManager/dispatcher.d/30-qubes_external_ip
|
||||||
/etc/xen/scripts/vif-route-qubes
|
/etc/xen/scripts/vif-route-qubes
|
||||||
/etc/dbus-1/system.d/qubes-nm-applet.conf
|
|
||||||
|
42
vchan/init.c
42
vchan/init.c
@ -65,15 +65,25 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
|
|||||||
struct xs_handle *xs;
|
struct xs_handle *xs;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
char ref[16];
|
char ref[16];
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_evtchn *evfd;
|
||||||
|
#else
|
||||||
int evfd;
|
int evfd;
|
||||||
|
#endif
|
||||||
evtchn_port_or_error_t port;
|
evtchn_port_or_error_t port;
|
||||||
xs = xs_domain_open();
|
xs = xs_domain_open();
|
||||||
if (!xs) {
|
if (!xs) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
evfd = xc_evtchn_open(NULL, 0);
|
||||||
|
if (!evfd)
|
||||||
|
goto fail;
|
||||||
|
#else
|
||||||
evfd = xc_evtchn_open();
|
evfd = xc_evtchn_open();
|
||||||
if (evfd < 0)
|
if (evfd < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#endif
|
||||||
ctrl->evfd = evfd;
|
ctrl->evfd = evfd;
|
||||||
// the following hardcoded 0 is the peer domain id
|
// the following hardcoded 0 is the peer domain id
|
||||||
port = xc_evtchn_bind_unbound_port(evfd, 0);
|
port = xc_evtchn_bind_unbound_port(evfd, 0);
|
||||||
@ -98,7 +108,11 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
fail2:
|
fail2:
|
||||||
if (ret)
|
if (ret)
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_evtchn_close(evfd);
|
||||||
|
#else
|
||||||
close(evfd);
|
close(evfd);
|
||||||
|
#endif
|
||||||
fail:
|
fail:
|
||||||
xs_daemon_close(xs);
|
xs_daemon_close(xs);
|
||||||
return ret;
|
return ret;
|
||||||
@ -152,10 +166,18 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
struct xs_handle *xs;
|
struct xs_handle *xs;
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_interface *xcfd;
|
||||||
|
#else
|
||||||
int xcfd;
|
int xcfd;
|
||||||
|
#endif
|
||||||
char buf[64];
|
char buf[64];
|
||||||
char *ref;
|
char *ref;
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_evtchn *evfd;
|
||||||
|
#else
|
||||||
int evfd;
|
int evfd;
|
||||||
|
#endif
|
||||||
int remote_port;
|
int remote_port;
|
||||||
xs = xs_daemon_open();
|
xs = xs_daemon_open();
|
||||||
if (!xs) {
|
if (!xs) {
|
||||||
@ -181,23 +203,43 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno)
|
|||||||
if (!remote_port)
|
if (!remote_port)
|
||||||
goto fail;
|
goto fail;
|
||||||
free(ref);
|
free(ref);
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xcfd = xc_interface_open(NULL, NULL, 0);
|
||||||
|
if (!xcfd)
|
||||||
|
goto fail;
|
||||||
|
#else
|
||||||
xcfd = xc_interface_open();
|
xcfd = xc_interface_open();
|
||||||
if (xcfd < 0)
|
if (xcfd < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#endif
|
||||||
ctrl->ring = (struct vchan_interface *)
|
ctrl->ring = (struct vchan_interface *)
|
||||||
xc_map_foreign_range(xcfd, domain, 4096,
|
xc_map_foreign_range(xcfd, domain, 4096,
|
||||||
PROT_READ | PROT_WRITE, ctrl->ring_ref);
|
PROT_READ | PROT_WRITE, ctrl->ring_ref);
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_interface_close(xcfd);
|
||||||
|
#else
|
||||||
close(xcfd);
|
close(xcfd);
|
||||||
|
#endif
|
||||||
if (ctrl->ring == 0 || ctrl->ring == MAP_FAILED)
|
if (ctrl->ring == 0 || ctrl->ring == MAP_FAILED)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
evfd = xc_evtchn_open(NULL, 0);
|
||||||
|
if (!evfd)
|
||||||
|
goto fail;
|
||||||
|
#else
|
||||||
evfd = xc_evtchn_open();
|
evfd = xc_evtchn_open();
|
||||||
if (evfd < 0)
|
if (evfd < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#endif
|
||||||
ctrl->evfd = evfd;
|
ctrl->evfd = evfd;
|
||||||
ctrl->evport =
|
ctrl->evport =
|
||||||
xc_evtchn_bind_interdomain(evfd, domain, remote_port);
|
xc_evtchn_bind_interdomain(evfd, domain, remote_port);
|
||||||
if (ctrl->evport < 0 || xc_evtchn_notify(evfd, ctrl->evport))
|
if (ctrl->evport < 0 || xc_evtchn_notify(evfd, ctrl->evport))
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_evtchn_close(evfd);
|
||||||
|
#else
|
||||||
close(evfd);
|
close(evfd);
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
fail:
|
||||||
|
@ -149,7 +149,7 @@ int libvchan_close(struct libvchan *ctrl)
|
|||||||
/// The fd to use for select() set
|
/// The fd to use for select() set
|
||||||
int libvchan_fd_for_select(struct libvchan *ctrl)
|
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
|
/// Unmasks event channel; must be called before calling select(), and only then
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <xenctrl.h>
|
||||||
typedef uint32_t VCHAN_RING_IDX;
|
typedef uint32_t VCHAN_RING_IDX;
|
||||||
|
|
||||||
/// struct vchan_interface is placed in memory shared between domains
|
/// struct vchan_interface is placed in memory shared between domains
|
||||||
@ -37,7 +38,11 @@ struct libvchan {
|
|||||||
struct vchan_interface *ring;
|
struct vchan_interface *ring;
|
||||||
uint32_t ring_ref;
|
uint32_t ring_ref;
|
||||||
/// descriptor to event channel interface
|
/// descriptor to event channel interface
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_evtchn *evfd;
|
||||||
|
#else
|
||||||
int evfd;
|
int evfd;
|
||||||
|
#endif
|
||||||
int evport;
|
int evport;
|
||||||
VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod;
|
VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod;
|
||||||
char *rd_ring, *wr_ring;
|
char *rd_ring, *wr_ring;
|
||||||
|
@ -1 +1 @@
|
|||||||
1.5.26
|
1.6.1
|
||||||
|
@ -1 +1 @@
|
|||||||
1.5.28
|
1.6.1
|
||||||
|
Loading…
Reference in New Issue
Block a user