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/qmemman && make clean) | ||||
| 	(cd common && make clean) | ||||
| 	(cd u2mfn && make clean) | ||||
| 	make -C qrexec clean | ||||
| 	make -C vchan clean | ||||
|  | ||||
| @ -5,9 +5,9 @@ dvm_file_editor: dvm_file_editor.o ../common/ioall.o | ||||
| 	$(CC) -pie -g -o $@ $^ | ||||
| qfile-agent-dvm: qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o | ||||
| 	$(CC) -pie -g -o $@ $^ | ||||
| qfile-agent: qfile-agent.o ../common/ioall.o ../common/gui-fatal.o copy_file.o crc32.o | ||||
| qfile-agent: qfile-agent.o ../common/ioall.o ../common/gui-fatal.o ../common/copy_file.o ../common/crc32.o | ||||
| 	$(CC) -pie -g -o $@ $^ | ||||
| qfile-unpacker: qfile-unpacker.o ../common/ioall.o ../common/gui-fatal.o copy_file.o unpack.o crc32.o | ||||
| qfile-unpacker: qfile-unpacker.o ../common/ioall.o ../common/gui-fatal.o ../common/copy_file.o ../common/unpack.o ../common/crc32.o | ||||
| 	$(CC) -pie -g -o $@ $^ | ||||
| 
 | ||||
| clean: | ||||
|  | ||||
| @ -20,15 +20,15 @@ | ||||
| # | ||||
| # | ||||
| 
 | ||||
| if [ x"$1" = "x--with-progress" ] ; then | ||||
| 	DO_PROGRESS=1 | ||||
| if [ x"$1" = "x--without-progress" ] ; then | ||||
| 	DO_PROGRESS=0 | ||||
| 	shift | ||||
| else | ||||
| 	DO_PROGRESS=0 | ||||
| 	DO_PROGRESS=1 | ||||
| fi | ||||
| 
 | ||||
| if [ $# -lt 2 ] ; then | ||||
| 	echo usage: $0 '[--with-progress] dest_vmname file [file]+' | ||||
| 	echo usage: $0 '[--without-progress] dest_vmname file [file]+' | ||||
| 	exit 1 | ||||
| fi | ||||
| 
 | ||||
|  | ||||
| @ -6,4 +6,4 @@ meminfo-writer: meminfo-writer.o | ||||
| xenstore-watch: xenstore-watch.o | ||||
| 	$(CC) -o xenstore-watch xenstore-watch.o -lxenstore | ||||
| clean: | ||||
| 	rm -f meminfo-writer *.o *~ | ||||
| 	rm -f meminfo-writer xenstore-watch *.o *~ | ||||
|  | ||||
| @ -5,7 +5,16 @@ | ||||
| # This creates dm-snapshot device on given arguments | ||||
| 
 | ||||
| dir=$(dirname "$0") | ||||
| . "$dir/block-common.sh" | ||||
| if [ "$1" = "prepare" ] || [ "$1" = "cleanup" ]; then | ||||
|   . "$dir/xen-hotplug-common.sh" | ||||
|   command=$1 | ||||
| else | ||||
|   . "$dir/block-common.sh" | ||||
| fi | ||||
| 
 | ||||
| shopt -s nullglob | ||||
| 
 | ||||
| HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}" | ||||
| 
 | ||||
