Browse Source

Clean up early initialization and setup of /rw

Manuel Amador (Rudd-O) 7 years ago
parent
commit
59aec8e5eb
44 changed files with 638 additions and 541 deletions
  1. 12 11
      Makefile
  2. 3 3
      archlinux/PKGBUILD.install
  3. 2 0
      debian/control
  4. 3 3
      debian/qubes-core-agent.postinst
  5. 14 0
      init/control-printer-icon.sh
  6. 117 0
      init/functions
  7. 15 0
      init/setup-dvm-home.sh
  8. 105 0
      init/setup-rw.sh
  9. 25 0
      init/setup-rwdev.sh
  10. BIN
      misc/dispvm-dotfiles.tbz
  11. 15 15
      misc/dispvm-prerun.sh
  12. 4 3
      misc/qubes-trigger-sync-appmenus.sh
  13. 2 2
      network/qubes-firewall
  14. 8 4
      network/qubes-nmhook
  15. 7 11
      network/setup-ip
  16. 4 2
      network/show-hide-nm-applet.sh
  17. 5 2
      network/update-proxy-configs
  18. 7 4
      qubes-rpc/prepare-suspend
  19. 25 37
      rpm_spec/core-vm.spec
  20. 28 133
      vm-init.d/qubes-core
  21. 0 104
      vm-init.d/qubes-core-appvm
  22. 44 0
      vm-init.d/qubes-core-early
  23. 7 24
      vm-init.d/qubes-core-netvm
  24. 43 0
      vm-init.d/qubes-dvm
  25. 8 6
      vm-init.d/qubes-firewall
  26. 7 5
      vm-init.d/qubes-netwatcher
  27. 6 4
      vm-init.d/qubes-qrexec-agent
  28. 34 0
      vm-init.d/qubes-sysinit
  29. 7 4
      vm-init.d/qubes-updates-proxy
  30. 6 11
      vm-systemd/bind-dirs.sh
  31. 3 0
      vm-systemd/cups.service.d/30_qubes.conf
  32. 5 10
      vm-systemd/misc-post.sh
  33. 13 84
      vm-systemd/mount-dirs.sh
  34. 22 16
      vm-systemd/prepare-dvm.sh
  35. 2 2
      vm-systemd/qubes-dvm.service
  36. 0 1
      vm-systemd/qubes-firewall.service
  37. 0 2
      vm-systemd/qubes-iptables.service
  38. 8 5
      vm-systemd/qubes-mount-dirs.service
  39. 0 1
      vm-systemd/qubes-netwatcher.service
  40. 0 1
      vm-systemd/qubes-network.service
  41. 0 1
      vm-systemd/qubes-qrexec-agent.service
  42. 4 2
      vm-systemd/qubes-random-seed.sh
  43. 0 1
      vm-systemd/qubes-sysinit.service
  44. 18 27
      vm-systemd/qubes-sysinit.sh

+ 12 - 11
Makefile