| get_dev() { | ||||
|   dev=$1 | ||||
| @ -89,7 +98,6 @@ create_dm_snapshot_origin() { | ||||
| 
 | ||||
| t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING') | ||||
| 
 | ||||
| 
 | ||||
| case "$command" in | ||||
|   add) | ||||
|     case $t in | ||||
| @ -117,24 +125,81 @@ case "$command" in | ||||
|         if [ "$t" == "snapshot" ]; then | ||||
|           #that's all for snapshot, store name of prepared device | ||||
|           xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname" | ||||
|           echo "/dev/mapper/$dm_devname" > "$HOTPLUG_STORE-node" | ||||
|           write_dev /dev/mapper/$dm_devname | ||||
|         elif [ "$t" == "origin" ]; then | ||||
|           # for origin - prepare snapshot-origin device and store its name | ||||
|           dm_devname=origin-$(stat -c '%D:%i' "$base") | ||||
|           create_dm_snapshot_origin $dm_devname "$base" | ||||
|           xenstore_write "$XENBUS_PATH/node" "/dev/mapper/$dm_devname" | ||||
|           echo "/dev/mapper/$dm_devname" > "$HOTPLUG_STORE-node" | ||||
|           write_dev /dev/mapper/$dm_devname | ||||
|         fi | ||||
|         # Save domain name for template commit on device remove | ||||
|         domain=$(xenstore_read_default "$XENBUS_PATH/domain" '') | ||||
|         if [ -z "$domain" ]; then | ||||
|           domid=$(xenstore_read "$XENBUS_PATH/frontend-id") | ||||
|           domain=$(xl domname $domid) | ||||
|         fi | ||||
|         echo $domain > "$HOTPLUG_STORE-domain" | ||||
| 
 | ||||
|         release_lock "block" | ||||
|         exit 0 | ||||
|         ;; | ||||
|     esac | ||||
|     ;; | ||||
|   prepare) | ||||
|     t=$2 | ||||
|     case $t in | ||||
|       snapshot|origin) | ||||
|         p=$3 | ||||
|         base=${p/:*/} | ||||
|         cow=${p/*:/} | ||||
| 
 | ||||
|         if [ -L "$base" ]; then | ||||
|           base=$(readlink -f "$base") || fatal "$base link does not exist." | ||||
|         fi | ||||
| 
 | ||||
|         if [ -L "$cow" ]; then | ||||
|           cow=$(readlink -f "$cow") || fatal "$cow link does not exist." | ||||
|         fi | ||||
| 
 | ||||
|         # first ensure that snapshot device exists (to write somewhere changes from snapshot-origin) | ||||
|         dm_devname=$(get_dm_snapshot_name "$base" "$cow") | ||||
| 
 | ||||
|         claim_lock "block" | ||||
| 
 | ||||
|         # prepare snapshot device | ||||
|         create_dm_snapshot $dm_devname "$base" "$cow" | ||||
| 
 | ||||
|         if [ "$t" == "snapshot" ]; then | ||||
|           #that's all for snapshot, store name of prepared device | ||||
|           echo "/dev/mapper/$dm_devname" | ||||
|         elif [ "$t" == "origin" ]; then | ||||
|           # for origin - prepare snapshot-origin device and store its name | ||||
|           dm_devname=origin-$(stat -c '%D:%i' "$base") | ||||
|           create_dm_snapshot_origin $dm_devname "$base" | ||||
|           echo "/dev/mapper/$dm_devname" | ||||
|         fi | ||||
| 
 | ||||
|         release_lock "block" | ||||
|         exit 0 | ||||
|         ;; | ||||
|     esac | ||||
|     ;; | ||||
|   remove) | ||||
|   remove|cleanup) | ||||
|     if [ "$command" = "cleanup" ]; then | ||||
|       t=$2 | ||||
|     else | ||||
|       t=$(cat $HOTPLUG_STORE-type) | ||||
|     fi | ||||
|     case $t in | ||||
|       snapshot|origin) | ||||
|         node=$(xenstore_read "$XENBUS_PATH/node") | ||||
|         if [ "$command" = "cleanup" ]; then | ||||
|           node=$3 | ||||
|         else | ||||
|           node=$(cat "$HOTPLUG_STORE-node") | ||||
|         fi | ||||
| 
 | ||||
|         if [ -z "$node" ]; then | ||||
|           fatal "No device node to remove" | ||||
| @ -174,14 +239,16 @@ case "$command" in | ||||
|               dmsetup remove $snap | ||||
|             fi | ||||
|           done | ||||
|           # Commit template changes | ||||
|           domain=$(xenstore_read "$XENBUS_PATH/domain") | ||||
|           if [ "$domain" ]; then | ||||
|             # Dont stop on errors | ||||
|             /usr/bin/qvm-template-commit "$domain" || true | ||||
|           if [ "$command" = "remove" ]; then | ||||
|             # Commit template changes | ||||
|             domain=$(cat "$HOTPLUG_STORE-domain") | ||||
|             if [ "$domain" ]; then | ||||
|               # Dont stop on errors | ||||
|               /usr/bin/qvm-template-commit "$domain" || true | ||||
|             fi | ||||
|           fi | ||||
|         fi | ||||
| 	 | ||||
| 
 | ||||
|         if [ -e $node ]; then | ||||
|           log debug "Removing $node" | ||||
|           dmsetup remove $node | ||||
|  | ||||
							
								
								
									
										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 <ioall.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 | ||||
| VMNAME=$2 | ||||
| VMDIR=/var/lib/qubes/appvms/$VMNAME | ||||
| VMTYPE=$3 | ||||
| if [ -z "$VMTYPE" ]; then | ||||
|     VMTYPE=appvms | ||||
| fi | ||||
| VMDIR=/var/lib/qubes/$VMTYPE/$VMNAME | ||||
| APPSDIR=$VMDIR/apps | ||||
| 
 | ||||
| if [ $# != 2 ]; then | ||||
|     echo "usage: $0 <apps_templates_dir> <vmname>" | ||||
| if [ $# -lt 2 ]; then | ||||
|     echo "usage: $0 <apps_templates_dir> <vmname> [appvms|vm-templates|servicevms]" | ||||
|     exit | ||||
| fi | ||||
| mkdir -p $APPSDIR | ||||
| 
 | ||||
| if [ "$SRCDIR" != "none" ]; then | ||||
|     echo "--> Converting Appmenu Templates..." | ||||
|     find $SRCDIR -name "*.desktop" -exec /usr/lib/qubes/convert_apptemplate2vm.sh {} $APPSDIR $VMNAME $VMDIR \; | ||||
|     if [ -r "$VMDIR/whitelisted-appmenus.list" ]; then | ||||
|         cat $VMDIR/whitelisted-appmenus.list | xargs -I{} /usr/lib/qubes/convert_apptemplate2vm.sh $SRCDIR/{} $APPSDIR $VMNAME $VMDIR | ||||
|     else | ||||
|         find $SRCDIR -name "*.desktop" $CHECK_WHITELISTED -exec /usr/lib/qubes/convert_apptemplate2vm.sh {} $APPSDIR $VMNAME $VMDIR \; | ||||
|     fi | ||||
|     /usr/lib/qubes/convert_apptemplate2vm.sh /usr/share/qubes/qubes-appmenu-select.template $APPSDIR $VMNAME $VMDIR | ||||
| 
 | ||||
|     /usr/lib/qubes/convert_dirtemplate2vm.sh $SRCDIR/qubes-vm.directory.template $APPSDIR/$VMNAME-vm.directory $VMNAME $VMDIR | ||||
|     /usr/lib/qubes/convert_dirtemplate2vm.sh $SRCDIR/qubes-*.directory.template $APPSDIR/$VMNAME-vm.directory $VMNAME $VMDIR | ||||
| fi | ||||
| 
 | ||||
| echo "--> Adding Apps to the Menu..." | ||||
|  | ||||
							
								
								
									
										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 | ||||
| VMNAME=$1 | ||||
| VMDIR=/var/lib/qubes/appvms/$VMNAME | ||||
| VMTYPE=$2 | ||||
| if [ -z "$VMTYPE" ]; then | ||||
|     VMTYPE=appvms | ||||
| fi | ||||
| VMDIR=/var/lib/qubes/$VMTYPE/$VMNAME | ||||
| APPSDIR=$VMDIR/apps | ||||
| 
 | ||||
| if [ $# != 1 ]; then | ||||
|     echo "usage: $0 <vmname>" | ||||
| if [ $# -lt 1 ]; then | ||||
|     echo "usage: $0 <vmname> [appvms|vm-templates|servicevms]" | ||||
|     exit | ||||
| fi | ||||
| 
 | ||||
| if ls $APPSDIR/*.directory $APPSDIR/*.desktop > /dev/null 2>&1; then | ||||
|     xdg-desktop-menu uninstall $APPSDIR/*.directory $APPSDIR/*.desktop | ||||
|     rm -f $APPSDIR/*.desktop $APPSDIR/*.directory | ||||
| fi | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										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() | ||||
| { | ||||
|     echo -n $"Executing Qubes Core scripts:" | ||||
|     modprobe evtchn | ||||
|     chgrp qubes /etc/xen | ||||
|     chmod 710 /etc/xen | ||||
|     chgrp qubes /var/run/xend | ||||
| @ -28,7 +29,21 @@ start() | ||||
|     chmod 660 /var/run/xend/xen-api.sock /var/run/xend/xmlrpc.sock | ||||
|     chgrp qubes /var/run/xenstored/* | ||||
|     chmod 660 /var/run/xenstored/* | ||||
|     xm sched-credit -d 0 -w 65535 | ||||
|     chgrp qubes /var/lib/xen | ||||
|     chmod 770 /var/lib/xen | ||||
|     chgrp qubes /var/log/xen | ||||
|     chmod 770 /var/log/xen | ||||
|     chgrp qubes /proc/xen/privcmd | ||||
|     chmod 660 /proc/xen/privcmd | ||||
|     chgrp qubes /dev/xen/evtchn | ||||
|     chmod 660 /dev/xen/evtchn | ||||
|     touch /var/run/qubes/xl-lock | ||||
|     chgrp qubes /var/run/qubes/xl-lock | ||||
|     chmod 660 /var/run/qubes/xl-lock | ||||
| 
 | ||||
|     xenstore-write /local/domain/0/name Domain-0 | ||||
|      | ||||
|     xl sched-credit -d 0 -w 512 | ||||
|     cp /var/lib/qubes/qubes.xml /var/lib/qubes/backup/qubes-$(date +%F-%T).xml | ||||
| 
 | ||||
|     /usr/lib/qubes/qmemman_daemon.py >/var/log/qubes/qmemman.log 2>/var/log/qubes/qmemman.errs &  | ||||
|  | ||||
| @ -22,10 +22,10 @@ NETVM=$(qvm-get-default-netvm) | ||||
| 
 | ||||
| get_running_netvms() { | ||||
|     # Actually get running VMs with PCI devices attached | ||||
|     RUNNING_VMS=`xm list --state=Running | tail -n +3 | cut -f 1 -d " "` | ||||
|     RUNNING_VMS=`xl list | tail -n +3 | cut -f 1 -d " "` | ||||
|     RUNNING_NETVMS="" | ||||
|     for VM in $RUNNING_VMS; do | ||||
|         if [ -n "`xm pci-list $VM`" ]; then | ||||
|         if [ -n "`xl pci-list $VM`" ]; then | ||||
|             echo "$VM" | ||||
|         fi | ||||
|     done | ||||
|  | ||||
							
								
								
									
										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() { | ||||
|     # Actually get running VMs with PCI devices attached | ||||
|     RUNNING_VMS=`xm list --state=Running | tail -n +3 | cut -f 1 -d " "` | ||||
|     RUNNING_VMS=`xl list | tail -n +3 | cut -f 1 -d " "` | ||||
|     RUNNING_NETVMS="" | ||||
|     for VM in $RUNNING_VMS; do | ||||
|         if [ -n "`xm pci-list $VM`" ]; then | ||||
|         if [ -n "`xl pci-list $VM|tail -n +2`" ]; then | ||||
|             echo "$VM" | ||||
|         fi | ||||
|     done | ||||
|  | ||||
| @ -9,6 +9,7 @@ class DomainState: | ||||
|     def __init__(self, id): | ||||
|         self.meminfo = None		#dictionary of memory info read from client | ||||
|         self.memory_actual = None	#the current memory size | ||||
|         self.memory_maximum = None	#the maximum memory size | ||||
|         self.mem_used = None		#used memory, computed based on meminfo | ||||
|         self.id = id			#domain id | ||||
|         self.last_target = 0		#the last memset target | ||||
| @ -27,6 +28,7 @@ class SystemState: | ||||
| 
 | ||||
|     def del_domain(self, id): | ||||
|         self.domdict.pop(id) | ||||
|         self.do_balance() | ||||
| 
 | ||||
|     def get_free_xen_memory(self): | ||||
|         return self.xc.physinfo()['free_memory']*1024 | ||||
| @ -42,6 +44,9 @@ class SystemState: | ||||
|             id = str(domain['domid']) | ||||
|             if self.domdict.has_key(id): | ||||
|                 self.domdict[id].memory_actual = domain['mem_kb']*1024 | ||||
|                 self.domdict[id].memory_maximum = self.xs.read('', '/local/domain/%s/memory/static-max' % str(id)) | ||||
|                 if not self.domdict[id].memory_maximum: | ||||
|                     self.domdict[id].memory_maximum = domain['maxmem_kb']*1024 | ||||
| 
 | ||||
| #the below works (and is fast), but then 'xm list' shows unchanged memory value | ||||
|     def mem_set(self, id, val): | ||||
| @ -51,6 +56,7 @@ class SystemState: | ||||
| #can happen in the middle of domain shutdown | ||||
| #apparently xc.lowlevel throws exceptions too | ||||
|         try: | ||||
|             self.xc.domain_setmaxmem(int(id), val/1024 + 1024) # LIBXL_MAXMEM_CONSTANT=1024 | ||||
|             self.xc.domain_set_target_mem(int(id), val/1024) | ||||
|         except: | ||||
|             pass | ||||
|  | ||||
| @ -60,8 +60,8 @@ def prefmem(domain): | ||||
|     CACHE_FACTOR = 1.3 | ||||
| #dom0 is special, as it must have large cache, for vbds. Thus, give it a special boost | ||||
|     if domain.id == '0': | ||||
|         return domain.mem_used*CACHE_FACTOR + 350*1024*1024 | ||||
|     return domain.mem_used*CACHE_FACTOR | ||||
|         return min(domain.mem_used*CACHE_FACTOR + 350*1024*1024, domain.memory_maximum) | ||||
|     return min(domain.mem_used*CACHE_FACTOR, domain.memory_maximum) | ||||
| 
 | ||||
| def memory_needed(domain): | ||||
| #do not change | ||||
| @ -104,8 +104,11 @@ def balloon(memsize, domain_dictionary): | ||||
| 
 | ||||
| #redistribute positive "total_available_memory" of memory between domains, proportionally to prefmem | ||||
| def balance_when_enough_memory(domain_dictionary, xen_free_memory, total_mem_pref, total_available_memory): | ||||
|     donors_rq = list() | ||||
|     acceptors_rq = list() | ||||
|     print 'balance_when_enough_memory(', xen_free_memory, total_mem_pref, total_available_memory, ')' | ||||
|     target_memory = {} | ||||
|     # memory not assigned because of static max | ||||
|     left_memory = 0 | ||||
|     acceptors_count = 0 | ||||
|     for i in domain_dictionary.keys(): | ||||
|         if domain_dictionary[i].meminfo is None: | ||||
|             continue | ||||
| @ -114,10 +117,43 @@ def balance_when_enough_memory(domain_dictionary, xen_free_memory, total_mem_pre | ||||
|         target_nonint = prefmem(domain_dictionary[i]) + scale*total_available_memory | ||||
| #prevent rounding errors | ||||
|         target = int(0.999*target_nonint) | ||||
| #do not try to give more memory than static max | ||||
|         if target > domain_dictionary[i].memory_maximum: | ||||
|             left_memory += target-domain_dictionary[i].memory_maximum | ||||
|             target = domain_dictionary[i].memory_maximum | ||||
|         else: | ||||
| # count domains which can accept more memory | ||||
|             acceptors_count += 1 | ||||
|         target_memory[i] = target | ||||
| # distribute left memory across all acceptors | ||||
|     while left_memory > 0 and acceptors_count > 0: | ||||
|         print '  left_memory:', left_memory, 'acceptors_count:', acceptors_count | ||||
|         new_left_memory = 0 | ||||
|         new_acceptors_count = acceptors_count | ||||
|         for i in target_memory.keys(): | ||||
|             target = target_memory[i] | ||||
|             if target < domain_dictionary[i].memory_maximum: | ||||
|                 memory_bonus = int(0.999*(left_memory/acceptors_count)) | ||||
|                 if target+memory_bonus >= domain_dictionary[i].memory_maximum: | ||||
|                     new_left_memory += target+memory_bonus - domain_dictionary[i].memory_maximum | ||||
|                     target = domain_dictionary[i].memory_maximum | ||||
|                     new_acceptors_count -= 1 | ||||
|                 else: | ||||
|                     target += memory_bonus | ||||
|             target_memory[i] = target | ||||
|         left_memory = new_left_memory | ||||
|         acceptors_count = new_acceptors_count | ||||
| # split target_memory dictionary to donors and acceptors | ||||
| #  this is needed to first get memory from donors and only then give it to acceptors | ||||
|     donors_rq = list() | ||||
|     acceptors_rq = list() | ||||
|     for i in target_memory.keys(): | ||||
|         target = target_memory[i] | ||||
|         if (target < domain_dictionary[i].memory_actual): | ||||
|             donors_rq.append((i, target)) | ||||
|         else: | ||||
|             acceptors_rq.append((i, target)) | ||||
| 
 | ||||
| #    print 'balance(enough): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq | ||||
|     return donors_rq + acceptors_rq | ||||
| 
 | ||||
| @ -140,7 +176,9 @@ def balance_when_low_on_memory(domain_dictionary, xen_free_memory, total_mem_pre | ||||
|     for i in acceptors: | ||||
|         scale = 1.0*prefmem(domain_dictionary[i])/total_mem_pref_acceptors | ||||
|         target_nonint = domain_dictionary[i].memory_actual + scale*squeezed_mem | ||||
|         acceptors_rq.append((i, int(target_nonint)))        | ||||
| #do not try to give more memory than static max | ||||
|         target = min(int(0.999*target_nonint), domain_dictionary[i].memory_maximum) | ||||
|         acceptors_rq.append((i, target)) | ||||
| #    print 'balance(low): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq | ||||
|     return donors_rq + acceptors_rq | ||||
| 
 | ||||
| @ -171,7 +209,7 @@ def balance(xen_free_memory, domain_dictionary): | ||||
|             continue | ||||
|         need = memory_needed(domain_dictionary[i]) | ||||
| #        print 'domain' , i, 'act/pref', domain_dictionary[i].memory_actual, prefmem(domain_dictionary[i]), 'need=', need | ||||
|         if need < 0: | ||||
|         if need < 0 or domain_dictionary[i].memory_actual >= domain_dictionary[i].memory_maximum: | ||||
|             donors.append(i) | ||||
|         else: | ||||
|             acceptors.append(i) | ||||
|  | ||||
| @ -29,10 +29,11 @@ class WatchType: | ||||
| class XS_Watcher: | ||||
|     def __init__(self): | ||||
|         self.handle = xen.lowlevel.xs.xs() | ||||
|         self.handle.watch('/vm', WatchType(XS_Watcher.domain_list_changed, None)) | ||||
|         self.handle.watch('/local/domain', WatchType(XS_Watcher.domain_list_changed, None)) | ||||
|         self.watch_token_dict = {} | ||||
| 
 | ||||
|     def domain_list_changed(self, param): | ||||
|         time.sleep(0.05) | ||||
|         curr = self.handle.ls('', '/local/domain') | ||||
|         if curr == None: | ||||
|             return | ||||
|  | ||||
							
								
								
									
										5
									
								
								dom0/qubes-cached.repo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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) | ||||
|         exit (1) | ||||
| 
 | ||||
|     try: | ||||
|         vm.add_to_xen_storage() | ||||
| 
 | ||||
|     except (IOError, OSError) as err: | ||||
|         print "ERROR: {0}".format(err) | ||||
|         qvm_collection.pop(vm.qid) | ||||
|         exit (1) | ||||
| 
 | ||||
|     qvm_collection.save() | ||||
|     qvm_collection.unlock_db() | ||||
|      | ||||
|  | ||||
| @ -164,7 +164,6 @@ def main(): | ||||
| 
 | ||||
|     try: | ||||
|         vm.create_on_disk(verbose=options.verbose, source_template=template_vm) | ||||
|         vm.add_to_xen_storage() | ||||
| 
 | ||||
|     except (IOError, OSError) as err: | ||||
|         print "ERROR: {0}".format(err) | ||||
|  | ||||
							
								
								
									
										20
									
								
								dom0/qvm-tools/qvm-dom0-upgrade
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										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 QubesHost | ||||
| from qubes.qubes import QubesException | ||||
| from optparse import OptionParser | ||||
| 
 | ||||
| @ -59,8 +60,8 @@ fields = { | ||||
| 
 | ||||
|     "xid" : {"func" : "vm.get_xid() if vm.is_running() else '-'"}, | ||||
| 
 | ||||
|     "mem" : {"func" : "(str(vm.get_mem()/1024/1024) + ' MB') if vm.is_running() else '-'"}, | ||||
|     "cpu" : {"func" : "round (vm.get_cpu_total_load(), 1) if vm.is_running() else '-'"}, | ||||
|     "mem" : {"func" : "(str(vm.get_mem()/1024) + ' MB') if vm.is_running() else '-'"}, | ||||
|     "cpu" : {"func" : "round (cpu_usages[vm.get_xid()]['cpu_usage'], 1) if vm.is_running() else '-'"}, | ||||
|     "disk": {"func" : "str(vm.get_disk_utilization()/(1024*1024)) + ' MB'"},  | ||||
|     "state": {"func" : "vm.get_power_state()"}, | ||||
| 
 | ||||
| @ -114,10 +115,14 @@ def main(): | ||||
| 
 | ||||
|     fields_to_display = ["name", "on", "state", "updbl", "type", "template", "netvm", "label" ] | ||||
| 
 | ||||
|     cpu_usages = None | ||||
| 
 | ||||
|     if (options.ids): | ||||
|         fields_to_display += ["qid", "xid"] | ||||
| 
 | ||||
|     if (options.cpu): | ||||
|         qhost = QubesHost() | ||||
|         (measure_time, cpu_usages) = qhost.measure_cpu_usage() | ||||
|         fields_to_display += ["cpu"] | ||||
| 
 | ||||
|     if (options.mem): | ||||
|  | ||||
| @ -32,7 +32,7 @@ def do_list(vm): | ||||
|     print fmt.format ("name", vm.name) | ||||
|     print fmt.format ("label", vm.label.name) | ||||
|     print fmt.format ("type", vm.type) | ||||
|     if vm.is_appvm(): | ||||
|     if vm.template_vm is not None: | ||||
|         print fmt.format ("template", vm.template_vm.name) | ||||
|     if vm.netvm_vm is not None: | ||||
|         print fmt.format ("netvm", vm.netvm_vm.name) | ||||
| @ -40,15 +40,18 @@ def do_list(vm): | ||||
|     print fmt.format ("installed by RPM?", vm.installed_by_rpm) | ||||
|     print fmt.format ("dir", vm.dir_path) | ||||
|     print fmt.format ("config", vm.conf_file) | ||||
|     print fmt.format ("pcidevs", vm.pcidevs) | ||||
|     if not vm.is_appvm(): | ||||
|         print fmt.format ("root img", vm.root_img) | ||||
|     if vm.is_template(): | ||||
|         print fmt.format ("root COW img", vm.rootcow_img) | ||||
|     if vm.is_appvm(): | ||||
|     if vm.template_vm is not None: | ||||
|         print fmt.format ("root img", vm.template_vm.root_img) | ||||
|         print fmt.format ("root volatile img", vm.volatile_img) | ||||
|     print fmt.format ("root volatile img", vm.volatile_img) | ||||
| 
 | ||||
|     print fmt.format ("private img", vm.private_img) | ||||
|     print fmt.format ("memory", vm.memory) | ||||
|     print fmt.format ("maxmem", vm.maxmem) | ||||
| 
 | ||||
| 
 | ||||
| def set_label(vms, vm, args): | ||||
| @ -65,6 +68,23 @@ def set_label(vms, vm, args): | ||||
|     vm.label = QubesVmLabels[label] | ||||
|     subprocess.check_call (["ln", "-sf", vm.label.icon_path, vm.icon_path]) | ||||
| 
 | ||||
| def set_memory(vms, vm, args): | ||||
|     if len (args) != 1: | ||||
|         print "Missing memory argument!" | ||||
| 
 | ||||
|     vm.memory = int(args[0]) | ||||
| 
 | ||||
| def set_maxmem(vms, vm, args): | ||||
|     if len (args) != 1: | ||||
|         print "Missing maxmem argument!" | ||||
| 
 | ||||
|     vm.maxmem = int(args[0]) | ||||
| 
 | ||||
| def set_pcidevs(vms, vm, args): | ||||
|     if len (args) != 1: | ||||
|         print "Missing memory argument!" | ||||
| 
 | ||||
|     vm.pcidevs = args[0] | ||||
| 
 | ||||
| def set_netvm(vms, vm, args): | ||||
|     if len (args) != 1: | ||||
| @ -151,8 +171,11 @@ def set_nonupdateable(vms, vm, args): | ||||
| properties = { | ||||
|     "updateable": set_updateable, | ||||
|     "nonupdateable": set_nonupdateable, | ||||
|     "pcidevs": set_pcidevs, | ||||
|     "label" : set_label, | ||||
|     "netvm" : set_netvm, | ||||
|     "maxmem" : set_maxmem, | ||||
|     "memory" : set_memory, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										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.verbose: | ||||
|             print "Shutting down VM: '{0}'...".format(vm.name) | ||||
|         subprocess.call (["/usr/sbin/xm", "shutdown", vm.name]) | ||||
|         subprocess.call (["/usr/sbin/xl", "shutdown", vm.name]) | ||||
|         return | ||||
| 
 | ||||
|     if options.pause: | ||||
|         if options.verbose: | ||||
|             print "Pausing VM: '{0}'...".format(vm.name) | ||||
|         subprocess.call (["/usr/sbin/xm", "pause", vm.name]) | ||||
|         subprocess.call (["/usr/sbin/xl", "pause", vm.name]) | ||||
|         return | ||||
| 
 | ||||
|     if options.unpause: | ||||
|         if options.verbose: | ||||
|             print "UnPausing VM: '{0}'...".format(vm.name) | ||||
|         subprocess.call (["/usr/sbin/xm", "unpause", vm.name]) | ||||
|         subprocess.call (["/usr/sbin/xl", "unpause", vm.name]) | ||||
|         return | ||||
| 
 | ||||
|     if options.verbose: | ||||
| @ -152,13 +152,13 @@ def main(): | ||||
|                       help="Wait for the VM(s) to shutdown") | ||||
| 
 | ||||
|     parser.add_option ("--shutdown", action="store_true", dest="shutdown", default=False, | ||||
|                       help="Do 'xm shutdown' for the VM(s) (can be combined this with --all and --wait)") | ||||
|                       help="Do 'xl shutdown' for the VM(s) (can be combined this with --all and --wait)") | ||||
| 
 | ||||
|     parser.add_option ("--pause", action="store_true", dest="pause", default=False, | ||||
|                       help="Do 'xm pause' for the VM(s) (can be combined this with --all and --wait)") | ||||
|                       help="Do 'xl pause' for the VM(s) (can be combined this with --all and --wait)") | ||||
| 
 | ||||
|     parser.add_option ("--unpause", action="store_true", dest="unpause", default=False, | ||||
|                       help="Do 'xm unpause' for the VM(s) (can be combined this with --all and --wait)") | ||||
|                       help="Do 'xl unpause' for the VM(s) (can be combined this with --all and --wait)") | ||||
| 
 | ||||
|     parser.add_option ("--pass_io", action="store_true", dest="passio", default=False, | ||||
|                       help="Pass stdin/stdout/stderr from remote program") | ||||
| @ -166,6 +166,9 @@ def main(): | ||||
|     parser.add_option ("--localcmd", action="store", dest="localcmd", default=None, | ||||
|                       help="With --pass_io, pass stdin/stdout/stderr to the given program") | ||||
| 
 | ||||
|     parser.add_option ("--force", action="store_true", dest="force", default=False, | ||||
|                       help="Force operation, even if may damage other VMs (eg shutdown of NetVM)") | ||||
| 
 | ||||
|     (options, args) = parser.parse_args () | ||||
| 
 | ||||
| 
 | ||||
| @ -218,8 +221,12 @@ def main(): | ||||
|      | ||||
|         # If stopping NetVM - stop connected VMs too | ||||
|         if options.shutdown and vm.is_netvm(): | ||||
|             vms_list += [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()] | ||||
|             vms_list.reverse() | ||||
|             connected_vms =  [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()] | ||||
|             if connected_vms and not options.force: | ||||
|                 print "ERROR: There are other VMs connected to this VM, " | ||||
|                 print "       shutdown them first or use --force option" | ||||
|                 print "VMs list: " + str([vm.name for vm in connected_vms]) | ||||
|                 exit(1) | ||||
| 
 | ||||
|     if takes_cmd_argument: | ||||
|         cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr) | ||||
|  | ||||
							
								
								
									
										46
									
								
								dom0/qvm-tools/qvm-set-updatevm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										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 | ||||
| 
 | ||||
| HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}" | ||||
| 
 | ||||
| hd_arr[10]=a | ||||
| hd_arr[11]=b | ||||
| hd_arr[12]=c | ||||
| @ -38,6 +40,8 @@ process() | ||||
| 	xenstore-write "$XENBUS_PATH/node" "$dev" \ | ||||
| 		"$XENBUS_PATH/physical-device" "7:"$HEXNUMBER \ | ||||
|  		"$XENBUS_PATH/hotplug-status" connected | ||||
| 	echo "$dev" > "$HOTPLUG_STORE-node" | ||||
| 	echo "file" > "$HOTPLUG_STORE-type" | ||||
| } | ||||
| 
 | ||||
| #exec 2>>/tmp/block.$$ | ||||
|  | ||||
| @ -22,8 +22,13 @@ | ||||
| import os | ||||
| import sys | ||||
| import subprocess | ||||
| import shutil | ||||
| import glob | ||||
| from qubes.qubes import QubesVmCollection | ||||
| 
 | ||||
| updates_dir = "/var/lib/qubes/updates" | ||||
| updates_rpm_dir = updates_dir + "/rpm" | ||||
| 
 | ||||
| def is_copy_allowed(vm): | ||||
| #    if vm.copy_allowed: | ||||
| #        return True | ||||
| @ -33,6 +38,36 @@ def is_copy_allowed(vm): | ||||
|     retcode = subprocess.call(['/usr/bin/kdialog', '--yesno', q, '--title', 'File transfer confirmation']) | ||||
|     return retcode == 0 | ||||
| 
 | ||||
| def dom0updates_fatal(msg): | ||||
|     print >> sys.stderr, msg | ||||
|     shutil.rmtree(updates_rpm_dir) | ||||
|     exit(1) | ||||
| 
 | ||||
| def handle_dom0updates(updatevm): | ||||
|     source=os.getenv("QREXEC_REMOTE_DOMAIN") | ||||
|     if source != updatevm.name: | ||||
|         print >> sys.stderr, 'Domain ' + source + ' not allowed to send dom0 updates' | ||||
|         exit(1) | ||||
|     # Clean old packages | ||||
|     if os.path.exists(updates_rpm_dir): | ||||
|         shutil.rmtree(updates_rpm_dir) | ||||
|     subprocess.check_call(["/usr/lib/qubes/qfile-dom0-unpacker", os.getlogin(), updates_rpm_dir]) | ||||
|     # Verify received files | ||||
|     for f in os.listdir(updates_rpm_dir): | ||||
|         if glob.fnmatch.fnmatch(f, "*.rpm"): | ||||
|             p = subprocess.Popen (["/bin/rpm", "-K", updates_rpm_dir + "/" + f], | ||||
|                     stdout=subprocess.PIPE) | ||||
|             output = p.communicate()[0] | ||||
|             if p.returncode != 0: | ||||
|                 dom0updates_fatal('Error while verifing %s signature: %s' % (f, output)) | ||||
|             if output.find("pgp") < 0: | ||||
|                 dom0updates_fatal('Domain ' + source + ' sent not signed rpm: ' + f) | ||||
|         else: | ||||
|             dom0updates_fatal('Domain ' + source + ' sent unexpected file: ' + f) | ||||
|     # After updates received - create repo metadata | ||||
|     subprocess.check_call(["/usr/bin/createrepo", "-q", "/var/lib/qubes/updates"]) | ||||
|     exit(0) | ||||
| 
 | ||||
| def main(): | ||||
|     FILECOPY_VMNAME_SIZE = 32 | ||||
|     blob=os.read(0, FILECOPY_VMNAME_SIZE) | ||||
| @ -42,6 +77,11 @@ def main(): | ||||
|     qvm_collection.lock_db_for_reading() | ||||
|     qvm_collection.load() | ||||
|     qvm_collection.unlock_db() | ||||
|      | ||||
|     if vmname == '@dom0updates': | ||||
|         updatevm = qvm_collection.get_updatevm_vm() | ||||
|         handle_dom0updates(updatevm) | ||||
|         # handle_dom0updates never returns | ||||
| 
 | ||||
|     vm = qvm_collection.get_vm_by_name(vmname) | ||||
| # we do not want to flood dom0 with error windows; so just log to stderr | ||||
|  | ||||
| @ -31,6 +31,7 @@ from qubes.qubes import QubesDaemonPidfile | ||||
| from qubes.qmemman_client import QMemmanClient | ||||
| 
 | ||||
| current_savefile = '/var/run/qubes/current_savefile' | ||||
| current_dvm_conf = '/var/run/qubes/current_dvm.conf' | ||||
| notify_object = None | ||||
| 
 | ||||
| class QfileDaemonDvm: | ||||
| @ -58,6 +59,7 @@ class QfileDaemonDvm: | ||||
|             return None | ||||
|         retcode = subprocess.call(['/usr/lib/qubes/qubes_restore', | ||||
|             current_savefile, | ||||
|             current_dvm_conf, | ||||
|             '-c', vm.label.color, | ||||
|             '-i', vm.label.icon, | ||||
|             '-l', str(vm.label.index)]) | ||||
| @ -130,8 +132,8 @@ def main(): | ||||
|     lockf.close() | ||||
|     if dispname is not None: | ||||
|         subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', dispname, 'directly:user:/usr/lib/qubes/dvm_file_editor']) | ||||
|         subprocess.call(['/usr/sbin/xm', 'destroy', dispname]) | ||||
|         subprocess.call(['/usr/sbin/xl', 'destroy', dispname]) | ||||
|         qfile.remove_disposable_from_qdb(dispname) | ||||
| 
 | ||||
| main() | ||||
|   | ||||
|   | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| #!/bin/sh | ||||
| #!/bin/bash | ||||
| get_encoded_script() | ||||
| { | ||||
| 	if ! [ -f "$1" ] ; then | ||||
| @ -42,22 +42,24 @@ if [ -n "$ENCODED_SCRIPT" ] ; then | ||||
| fi | ||||
| #set -x | ||||
| xenstore-write /local/domain/$ID/qubes_save_request 1  | ||||
| xenstore-watch /local/domain/$ID/device/qubes_used_mem | ||||
| xenstore-watch-qubes /local/domain/$ID/device/qubes_used_mem | ||||
| xenstore-read /local/domain/$ID/qubes_gateway | \ | ||||
| 	cut -d . -f 2 | tr -d "\n" > $VMDIR/netvm_id.txt | ||||
| xm block-detach $1 /dev/xvdb | ||||
| 	cut -d . -f 3 | tr -d "\n" > $VMDIR/netvm_id.txt | ||||
| xl block-detach $1 xvdb | ||||
| MEM=$(xenstore-read /local/domain/$ID/device/qubes_used_mem) | ||||
| echo "DVM boot complete, memory used=$MEM. Saving image..." | ||||
| QMEMMAN_STOP=/var/run/qubes/do-not-membalance | ||||
| touch $QMEMMAN_STOP | ||||
| xm mem-set $1 $(($MEM/1000)) | ||||
| xl mem-set $1 $(($MEM/1000)) | ||||
| sleep 1 | ||||
| touch $2 | ||||
| if ! xm save $1 $2 ; then  | ||||
| if ! xl save $1 $2 ; then  | ||||
| 	rm -f $QMEMMAN_STOP | ||||
| 	exit 1 | ||||
| fi | ||||
| rm -f $QMEMMAN_STOP | ||||
| cd $VMDIR | ||||
| # Fix start memory | ||||
| sed -i -e "s/^memory.*/memory = $((MEM/1000))/" dvm.conf | ||||
| tar -Scvf saved_cows.tar volatile.img | ||||
| echo "DVM savefile created successfully." | ||||
|  | ||||
| @ -12,95 +12,73 @@ | ||||
| #include <syslog.h> | ||||
| #include <xs.h> | ||||
| 
 | ||||
| char xmlrpc_header[] = | ||||
|     "POST /RPC2 HTTP/1.0\r\n" | ||||
|     "Host: \r\n" | ||||
|     "User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\n" | ||||
|     "Content-Type: text/xml\r\n" "Content-Length: %d\r\n" "\r\n"; | ||||
| char xmlrpc_body_restore[] = | ||||
|     "<?xml version='1.0'?>\n" | ||||
|     "<methodCall>\n" | ||||
|     "<methodName>xend.domain.restore</methodName>\n" | ||||
|     "<params>\n" | ||||
|     "<param>\n" | ||||
|     "<value><string>%s</string></value>\n" | ||||
|     "</param>\n" | ||||
|     "<param>\n" | ||||
|     "<value><boolean>0</boolean></value>\n" | ||||
|     "</param>\n" "</params>\n" "</methodCall>\n"; | ||||
| 
 | ||||
| char xmlrpc_body_setmem[] = | ||||
|     "<?xml version='1.0'?>\n<methodCall>\n<methodName>xend.domain.setMemoryTarget</methodName>\n<params>\n<param>\n<value><string>%d</string></value>\n</param>\n<param>\n<value><int>%d</int></value>\n</param>\n</params>\n</methodCall>\n"; | ||||
| 
 | ||||
| void send_raw(int fd, char *body) | ||||
| { | ||||
| 	char *header; | ||||
| 	asprintf(&header, xmlrpc_header, strlen(body)); | ||||
| 	if (write(fd, header, strlen(header)) != strlen(header)) { | ||||
| 		perror("write xend"); | ||||
| int restore_domain(char *restore_file, char *conf_file, char *name) { | ||||
| 	int pid, status, domid; | ||||
| 	int pipe_fd[2]; | ||||
| 	char buf[256]; | ||||
| 	char *endptr; | ||||
| 	switch (pid = fork()) { | ||||
| 	case -1: | ||||
| 		perror("fork"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (write(fd, body, strlen(body)) != strlen(body)) { | ||||
| 		perror("write xend"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	shutdown(fd, SHUT_WR); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void send_req_restore(int fd, char *name) | ||||
| { | ||||
| 	char *body; | ||||
| 	asprintf(&body, xmlrpc_body_restore, name); | ||||
| 	send_raw(fd, body); | ||||
| } | ||||
| 
 | ||||
| void send_req_setmem(int fd, int domid, int mem) | ||||
| { | ||||
| 	char *body; | ||||
| 	asprintf(&body, xmlrpc_body_setmem, domid, mem); | ||||
| 	send_raw(fd, body); | ||||
| } | ||||
| 
 | ||||
| char *recv_resp(int fd) | ||||
| { | ||||
| #define RESPSIZE 65536 | ||||
| 	static char buf[RESPSIZE]; | ||||
| 	int total = 0; | ||||
| 	int n; | ||||
| 	for (;;) { | ||||
| 		n = read(fd, buf + total, RESPSIZE - total); | ||||
| 		if (n == 0) { | ||||
| 			buf[total] = 0; | ||||
| 			close(fd); | ||||
| 			return buf; | ||||
| 		} | ||||
| 		if (n < 0) { | ||||
| 			perror("xend read"); | ||||
| 	case 0: | ||||
| 		close(1); | ||||
| 		if (dup2(open("/dev/null", O_RDWR), 1)==-1) { | ||||
| 			perror("dup2 or open"); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		total += n; | ||||
| 		execl("/usr/sbin/xl", "xl", "restore", conf_file, restore_file, NULL); | ||||
| 		perror("execl"); | ||||
| 		exit(1); | ||||
| 	default:; | ||||
| 	} | ||||
| 	if (waitpid(pid, &status, 0) < 0) { | ||||
| 		perror("waitpid"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (status != 0) { | ||||
| 		fprintf(stderr, "Error starting VM\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	// read domid
 | ||||
| 	if (pipe(pipe_fd)==-1) { | ||||
| 		perror("pipe"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	switch (pid = fork()) { | ||||
| 	case -1: | ||||
| 		perror("fork"); | ||||
| 		exit(1); | ||||
| 	case 0: | ||||
| 		close(1); | ||||
| 		if (dup2(pipe_fd[1], 1) == -1) { | ||||
| 			perror("dup2"); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		execl("/usr/sbin/xl", "xl", "domid", name, NULL); | ||||
| 		perror("execl"); | ||||
| 		exit(1); | ||||
| 	default:; | ||||
| 	} | ||||
| 	read(pipe_fd[0], buf, sizeof(buf)-1); | ||||
| 	buf[sizeof(buf)-1] = 0; | ||||
| 	domid = strtoul(buf, &endptr, 10); | ||||
| 	if (domid <= 0 || *endptr != '\n') { | ||||
| 		fprintf(stderr, "Cannot get DispVM xid\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (waitpid(pid, &status, 0) < 0) { | ||||
| 		perror("waitpid"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (status != 0) { | ||||
| 		fprintf(stderr, "Error getting DispVM xid\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	return domid; | ||||
| } | ||||
| 
 | ||||
| void bad_resp(char *resp) | ||||
| { | ||||
| 	fprintf(stderr, "Error; Xend response:\n%s\n", resp); | ||||
| 	exit(1); | ||||
| } | ||||
| 
 | ||||
| int parse_resp(char *resp) | ||||
| { | ||||
| 	char *domid; | ||||
| 	if (strstr(resp, "<fault>")) | ||||
| 		bad_resp(resp); | ||||
| 	if (!strstr(resp, "domid")) | ||||
| 		bad_resp(resp); | ||||
| 	domid = strstr(resp, "<int>"); | ||||
| 	if (!domid) | ||||
| 		bad_resp(resp); | ||||
| 	return strtoul(domid + 5, NULL, 0); | ||||
| } | ||||
| 
 | ||||
| char *gettime() | ||||
| { | ||||
| @ -161,27 +139,6 @@ void preload_cache(int fd) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int xend_connect() | ||||
| { | ||||
| 	struct sockaddr_un server; | ||||
| 	int s; | ||||
| 
 | ||||
| 	s = socket(AF_UNIX, SOCK_STREAM, 0); | ||||
| 	if (s < 0) { | ||||
| 		perror("socket af_unix"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	server.sun_family = AF_UNIX; | ||||
| 	strcpy(server.sun_path, "/var/run/xend/xmlrpc.sock"); | ||||
| 	if (connect | ||||
| 	    (s, (struct sockaddr *) &server, | ||||
| 	     strlen(server.sun_path) + sizeof(server.sun_family))) { | ||||
| 		perror("connext xend"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	return s; | ||||
| } | ||||
| 
 | ||||
| void start_rexec(int domid) | ||||
| { | ||||
| 	int pid, status; | ||||
| @ -214,40 +171,13 @@ void start_guid(int domid, int argc, char **argv) | ||||
| 	guid_args[0] = "qubes_guid"; | ||||
| 	guid_args[1] = "-d"; | ||||
| 	guid_args[2] = dstr; | ||||
| 	for (i = 2; i < argc; i++) | ||||
| 	for (i = 3; i < argc; i++) | ||||
| 		guid_args[i + 1] = argv[i]; | ||||
| 	guid_args[argc + 1] = NULL; | ||||
| 	execv("/usr/bin/qubes_guid", guid_args); | ||||
| 	perror("execv"); | ||||
| } | ||||
| 
 | ||||
| // modify the savefile. fd = fd to the open savefile,
 | ||||
| // buf - already read 1st page of the savefile
 | ||||
| // pattern - pattern to search for
 | ||||
| // val - string to replace pattern with
 | ||||
| void fix_savefile(int fd, char *buf, char *pattern, char *val) | ||||
| { | ||||
| 	int i, len = strlen(val), origlen; | ||||
| 	char *bracket; | ||||
| 	char *loc = strstr(buf + 20, pattern) + strlen(pattern); | ||||
| 	if (!loc) | ||||
| 		return; | ||||
| 	bracket = index(loc, ')'); | ||||
| 	if (!bracket) | ||||
| 		return; | ||||
| 	origlen = (long) bracket - (long) loc; | ||||
| 	if (origlen < len) { | ||||
| 		fprintf(stderr, "too long string %s\n", val); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	for (i = 0; i < origlen - len; i++) | ||||
| 		loc[i] = ' '; | ||||
| 	memcpy(loc + i, val, strlen(val)); | ||||
| 	lseek(fd, (long) loc - (long) buf, SEEK_SET); | ||||
| 	write(fd, loc, origlen); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| char *dispname_by_dispid(int dispid) | ||||
| { | ||||
| 	static char retbuf[16]; | ||||
| @ -258,8 +188,7 @@ char *dispname_by_dispid(int dispid) | ||||
| char *build_dvm_ip(int netvm, int id) | ||||
| { | ||||
| 	static char buf[256]; | ||||
| 	snprintf(buf, sizeof(buf), "10.%d.%d.%d", netvm, id / 254 + 200, | ||||
| 		 (id % 254) + 1); | ||||
| 	snprintf(buf, sizeof(buf), "10.138.%d.%d", netvm, (id % 254) + 1); | ||||
| 	return buf; | ||||
| } | ||||
| 
 | ||||
| @ -270,15 +199,17 @@ char *build_dvm_ip(int netvm, int id) | ||||
| // normally, it should be "templatename-dvm"
 | ||||
| char *get_vmname_from_savefile(int fd) | ||||
| { | ||||
| 	int buflen; | ||||
| 	static char buf[4096]; | ||||
| 	char *name; | ||||
| 	char *slash; | ||||
| 	lseek(fd, 0, SEEK_SET); | ||||
| 	if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { | ||||
| 		perror("read savefile"); | ||||
| 	buflen = read(fd, buf, sizeof(buf) - 1); | ||||
| 	if (buflen < 0) { | ||||
| 		perror("read vm conf"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	buf[sizeof(buf) - 1] = 0; | ||||
| 	buf[buflen] = 0; | ||||
| 	name = strstr(buf + 20, NAME_PATTERN); | ||||
| 	if (!name) { | ||||
| 		fprintf(stderr, | ||||
| @ -296,25 +227,69 @@ char *get_vmname_from_savefile(int fd) | ||||
| 	return slash + 1; | ||||
| } | ||||
| 
 | ||||
| void fix_savefile_all(int fd, int dispid, int netvm_id) | ||||
| void fill_field(FILE *conf, char *field, int dispid, int netvm_id) | ||||
| { | ||||
| 	char val[256]; | ||||
| 	char buf[4096]; | ||||
| 	lseek(fd, 0, SEEK_SET); | ||||
| 	if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { | ||||
| 		perror("read savefile"); | ||||
| 	if (!strcmp(field, "NAME")) { | ||||
| 		fprintf(conf, "%s", dispname_by_dispid(dispid)); | ||||
| 	} else if (!strcmp(field, "MAC")) { | ||||
| 		fprintf(conf, "00:16:3e:7c:8b:%02x", dispid); | ||||
| 	} else if (!strcmp(field, "IP")) { | ||||
| 		fprintf(conf, "%s", build_dvm_ip(netvm_id, dispid)); | ||||
| 	} else if (!strcmp(field, "UUID")) { | ||||
| 		// currently not present in conf file
 | ||||
| 		fprintf(conf, "064cd14c-95ad-4fc2-a4c9-cf9f522e5b%02x", dispid); | ||||
| 	} else { | ||||
| 		fprintf(stderr, "unknown field in vm conf: %s\n", field); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	buf[sizeof(buf) - 1] = 0; | ||||
| 	snprintf(val, sizeof(val), | ||||
| 		 "064cd14c-95ad-4fc2-a4c9-cf9f522e5b%02x", dispid); | ||||
| 	fix_savefile(fd, buf, "(uuid ", val); | ||||
| 	fix_savefile(fd, buf, "(name ", dispname_by_dispid(dispid)); | ||||
| 	snprintf(val, sizeof(val), "00:16:3e:7c:8b:%02x", dispid); | ||||
| 	fix_savefile(fd, buf, "(mac ", val); | ||||
| 	fix_savefile(fd, buf, "(ip ", build_dvm_ip(netvm_id, dispid)); | ||||
| } | ||||
| 
 | ||||
| // modify the config file. conf = FILE of the new config,
 | ||||
| // conf_templ - fd of config template
 | ||||
| // pattern - pattern to search for
 | ||||
| // val - string to replace pattern with
 | ||||
| void fix_conffile(FILE *conf, int conf_templ, int dispid, int netvm_id) | ||||
| { | ||||
| 	int buflen, cur_len = 0; | ||||
| 	char buf[4096]; | ||||
| 	char *bufpos = buf; | ||||
| 	char *pattern, *patternend; | ||||
| 
 | ||||
| 	/* read config template */ | ||||
| 	lseek(conf_templ, 0, SEEK_SET); | ||||
| 	while ((cur_len = read(conf_templ, buf+cur_len, sizeof(buf)-cur_len)) > 0) { | ||||
| 		buflen+=cur_len; | ||||
| 	} | ||||
| 	if (cur_len < 0) { | ||||
| 		perror("read vm conf"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	while ((pattern = index(bufpos, '%'))) { | ||||
| 		fwrite(bufpos, 1, pattern-bufpos, conf); | ||||
| 		if (ferror(conf)) { | ||||
| 			perror("write vm conf"); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		patternend = index(pattern+1, '%'); | ||||
| 		if (!patternend) { | ||||
| 			fprintf(stderr, "Unmatched '%%' in VM config\n"); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		*patternend = '\0'; | ||||
| 		fill_field(conf, pattern+1, dispid, netvm_id); | ||||
| 		bufpos = patternend+1; | ||||
| 	} | ||||
| 	while ((cur_len = fwrite(bufpos, 1, buflen-(bufpos-buf), conf)) > 0) { | ||||
| 		bufpos+=cur_len; | ||||
| 	} | ||||
| 	if (ferror(conf)) { | ||||
| 		perror("write vm conf"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void unpack_cows(char *name) | ||||
| { | ||||
| 	char vmdir[4096]; | ||||
| @ -355,6 +330,17 @@ void write_xs_single(struct xs_handle *xs, int domid, char *name, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void perm_xs_single(struct xs_handle *xs, int domid, char *name, | ||||
| 		     struct xs_permissions *perms, int nperms) | ||||
| { | ||||
| 	char key[256]; | ||||
| 	snprintf(key, sizeof(key), "/local/domain/%d/%s", domid, name); | ||||
| 	if (!xs_set_permissions(xs, XBT_NULL, key, perms, nperms)) { | ||||
| 		fprintf(stderr, "xs_set_permissions"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int get_netvm_id_from_name(char *name) | ||||
| { | ||||
| 	int fd, n; | ||||
| @ -377,6 +363,7 @@ void setup_xenstore(int netvm_id, int domid, int dvmid, char *name) | ||||
| { | ||||
| 	char val[256]; | ||||
| 	struct xs_handle *xs = xs_daemon_open(); | ||||
| 	struct xs_permissions perm[1]; | ||||
| 	if (!xs) { | ||||
| 		perror("xs_daemon_open"); | ||||
| 		exit(1); | ||||
| @ -385,12 +372,18 @@ void setup_xenstore(int netvm_id, int domid, int dvmid, char *name) | ||||
| 	write_xs_single(xs, domid, "qubes_ip", | ||||
| 			build_dvm_ip(netvm_id, dvmid)); | ||||
| 	write_xs_single(xs, domid, "qubes_netmask", "255.255.0.0"); | ||||
| 	snprintf(val, sizeof(val), "10.%d.0.1", netvm_id); | ||||
| 	snprintf(val, sizeof(val), "10.137.%d.1", netvm_id); | ||||
| 	write_xs_single(xs, domid, "qubes_gateway", val); | ||||
| 	snprintf(val, sizeof(val), "10.%d.255.254", netvm_id); | ||||
| 	snprintf(val, sizeof(val), "10.137.%d.254", netvm_id); | ||||
| 	write_xs_single(xs, domid, "qubes_secondary_dns", val); | ||||
| 	write_xs_single(xs, domid, "qubes_vm_type", "AppVM"); | ||||
| 	write_xs_single(xs, domid, "qubes_restore_complete", "True"); | ||||
| 
 | ||||
| 	perm[0].id = domid; | ||||
| 	perm[0].perms = XS_PERM_NONE; | ||||
| 	perm_xs_single(xs, domid, "device", perm, 1); | ||||
| 	perm_xs_single(xs, domid, "memory", perm, 1); | ||||
| 
 | ||||
| 	xs_daemon_close(xs); | ||||
| 
 | ||||
| } | ||||
| @ -437,46 +430,45 @@ void redirect_stderr() | ||||
| 
 | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	int fd, domid, dispid, netvm_id; | ||||
| 	char *resp; | ||||
| 	int conf_templ, domid, dispid, netvm_id; | ||||
| 	FILE *conf; | ||||
| 	char *name; | ||||
| 	if (argc < 2) { | ||||
| 	char confname[256]; | ||||
| 	if (argc < 3) { | ||||
| 		fprintf(stderr, | ||||
| 			"usage: %s savefile [guid args] \n", argv[0]); | ||||
| 			"usage: %s savefile conf_templ [guid args] \n", argv[0]); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	redirect_stderr(); | ||||
| 	fprintf(stderr, "time=%s, starting\n", gettime()); | ||||
| 	set_fast_flag(); | ||||
| 	atexit(rm_fast_flag); | ||||
| 	fd = open(argv[1], O_RDWR); | ||||
| 	if (fd < 0) { | ||||
| 		perror("open savefile"); | ||||
| 	conf_templ = open(argv[2], O_RDONLY); | ||||
| 	if (conf_templ < 0) { | ||||
| 		perror("fopen vm conf"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	dispid = get_next_disposable_id(); | ||||
| 	name = get_vmname_from_savefile(fd); | ||||
| 	name = get_vmname_from_savefile(conf_templ); | ||||
| 	netvm_id = get_netvm_id_from_name(name); | ||||
| 	fix_savefile_all(fd, dispid, netvm_id); | ||||
| 	snprintf(confname, sizeof(confname), "/tmp/qubes-dvm-%d.xl", dispid); | ||||
| 	conf = fopen(confname, "w"); | ||||
| 	if (!conf) { | ||||
| 		perror("fopen new vm conf"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	fix_conffile(conf, conf_templ, dispid, netvm_id); | ||||
| 	close(conf_templ); | ||||
| 	fclose(conf); | ||||
| //      printf("name=%s\n", name);
 | ||||
| 	unpack_cows(name); | ||||
| //      no preloading for now, assume savefile in shm
 | ||||
| //      preload_cache(fd);
 | ||||
| 	fd = xend_connect(); | ||||
| 	send_req_restore(fd, argv[1]); | ||||
| 	resp = recv_resp(fd); | ||||
| 	domid = parse_resp(resp); | ||||
| 	domid=restore_domain(argv[1], confname, dispname_by_dispid(dispid)); | ||||
| 	write_varrun_domid(domid, dispname_by_dispid(dispid), name); | ||||
| 	fprintf(stderr, | ||||
| 		"time=%s, created domid=%d, creating xenstore entries\n", | ||||
| 		gettime(), domid); | ||||
| #if 0 | ||||
| 	fd = xend_connect(); | ||||
| 	send_req_setmem(fd, domid, 400); | ||||
| 	resp = recv_resp(fd); | ||||
| //      printf("%s\n", resp);
 | ||||
| 	fprintf(stderr, "time=%s, creating xenstore entries\n", gettime()); | ||||
| #endif | ||||
| 	setup_xenstore(netvm_id, domid, dispid, name); | ||||
| 	fprintf(stderr, "time=%s, starting qubes_guid\n", gettime()); | ||||
| 	rm_fast_flag(); | ||||
|  | ||||
| @ -40,12 +40,16 @@ if ! /usr/lib/qubes/qubes_prepare_saved_domain.sh \ | ||||
| fi | ||||
| ROOT=/var/lib/qubes/dvmdata/savefile_root | ||||
| DEFAULT=/var/lib/qubes/dvmdata/default_savefile | ||||
| DEFAULTCONF=/var/lib/qubes/dvmdata/default_dvm.conf | ||||
| CURRENT=/var/run/qubes/current_savefile | ||||
| CURRENTCONF=/var/run/qubes/current_dvm.conf | ||||
| SHMDIR=/dev/shm/qubes | ||||
| SHMCOPY=$SHMDIR/current_savefile | ||||
| rm -f $ROOT $DEFAULT $CURRENT | ||||
| rm -f $ROOT $DEFAULT $CURRENT $DEFAULTCONF $CURRENTCONF | ||||
| ln -s "/var/lib/qubes/appvms/$DVMTMPL/dvm-savefile" $DEFAULT | ||||
| ln -s "/var/lib/qubes/vm-templates/$TEMPLATENAME/root.img" $ROOT | ||||
| ln -s $DVMTMPLDIR/dvm.conf $DEFAULTCONF | ||||
| ln -s $DVMTMPLDIR/dvm.conf $CURRENTCONF | ||||
| if [ -f /var/lib/qubes/dvmdata/dont_use_shm ] ; then | ||||
|             ln -s $DEFAULT $CURRENT | ||||
| else | ||||
|  | ||||
| @ -4,8 +4,13 @@ | ||||
| struct xen_sysctl_physinfo xphysinfo; | ||||
| main() | ||||
| { | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
| 	xc_interface *handle = xc_interface_open(NULL, NULL, 0); | ||||
| 	if (!handle) { | ||||
| #else | ||||
| 	int handle = xc_interface_open(); | ||||
| 	if (handle == -1) { | ||||
| #endif | ||||
| 		perror("xc_interface_open"); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| @ -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') | ||||
| 		OUT=`echo -e "$RULES\n$IPTABLES_SAVE" | /sbin/iptables-restore 2>&1 || :` | ||||
| 		/usr/bin/xenstore-write $XENSTORE_ERROR "$OUT" | ||||
| 		if [ "$OUT" ]; then | ||||
| 			DISPLAY=:0 /usr/bin/notify-send -t 3000 "Firewall loading error ($HOSTNAME)" "$OUT" || : | ||||
| 		fi | ||||
| 
 | ||||
| 		if [[ -z "$OUT" ]]; then | ||||
| 			# If OK save it for later | ||||
| @ -29,5 +32,5 @@ while true; do | ||||
| 	fi | ||||
| 
 | ||||
| 	# Wait for changes in xenstore file | ||||
| 	/usr/bin/xenstore-watch $XENSTORE_IPTABLES | ||||
| 	/usr/bin/xenstore-watch-qubes $XENSTORE_IPTABLES | ||||
| done | ||||
|  | ||||
| @ -24,8 +24,8 @@ while true; do | ||||
| 			/usr/bin/xenstore-write qubes_netvm_external_ip "$CURR_NETCFG" | ||||
| 		fi | ||||
| 
 | ||||
| 		/usr/bin/xenstore-watch /local/domain/$NET_DOMID/qubes_netvm_external_ip | ||||
| 		/usr/bin/xenstore-watch-qubes /local/domain/$NET_DOMID/qubes_netvm_external_ip | ||||
| 	else | ||||
| 		/usr/bin/xenstore-watch qubes_netvm_domid | ||||
| 		/usr/bin/xenstore-watch-qubes qubes_netvm_domid | ||||
| 	fi | ||||
| done | ||||
|  | ||||
| @ -51,7 +51,8 @@ enum { | ||||
| 
 | ||||
| enum { | ||||
| 	QREXEC_EXECUTE_FILE_COPY=0x700, | ||||
| 	QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM | ||||
| 	QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM, | ||||
| 	QREXEC_EXECUTE_APPMENUS_SYNC | ||||
| }; | ||||
| 	 | ||||
| struct server_header { | ||||
|  | ||||
| @ -482,6 +482,9 @@ void handle_trigger_io() | ||||
| 		else if (!strcmp(buf, "DVMR")) | ||||
| 			s_hdr.client_id = | ||||
| 			    QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM; | ||||
| 		else if (!strcmp(buf, "SYNC")) | ||||
| 			s_hdr.client_id = | ||||
| 			    QREXEC_EXECUTE_APPMENUS_SYNC; | ||||
| 		if (s_hdr.client_id) { | ||||
| 			s_hdr.type = MSG_AGENT_TO_SERVER_TRIGGER_EXEC; | ||||
| 			write_all_vchan_ext(&s_hdr, sizeof s_hdr); | ||||
|  | ||||
| @ -361,6 +361,10 @@ void handle_execute_predefined_command(int req) | ||||
| 		rcmd = "directly:user:/usr/lib/qubes/qfile-agent-dvm"; | ||||
| 		lcmd = "/usr/lib/qubes/qfile-daemon-dvm"; | ||||
| 		break; | ||||
| 	case QREXEC_EXECUTE_APPMENUS_SYNC: | ||||
| 		rcmd = "user:grep -H = /usr/share/applications/*.desktop"; | ||||
| 		lcmd = "/usr/bin/qvm-sync-appmenus"; | ||||
| 		break; | ||||
| 	default:		/* cannot happen, already sanitized */ | ||||
| 		fprintf(stderr, "got trigger exec no %d\n", req); | ||||
| 		exit(1); | ||||
| @ -402,7 +406,8 @@ void sanitize_message_from_agent(struct server_header *untrusted_header) | ||||
| 	case MSG_AGENT_TO_SERVER_TRIGGER_EXEC: | ||||
| 		untrusted_cmd = untrusted_header->client_id; | ||||
| 		if (untrusted_cmd != QREXEC_EXECUTE_FILE_COPY && | ||||
| 		    untrusted_cmd != QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM) { | ||||
| 		    untrusted_cmd != QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM && | ||||
| 		    untrusted_cmd != QREXEC_EXECUTE_APPMENUS_SYNC) { | ||||
| 			fprintf(stderr, | ||||
| 				"received MSG_AGENT_TO_SERVER_TRIGGER_EXEC cmd %d ?\n", | ||||
| 				untrusted_cmd); | ||||
|  | ||||
| @ -83,7 +83,11 @@ int buffer_space_vchan_ext() | ||||
| // if the remote domain is destroyed, we get no notification
 | ||||
| // thus, we check for the status periodically
 | ||||
| 
 | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
| static xc_interface *xc_handle = NULL; | ||||
| #else | ||||
| static int xc_handle = -1; | ||||
| #endif | ||||
| void slow_check_for_libvchan_is_eof(struct libvchan *ctrl) | ||||
| { | ||||
| 	struct evtchn_status evst; | ||||
| @ -198,8 +202,13 @@ char *peer_client_init(int dom, int port) | ||||
| 	// now client init should succeed; "while" is redundant
 | ||||
| 	while (!(ctrl = libvchan_client_init(dom, port))); | ||||
| 
 | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
| 	xc_handle = xc_interface_open(NULL, 0, 0); | ||||
| 	if (!xc_handle) { | ||||
| #else | ||||
| 	xc_handle = xc_interface_open(); | ||||
| 	if (xc_handle < 0) { | ||||
| #endif | ||||
| 		perror("xc_interface_open"); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| @ -33,6 +33,7 @@ License:	GPL | ||||
| URL:		http://www.qubes-os.org | ||||
| Requires:	/usr/bin/xenstore-read | ||||
| Requires:   fedora-release | ||||
| Requires:   yum-plugin-post-transaction-actions | ||||
| BuildRequires: xen-devel | ||||
| 
 | ||||
| %define _builddir %(pwd)/common | ||||
| @ -71,24 +72,76 @@ install -m 644 RPM-GPG-KEY-qubes* $RPM_BUILD_ROOT/etc/pki/rpm-gpg/ | ||||
| mkdir -p $RPM_BUILD_ROOT/sbin | ||||
| cp qubes_serial_login $RPM_BUILD_ROOT/sbin | ||||
| mkdir -p $RPM_BUILD_ROOT/usr/bin | ||||
| cp xenstore-watch $RPM_BUILD_ROOT/usr/bin | ||||
| cp xenstore-watch $RPM_BUILD_ROOT/usr/bin/xenstore-watch-qubes | ||||
| mkdir -p $RPM_BUILD_ROOT/etc | ||||
| cp serial.conf $RPM_BUILD_ROOT/var/lib/qubes/ | ||||
| mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d | ||||
| cp qubes_network.rules $RPM_BUILD_ROOT/etc/udev/rules.d/ | ||||
| mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| cp setup_ip $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| cp qubes_download_dom0_updates.sh $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| mkdir -p $RPM_BUILD_ROOT/etc/yum/post-actions | ||||
| cp qubes_trigger_sync_appmenus.action $RPM_BUILD_ROOT/etc/yum/post-actions/ | ||||
| mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| cp qubes_trigger_sync_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/dom0-updates | ||||
| 
 | ||||
| %triggerin -- initscripts | ||||
| cp /var/lib/qubes/serial.conf /etc/init/serial.conf | ||||
| 
 | ||||
| %post | ||||
| 
 | ||||
| # Disable gpk-update-icon | ||||
| sed 's/^NotShowIn=KDE;$/\0QUBES;/' -i /etc/xdg/autostart/gpk-update-icon.desktop | ||||
| # disable some Upstart services | ||||
| for F in plymouth-shutdown prefdm splash-manager start-ttys tty ; do | ||||
| 	if [ -e /etc/init/$F.conf ]; then | ||||
| 		mv -f /etc/init/$F.conf /etc/init/$F.conf.disabled | ||||
| 	fi | ||||
| done | ||||
| 
 | ||||
| remove_ShowIn () { | ||||
| 	if [ -e /etc/xdg/autostart/$1.desktop ]; then | ||||
| 		sed -i '/^\(Not\|Only\)ShowIn/d' /etc/xdg/autostart/$1.desktop | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| # don't want it at all | ||||
| for F in abrt-applet deja-dup-monitor imsettings-start krb5-auth-dialog pulseaudio restorecond sealertauto ; do | ||||
| 	if [ -e /etc/xdg/autostart/$F.desktop ]; then | ||||
| 		remove_ShowIn $F | ||||
| 		echo 'NotShowIn=QUBES' >> /etc/xdg/autostart/$F.desktop | ||||
| 	fi | ||||
| done | ||||
| 
 | ||||
| # don't want it in DisposableVM | ||||
| for F in gcm-apply ; do | ||||
| 	if [ -e /etc/xdg/autostart/$F.desktop ]; then | ||||
| 		remove_ShowIn $F | ||||
| 		echo 'NotShowIn=DisposableVM' >> /etc/xdg/autostart/$F.desktop | ||||
| 	fi | ||||
| done | ||||
| 
 | ||||
| # want it in AppVM only | ||||
| for F in gnome-keyring-gpg gnome-keyring-pkcs11 gnome-keyring-secrets gnome-keyring-ssh gnome-settings-daemon user-dirs-update-gtk gsettings-data-convert ; do | ||||
| 	if [ -e /etc/xdg/autostart/$F.desktop ]; then | ||||
| 		remove_ShowIn $F | ||||
| 		echo 'OnlyShowIn=GNOME;AppVM;' >> /etc/xdg/autostart/$F.desktop | ||||
| 	fi | ||||
| done | ||||
| 
 | ||||
| # remove existing rule to add own later | ||||
| for F in gpk-update-icon nm-applet ; do | ||||
| 	remove_ShowIn $F | ||||
| done | ||||
| 
 | ||||
| echo 'OnlyShowIn=GNOME;UpdateableVM;' >> /etc/xdg/autostart/gpk-update-icon.desktop || : | ||||
| echo 'OnlyShowIn=GNOME;NetVM;' >> /etc/xdg/autostart/nm-applet.desktop || : | ||||
| 
 | ||||
| usermod -p '' root | ||||
| if [ "$1" !=  1 ] ; then | ||||
| # do this whole %post thing only when updating for the first time... | ||||
| exit 0 | ||||
| fi | ||||
| 
 | ||||
| usermod -L root | ||||
| if ! [ -f /var/lib/qubes/serial.orig ] ; then | ||||
| 	cp /etc/init/serial.conf /var/lib/qubes/serial.orig | ||||
| fi | ||||
| @ -177,4 +230,9 @@ rm -rf $RPM_BUILD_ROOT | ||||
| /etc/yum.repos.d/qubes%{dist}.repo | ||||
| /etc/pki/rpm-gpg/RPM-GPG-KEY-qubes* | ||||
| /sbin/qubes_serial_login | ||||
| /usr/bin/xenstore-watch | ||||
| /usr/bin/xenstore-watch-qubes | ||||
| /etc/udev/rules.d/qubes_network.rules | ||||
| /usr/lib/qubes/setup_ip | ||||
| /etc/yum/post-actions/qubes_trigger_sync_appmenus.action | ||||
| /usr/lib/qubes/qubes_trigger_sync_appmenus.sh | ||||
| /usr/lib/qubes/qubes_download_dom0_updates.sh | ||||
|  | ||||
| @ -39,8 +39,9 @@ URL:		http://www.qubes-os.org | ||||
| BuildRequires:  xen-devel | ||||
| Requires:	python, xen-runtime, pciutils, python-inotify, python-daemon, kernel-qubes-dom0 | ||||
| Conflicts:      qubes-gui-dom0 < 1.1.13 | ||||
| Requires:       yum-plugin-post-transaction-actions | ||||
| Requires:       NetworkManager >= 0.8.1-1 | ||||
| Requires:       xen >= 3.4.3-6 | ||||
| Requires:       xen >= 4.1.0-2 | ||||
| %define _builddir %(pwd)/dom0 | ||||
| 
 | ||||
| %description | ||||
| @ -50,6 +51,7 @@ The Qubes core files for installation on Dom0. | ||||
| python -m compileall qvm-core qmemman | ||||
| python -O -m compileall qvm-core qmemman | ||||
| make -C restore | ||||
| make -C aux-tools | ||||
| make -C ../common | ||||
| make -C ../vchan | ||||
| make -C ../u2mfn | ||||
| @ -89,17 +91,26 @@ cp aux-tools/convert_dirtemplate2vm.sh $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| cp aux-tools/create_apps_for_appvm.sh $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| cp aux-tools/remove_appvm_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| cp aux-tools/reset_vm_configs.py  $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| cp aux-tools/sync_rpmdb_updatevm.sh $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| cp qmemman/server.py $RPM_BUILD_ROOT/usr/lib/qubes/qmemman_daemon.py | ||||
| cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| cp ../qrexec/qrexec_daemon $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| cp ../qrexec/qrexec_client $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| cp aux-tools/qfile-dom0-unpacker $RPM_BUILD_ROOT/usr/lib/qubes/ | ||||
| 
 | ||||
| cp restore/xenstore-watch restore/qvm-create-default-dvm $RPM_BUILD_ROOT/usr/bin | ||||
| cp restore/qvm-create-default-dvm $RPM_BUILD_ROOT/usr/bin | ||||
| cp restore/xenstore-watch $RPM_BUILD_ROOT/usr/bin/xenstore-watch-qubes | ||||
| cp restore/qubes_restore restore/xenfreepages $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| cp restore/qubes_prepare_saved_domain.sh  $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| cp restore/qfile-daemon-dvm $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| cp restore/qfile-daemon $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| 
 | ||||
| mkdir -p $RPM_BUILD_ROOT/etc/yum.real.repos.d | ||||
| cp qubes-cached.repo $RPM_BUILD_ROOT/etc/yum.real.repos.d/ | ||||
| 
 | ||||
| mkdir -p $RPM_BUILD_ROOT/etc/yum/post-actions | ||||
| cp misc/qubes_sync_rpmdb_updatevm.action $RPM_BUILD_ROOT/etc/yum/post-actions/ | ||||
| 
 | ||||
| mkdir -p $RPM_BUILD_ROOT/var/lib/qubes | ||||
| mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/vm-templates | ||||
| mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/appvms | ||||
| @ -108,8 +119,14 @@ mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/servicevms | ||||
| mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/backup | ||||
| mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/dvmdata | ||||
| 
 | ||||
| mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/updates | ||||
| 
 | ||||
| mkdir -p $RPM_BUILD_ROOT/usr/share/qubes/icons | ||||
| cp icons/*.png $RPM_BUILD_ROOT/usr/share/qubes/icons | ||||
| cp misc/qubes-vm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/ | ||||
| cp misc/qubes-templatevm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/ | ||||
| cp misc/qubes-appmenu-select.template $RPM_BUILD_ROOT/usr/share/qubes/ | ||||
| cp misc/vm-template.conf $RPM_BUILD_ROOT/usr/share/qubes/ | ||||
| 
 | ||||
| mkdir -p $RPM_BUILD_ROOT/usr/bin | ||||
| cp ../common/qubes_setup_dnat_to_ns $RPM_BUILD_ROOT/usr/lib/qubes | ||||
| @ -120,6 +137,8 @@ mkdir -p $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/ | ||||
| cp ../common/qubes_nmhook $RPM_BUILD_ROOT/etc/NetworkManager/dispatcher.d/ | ||||
| mkdir -p $RPM_BUILD_ROOT/etc/sysconfig | ||||
| cp ../common/iptables $RPM_BUILD_ROOT/etc/sysconfig | ||||
| mkdir -p $RPM_BUILD_ROOT/etc/security/limits.d | ||||
| cp misc/limits-qubes.conf $RPM_BUILD_ROOT/etc/security/limits.d/99-qubes.conf | ||||
| 
 | ||||
| mkdir -p $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d | ||||
| cp pm-utils/01qubes-sync-vms-clock $RPM_BUILD_ROOT/usr/lib64/pm-utils/sleep.d/ | ||||
| @ -150,6 +169,13 @@ fi | ||||
| 
 | ||||
| sed 's/^net.ipv4.ip_forward.*/net.ipv4.ip_forward = 1/'  -i /etc/sysctl.conf | ||||
| 
 | ||||
| sed '/^autoballoon=/d;/^lockfile=/d' -i /etc/xen/xl.conf | ||||
| echo 'autoballoon=0' >> /etc/xen/xl.conf | ||||
| echo 'lockfile="/var/run/qubes/xl-lock"' >> /etc/xen/xl.conf | ||||
| 
 | ||||
| sed '/^reposdir=/d' -i /etc/yum.conf | ||||
| echo reposdir=/etc/yum.real.repos.d >> /etc/yum.conf | ||||
| 
 | ||||
| chkconfig --add qubes_core || echo "WARNING: Cannot add service qubes_core!" | ||||
| chkconfig --add qubes_netvm || echo "WARNING: Cannot add service qubes_netvm!" | ||||
| chkconfig --add qubes_setupdvm || echo "WARNING: Cannot add service qubes_setupdvm!" | ||||
| @ -158,6 +184,10 @@ chkconfig --level 5 qubes_core on || echo "WARNING: Cannot enable service qubes_ | ||||
| chkconfig --level 5 qubes_netvm on || echo "WARNING: Cannot enable service qubes_netvm!" | ||||
| chkconfig --level 5 qubes_setupdvm on || echo "WARNING: Cannot enable service qubes_setupdvm!" | ||||
| 
 | ||||
| # Conflicts with libxl stack, so disable it | ||||
| service xend stop | ||||
| chkconfig --level 5 xend off | ||||
| 
 | ||||
| HAD_SYSCONFIG_NETWORK=yes | ||||
| if ! [ -e /etc/sysconfig/network ]; then | ||||
|     HAD_SYSCONFIG_NETWORK=no | ||||
| @ -167,10 +197,7 @@ fi | ||||
| 
 | ||||
| # Load evtchn module - xenstored needs it | ||||
| modprobe evtchn | ||||
| 
 | ||||
| # Now launch xend - we will need it for subsequent steps | ||||
| service xenstored start | ||||
| service xend start | ||||
| 
 | ||||
| if ! [ -e /var/lib/qubes/qubes.xml ]; then | ||||
| #    echo "Initializing Qubes DB..." | ||||
| @ -259,13 +286,20 @@ fi | ||||
| /usr/lib/qubes/meminfo-writer | ||||
| /usr/lib/qubes/qfile-daemon-dvm* | ||||
| /usr/lib/qubes/qfile-daemon | ||||
| /usr/lib/qubes/sync_rpmdb_updatevm.sh | ||||
| %attr(4750,root,qubes) /usr/lib/qubes/qfile-dom0-unpacker | ||||
| %attr(770,root,qubes) %dir /var/lib/qubes | ||||
| %attr(770,root,qubes) %dir /var/lib/qubes/vm-templates | ||||
| %attr(770,root,qubes) %dir /var/lib/qubes/appvms | ||||
| %attr(770,root,qubes) %dir /var/lib/qubes/servicevms | ||||
| %attr(770,root,qubes) %dir /var/lib/qubes/backup | ||||
| %attr(770,root,qubes) %dir /var/lib/qubes/dvmdata | ||||
| %attr(770,root,qubes) %dir /var/lib/qubes/updates | ||||
| %dir /usr/share/qubes/icons/*.png | ||||
| /usr/share/qubes/qubes-vm.directory.template | ||||
| /usr/share/qubes/qubes-templatevm.directory.template | ||||
| /usr/share/qubes/qubes-appmenu-select.template | ||||
| /usr/share/qubes/vm-template.conf | ||||
| /usr/lib/qubes/qubes_setup_dnat_to_ns | ||||
| /usr/lib/qubes/qubes_fix_nm_conf.sh | ||||
| /etc/dhclient.d/qubes_setup_dnat_to_ns.sh | ||||
| @ -274,7 +308,7 @@ fi | ||||
| /usr/lib64/pm-utils/sleep.d/01qubes-sync-vms-clock | ||||
| /usr/lib64/pm-utils/sleep.d/01qubes-suspend-netvm | ||||
| /usr/lib64/pm-utils/sleep.d/02qubes-pause-vms | ||||
| /usr/bin/xenstore-watch | ||||
| /usr/bin/xenstore-watch-qubes | ||||
| /usr/lib/qubes/qubes_restore | ||||
| /usr/lib/qubes/qubes_prepare_saved_domain.sh | ||||
| /etc/xen/scripts/block.qubes | ||||
| @ -288,5 +322,8 @@ fi | ||||
| %attr(770,root,qubes) %dir /var/run/qubes | ||||
| %{_libdir}/libvchan.so | ||||
| %{_libdir}/libu2mfn.so | ||||
| /etc/yum.real.repos.d/qubes-cached.repo | ||||
| /etc/sudoers.d/qubes | ||||
| /etc/xdg/autostart/qubes-guid.desktop | ||||
| /etc/security/limits.d/99-qubes.conf | ||||
| /etc/yum/post-actions/qubes_sync_rpmdb_updatevm.action | ||||
|  | ||||
| @ -66,9 +66,6 @@ mkdir -p $RPM_BUILD_ROOT/var/run/qubes | ||||
| mkdir -p $RPM_BUILD_ROOT/etc/xen/scripts | ||||
| cp ../common/vif-route-qubes $RPM_BUILD_ROOT/etc/xen/scripts | ||||
| 
 | ||||
| mkdir -p $RPM_BUILD_ROOT/etc/dbus-1/system.d | ||||
| cp ../netvm/dbus-nm-applet.conf $RPM_BUILD_ROOT/etc/dbus-1/system.d/qubes-nm-applet.conf | ||||
| 
 | ||||
| %post | ||||
| 
 | ||||
| # Create NetworkManager configuration if we do not have it | ||||
| @ -91,11 +88,6 @@ if [ "$1" = 0 ] ; then | ||||
|     chkconfig qubes_core_netvm off | ||||
| fi | ||||
| 
 | ||||
| %triggerin -- NetworkManager | ||||
| # Fix PolicyKit settings to allow run as normal user not visible to ConsoleKit | ||||
| sed 's#<defaults>$#\0<allow_any>yes</allow_any>#' -i /usr/share/polkit-1/actions/org.freedesktop.NetworkManager.policy | ||||
| 
 | ||||
| 
 | ||||
| %clean | ||||
| rm -rf $RPM_BUILD_ROOT | ||||
| 
 | ||||
| @ -108,4 +100,3 @@ rm -rf $RPM_BUILD_ROOT | ||||
| /etc/NetworkManager/dispatcher.d/qubes_nmhook | ||||
| /etc/NetworkManager/dispatcher.d/30-qubes_external_ip | ||||
| /etc/xen/scripts/vif-route-qubes | ||||
| /etc/dbus-1/system.d/qubes-nm-applet.conf | ||||
|  | ||||
							
								
								
									
										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; | ||||
| 	char buf[64]; | ||||
| 	char ref[16]; | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
|     xc_evtchn *evfd; | ||||
| #else | ||||
| 	int evfd; | ||||
| #endif | ||||
| 	evtchn_port_or_error_t port; | ||||
| 	xs = xs_domain_open(); | ||||
| 	if (!xs) { | ||||
| 		return ret; | ||||
| 	} | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
| 	evfd = xc_evtchn_open(NULL, 0); | ||||
| 	if (!evfd) | ||||
| 		goto fail; | ||||
| #else | ||||
| 	evfd = xc_evtchn_open(); | ||||
| 	if (evfd < 0) | ||||
| 		goto fail; | ||||
| #endif | ||||
| 	ctrl->evfd = evfd; | ||||
| 	// the following hardcoded 0 is the peer domain id
 | ||||
| 	port = xc_evtchn_bind_unbound_port(evfd, 0);	 | ||||
| @ -98,7 +108,11 @@ static int server_interface_init(struct libvchan *ctrl, int devno) | ||||
| 	ret = 0; | ||||
|       fail2: | ||||
| 	if (ret) | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
|         xc_evtchn_close(evfd); | ||||
| #else | ||||
| 		close(evfd); | ||||
| #endif | ||||
|       fail: | ||||
| 	xs_daemon_close(xs); | ||||
| 	return ret; | ||||
| @ -152,10 +166,18 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno) | ||||
| 	int ret = -1; | ||||
| 	unsigned int len; | ||||
| 	struct xs_handle *xs; | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
|     xc_interface *xcfd; | ||||
| #else | ||||
| 	int xcfd; | ||||
| #endif | ||||
| 	char buf[64]; | ||||
| 	char *ref; | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
|     xc_evtchn *evfd; | ||||
| #else | ||||
| 	int evfd; | ||||
| #endif | ||||
| 	int remote_port; | ||||
| 	xs = xs_daemon_open(); | ||||
| 	if (!xs) { | ||||
| @ -181,23 +203,43 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno) | ||||
| 	if (!remote_port) | ||||
| 		goto fail; | ||||
| 	free(ref); | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
| 	xcfd = xc_interface_open(NULL, NULL, 0); | ||||
| 	if (!xcfd) | ||||
| 		goto fail; | ||||
| #else | ||||
| 	xcfd = xc_interface_open(); | ||||
| 	if (xcfd < 0) | ||||
| 		goto fail; | ||||
| #endif | ||||
| 	ctrl->ring = (struct vchan_interface *) | ||||
| 	    xc_map_foreign_range(xcfd, domain, 4096, | ||||
| 				 PROT_READ | PROT_WRITE, ctrl->ring_ref); | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
|     xc_interface_close(xcfd); | ||||
| #else | ||||
| 	close(xcfd); | ||||
| #endif | ||||
| 	if (ctrl->ring == 0 || ctrl->ring == MAP_FAILED) | ||||
| 		goto fail; | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
| 	evfd = xc_evtchn_open(NULL, 0); | ||||
| 	if (!evfd) | ||||
| 		goto fail; | ||||
| #else | ||||
| 	evfd = xc_evtchn_open(); | ||||
| 	if (evfd < 0) | ||||
| 		goto fail; | ||||
| #endif | ||||
| 	ctrl->evfd = evfd; | ||||
| 	ctrl->evport = | ||||
| 	    xc_evtchn_bind_interdomain(evfd, domain, remote_port); | ||||
| 	if (ctrl->evport < 0 || xc_evtchn_notify(evfd, ctrl->evport)) | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
|         xc_evtchn_close(evfd); | ||||
| #else | ||||
| 		close(evfd); | ||||
| #endif | ||||
| 	else | ||||
| 		ret = 0; | ||||
|       fail: | ||||
|  | ||||
| @ -149,7 +149,7 @@ int libvchan_close(struct libvchan *ctrl) | ||||
| /// The fd to use for select() set
 | ||||
| int libvchan_fd_for_select(struct libvchan *ctrl) | ||||
| { | ||||
| 	return ctrl->evfd; | ||||
| 	return xc_evtchn_fd(ctrl->evfd); | ||||
| } | ||||
| 
 | ||||
| /// Unmasks event channel; must be called before calling select(), and only then
 | ||||
|  | ||||
| @ -20,6 +20,7 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <xenctrl.h> | ||||
| typedef uint32_t VCHAN_RING_IDX; | ||||
| 
 | ||||
| /// struct vchan_interface is placed in memory shared between domains
 | ||||
| @ -37,7 +38,11 @@ struct libvchan { | ||||
| 	struct vchan_interface *ring; | ||||
| 	uint32_t ring_ref; | ||||
| 	/// descriptor to event channel interface
 | ||||
| #ifdef XENCTRL_HAS_XC_INTERFACE | ||||
|     xc_evtchn *evfd; | ||||
| #else | ||||
| 	int evfd; | ||||
| #endif | ||||
| 	int evport; | ||||
| 	VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod; | ||||
| 	char *rd_ring, *wr_ring; | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| 1.5.26 | ||||
| 1.6.1 | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| 1.5.28 | ||||
| 1.6.1 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Joanna Rutkowska
						Joanna Rutkowska