@@ -86,9 +86,15 @@ install-systemd-dropins:
 	    install -m 0644 vm-systemd/user/$${dropin}.d/*.conf $(DESTDIR)/$(DROPIN_DIR)/user/$${dropin}.d/ ;\
 	done
 
-install-systemd:
+install-init:
+	install -d $(DESTDIR)$(LIBDIR)/qubes/init
+	# FIXME: do a source code move vm-systemd/*.sh to init/
+	# since those scripts are shared between sysvinit and systemd.
+	install -m 0755 init/*.sh vm-systemd/*.sh $(DESTDIR)$(LIBDIR)/qubes/init/
+	install -m 0644 init/functions $(DESTDIR)$(LIBDIR)/qubes/init/
+
+install-systemd: install-init
 	install -d $(DESTDIR)$(SYSLIBDIR)/systemd/system{,-preset} $(DESTDIR)$(LIBDIR)/qubes/init $(DESTDIR)$(SYSLIBDIR)/modules-load.d
-	install -m 0755 vm-systemd/*.sh $(DESTDIR)$(LIBDIR)/qubes/init/
 	install -m 0644 vm-systemd/qubes-*.service $(DESTDIR)$(SYSLIBDIR)/systemd/system/
 	install -m 0644 vm-systemd/qubes-*.timer $(DESTDIR)$(SYSLIBDIR)/systemd/system/
 	install -m 0644 vm-systemd/75-qubes-vm.preset $(DESTDIR)$(SYSLIBDIR)/systemd/system-preset/
@@ -98,15 +104,17 @@ install-systemd:
 	install -D -m 0644 vm-systemd/qubes-core-agent-linux.tmpfiles \
 		$(DESTDIR)/usr/lib/tmpfiles.d/qubes-core-agent-linux.conf
 
-install-sysvinit:
+install-sysvinit: install-init
 	install -d $(DESTDIR)/etc/init.d
+	install vm-init.d/qubes-sysinit $(DESTDIR)/etc/init.d/
+	install vm-init.d/qubes-core-early $(DESTDIR)/etc/init.d/
 	install vm-init.d/qubes-core $(DESTDIR)/etc/init.d/
-	install vm-init.d/qubes-core-appvm $(DESTDIR)/etc/init.d/
 	install vm-init.d/qubes-core-netvm $(DESTDIR)/etc/init.d/
 	install vm-init.d/qubes-firewall $(DESTDIR)/etc/init.d/
 	install vm-init.d/qubes-netwatcher $(DESTDIR)/etc/init.d/
 	install vm-init.d/qubes-qrexec-agent $(DESTDIR)/etc/init.d/
 	install vm-init.d/qubes-updates-proxy $(DESTDIR)/etc/init.d/
+	install vm-init.d/qubes-dvm $(DESTDIR)/etc/init.d/
 	install -D vm-init.d/qubes-core.modules $(DESTDIR)/etc/sysconfig/modules/qubes-core.modules
 	install -D vm-init.d/qubes-misc.modules $(DESTDIR)/etc/sysconfig/modules/qubes-misc.modules
 	install network/qubes-iptables $(DESTDIR)/etc/init.d/
@@ -164,13 +172,6 @@ install-common:
 	install -g user -m 2775 -d $(DESTDIR)/var/lib/qubes/dom0-updates
 	install -D -m 0644 misc/qubes-master-key.asc $(DESTDIR)/usr/share/qubes/qubes-master-key.asc
 
-	if [ -r misc/dispvm-dotfiles.$(DIST).tbz ] ; \
-	then \
-		install misc/dispvm-dotfiles.$(DIST).tbz $(DESTDIR)/etc/dispvm-dotfiles.tbz ; \
-	else \
-		install misc/dispvm-dotfiles.tbz $(DESTDIR)/etc/dispvm-dotfiles.tbz ; \
-	fi;
-
 	install misc/dispvm-prerun.sh $(DESTDIR)$(LIBDIR)/qubes/dispvm-prerun.sh
 	install misc/close-window $(DESTDIR)$(LIBDIR)/qubes/close-window
 

+ 3 - 3
archlinux/PKGBUILD.install

@@ -104,10 +104,10 @@ update_qubesconfig() {
 
 	# Location of files which contains list of protected files
 	mkdir -p /etc/qubes/protected-files.d
-	PROTECTED_FILE_LIST='/etc/qubes/protected-files.d'
+	. /usr/lib/qubes/init/functions
 
 	# qubes-core-vm has been broken for some time - it overrides /etc/hosts; restore original content
-	if ! grep -rq "^/etc/hosts$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
+	if ! is_protected_file /etc/hosts ; then
 	    if ! grep -q localhost /etc/hosts; then
 	      cat <<EOF > /etc/hosts
 	127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 `hostname`
@@ -118,7 +118,7 @@ EOF
 
 	# ensure that hostname resolves to 127.0.0.1 resp. ::1 and that /etc/hosts is
 	# in the form expected by qubes-sysinit.sh
-	if ! grep -rq "^/etc/hostname$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
+	if ! is_protected_file /etc/hostname ; then
 	    for ip in '127\.0\.0\.1' '::1'; do
 	        if grep -q "^${ip}\(\s\|$\)" /etc/hosts; then
 	            sed -i "/^${ip}\s/,+0s/\(\s`hostname`\)\+\(\s\|$\)/\2/g" /etc/hosts

+ 2 - 0
debian/control

@@ -37,6 +37,8 @@ Depends:
     ncurses-term,
     net-tools,
     psmisc,
+    procps,
+    util-linux,
     python2.7,
     python-gi,
     python-xdg,

+ 3 - 3
debian/qubes-core-agent.postinst

@@ -78,11 +78,11 @@ case "${1}" in
             /usr/lib/qubes/qubes-fix-nm-conf.sh
 
             # Location of files which contains list of protected files
-            PROTECTED_FILE_LIST='/etc/qubes/protected-files.d'
+            . /usr/lib/qubes/init/functions
 
             # ensure that hostname resolves to 127.0.1.1 resp. ::1 and that /etc/hosts is
             # in the form expected by qubes-sysinit.sh
-            if ! grep -rq "^/etc/hostname$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
+            if ! is_protected_file /etc/hostname ; then
                 for ip in '127\.0\.1\.1' '::1'; do
                     if grep -q "^${ip}\(\s\|$\)" /etc/hosts; then
                         sed -i "/^${ip}\s/,+0s/\(\s`hostname`\)\+\(\s\|$\)/\2/g" /etc/hosts || true
@@ -95,7 +95,7 @@ case "${1}" in
 
             # remove hostname from 127.0.0.1 line (in debian the hostname is by default
             # resolved to 127.0.1.1)
-            if ! grep -rq "^/etc/hosts$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
+            if ! is_protected_file /etc/hosts ; then
                 sed -i "/^127\.0\.0\.1\s/,+0s/\(\s`hostname`\)\+\(\s\|$\)/\2/g" /etc/hosts || true
             fi
 

+ 14 - 0
init/control-printer-icon.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
+if ! is_fully_persistent && test -f /etc/xdg/autostart/print-applet.desktop ; then
+	if qsvc cups ; then
+		# Allow also notification icon
+		sed -i -e '/^NotShowIn=.*QUBES/s/;QUBES//' /etc/xdg/autostart/print-applet.desktop
+	else
+		# Disable notification icon
+		sed -i -e '/QUBES/!s/^NotShowIn=\(.*\)/NotShowIn=QUBES;\1/' /etc/xdg/autostart/print-applet.desktop
+	fi
+fi

+ 117 - 0
init/functions

@@ -0,0 +1,117 @@
+#!/bin/bash
+
+# Location of files which contains list of protected files
+PROTECTED_FILE_LIST='/etc/qubes/protected-files.d'
+
+qsvc() {
+    # Returns whether a service is enabled.
+    # Usage: qsvc <nameofservice>
+    #
+    # Must only be used after qubes-sysinit has started.
+    # See qsvc_early for more information.
+    local count=100
+    while [ ! -e /var/run/qubes-service-environment ] ; do
+        if [ "$count" = "0" ] ; then
+            echo "qsvc: Warning: qubes-sysinit has not finished executing yet" >&2
+            break
+        fi
+        sleep 0.1
+        count=$(( count - 1 ))
+    done
+    [ -e /var/run/qubes-service/"$1" ]
+}
+
+under_systemd() {
+    pidof systemd >/dev/null 2>&1
+}
+
+systemd_version_changed() {
+    under_systemd || return
+    systemd_pkg_version=`systemctl --version|head -n 1`
+    if dmesg | grep -q "$systemd_pkg_version running in system mode."; then
+        return 0
+    fi
+    return 1
+}
+
+possibly_run_save_script() {
+    ENCODED_SCRIPT=$(qubesdb-read /qubes-save-script)
+    if [ -z "$ENCODED_SCRIPT" ] ; then return ; fi
+    tmpfile=$(mktemp /tmp/qubes-save-script.XXXXXXXXX)
+    echo $ENCODED_SCRIPT|perl -e 'use MIME::Base64 qw(decode_base64); local($/) = undef;print decode_base64(<STDIN>)' >"$tmpfile"
+    chmod 755 "$tmpfile"
+    DISPLAY=:0 su - user -c "$tmpfile"
+    ret=$?
+    rm -f "$tmpfile"
+    return $ret
+}
+
+have_qubesdb() {
+    # Tests whether qubesdb-read exists and can be executed.
+    type qubesdb-read >/dev/null 2>&1
+}
+
+have_qrexec_agent() {
+    # Tests whether qrexec-agent exists and can be executed.
+    PATH=/usr/lib/qubes type qrexec-agent >/dev/null 2>&1
+}
+
+qubes_vm_type() {
+    qubesdb-read /qubes-vm-type
+}
+
+is_netvm() {
+    [ "$(qubes_vm_type)" = "NetVM" ]
+}
+
+is_appvm() {
+    [ "$(qubes_vm_type)" = "AppVM" ]
+}
+
+is_proxyvm() {
+    [ "$(qubes_vm_type)" = "ProxyVM" ]
+}
+
+is_templatevm() {
+    [ "$(qubes_vm_type)" = "TemplateVM" ]
+}
+
+is_dispvm() {
+    [ "$(qubes_vm_type)" = "DisposableVM" ]
+}
+
+is_fully_persistent() {
+    [ "$(qubesdb-read /qubes-vm-persistence)" = "full" ]
+}
+
+is_rwonly_persistent() {
+    [ "$(qubesdb-read /qubes-vm-persistence)" = "rw-only" ]
+}
+
+is_updateable() {
+    [ "$(qubesdb-read /qubes-vm-updateable)" = "True" ]
+}
+
+reload_random_seed() {
+    qubesdb-read /qubes-random-seed | base64 -d > /dev/urandom
+    qubesdb-rm /qubes-random-seed
+}
+
+is_protected_file() {
+    grep -Fxrq --exclude='*.rpmsave' --exclude='*~' --exclude='*.rpmnew' --exclude='*.rpmold' -- "${1}" "$PROTECTED_FILE_LIST" 2>/dev/null
+}
+
+umount_retry() {
+    local count=5
+    while mountpoint -q "$1" ; do
+        if umount "$1" ; then break ; fi
+        echo "Something prevents unmounting $1:" >&2
+        fuser -vmM "$1" >&2
+        if [ "$count" = "0" ] ; then
+            return 1
+        fi
+        sleep 5
+        count=$(( count - 1 ))
+    done
+    return 0
+}

+ 15 - 0
init/setup-dvm-home.sh

@@ -0,0 +1,15 @@
+#!/bin/sh
+
+echo "Setting up DVM home" >&2
+
+touch /etc/this-is-dvm
+
+# If the user has customized DispVM settings, use its home instead of default skel
+[ -e /home_volatile/user/.qubes-dispvm-customized ] && already_customized=yes || already_customized=no
+[ -e /rw/home/user/.qubes-dispvm-customized ] && wants_customization=yes || wants_customization=no
+if [ "$wants_customization" = "yes" -a "$already_customized" = "no" ] ; then
+    echo "Customizing /home from /rw/home/user" >&2
+    rm -rf /home_volatile/user
+    cp -af /rw/home/user /home_volatile/user
+    chown -R user.user /home_volatile/user
+fi

+ 105 - 0
init/setup-rw.sh

@@ -0,0 +1,105 @@
+#!/bin/sh
+
+if mountpoint -q /rw ; then
+    # This means /rw is mounted now.
+    echo "Checking /rw" >&2
+
+    if ! [ -d /rw/config ] ; then
+        echo "Virgin boot of the VM: populating /rw/config" >&2
+
+        mkdir -p /rw/config
+        touch /rw/config/rc.local
+        cat > /rw/config/rc.local <<EOF
+#!/bin/sh
+
+# This script will be executed at every VM startup, you can place your own
+# custom commands here. This include overriding some configuration in /etc,
+# starting services etc.
+#
+# You need to make this script executable to have it enabled.
+
+# Example for overriding the whole CUPS configuration:
+#  rm -rf /etc/cups
+#  ln -s /rw/config/cups /etc/cups
+#  systemctl --no-block restart cups
+EOF
+
+        touch /rw/config/qubes-firewall-user-script
+        cat > /rw/config/qubes-firewall-user-script <<EOF
+#!/bin/sh
+
+# This script is called in ProxyVM after firewall every update (configuration
+# change, starting some VM etc). This is good place to write own custom
+# firewall rules, in addition to autogenerated one. Remember that in most cases
+# you'll need to insert the rules at the beginning (iptables -I) to have it
+# efective.
+#
+# You need to make this script executable to have it enabled.
+EOF
+
+        touch /rw/config/suspend-module-blacklist
+        cat > /rw/config/suspend-module-blacklist <<EOF
+# You can list here modules you want to be unloaded before going to sleep. This
+# file is used only if the VM has any PCI device assigned. Modules will be
+# automatically loaded after resume.
+EOF
+    fi
+
+    if ! [ -d /rw/usrlocal ] ; then
+        if [ -d /usr/local.orig ] ; then
+            echo "Virgin boot of the VM: populating /rw/usrlocal from /usr/local.orig" >&2
+            cp -af /usr/local.orig /rw/usrlocal
+        else
+            echo "Virgin boot of the VM: creating /rw/usrlocal" >&2
+            mkdir -p /rw/usrlocal
+        fi
+    fi
+
+    if ! [ -d /rw/home ] ; then
+        echo "Virgin boot of the VM: populating /rw/home" >&2
+        mkdir -p /rw/home
+    fi
+
+    # Chown home if users' UIDs have changed - can be the case on template switch.
+    for pair in $(getent passwd | awk -F : '/\/home/ { print $1":"$3":"$4":"$6 } ') ; do
+        user=$(echo "$pair" | awk -F : ' { print $1 } ')
+        uid=$(echo "$pair" | awk -F : ' { print $2 } ')
+        gid=$(echo "$pair" | awk -F : ' { print $3 } ')
+        homedir=$(echo "$pair" | awk -F : ' { print $4 } ')
+        if ! test -d /rw"$homedir" ; then
+            if [ "$homedir" == "/home/user" -a -d /home.orig/"$user" ] ; then
+                echo "Virgin boot of the VM: populating /rw$homedir from /home.orig/$user" >&2
+                cp -af /home.orig/"$user" /rw"$homedir"
+            else
+                echo "Virgin boot of the VM: populating /rw$homedir from /etc/skel" >&2
+                cp -af /etc/skel /rw"$homedir"
+            fi
+            chown -R "$uid"  /rw"$homedir" &
+            chgrp -R "$gid"  /rw"$homedir" &
+            chmod 700 /rw"$homedir" &
+            wait
+        fi
+        homedir_uid=$(ls -dn /rw"$homedir" | awk '{print $3}')
+        homedir_gid=$(ls -dn /rw"$homedir" | awk '{print $4}')
+        if [ "$uid" -ne "$homedir_uid" ]; then
+            echo "Virgin boot of the VM: adjusting ownership on /rw$homedir to $uid" >&2
+            find /rw/"$homedir" -uid "$homedir_uid" -print0 | xargs -0 echo chown "$uid"
+        fi
+        if [ "$gid" -ne "$homedir_gid" ]; then
+            echo "Virgin boot of the VM: adjusting groupship on /rw$homedir to $gid" >&2
+            find /rw/"$homedir" -gid "$homedir_gid" -print0 | xargs -0 echo chgrp "$gid"
+        fi
+    done
+
+    echo "Finished checking /rw" >&2
+fi
+
+# Old Qubes versions had symlink /home -> /rw/home; now we use mount --bind
+if [ -L /home ]; then
+    rm /home
+    mkdir /home
+fi
+
+if [ ! -e /var/lib/qubes/first-boot-completed ]; then
+    touch /var/lib/qubes/first-boot-completed
+fi

+ 25 - 0
init/setup-rwdev.sh

@@ -0,0 +1,25 @@
+#!/bin/sh
+
+set -e
+
+if [ -e /dev/xvdb ] ; then
+    # The private /dev/xvdb device is present.
+
+    # check if private.img (xvdb) is empty - all zeros
+    private_size_512=`blockdev --getsz /dev/xvdb`
+    if dd if=/dev/zero bs=512 count=$private_size_512 2>/dev/null | diff /dev/xvdb - >/dev/null; then
+        # the device is empty, create filesystem
+        echo "Virgin boot of the VM: creating private.img filesystem" >&2
+        mkfs.ext4 -m 0 -q /dev/xvdb || exit 1
+    fi
+
+    tune2fs -m 0 /dev/xvdb
+    echo "Virgin boot of the VM: marking private.img as clean" >&2
+    fsck.ext4 -fp /dev/xvdb
+    echo "Virgin boot of the VM: enlarging private.img" >&2
+    if ! content=$(resize2fs /dev/xvdb 2>&1) ; then
+        echo "resize2fs /dev/xvdb failed:" >&2
+        echo "$content" >&2
+    fi
+
+fi

BIN
misc/dispvm-dotfiles.tbz


+ 15 - 15
misc/dispvm-prerun.sh

@@ -1,22 +1,24 @@
 #!/bin/sh
 
+# This script must be run as the `user` user.
+# It is customarily launched from prepare-dvm.sh.
+
+# At this point, the DispVM home directory customizations
+# undertaken by mount-dirs.sh have taken place.
+# We know this because dispvm-prerun.sh executes after
+# local-fs.target, and mount-dirs.sh runs before it.
+
+me=$( basename "$0" )
 apps="/usr/libexec/evinced"
 
-#If user have customized DispVM settings, use its home instead of default dotfiles
-if [ ! -e /home/user/.qubes-dispvm-customized ]; then
-	if [ -e /rw/home/user/.qubes-dispvm-customized ]; then
-		cp -af /rw/home/user /home/
-	else
-		cat /etc/dispvm-dotfiles.tbz | tar -xjf- --overwrite -C /home/user --owner user 2>&1 >/tmp/dispvm-dotfiles-errors.log
-	fi
-fi
+echo "$me started." >&2
 
 for app in $apps ; do
-    echo "Launching: $app..."
-    $app >>/tmp/dispvm_prerun_errors.log 2>&1 &
+    echo "Launching $app" >&2
+    $app &
 done
 
-echo "Sleeping..."
+echo "Waiting for I/O to quiesce" >&2
 PREV_IO=0
 while true; do
 	IO=`vmstat -D | awk '/read|write/ {IOs+=$1} END {print IOs}'`
@@ -27,11 +29,9 @@ while true; do
 	sleep 2
 done
 
-ps aufwwx > /tmp/dispvm-prerun-proclist.log
-
-echo "Closing windows..."
+echo "Closing windows" >&2
 /usr/lib/qubes/close-window `xwininfo -root -children|tail -n +7 |awk '{print $1}'`
 sleep 1
 fuser -vkm /rw
 
-echo done.
+echo "$me finished." >&2

+ 4 - 3
misc/qubes-trigger-sync-appmenus.sh

@@ -1,7 +1,8 @@
-#!/bin/sh
+#!/bin/bash
 
-UPDATEABLE=`qubesdb-read /qubes-vm-updateable`
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
 
-if [ "$UPDATEABLE" = "True" ]; then
+if is_updateable ; then
     /usr/lib/qubes/qrexec-client-vm dom0 qubes.SyncAppMenus /bin/sh /etc/qubes-rpc/qubes.GetAppmenus
 fi

+ 2 - 2
network/qubes-firewall

@@ -23,8 +23,8 @@ while true; do
 		TRIGGER=reload
 	else
 		# Wait for changes in qubesdb file
-		/usr/bin/qubesdb-watch $XENSTORE_IPTABLES
-		TRIGGER=$(/usr/bin/qubesdb-read $XENSTORE_IPTABLES)
+		qubesdb-watch $XENSTORE_IPTABLES
+		TRIGGER=$(qubesdb-read $XENSTORE_IPTABLES)
 	fi
 
 	if ! [ "$TRIGGER" = "reload" ]; then continue ; fi

+ 8 - 4
network/qubes-nmhook

@@ -1,9 +1,13 @@
 #!/bin/sh
+
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 /usr/lib/qubes/qubes-setup-dnat-to-ns
 
-# Tinyproxy does not reload DNS servers 
-if [ -x /bin/systemctl ]; then
-    /bin/systemctl --no-block try-restart qubes-updates-proxy.service
+# FIXME: Tinyproxy does not reload DNS servers.
+if under_systemd ; then
+    systemctl --no-block try-restart qubes-updates-proxy.service
 else
-    /usr/sbin/service qubes-updates-proxy try-restart
+    service qubes-updates-proxy try-restart
 fi

+ 7 - 11
network/setup-ip

@@ -1,13 +1,9 @@
 #!/bin/sh
 
-# setup-ip is potentially invoked before qubes-sysinit.sh is done, therefore
-# we perform our qubesdb reads here instead of relying on qvm-service
-# files under /var/run/qubes-service/
-disablegw=`qubesdb-read /qubes-service/disable-default-route 2> /dev/null`
-disabledns=`qubesdb-read /qubes-service/disable-dns-server 2> /dev/null`
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
 
-# Location of files which contains list of protected files
-PROTECTED_FILE_LIST='/etc/qubes/protected-files.d'
+have_qubesdb || exit 0
 
 ip=`/usr/bin/qubesdb-read /qubes-ip 2> /dev/null`
 if [ x$ip != x ]; then
@@ -18,7 +14,7 @@ if [ x$ip != x ]; then
     /sbin/ethtool -K $INTERFACE sg off
     /sbin/ethtool -K $INTERFACE tx off
     # If NetworkManager is enabled, let it configure the network
-    if [ -f /var/run/qubes-service/network-manager ]; then
+    if qsvc network-manager ; then
         nm_config=/etc/NetworkManager/system-connections/qubes-uplink-$INTERFACE
         cat > $nm_config <<__EOF__
 [802-3-ethernet]
@@ -39,10 +35,10 @@ method=ignore
 method=manual
 may-fail=false
 __EOF__
-        if [ "x$disabledns" != "x1" ]; then
+        if ! qsvc disable-dns-server ; then
             echo "dns=$primary_dns;$secondary_dns" >> $nm_config
         fi
-        if [ "x$disablegw" != "x1" ]; then
+        if ! qsvc disable-default-route ; then
             echo "addresses1=$ip;32;$gateway" >> $nm_config
         else
             echo "addresses1=$ip;32" >> $nm_config
@@ -58,7 +54,7 @@ __EOF__
         if [ "x$disablegw" != "x1" ]; then
             /sbin/route add default gw $gateway
         fi
-        if ! grep -rq "^/etc/resolv[.]conf$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
+        if ! is_protected_file /etc/resolv.conf ; then
             echo > /etc/resolv.conf
             if [ "x$disabledns" != "x1" ]; then
                 echo "nameserver $primary_dns" > /etc/resolv.conf

+ 4 - 2
network/show-hide-nm-applet.sh

@@ -2,7 +2,9 @@
 
 type nm-applet > /dev/null 2>&1 || exit 0
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 # Hide nm-applet when network-manager is disabled
-nm_enabled=false
-[ -f /var/run/qubes-service/network-manager ] && nm_enabled=true
+qsvc network-manager && nm_enabled=true || nm_enabled=false
 gsettings set org.gnome.nm-applet show-applet $nm_enabled

+ 5 - 2
network/update-proxy-configs

@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # The Qubes OS Project, http://www.qubes-os.org
 #
@@ -21,6 +21,9 @@
 #
 #
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 BEGIN_MARKER="### QUBES BEGIN ###"
 END_MARKER="### QUBES END ###"
 
@@ -71,7 +74,7 @@ EOF
 ### helper functions end
 
 # Determine whether the proxy should be used
-if [ -f /var/run/qubes-service/yum-proxy-setup -o -f /var/run/qubes-service/updates-proxy-setup ]; then
+if qsvc yum-proxy-setup || qsvc updates-proxy-setup ; then
     PROXY_ADDR="http://10.137.255.254:8082/"
     PROXY_CONF_ENTRY="proxy=$PROXY_ADDR"
 else

+ 7 - 4
qubes-rpc/prepare-suspend

@@ -1,4 +1,7 @@
-#!/bin/sh
+#!/bin/bash
+
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
 
 action=$1
 [ -z "$action" ] && action=suspend
@@ -12,7 +15,7 @@ if [ -r /rw/config/suspend-module-blacklist ]; then
 fi
 
 if [ x"$action" = x"suspend" ]; then
-    if [ -f /var/run/qubes-service/network-manager ]; then
+    if qsvc network-manager ; then
         dbus-send --system --print-reply          \
             --dest=org.freedesktop.NetworkManager \
             /org/freedesktop/NetworkManager       \
@@ -38,11 +41,11 @@ else
     for mod in `cat /var/run/qubes/suspend-modules-loaded`; do
         modprobe $mod
     done
-    if [ -f /var/run/qubes-service/network-manager ]; then
+    if qsvc network-manager ; then
         dbus-send --system --print-reply          \
             --dest=org.freedesktop.NetworkManager \
             /org/freedesktop/NetworkManager       \
             org.freedesktop.NetworkManager.Sleep boolean:false ||  \
-            { [ -x /bin/systemctl ] && systemctl start NetworkManager.service; } || service qubes-core-netvm start
+            { under_systemd && systemctl start NetworkManager.service; } || service qubes-core-netvm start
     fi
 fi

+ 25 - 37
rpm_spec/core-vm.spec

@@ -20,6 +20,8 @@
 #
 #
 
+%define qubes_services qubes-core qubes-core-netvm qubes-core-early qubes-firewall qubes-netwatcher qubes-iptables qubes-updates-proxy qubes-qrexec-agent qubes-dvm
+
 %{!?version: %define version %(cat version)}
 %{!?backend_vmm: %define backend_vmm %(echo $BACKEND_VMM)}
 
@@ -49,6 +51,10 @@ Requires:   net-tools
 Requires:   nautilus-python
 Requires:   qubes-utils >= 3.1.3
 Requires:   initscripts
+Requires:   gawk
+# for dispvm-prerun.sh
+Requires:   procps-ng
+Requires:   util-linux
 # for qubes-desktop-run
 Requires:   pygobject3-base
 Requires:   dbus-python
@@ -191,10 +197,10 @@ fi
 
 # Location of files which contains list of protected files
 mkdir -p /etc/qubes/protected-files.d
-PROTECTED_FILE_LIST='/etc/qubes/protected-files.d'
+. /usr/lib/qubes/init/functions
 
 # qubes-core-vm has been broken for some time - it overrides /etc/hosts; restore original content
-if ! grep -rq "^/etc/hosts$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
+if ! is_protected_file /etc/hosts ; then
     if ! grep -q localhost /etc/hosts; then
       cat <<EOF > /etc/hosts
 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 `hostname`
@@ -205,7 +211,7 @@ fi
 
 # ensure that hostname resolves to 127.0.0.1 resp. ::1 and that /etc/hosts is
 # in the form expected by qubes-sysinit.sh
-if ! grep -rq "^/etc/hostname$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
+if ! is_protected_file /etc/hostname ; then
     for ip in '127\.0\.0\.1' '::1'; do
         if grep -q "^${ip}\(\s\|$\)" /etc/hosts; then
             sed -i "/^${ip}\s/,+0s/\(\s`hostname`\)\+\(\s\|$\)/\2/g" /etc/hosts
@@ -324,7 +330,6 @@ rm -f %{name}-%{version}
 /etc/NetworkManager/dispatcher.d/30-qubes-external-ip
 /etc/NetworkManager/dispatcher.d/qubes-nmhook
 %config(noreplace) /etc/X11/xorg-preload-apps.conf
-/etc/dispvm-dotfiles.tbz
 /etc/dhclient.d/qubes-setup-dnat-to-ns.sh
 /etc/fstab
 /etc/pki/rpm-gpg/RPM-GPG-KEY-qubes*
@@ -425,6 +430,9 @@ rm -f %{name}-%{version}
 /usr/lib/yum-plugins/yum-qubes-hooks.py*
 /usr/lib/dracut/dracut.conf.d/30-qubes.conf
 /usr/lib/NetworkManager/conf.d/30-qubes.conf
+%dir /usr/lib/qubes/init
+/usr/lib/qubes/init/*.sh
+/usr/lib/qubes/init/functions
 %dir /usr/lib/qubes-bind-dirs.d
 /usr/lib/qubes-bind-dirs.d/30_cron.conf
 /usr/lib64/python2.7/site-packages/qubes/xdg.py*
@@ -464,8 +472,10 @@ Conflicts:      qubes-core-vm-systemd
 The Qubes core startup configuration for SysV init (or upstart).
 
 %files sysvinit
+/etc/init.d/qubes-sysinit
+/etc/init.d/qubes-core-early
 /etc/init.d/qubes-core
-/etc/init.d/qubes-core-appvm
+/etc/init.d/qubes-dvm
 /etc/init.d/qubes-core-netvm
 /etc/init.d/qubes-firewall
 /etc/init.d/qubes-netwatcher
@@ -495,22 +505,13 @@ done
 chkconfig rsyslog on
 chkconfig haldaemon on
 chkconfig messagebus on
-chkconfig --add qubes-core || echo "WARNING: Cannot add service qubes-core!"
-chkconfig qubes-core on || echo "WARNING: Cannot enable service qubes-core!"
-chkconfig --add qubes-core-netvm || echo "WARNING: Cannot add service qubes-core-netvm!"
-chkconfig qubes-core-netvm on || echo "WARNING: Cannot enable service qubes-core-netvm!"
-chkconfig --add qubes-core-appvm || echo "WARNING: Cannot add service qubes-core-appvm!"
-chkconfig qubes-core-appvm on || echo "WARNING: Cannot enable service qubes-core-appvm!"
-chkconfig --add qubes-firewall || echo "WARNING: Cannot add service qubes-firewall!"
-chkconfig qubes-firewall on || echo "WARNING: Cannot enable service qubes-firewall!"
-chkconfig --add qubes-netwatcher || echo "WARNING: Cannot add service qubes-netwatcher!"
-chkconfig qubes-netwatcher on || echo "WARNING: Cannot enable service qubes-netwatcher!"
-chkconfig --add qubes-iptables || echo "WARNING: Cannot add service qubes-iptables!"
-chkconfig qubes-iptables on || echo "WARNING: Cannot enable service qubes-iptables!"
-chkconfig --add qubes-updates-proxy || echo "WARNING: Cannot add service qubes-updates-proxy!"
-chkconfig qubes-updates-proxy on || echo "WARNING: Cannot enable service qubes-updates-proxy!"
-chkconfig --add qubes-qrexec-agent || echo "WARNING: Cannot add service qubes-qrexec-agent!"
-chkconfig qubes-qrexec-agent on || echo "WARNING: Cannot enable service qubes-qrexec-agent!"
+for svc in %qubes_services ; do
+    if [ "$1" = 1 ] ; then
+        chkconfig --add $svc || echo "WARNING: Cannot add service $svc!"
+    else
+        chkconfig $svc resetpriorities || echo "WARNING: Cannot reset priorities of service $svc!"
+    fi
+done
 
 # TODO: make this not display the silly message about security context...
 sed -i s/^id:.:initdefault:/id:3:initdefault:/ /etc/inittab
@@ -518,13 +519,9 @@ sed -i s/^id:.:initdefault:/id:3:initdefault:/ /etc/inittab
 %preun sysvinit
 if [ "$1" = 0 ] ; then
     # no more packages left
-    chkconfig qubes-core off
-    chkconfig qubes-core-netvm off
-    chkconfig qubes-core-appvm off
-    chkconfig qubes-firewall off
-    chkconfig qubes-netwatcher off
-    chkconfig qubes-updates-proxy off
-    chkconfig qubes-qrexec-agent off
+    for svc in %qubes_services ; do
+        chkconfig --del $svc
+    done
 fi
 
 %package systemd
@@ -559,16 +556,7 @@ The Qubes core startup configuration for SystemD init.
 /lib/systemd/system-preset/75-qubes-vm.preset
 /lib/modules-load.d/qubes-core.conf
 /lib/modules-load.d/qubes-misc.conf
-%dir /usr/lib/qubes/init
-/usr/lib/qubes/init/prepare-dvm.sh
-/usr/lib/qubes/init/network-proxy-setup.sh
 /usr/lib/qubes/init/qubes-iptables
-/usr/lib/qubes/init/misc-post.sh
-/usr/lib/qubes/init/misc-post-stop.sh
-/usr/lib/qubes/init/mount-dirs.sh
-/usr/lib/qubes/init/qubes-random-seed.sh
-/usr/lib/qubes/init/qubes-sysinit.sh
-/usr/lib/qubes/init/bind-dirs.sh
 /lib/systemd/system/chronyd.service.d/30_qubes.conf
 /lib/systemd/system/crond.service.d/30_qubes.conf
 /lib/systemd/system/cups.service.d/30_qubes.conf

+ 28 - 133
vm-init.d/qubes-core

@@ -1,154 +1,49 @@
 #!/bin/bash
 #
 # chkconfig: 345 90 90
-# description: Executes Qubes core scripts at VM boot
+# description: Executes supplementary Qubes core scripts at VM boot
 #
 # Source function library.
 . /etc/rc.d/init.d/functions
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 start()
 {
-	echo -n $"Executing Qubes Core scripts:"
-
-	# Set permissions to /proc/xen/xenbus, so normal user can access xenstore
-	chmod 666 /proc/xen/xenbus
-	# Set permissions to files needed by gui-agent
-	chmod 666 /proc/u2mfn
-
-	mkdir -p /var/run/xen-hotplug
-	mkdir -p /var/run/qubes
-	chgrp qubes /var/run/qubes
-	chmod 0775 /var/run/qubes
-
-	# Load random seed from dom0
-	qubesdb-read /qubes-random-seed | base64 -d > /dev/urandom
-	qubesdb-rm /qubes-random-seed
-
-	# Location of files which contains list of protected files
-	PROTECTED_FILE_LIST='/etc/qubes/protected-files.d'
+	have_qubesdb || return
 
-	# Set the hostname
-	if ! grep -rq "^/etc/hostname$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
-		name=$(/usr/bin/qubesdb-read /name)
-		if ! [ -f /etc/this-is-dvm ] ; then
-			# we don't want to set hostname for DispVM
-			# because it makes some of the pre-created dotfiles invalid (e.g. .kde/cache-<hostname>)
-			# (let's be frank: nobody's gonna use xterm on DispVM)
-			hostname $name
-			sed -i "s/^\(127\.0\.0\.1[\t ].*\) \($name \)\?\(.*\)/\1\2 $name/" /etc/hosts
+	# Start AppVM specific services
+	for svc in cups ntpd ; do
+		if qsvc $svc && test -e /etc/init.d/$svc ; then
+			/sbin/service $svc start
 		fi
-	fi
-
-	# Set the timezone
-	if ! grep -rq "^/etc/timezone$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
-		timezone=`/usr/bin/qubesdb-read /qubes-timezone 2> /dev/null`
-		if [ -n "$timezone" ]; then
-			ln -f /usr/share/zoneinfo/$timezone /etc/localtime
-			echo "# Clock configuration autogenerated based on Qubes dom0 settings" > /etc/sysconfig/clock
-			echo "ZONE=\"$timezone\"" >> /etc/sysconfig/clock
-		fi
-	fi
-
-	/usr/lib/qubes/update-proxy-configs
-
-	# Set IP address again (besides action in udev rules); this is needed by
-	# DispVM (to override DispVM-template IP) and in case when qubes-ip was
-	# called by udev before loading evtchn kernel module - in which case
-	# qubesdb-read fails
-	INTERFACE=eth0 /usr/lib/qubes/setup-ip
-
-	if [ -e /dev/xvdb ] ; then
-		# check if private.img (xvdb) is empty - all zeros
-		private_size_512=`blockdev --getsz /dev/xvdb`
-		if dd if=/dev/zero bs=512 count=$private_size_512 | diff /dev/xvdb - >/dev/null; then
-			# the device is empty, create filesystem
-			echo "--> Virgin boot of the VM: creating filesystem on private.img"
-			mkfs.ext4 -m 0 -q /dev/xvdb || exit 1
-		fi
-
-		mount /rw
-		resize2fs /dev/xvdb 2> /dev/null || echo "'resize2fs /dev/xvdb' failed"
-
-        if ! [ -d /rw/home ] ; then
-        	echo
-        	echo "--> Virgin boot of the VM: Linking /home to /rw/home"
-
-        	mkdir -p /rw/config
-		cat > /rw/config/rc.local <<EOF
-#!/bin/sh
-
-# This script will be executed at every VM startup, you can place your own
-# custom commands here. This include overriding some configuration in /etc,
-# starting services etc.
-#
-# You need to make this script executable to have it enabled.
-
-# Example for overriding the whole CUPS configuration:
-#  rm -rf /etc/cups
-#  ln -s /rw/config/cups /etc/cups
-#  systemctl --no-block restart cups
-EOF
-
-			touch /rw/config/qubes-firewall-user-script
-			cat > /rw/config/qubes-firewall-user-script <<EOF
-#!/bin/sh
-
-# This script is called in ProxyVM after firewall every update (configuration
-# change, starting some VM etc). This is good place to write own custom
-# firewall rules, in addition to autogenerated one. Remember that in most cases
-# you'll need to insert the rules at the beginning (iptables -I) to have it
-# efective.
-#
-# You need to make this script executable to have it enabled.
-EOF
-
-			touch /rw/config/suspend-module-blacklist
-			cat > /rw/config/suspend-module-blacklist <<EOF
-# You can list here modules you want to be unloaded before going to sleep. This
-# file is used only if the VM has any PCI device assigned. Modules will be
-# automatically loaded after resume.
-EOF
-
-            mkdir -p /rw/home
-            cp -a /home.orig/user /rw/home
-
-            mkdir -p /rw/usrlocal
-            cp -a /usr/local.orig/* /rw/usrlocal
-
-            touch /var/lib/qubes/first-boot-completed
-        fi
-	fi
-    if [ -L /home ]; then
-        rm /home
-        mkdir /home
-    fi
-    mount /home
-
-    if [ -n "`ls -A /usr/local/lib 2>/dev/null`" -o \
-         -n "`ls -A /usr/local/lib64 2>/dev/null`" ]; then
-        ldconfig
-    fi
-
-	[ -x /rw/config/rc.local ] && /rw/config/rc.local
+	done
 
+	echo -n $"Finagling printer icon:"
+	/usr/lib/qubes/init/control-printer-icon.sh
 	success
-	echo ""
-
-	start_ntpd=$(/usr/bin/qubesdb-read /qubes-service/ntpd 2> /dev/null)
-	if [ "$start_ntpd" == "1" ]; then
-		/sbin/service ntpd start
+	echo
+
+	if qsvc meminfo-writer ; then
+		MEM_CHANGE_THRESHOLD_KB=30000
+		MEMINFO_DELAY_USEC=100000
+		echo -n $"Starting Qubes memory information service:"
+		/usr/lib/qubes/meminfo-writer $MEM_CHANGE_THRESHOLD_KB $MEMINFO_DELAY_USEC /var/run/meminfo-writer.pid
+		success
+		echo ""
 	fi
-	return 0
+
+	echo -n $"Executing Qubes misc post scripts:"
+	/usr/lib/qubes/init/misc-post.sh && success || failure
+	echo
 }
 
 stop()
 {
-	su -c 'mkdir -p /home_volatile/user/.local/share/applications' user
-	su -c 'cp -a /usr/share/applications/defaults.list /home_volatile/user/.local/share/applications/' user
-	if [ -r '/home/user/.local/share/applications/defaults.list' ]; then
-		su -c 'cat /home/user/.local/share/applications/defaults.list >> /home_volatile/user/.local/share/applications/defaults.list' user
-	fi
-	return 0
+	have_qubesdb || return
+
+	/usr/lib/qubes/init/misc-post-stop.sh
 }
 
 case "$1" in

+ 0 - 104
vm-init.d/qubes-core-appvm

@@ -1,104 +0,0 @@
-#!/bin/bash
-#
-# chkconfig: 345 85 85
-# description: Executes Qubes core scripts at AppVM boot
-#
-# Source function library.
-. /etc/rc.d/init.d/functions
-
-possibly_run_save_script()
-{
-	ENCODED_SCRIPT=$(qubesdb-read /qubes-save-script)
-	if [ -z "$ENCODED_SCRIPT" ] ; then return ; fi
-	echo $ENCODED_SCRIPT|perl -e 'use MIME::Base64 qw(decode_base64); local($/) = undef;print decode_base64(<STDIN>)' >/tmp/qubes-save-script
-	chmod 755 /tmp/qubes-save-script
-	Xorg -config /etc/X11/xorg-preload-apps.conf :0 &
-	while ! [ -S /tmp/.X11-unix/X0 ]; do sleep 0.5; done
-	DISPLAY=:0 su - user -c /tmp/qubes-save-script
-	killall Xorg
-}
-
-start()
-{
-	type=$(/usr/bin/qubesdb-read /qubes-vm-type)
-	if [ "$type" != "AppVM" -a "$type" != "DisposableVM" -a "$type" != "TemplateVM" ]; then
-		# This script runs only on AppVMs
-		return 0
-	fi
-
-	# Start AppVM specific services
-	start_cups=$(/usr/bin/qubesdb-read /qubes-service/cups 2> /dev/null)
-	if [ "$start_cups" != "0" ]; then
-		/sbin/service cups start
-		# Allow also notification icon
-		sed -i -e '/^NotShowIn=.*QUBES/s/;QUBES//' /etc/xdg/autostart/print-applet.desktop
-	else
-		# Disable notification icon
-		sed -i -e '/QUBES/!s/^NotShowIn=\(.*\)/NotShowIn=QUBES;\1/' /etc/xdg/autostart/print-applet.desktop
-
-	fi
-
-	echo -n $"Executing Qubes Core scripts for AppVM:"
-
-	if qubesdb-read /qubes-save-request 2>/dev/null ; then
-        if [ -L /home ]; then
-            rm /home
-            mkdir /home
-        fi
-        mount --bind /home_volatile /home
-		touch /etc/this-is-dvm
-		mount /rw
-		possibly_run_save_script
-		umount /rw
-		dmesg -c >/dev/null
-		free | grep Mem: |
-			(read a b c d ; qubesdb-write /qubes-used-mem $c)
-		# give dom0 time to read some entries, when done it will shutdown qubesdb,
-		# so wait for it
-		qubesdb-watch /stop-qubesdb
-		# just to make sure
-		systemctl stop qubes-db.service
-
-		# we're still running in DispVM template
-		echo "Waiting for save/restore..."
-		# the service will start only after successful restore
-		systemctl start qubes-db.service
-		echo Back to life.
-
-        # Reload random seed
-        qubesdb-read /qubes-random-seed | base64 -d > /dev/urandom
-        qubesdb-rm /qubes-random-seed
-
-	fi
-
-	start_meminfo_writer=$(/usr/bin/qubesdb-read /qubes-service/meminfo-writer 2>/dev/null)
-	if [ "$start_meminfo_writer" != "0" ]; then
-		MEM_CHANGE_THRESHOLD_KB=30000
-		MEMINFO_DELAY_USEC=100000
-		/usr/lib/qubes/meminfo-writer $MEM_CHANGE_THRESHOLD_KB $MEMINFO_DELAY_USEC /var/run/meminfo-writer.pid
-	fi
-
-	success
-	echo ""
-	return 0
-}
-
-stop()
-{
-	return 0
-}
-
-case "$1" in
-  start)
-	start
-	;;
-  stop)
-	stop
-	;;
-  *)
-	echo $"Usage: $0 {start|stop}"
-	exit 3
-	;;
-esac
-
-exit $RETVAL

+ 44 - 0
vm-init.d/qubes-core-early

@@ -0,0 +1,44 @@
+#!/bin/bash
+#
+# chkconfig: 345 84 84
+# description: Executes early necessary Qubes core scripts at VM boot
+#
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
+start()
+{
+	have_qubesdb || return
+
+	echo -n $"Setting up Qubes persistent file systems:"
+	/usr/lib/qubes/init/mount-dirs.sh && success || failure
+	echo
+
+	echo -n $"Executing Qubes random seed scripts:"
+	/usr/lib/qubes/init/qubes-random-seed.sh && success || failure
+	echo
+
+}
+
+stop()
+{
+	return 0
+}
+
+case "$1" in
+  start)
+	start
+	;;
+  stop)
+	stop
+	;;
+  *)
+	echo $"Usage: $0 {start|stop}"
+	exit 3
+	;;
+esac
+
+exit $RETVAL

+ 7 - 24
vm-init.d/qubes-core-netvm

@@ -6,38 +6,21 @@
 # Source function library.
 . /etc/rc.d/init.d/functions
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 start()
 {
-	if ! [ -x /usr/bin/qubesdb-read ] ; then
-		echo "ERROR: /usr/bin/qubesdb-read not found!"
-		exit 1
-	fi
+	have_qubesdb || return
 
-	type=$(/usr/bin/qubesdb-read /qubes-vm-type)
-	if [ "$type" == "NetVM" ]; then
+	if is_netvm; then
 		/usr/lib/qubes/network-manager-prepare-conf-dir
 		/sbin/service NetworkManager start
 	fi
 
 	echo -n $"Executing Qubes Core scripts NetVM:"
-
-	# Setup gateway for all the VMs this netVM is serviceing...
-	network=$(/usr/bin/qubesdb-read /qubes-netvm-network 2>/dev/null)
-	if [ "x$network" != "x" ]; then
-		gateway=$(/usr/bin/qubesdb-read /qubes-netvm-gateway)
-		netmask=$(/usr/bin/qubesdb-read /qubes-netvm-netmask)
-		primary_dns=$(/usr/bin/qubesdb-read /qubes-netvm-primary-dns || echo $gateway)
-		secondary_dns=$(/usr/bin/qubesdb-read /qubes-netvm-secondary-dns)
-		modprobe netbk 2> /dev/null || modprobe xen-netback
-		echo "NS1=$primary_dns" > /var/run/qubes/qubes-ns
-		echo "NS2=$secondary_dns" >> /var/run/qubes/qubes-ns
-		/usr/lib/qubes/qubes-setup-dnat-to-ns
-		echo "1" > /proc/sys/net/ipv4/ip_forward
-	fi
-
-	success
-	echo ""
-	return 0
+	/usr/lib/qubes/init/network-proxy-setup && success || failure
+	echo
 }
 
 stop()

+ 43 - 0
vm-init.d/qubes-dvm

@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# chkconfig: 345 91 91
+# description: Executes Qubes core scripts at AppVM boot
+#
+# This must run after GUI agent has started.  Hence 91.
+#
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
+start()
+{
+	have_qubesdb || return
+
+	if qsvc qubes-dvm; then
+		echo -n $"Preparing Qubes DVM:"
+		/usr/lib/qubes/init/prepare-dvm.sh && success || failure
+		echo
+	fi
+}
+
+stop()
+{
+	return 0
+}
+
+case "$1" in
+  start)
+	start
+	;;
+  stop)
+	stop
+	;;
+  *)
+	echo $"Usage: $0 {start|stop}"
+	exit 3
+	;;
+esac
+
+exit $RETVAL

+ 8 - 6
vm-init.d/qubes-firewall

@@ -1,32 +1,34 @@
 #!/bin/bash
 #
-# chkconfig: 345 91 91
+# chkconfig: 345 92 92
 # description: Starts Qubes Firewall monitor
 #
 # Source function library.
 . /etc/rc.d/init.d/functions
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 PIDFILE=/var/run/qubes/qubes-firewall.pid
 
 start()
 {
-    type=$(/usr/bin/qubesdb-read /qubes-vm-type)
-    start_firewall=$(/usr/bin/qubesdb-read /qubes-service/qubes-firewall 2> /dev/null)
-    if [ -z "$start_firewall" ] && [ "$type" == "ProxyVM" ] || [ "$start_firewall" == "1" ]; then
+    have_qubesdb || return
+
+    if qsvc qubes-firewall ; then
         echo -n $"Starting Qubes Firewall monitor:"
         /sbin/ethtool -K eth0 sg off
         /usr/sbin/qubes-firewall &
         success
         echo ""
     fi
-	return 0
 }
 
 stop()
 {
     if [ -r $PIDFILE ]; then
         echo -n "Stopping Qubes Firewall monitor:"
-        kill -9 $(cat $PIDFILE) 2>/dev/null  && success || failure
+        kill -9 $(cat $PIDFILE) 2>/dev/null && success || failure
         echo ""
     fi
 	return 0

+ 7 - 5
vm-init.d/qubes-netwatcher

@@ -1,25 +1,27 @@
 #!/bin/bash
 #
-# chkconfig: 345 92 92
+# chkconfig: 345 93 93
 # description: Starts Qubes Network monitor
 #
 # Source function library.
 . /etc/rc.d/init.d/functions
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 PIDFILE=/var/run/qubes/qubes-netwatcher.pid
 
 start()
 {
-    type=$(/usr/bin/qubesdb-read /qubes-vm-type)
-    start_netwatcher=$(/usr/bin/qubesdb-read /qubes-service/qubes-netwatcher 2>/dev/null)
-    if [ -z "$start_netwatcher" ] && [ "$type" == "ProxyVM" ] || [ "$start_netwatcher" == "1" ]; then
+    have_qubesdb || return
+
+    if qsvc qubes-netwatcher ; then
         echo -n $"Starting Qubes Network monitor:"
         /sbin/ethtool -K eth0 sg off
         /usr/sbin/qubes-netwatcher &
         success
         echo ""
     fi
-	return 0
 }
 
 stop()

+ 6 - 4
vm-init.d/qubes-qrexec-agent

@@ -6,21 +6,23 @@
 # Source function library.
 . /etc/rc.d/init.d/functions
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 start()
 {
+	have_qrexec_agent || return
 	echo -n $"Starting Qubes RPC agent:"
-
 	/usr/lib/qubes/qrexec-agent 2>/var/log/qubes/qrexec-agent.log &
-
 	success
 	echo ""
-
 	return 0
 }
 
 stop()
 {
-    killproc qrexec-agent
+	have_qrexec_agent || return
+	killproc qrexec-agent
 }
 
 case "$1" in

+ 34 - 0
vm-init.d/qubes-sysinit

@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# chkconfig: 345 80 80
+# description: Executes Qubes system initialization scripts at VM boot
+#
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+start()
+{
+	echo -n $"Executing Qubes system initialization scripts:"
+	/usr/lib/qubes/init/qubes-sysinit.sh && success || failure ; echo
+}
+
+stop()
+{
+	return 0
+}
+
+case "$1" in
+  start)
+	start
+	;;
+  stop)
+	stop
+	;;
+  *)
+	echo $"Usage: $0 {start|stop}"
+	exit 3
+	;;
+esac
+
+exit $RETVAL

+ 7 - 4
vm-init.d/qubes-updates-proxy

@@ -2,7 +2,7 @@
 #
 # tinyproxy     Startup script for the tinyproxy server as Qubes updates proxy
 #
-# chkconfig:   - 85 15
+# chkconfig: 345 85 15
 # description: small, efficient HTTP/SSL proxy daemon
 #
 # processname: tinyproxy
@@ -16,6 +16,9 @@
 # Source function library.
 . /etc/rc.d/init.d/functions
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 # Source networking configuration.
 .  /etc/sysconfig/network
 
@@ -32,9 +35,9 @@ pidfile="/var/run/tinyproxy-updates/tinyproxy.pid"
 lockfile=/var/lock/subsys/tinyproxy-updates
 
 start() {
-    type=`/usr/bin/qubesdb-read /qubes-vm-type`
-    start_updates_proxy=`/usr/bin/qubesdb-read /qubes-service/qubes-updates-proxy 2>/dev/null`
-    if [ -z "$start_updates_proxy" ] && [ "$type" != "NetVM" ] || [ "$start_updates_proxy" != "1" ]; then
+    have_qubesdb || return
+
+    if qsvc qubes-updates-proxy ; then
         # Yum proxy disabled
         exit 0
     fi

+ 6 - 11
vm-systemd/bind-dirs.sh

@@ -23,21 +23,14 @@
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-set -x
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
 
 prerequisite() {
-   qubes_vm_persistence="$(qubesdb-read /qubes-vm-persistence)"
-   if [ ! "$qubes_vm_persistence" = "rw-only" ]; then
+   if ! is_rwonly_persistent ; then
       true "No TemplateBasedVM detected. Exiting."
       exit 0
    fi
-   if [ -f "/var/run/qubes-service/qubes-dvm" ]; then
-      # https://github.com/QubesOS/qubes-issues/issues/1328#issuecomment-169483029
-      # Do none of the following in a DispVM.
-      # During DispVM savefile generation, 'qubesdb-read /qubes-vm-persistence'
-      # outputs 'rw'.
-      exit 0
-   fi
 }
 
 init() {
@@ -96,7 +89,8 @@ bind_dirs() {
       # Initially copy over data directories to /rw if rw directory does not exist.
       if [ -d "$fso_ro" ] || [ -f "$fso_ro" ]; then
          if ! [ -d "$fso_rw" -o -f "$fso_rw" ]; then
-            cp --verbose --archive --recursive --parents "$fso_ro" "$rw_dest_dir"
+            echo "Initializing $rw_dest_dir with files from $fso_ro" >&2
+            cp --archive --recursive --parents "$fso_ro" "$rw_dest_dir"
          fi
       else
          true "$fso_ro is neither a directory nor a file or does not exist, skipping."
@@ -104,6 +98,7 @@ bind_dirs() {
       fi
 
       # Bind the fso.
+      echo "Bind mounting $fso_rw onto $fso_ro" >&2
       mount --bind "$fso_rw" "$fso_ro"
    done
 }

+ 3 - 0
vm-systemd/cups.service.d/30_qubes.conf

@@ -1,3 +1,6 @@
 [Unit]
 ConditionPathExists=/var/run/qubes-service/cups
 After=qubes-sysinit.service
+
+[Service]
+ExecStartPost=/usr/lib/qubes/init/control-printer-icon.sh

+ 5 - 10
vm-systemd/misc-post.sh

@@ -1,5 +1,8 @@
 #!/bin/sh
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 /usr/lib/qubes/update-proxy-configs
 
 if [ -n "`ls -A /usr/local/lib 2>/dev/null`" -o \
@@ -13,14 +16,6 @@ fi
 # qubesdb-read fails
 INTERFACE=eth0 /usr/lib/qubes/setup-ip
 
-[ -x /rw/config/rc.local ] && /rw/config/rc.local
-
-# Start services which haven't own proper systemd unit:
-
-if [ ! -f /usr/lib/systemd/system/cups.service ]; then
-    if [ -f /var/run/qubes-service/cups ]; then
-        /usr/sbin/service cups start
-    fi
+if [ -x /rw/config/rc.local ] ; then
+    /rw/config/rc.local
 fi
-
-exit 0

+ 13 - 84
vm-systemd/mount-dirs.sh

@@ -1,93 +1,22 @@
 #!/bin/sh
 
-# check if private.img (xvdb) is empty - all zeros
-private_size_512=`blockdev --getsz /dev/xvdb`
-if dd if=/dev/zero bs=512 count=$private_size_512 2>/dev/null | diff /dev/xvdb - >/dev/null; then
-    # the device is empty, create filesystem
-    echo "--> Virgin boot of the VM: creating filesystem on private.img"
-    mkfs.ext4 -m 0 -q /dev/xvdb || exit 1
-fi
-
-tune2fs -m 0 /dev/xvdb
-mount /rw
-resize2fs /dev/xvdb 2> /dev/null || echo "'resize2fs /dev/xvdb' failed"
-
-if ! [ -d /rw/home ] ; then
-    echo
-    echo "--> Virgin boot of the VM: Populating /rw/home"
-
-    mkdir -p /rw/config
-    touch /rw/config/rc.local
-    cat > /rw/config/rc.local <<EOF
-#!/bin/sh
-
-# This script will be executed at every VM startup, you can place your own
-# custom commands here. This include overriding some configuration in /etc,
-# starting services etc.
-#
-# You need to make this script executable to have it enabled.
-
-# Example for overriding the whole CUPS configuration:
-#  rm -rf /etc/cups
-#  ln -s /rw/config/cups /etc/cups
-#  systemctl --no-block restart cups
-EOF
-
-    touch /rw/config/qubes-firewall-user-script
-    cat > /rw/config/qubes-firewall-user-script <<EOF
-#!/bin/sh
-
-# This script is called in ProxyVM after firewall every update (configuration
-# change, starting some VM etc). This is good place to write own custom
-# firewall rules, in addition to autogenerated one. Remember that in most cases
-# you'll need to insert the rules at the beginning (iptables -I) to have it
-# efective.
-#
-# You need to make this script executable to have it enabled.
-EOF
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
 
-    touch /rw/config/suspend-module-blacklist
-    cat > /rw/config/suspend-module-blacklist <<EOF
-# You can list here modules you want to be unloaded before going to sleep. This
-# file is used only if the VM has any PCI device assigned. Modules will be
-# automatically loaded after resume.
-EOF
+set -e
 
-    mkdir -p /rw/home
-    cp -a /home.orig/user /rw/home
+/usr/lib/qubes/init/setup-rwdev.sh
+if [ -e /dev/xvdb ] ; then mount /rw ; fi
+/usr/lib/qubes/init/setup-rw.sh
 
-    mkdir -p /rw/usrlocal
-    cp -a /usr/local.orig/* /rw/usrlocal
-
-    touch /var/lib/qubes/first-boot-completed
-fi
-
-# Chown home if user UID have changed - can be the case on template switch
-HOME_USER_UID=`ls -dn /rw/home/user | awk '{print $3}'`
-if [ "`id -u user`" -ne "$HOME_USER_UID" ]; then
-    find /rw/home/user -uid "$HOME_USER_UID" -print0 | xargs -0 chown user:user
-fi
-
-# Old Qubes versions had symlink /home -> /rw/home; now we use mount --bind
-if [ -L /home ]; then
-    rm /home
-    mkdir /home
-fi
-
-if [ -e /var/run/qubes-service/qubes-dvm ]; then
+if qsvc qubes-dvm; then
+    /usr/lib/qubes/init/setup-dvm-home.sh
+    echo "Mounting /home_volatile onto /home" >&2
     mount --bind /home_volatile /home
-    touch /etc/this-is-dvm
-
-    #If user have customized DispVM settings, use its home instead of default dotfiles
-    if [ ! -e /home/user/.qubes-dispvm-customized ]; then
-        if [ -e /rw/home/user/.qubes-dispvm-customized ]; then
-            cp -af /rw/home/user /home/
-        else
-            cat /etc/dispvm-dotfiles.tbz | tar -xjf- --overwrite -C /home/user --owner user 2>&1 >/tmp/dispvm-dotfiles-errors.log
-        fi
-    fi
 else
+    echo "Mounting /home" >&2
     mount /home
+    # https://github.com/QubesOS/qubes-issues/issues/1328#issuecomment-169483029
+    # Do none of the following in a DispVM.
+    /usr/lib/qubes/init/bind-dirs.sh
 fi
-
-/usr/lib/qubes/init/bind-dirs.sh

+ 22 - 16
vm-systemd/prepare-dvm.sh

@@ -1,24 +1,30 @@
 #!/bin/bash
 
-possibly_run_save_script()
-{
-	ENCODED_SCRIPT=$(qubesdb-read /qubes-save-script)
-	if [ -z "$ENCODED_SCRIPT" ] ; then return ; fi
-	echo $ENCODED_SCRIPT|perl -e 'use MIME::Base64 qw(decode_base64); local($/) = undef;print decode_base64(<STDIN>)' >/tmp/qubes-save-script
-	chmod 755 /tmp/qubes-save-script
-	DISPLAY=:0 su - user -c /tmp/qubes-save-script
-}
-
-echo user | /bin/sh /etc/qubes-rpc/qubes.WaitForSession
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
+set -e
+
+echo "Waiting for user session to quiesce." >&2
+echo user | /bin/sh /etc/qubes-rpc/qubes.WaitForSession || :
+
+echo "Possibly running save script." >&2
 possibly_run_save_script
-umount /rw
-dmesg -c >/dev/null
+
+echo "Unmounting /rw filesystem." >&2
+umount_retry /rw || echo "Giving up and proceeding.  Warning: this may not work." >&2
+
+dmesg -C
 qubesdb-watch /qubes-restore-complete &
 watch_pid=$!
 free | grep Mem: |
     (read label total used free shared buffers cached; qubesdb-write /qubes-used-mem $(( $used + $cached )) )
+
 # we're still running in DispVM template
-echo "Waiting for save/restore..."
-qubesdb-read /qubes-restore-complete || wait $watch_pid
-echo Back to life.
-systemctl restart systemd-random-seed.service
+echo "Waiting for restore signal." >&2
+qubesdb-read /qubes-restore-complete >/dev/null || wait $watch_pid
+echo "Restore complete." >&2
+
+# Reload random seed
+echo "Reloading random seed." >&2
+reload_random_seed

+ 2 - 2
vm-systemd/qubes-dvm.service

@@ -1,14 +1,14 @@
 [Unit]
 Description=Prepare Qubes DispVM Template
 ConditionPathExists=/var/run/qubes-service/qubes-dvm
-After=systemd-readahead-replay.service
+After=systemd-readahead-replay.service qubes-gui-agent.service
+Wants=qubes-gui-agent.service
 Before=xendriverdomain.service
 
 [Service]
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=/usr/lib/qubes/init/prepare-dvm.sh
-StandardOutput=syslog
 
 [Install]
 WantedBy=multi-user.target

+ 0 - 1
vm-systemd/qubes-firewall.service

@@ -5,7 +5,6 @@ After=qubes-network.service
 
 [Service]
 ExecStart=/usr/sbin/qubes-firewall
-StandardOutput=syslog
 
 [Install]
 WantedBy=multi-user.target

+ 0 - 2
vm-systemd/qubes-iptables.service

@@ -5,8 +5,6 @@ Description=Qubes base firewall settings
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=/usr/lib/qubes/init/qubes-iptables start
-StandardOutput=syslog
-StandardError=syslog
 
 [Install]
 WantedBy=basic.target

+ 8 - 5
vm-systemd/qubes-mount-dirs.service

@@ -1,16 +1,19 @@
 [Unit]
 Description=Initialize and mount /rw and /home
-After=qubes-sysinit.service
+# There is a dependency on dev-xvdb.device because
+# mount-dirs.sh calls setup-rwdev.sh which
+# must happen only when /dev/xvdb has appeared.
+After=qubes-sysinit.service dev-xvdb.device
 DefaultDependencies=no
-Before=local-fs.target qubes-gui-agent.service
+Before=local-fs.target rw.mount home.mount qubes-gui-agent.service
 
 [Service]
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=/usr/lib/qubes/init/mount-dirs.sh
-# Fedora and Debian have different paths for fuser
-ExecStop=/bin/sh -c 'fuser -kMm /home' ; /bin/umount /home
-ExecStopPost=-/bin/umount /rw
+# There is no need for an ExecStop because systemd
+# cleans up mount units in the right order, killing
+# processes as needed.
 
 [Install]
 WantedBy=multi-user.target

+ 0 - 1
vm-systemd/qubes-netwatcher.service

@@ -5,7 +5,6 @@ After=network-pre.target qubes-firewall.service
 
 [Service]
 ExecStart=/usr/sbin/qubes-netwatcher
-StandardOutput=syslog
 
 [Install]
 WantedBy=multi-user.target

+ 0 - 1
vm-systemd/qubes-network.service

@@ -8,7 +8,6 @@ After=network-pre.target qubes-iptables.service
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=/usr/lib/qubes/init/network-proxy-setup.sh
-StandardOutput=syslog
 
 [Install]
 WantedBy=multi-user.target

+ 0 - 1
vm-systemd/qubes-qrexec-agent.service

@@ -5,7 +5,6 @@ After=qubes-dvm.service xendriverdomain.service
 [Service]
 ExecStartPre=/bin/sh -c '[ -e /dev/xen/evtchn ] || modprobe xen_evtchn'
 ExecStart=/usr/lib/qubes/qrexec-agent
-StandardOutput=syslog
 
 [Install]
 WantedBy=multi-user.target

+ 4 - 2
vm-systemd/qubes-random-seed.sh

@@ -1,7 +1,9 @@
 #!/bin/bash
 
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
+
 set -e
 set -o pipefail
 
-qubesdb-read /qubes-random-seed | base64 -d > /dev/urandom
-qubesdb-rm /qubes-random-seed
+reload_random_seed

+ 0 - 1
vm-systemd/qubes-sysinit.service

@@ -8,7 +8,6 @@ After=proc-xen.mount systemd-modules-load.service qubes-db.service
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=/usr/lib/qubes/init/qubes-sysinit.sh
-StandardOutput=syslog
 
 [Install]
 WantedBy=sysinit.target

+ 18 - 27
vm-systemd/qubes-sysinit.sh

@@ -1,4 +1,7 @@
-#!/bin/sh
+#!/bin/bash
+
+# Source Qubes library.
+. /usr/lib/qubes/init/functions
 
 # List of services enabled by default (in case of absence of qubesdb entry)
 DEFAULT_ENABLED_NETVM="network-manager qubes-network qubes-update-check qubes-updates-proxy"
@@ -7,18 +10,7 @@ DEFAULT_ENABLED_APPVM="meminfo-writer cups qubes-update-check"
 DEFAULT_ENABLED_TEMPLATEVM="$DEFAULT_ENABLED_APPVM updates-proxy-setup"
 DEFAULT_ENABLED="meminfo-writer"
 
-QDB_READ=qubesdb-read
-QDB_LS=qubesdb-multiread
-
-# Location of files which contains list of protected files
-PROTECTED_FILE_LIST='/etc/qubes/protected-files.d'
-
-read_service() {
-    $QDB_READ /qubes-service/$1 2> /dev/null
-}
-
-systemd_pkg_version=`systemctl --version|head -n 1`
-if ! dmesg | grep -q "$systemd_pkg_version running in system mode."; then
+if systemd_version_changed ; then
     # Ensure we're running right version of systemd (the one started by initrd may be different)
     systemctl daemon-reexec
 fi
@@ -48,11 +40,10 @@ chgrp qubes /proc/xen/privcmd
 chmod 666 /proc/u2mfn
 
 # Set default services depending on VM type
-TYPE=`$QDB_READ /qubes-vm-type 2> /dev/null`
-[ "$TYPE" = "AppVM" ] && DEFAULT_ENABLED=$DEFAULT_ENABLED_APPVM && touch /var/run/qubes/this-is-appvm
-[ "$TYPE" = "NetVM" ] && DEFAULT_ENABLED=$DEFAULT_ENABLED_NETVM && touch /var/run/qubes/this-is-netvm
-[ "$TYPE" = "ProxyVM" ] && DEFAULT_ENABLED=$DEFAULT_ENABLED_PROXYVM && touch /var/run/qubes/this-is-proxyvm
-[ "$TYPE" = "TemplateVM" ] && DEFAULT_ENABLED=$DEFAULT_ENABLED_TEMPLATEVM && touch /var/run/qubes/this-is-templatevm
+is_appvm && DEFAULT_ENABLED=$DEFAULT_ENABLED_APPVM && touch /var/run/qubes/this-is-appvm
+is_netvm && DEFAULT_ENABLED=$DEFAULT_ENABLED_NETVM && touch /var/run/qubes/this-is-netvm
+is_proxyvm && DEFAULT_ENABLED=$DEFAULT_ENABLED_PROXYVM && touch /var/run/qubes/this-is-proxyvm
+is_templatevm && DEFAULT_ENABLED=$DEFAULT_ENABLED_TEMPLATEVM && touch /var/run/qubes/this-is-templatevm
 
 # Enable default services
 for srv in $DEFAULT_ENABLED; do
@@ -60,18 +51,18 @@ for srv in $DEFAULT_ENABLED; do
 done
 
 # Enable services
-for srv in `$QDB_LS /qubes-service/ 2>/dev/null |grep ' = 1'|cut -f 1 -d ' '`; do
+for srv in `qubesdb-multiread /qubes-service/ 2>/dev/null |grep ' = 1'|cut -f 1 -d ' '`; do
     touch /var/run/qubes-service/$srv
 done
 
 # Disable services
-for srv in `$QDB_LS /qubes-service/ 2>/dev/null |grep ' = 0'|cut -f 1 -d ' '`; do
+for srv in `qubesdb-multiread /qubes-service/ 2>/dev/null |grep ' = 0'|cut -f 1 -d ' '`; do
     rm -f /var/run/qubes-service/$srv
 done
 
 # Set the hostname
-if ! grep -rq "^/etc/hostname$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
-    name=`$QDB_READ /name`
+if ! is_protected_file /etc/hostname ; then
+    name=`qubesdb-read /name`
     if [ -n "$name" ]; then
         hostname $name
         if [ -e /etc/debian_version ]; then
@@ -85,13 +76,13 @@ if ! grep -rq "^/etc/hostname$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
 fi
 
 # Set the timezone
-if ! grep -rq "^/etc/timezone$" "${PROTECTED_FILE_LIST}" 2>/dev/null; then
-    timezone=`$QDB_READ /qubes-timezone 2> /dev/null`
+if ! is_protected_file /etc/timezone ; then
+    timezone=`qubesdb-read /qubes-timezone 2> /dev/null`
     if [ -n "$timezone" ]; then
-        ln -sf ../usr/share/zoneinfo/$timezone /etc/localtime
+        ln -sf ../usr/share/zoneinfo/"$timezone" /etc/localtime
         if [ -e /etc/debian_version ]; then
             echo "$timezone" > /etc/timezone
-        else
+        elif test -d /etc/sysconfig ; then
             echo "# Clock configuration autogenerated based on Qubes dom0 settings" > /etc/sysconfig/clock
             echo "ZONE=\"$timezone\"" >> /etc/sysconfig/clock
         fi
@@ -101,7 +92,7 @@ fi
 # Prepare environment for other services
 echo > /var/run/qubes-service-environment
 
-debug_mode=`$QDB_READ /qubes-debug-mode 2> /dev/null`
+debug_mode=`qubesdb-read /qubes-debug-mode 2> /dev/null`
 if [ -n "$debug_mode" -a "$debug_mode" -gt 0 ]; then
     echo "GUI_OPTS=-vv" >> /var/run/qubes-service-environment
 fi