Compare commits

...

23 Commits

Author SHA1 Message Date
Christopher Laprise
b85fac0282
Fix formatting 2023-05-01 13:39:26 -04:00
Christopher Laprise
1b9b0ce529
Revise dom0 instructions for sudo prompt 2023-05-01 13:28:02 -04:00
Christopher Laprise
bcd840c318
makefile and debian 2019-09-02 08:50:18 -04:00
Christopher Laprise
05d8649e05
add nosuid,nodev protection 2019-08-27 21:13:20 -04:00
Christopher Laprise
47b42547d1
fix vm-boot-protect mode
issue #40
2019-08-18 15:49:10 -04:00
Christopher Laprise
13d5c5d2de
optimize, add tag wiperw 2019-08-17 15:12:13 -04:00
Christopher Laprise
bbdc5b711b
move rc back before mount 2019-08-17 13:28:36 -04:00
Christopher Laprise
67315b0119
add note 2019-08-15 15:44:21 -04:00
Christopher Laprise
9bff232683
version 0.9.0 2019-08-15 15:08:44 -04:00
Christopher Laprise
8327e1e106
umount in template 2019-08-14 01:34:39 -04:00
Christopher Laprise
e385fa995b
fix template exit condition 2019-08-14 01:18:54 -04:00
Christopher Laprise
b203c69a3c
fix uninstall exit 2019-08-13 16:22:27 -04:00
Christopher Laprise
700016197e
fix spelling, add tag noqbackup 2019-08-13 15:55:13 -04:00
Christopher Laprise
876491ceee
fix backup rm sequence 2019-08-13 14:46:03 -04:00
Christopher Laprise
8f8e7e6595
add uninstall, refine ibrowse 2019-08-13 13:46:52 -04:00
Christopher Laprise
ebe40e1391
tweaks to log, tags and cleanup 2019-08-11 06:28:22 -04:00
Christopher Laprise
ca67ef7fe3
var and rc tweaks, add tag files 2019-08-11 06:26:26 -04:00
Christopher Laprise
204e90a626
add 3 rc files, add tagging feature, simplify
issue #9, issue #35
2019-08-03 00:15:21 -04:00
Christopher Laprise
850843e7c0
fix placeholder func, faster home populate 2019-08-01 18:50:20 -04:00
Christopher Laprise
d877085494
add vm_boot_finish hook 2019-07-30 23:43:32 -04:00
Christopher Laprise
55181dc2dd
mutable for rm, use mkhomedir_helper 2019-07-30 23:25:35 -04:00
Christopher Laprise
302c968313
begin rc, chfiles as user, process etc/skel 2019-07-30 17:19:11 -04:00
Christopher Laprise
43ca3dcf17
chfiles optional default. fix immutable in template. 2019-07-28 15:42:57 -04:00
22 changed files with 395 additions and 111 deletions

7
Makefile Normal file
View File

@ -0,0 +1,7 @@
VERSION := $(shell cat version)
install: install-vm
install-vm:
bash ./install
bash ./configure-sudo-prompt --force

View File

@ -7,7 +7,8 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock-
* Acts at VM startup before private volume /rw mounts
* User: Protect /home desktop & shell startup executables
* Root: Quarantine all /rw configs & scripts, with whitelisting
* Re-deploy custom or default files to /rw on each boot
* Organize configurations with named tags
* Deploy trusted custom files to /rw on each boot
* SHA256 hash checking against unwanted changes
* Provides rescue shell on error or request
* Works with template-based AppVMs, sys-net and sys-vpn
@ -15,23 +16,29 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock-
### Installing
1. In a template VM, install the service files
```
cd Qubes-VM-hardening
sudo sh ./install
```
1. In dom0, enter the following commands to enable `sudo` prompts:
2. Activate by specifying one of the following Qubes services for your VM(s)...
sudo su -
echo "/usr/bin/echo 1" >/etc/qubes-rpc/qubes.VMAuth
chmod +x /etc/qubes-rpc/qubes.VMAuth
echo "@anyvm dom0 ask,default_target=dom0" >/etc/qubes-rpc/policy/qubes.VMAuth
2. In a template VM, install and configure
cd Qubes-VM-hardening
sudo bash install
sudo bash configure-sudo-prompt
As an alternative, you can skip _'configure-sudo-prompt'_ and Step 1 and instead uninstall the `qubes-core-agent-passwordless-root` package from the template. After doing this, you will have to use `qvm-run -u root` from dom0 to run any VM commands as root.
3. Activate by specifying one of the following Qubes services for your VM(s)...
- `vm-boot-protect` - Protects executables/scripts within /home/user and may be used with wide array of Qubes VMs including standalone, appVMs, netVMs, Whonix, etc.
- `vm-boot-protect-root` - Protects /home/user as above, automatic /rw executable deactivation, whitelisting, checksumming, deployment. Works with appVMs, netVMs, etc. that are _template-based_.
```
CAUTION: The -root option by default **removes** prior copies of /rw/config, /rw/usrlocal and /rw/bind-dirs. This can delete data!
3. Disable Qubes default passwordless-root. This is necessary for the above measures to work effectively...
For Debian-based templates the installer will launch `configure-sudo-prompt` automatically to enable a sudo [yes/no prompt](https://www.qubes-os.org/doc/vm-sudo/#replacing-password-less-root-access-with-dom0-user-prompt) that appears in dom0. This handles the template configuration then displays several commands to manually configure dom0 (the dom0 step is required only once, regardless of how many templates you configure). You may test the `configure-sudo-prompt` script in a regular template-based appVM to see if it works, although the effect will be temporary.
Alternately, you can uninstall the `qubes-core-agent-passwordless-root` package from the template. After doing this, you will have to use `qvm-run -u root` from dom0 to run any VM commands as root.
---
@ -48,7 +55,7 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock-
### Configuration
Files can be added to /etc/default/vms in the template to enable the following features...
Files can be added to /etc/default/vms in the template to configure the following `vm-boot-protect-root` features...
**Hashes/Checksums** are checked in ../vms/vms.all.SHA and ../vms/$vmname.SHA files. File paths contained in them must be absolute, and references to '/home' must be prefixed with '/rw/'. Hashes in $vmname.SHA will override hashes specified for the same paths in vms.all.SHA. See also man page for `sha256sum -c`.
@ -57,6 +64,10 @@ Leverage Qubes template non-persistence to fend off malware at VM startup: Lock-
**Deployment** files are copied _recursively_ from ../vms/vms.all/rw/ and ../vms/$vmname/rw/ dirs. Example is to place the .bashrc file in /etc/default/vms/vms.all/rw/home/user/.bashrc for deployment to /rw/home/user/.bashrc. Once copying is complete,
the /etc/defaults/vms folder is deleted from the running VM (this has no effect on the original in the template).
**rc files** are sh script fragments sourced from ../vms/vms.all.rc and ../vms/$vmname.rc. They run near the beginning of the vm-boot-protect service before mounting /rw, and can be used to override variable definitions like `privdirs` as well as the `vm_boot_finish` function which runs near the end before dismount. Another use for rc files is to run threat detection tools such as antivirus.
**Tags:** Any of the above configs may be defined as tags so that you are not limited to specifying them for either all VMs or specifically-named VMs. Simply configure them as you would acccording to the above directions, but place the files under the '@tags' subdir instead. For example '/etc/default/vms/@tags/special.whitelist' defines a whitelist for the tag 'special'. A tag can be activated for one or more VMs by adding a Qubes service prefixed with `vm-boot-tag-` (i.e. vm-boot-tag-special) to the VMs. Also, multiple tags may be activated for a VM.
### Where to use: Basic examples
After installing into a template, simply enable `vm-boot-protect-root` service without configuration. Recommended for the following types of VMs:
@ -71,17 +82,33 @@ Examples where -root should *not* be enabled:
* Standalone VMs. Plain `vm-boot-protect` makes more sense for these.
* Non-Linux VMs (currently unsupported for any mode)
### Example tags
Some useful configurations have been supplied in /etc/default/vms:
* vm-boot-tag-network: Contains a whitelist for Network Manager connections and the module blacklist which is often used with network interfaces in Qubes. By default, this config also activates for any VM named 'sys-net'.
* vm-boot-tag-qhome: Quarantines /home in addition to the /rw system dirs. Useful for 'sys-usb' and DispVM-like functionality.
* vm-boot-tag-noqbackup: Deletes all quarantined files that are not whitelisted.
* vm-boot-tag-ibrowse: Preserves Firefox bookmarks while quarantining the /home folder. [Currently](https://github.com/tasket/Qubes-VM-hardening/issues/39) works with Firefox ESR. See Notes below.
* vm-boot-wiperw: Completely wipe and reformat the /rw partition.
### Scope and Limitations
The *vm-boot-protect* concept enhances the guest operating system's own defenses by using the *root volume non-persistence* provided by the Qubes template system; thus a relatively pristine startup state may be achieved if the *private* volume is brought online in a controlled manner. Protecting the init/autostart files should result in Qubes template-based VMs that boot 'cleanly' with much less chance of being affected by malware initially. Even if malware persists in a VM, it should be possible to run other apps and terminals without interference if the malware has not escalated to root (admittedly, a big 'if').
Conversely, attacks which damage/exploit the Ext4 private filesystem itself or quickly re-exploit network vulnerabilities could conceivably still persist at startup. Further, repeated running of some apps such as Firefox, Chrome, LibreOffice, PDF viewers, online games, etc. may reactivate malware; this is not only because of the complexity of the formats handled by such apps, but also because of settings contained in javascript or which specify commands to be executed by the app. Therefore, setting apps to autostart can diminish protection of the startup environment.
Conversely, attacks which damage/exploit the Ext4 private filesystem itself or quickly re-exploit network vulnerabilities could conceivably still persist at startup. Further, repeated running of complex apps, games, and programming environments may reactivate malware; this is because of the complexity of the formats and settings handled by such apps. Therefore, setting apps to autostart can diminish protection of the startup environment.
Note that as vulnerabilities are patched via system updates, malware that used those vulns to gain entry may cease to function without the kind of loopholes that *vm-boot-protect* closes.
Note that as system and app vulnerabilities are patched via system updates, malware that used those vulns to gain entry may cease to function without the kind of loopholes that *vm-boot-protect* closes.
Efficient template re-use is another aspect of using *vm-boot-protect-root* features, since a single template can be customized for various roles. However, note that some customizations may not be appropriate to run during VM startup.
### Notes
* The /rw/home directory can be added to `privdirs` so it is quarantined much like the other /rw dirs. The easiest way to configure this is to define `privdirs_add=/rw/home` in an rc file; see 'qhome.rc' for an exmaple.
* The ibrowse tag works with Firefox versions up to 66 and uses a generic profile named 'profile.default'. If you wish to carry over existing bookmarks for use with ibrowse, rename the current profile folder in '.mozilla/firefox' to 'profile.default' before enabling the ibrowse tag.
* A bug in v0.8.4 will erase anything in '/etc/default/vms' when booting into the template. For proper
future operation with sys-net or other VMs you may have customized in that path, updating Qubes-VM-hardening
to the latest version (using the install script) is recommended, along with restoring any custom files
@ -89,20 +116,27 @@ Examples where -root should *not* be enabled:
* All the user-writable startup files in /home should be protected by the immutable flag; See issue #9 if you notice an omission or other problem. An extra step of disabling the flag using `sudo chattr -i` is required whenever the user wants to modify these startup files.
* Adding /home or subdirs of it to $privdirs is possible. This would quarantine everything there to set the stage for applying whitelists on /home contents. The $privdirs variable can be changed via the service file, for example adding a .conf file in /lib/systemd/system/vm-boot-protect.d.
* The sys-net VM should work 'out of the box' with the vm-boot-protect-root service via the included whitelist file. Additional network VMs may require configuration, such as `cp sys-net.whitelist sys-net2.whitelist`.
* Using the -root service with a [VPN VM](https://github.com/tasket/Qubes-vpn-support) requires manual configuration in the template and can be approached different ways: Whitelist (optionally with SHA) can be made for the appropriate files. Alternately, all VPN configs can be added under /etc/default/vms/vmname/rw so they'll be automatically deployed.
* Currently the service cannot seamlessly handle 'first boot' when the private volume must be initialized. If you enabled the service on a VM before its first startup, on first start the shell will display a notice telling you to restart the VM. Subsequent starts will proceed normally.
* The service can be removed from the system with `cd Qubes-VM-hardening; sudo bash install --uninstall`
### Links
- Qubes VM sudo [page](https://www.qubes-os.org/doc/vm-sudo/#replacing-password-less-root-access-with-dom0-user-prompt)
## Releases
- v0.9.4 Revise dom0 instructions for sudo prompt
- v0.9.3 Protect against suid and device nodes
- v0.9.2 Fix vm-boot-protect mode
- v0.9.1 Optimized, fix rc order, new "wiperw" tag
- v0.9.0 Add tags and rc files, protect more home scripts, reinitialize home
- v0.8.5 Fix template detection, /etc/default/vms erasure
- v0.8.4 Add protection to /home/user/.config/systemd
- v0.8.3 Fix for install script copying to /etc/default/vms
- v0.8.2 Working rescue shell. Add sys-net whitelist, sudo config, fixes.
- v0.8.0 Adds protection to /rw, file SHA checksums, whitelists, deployment
- v0.2.0 Protects /home/user files and dirs

View File

@ -1,5 +1,6 @@
#!/bin/bash
# From https://github.com/tasket/Qubes-VM-hardening
# installer version 0.9.4
set -e
[ `id -u` -eq 0 ] || exit
@ -17,11 +18,27 @@ See https://qubes-os.org/doc/vm-sudo for manual instructions."
exit 1
fi
if [ "$1" = "--force" ]; then
force=1
else
force=0
fi
if grep -q '^auth .* dom0\squbes\.VMAuth' /etc/pam.d/common-auth && [ $force = 0 ]; then
echo "System appears already configured for sudo prompts."
echo "To force re-configuration run 'configure-sudo-prompt --force'."
exit 0
fi
echo -e "\n--+ Enable yes/no authentication prompt for sudo +--
Warning: Before opting for this change a backup or clone
should me made of this template!"
if [ $force = 0 ]; then
read -p "Configure sudo authentication prompt now? (y/n): " answer
if [[ $answer == @(y|Y) ]]; then
fi
if [[ $answer == @(y|Y) ]] || [ $force = 1 ]; then
mv -fb /etc/pam.d/common-auth /etc/pam.d/common-auth~
cat >/etc/pam.d/common-auth <<_EOF
@ -48,7 +65,8 @@ _EOF
Next.... Enable auth prompts in dom0 with the following commands:
[user@dom0 ~]$ sudo su -
[root@dom0 /]# echo "/usr/bin/echo 1" >/etc/qubes-rpc/qubes.VMAuth
[root@dom0 /]# echo "\$anyvm dom0 ask,default_target=dom0" \
[root@dom0 /]# chmod +x /etc/qubes-rpc/qubes.VMAuth
[root@dom0 /]# echo "@anyvm dom0 ask,default_target=dom0" \
>/etc/qubes-rpc/policy/qubes.VMAuth
'

5
debian/changelog vendored Normal file
View File

@ -0,0 +1,5 @@
qubes-vm-hardening (0.9.3-1) unstable; urgency=medium
* Initial release
-- Christopher Laprise <tasket@protonmail.com> Mon, 2 Sep 2018 08:01:15 -0400

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
10

18
debian/control vendored Normal file
View File

@ -0,0 +1,18 @@
Source: Qubes-VM-hardening
Section: admin
Priority: optional
Maintainer: Christopher Laprise <tasket@protonmail.com>
Build-Depends: debhelper (>= 10)
Standards-Version: 4.1.2
Homepage: https://www.qubes-os.org
Package: qubes-vm-hardening
Architecture: all
Depends: ${misc:Depends} qubes-core-agent
Description: Prevent malware persistence in Qubes virtual machines.
Reconfigures Qubes VM templates to block casual sudo access,
protects user startup scripts, and includes a service that can
quarantine, whitelist and check file hashes at startup before
the /rw volume comes online.
See https://www.github.com/tasket/Qubes-VM-hardening for more info.

18
debian/copyright vendored Normal file
View File

@ -0,0 +1,18 @@
Files: debian/*
Copyright: 2018-2019 Christopher Laprise <tasket@protonmail.com>
License: GPL-3
This package 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 3 of the License, or
(at your option) any later version.
.
This package 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, see <https://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".

1
debian/install vendored Normal file
View File

@ -0,0 +1 @@

48
debian/postinst vendored Normal file
View File

@ -0,0 +1,48 @@
#!/bin/sh
# postinst script for qubes-tunnel
#
# see: dh_installdeb(1)
### TODO:
### Fix postinst and install files in 'debian' folder.
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure)
systemctl daemon-reload
systemctl enable vm-boot-protect.service
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

25
debian/rules vendored Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable)
# output every command that modifies files on the build system.
#export DH_VERBOSE = 1
# see FEATURE AREAS in dpkg-buildflags(1)
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# see ENVIRONMENT in dpkg-buildflags(1)
# package maintainers to append CFLAGS
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
# package maintainers to append LDFLAGS
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
%:
dh $@
# dh_make generated override targets
# This is example for Cmake (See https://bugs.debian.org/641051 )
#override_dh_auto_configure:
# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (quilt)

View File

@ -0,0 +1,2 @@
# Browser-focused config that saves only bookmarks, starts with /home quarantine
privdirs_add="/rw/home"

View File

@ -0,0 +1,3 @@
/rw/home/user/.mozilla/firefox/profile.default/places.sqlite
/rw/home/user/.mozilla/firefox/profile.default/places.sqlite-shm
/rw/home/user/.mozilla/firefox/profile.default/places.sqlite-wal

View File

@ -0,0 +1,6 @@
// Remove history from places.sqlite
user_pref("privacy.history.custom",true);
user_pref("privacy.sanitize.sanitizeOnShutdown",true);
user_pref("privacy.clearOnShutdown.downloads",true);
user_pref("privacy.clearOnShutdown.history",true);
user_pref("browser.search.suggest.enabled",false);

View File

@ -0,0 +1,9 @@
[General]
StartWithLastProfile=1
[Profile0]
Name=default
IsRelative=1
Path=profile.default
Default=1

View File

@ -0,0 +1,2 @@
/rw/config/NM-system-connections/
/rw/config/suspend-module-blacklist

View File

@ -0,0 +1,2 @@
# Removes any files that were quarantined under /rw/vm-boot-protect/
save_backup=0

View File

@ -0,0 +1,2 @@
# Quarantine entire /home directory
privdirs_add="/rw/home"

View File

@ -0,0 +1,4 @@
# Completely wipes private volume contents
blkdiscard $dev
mkfs.ext4 $dev

View File

@ -1,2 +0,0 @@
/rw/config/NM-system-connections/
/rw/config/suspend-module-blacklist

View File

@ -0,0 +1 @@
@tags/network.whitelist

27
install
View File

@ -1,12 +1,25 @@
#!/bin/bash
# From https://github.com/tasket/Qubes-VM-hardening
# installer version 0.8.4
# installer version 0.9.3
set -e
[ `id -u` -eq 0 ] || exit
echo "Disabling the pre-release service (if present)..."
systemctl disable vm-sudo-protect.service || true
if [ "$1" = "--uninstall" ]; then
echo "Removing vm-boot-protect.service..."
echo "Warning: This will remove any custom files added to /etc/default/vms!"
read -p "Proceed [y/N]? " ans
if [[ $ans == @(Y|y) ]]; then
systemctl disable vm-boot-protect.service
rm -r /lib/systemd/system/vm-boot-protect.service /usr/lib/qubes/init/vm-boot-protect.sh /etc/default/vms
systemctl daemon-reload
echo "Done."
else
echo "Aborted."
fi
exit 0
fi
echo "Installing vm-boot-protect.service..."
cp vm-boot-protect.sh /usr/lib/qubes/init
@ -20,8 +33,14 @@ mkdir -p /etc/default/vms
# Careful... ownership & mode are not preserved here!
cp -riv default/vms/* /etc/default/vms
echo "Adding nosuid,nodev options to /etc/fstab..."
cp /etc/fstab /etc/fstab.bak
awk '($1~"^/rw/" || $2~"^/rw$") && ($4!~"nosuid" || $4!~"nodev") {$4=$4",nosuid,nodev"}1' \
/etc/fstab.bak >/etc/fstab
echo -e "\nvm-boot-protect installed!\n"
bash ./configure-sudo-prompt
#bash ./configure-sudo-prompt
exit 0

178
vm-boot-protect.sh Normal file → Executable file
View File

@ -23,32 +23,63 @@
# Source Qubes library.
. /usr/lib/qubes/init/functions
# Define sh, bash, X and desktop init scripts in /home/user
# to be protected
chfiles=".bashrc .bash_profile .bash_login .bash_logout .profile \
.xprofile .xinitrc .xserverrc .xsession"
chdirs="bin .local/bin .config/autostart .config/plasma-workspace/env \
.config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd"
vmname=`qubesdb-read /name`
dev=/dev/xvdb
rw=/mnt/rwtmp
rwbak=$rw/vm-boot-protect
errlog=/var/run/vm-protect-error
servicedir=/var/run/qubes-service
defdir=/etc/default/vms
version="0.8.5"
version=0.9.3
# Define sh, bash, X and desktop init scripts in /home/user
# to be protected
chfiles=${chfiles:-".bashrc .bash_profile .bash_login .bash_logout .profile \
.pam_environment .xprofile .xinitrc .xserverrc .Xsession .xsession .xsessionrc"}
chfiles_add=${chfiles_add:-""}
chdirs=${chdirs:-"bin .local/bin .config/autostart .config/plasma-workspace/env \
.config/plasma-workspace/shutdown .config/autostart-scripts .config/systemd"}
chdirs_add=${chdirs_add:-""}
# Define dirs to apply quarantine / whitelists
privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"}
privdirs_add=${privdirs_add:-""}
save_backup=${save_backup:-1}
if is_rwonly_persistent; then
rwonly_pers=1
else
rwonly_pers=0
fi
# Placeholder function: Runs at end
vm_boot_finish() { return; }
# Remount fs as read-write
remount_rw() {
# Begin write operations
if [ -e $dev ] && mount -o remount,rw,nosuid,nodev $dev $rw ; then
echo Good rw remount.
else
abort_startup RELOCATE "Remount failed!"
fi
}
# Function: Make user scripts immutable.
make_immutable() {
echo "Making files IMMUTABLE"
remount_rw
#initialize_home $rw/home ifneeded
cd $rw/home/user
mkdir -p $chdirs
touch $chfiles
chattr -R -f +i $chfiles $chdirs
su user -c "mkdir -p $chdirs $chdirs_add; touch $chfiles $chfiles_add 2>/dev/null"
chattr -R -f +i $chfiles $chfiles_add $chdirs $chdirs_add
cd /root
}
# Start rescue shell then exit/fail
abort_startup() {
type="$1"
@ -85,29 +116,30 @@ abort_startup() {
}
# Don't bother with root protections in template or standalone
if ! is_rwonly_persistent; then
if qsvc vm-boot-protect; then
make_immutable
fi
if ! is_templatevm; then
# Keep configs invisible for standalone vms
rm -rf "$defdir"
fi
exit 0
# cannot use abort_startup() before this point
fi
echo >$errlog # Clear
if qsvc vm-boot-protect-cli; then
abort_startup RELOCATE "CLI requested."
fi
# Run rc file commands if they exist
if qsvc vm-boot-protect-root && [ $rwonly_pers = 1 ]; then
# Get list of enabled tags from Qubes services
tags=`find $servicedir -name 'vm-boot-tag-*' -type f -printf '%f\n' \
| sort | sed -E 's|^vm-boot-tag-|\@tags/|'`
for rcbase in vms.all $tags $vmname; do
if [ -e "$defdir/$rcbase.rc" ]; then
. "$defdir/$rcbase.rc"
fi
done
fi
if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then
# Mount private volume in temp location
mkdir -p $rw
if [ -e $dev ] && mount -o ro $dev $rw ; then
if [ -e $dev ] && mount -o ro,nosuid,nodev $dev $rw ; then
echo "Good read-only mount."
else
echo "Mount failed."
@ -120,6 +152,17 @@ if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then
abort_startup RELOCATE "Mount failed; BAD private volume!"
fi
fi
# Begin exit if in template or standalone
if [ $rwonly_pers = 0 ]; then
make_immutable
umount $rw
fi
fi
# Exit if in template or standalone
if [ $rwonly_pers = 0 ]; then
exit 0
fi
@ -128,27 +171,23 @@ fi
# * Hashes in vms/vms.all.SHA and vms/$vmname.SHA files will be checked.
# * Remove /rw root startup files (config, usrlocal, bind-dirs).
# * Contents of vms/vms.all and vms/$vmname folders will be copied.
privdirs=${privdirs:-"/rw/config /rw/usrlocal /rw/bind-dirs"}
if qsvc vm-boot-protect-root && is_rwonly_persistent; then
if qsvc vm-boot-protect-root && [ $rwonly_pers = 1 ]; then
# Check hashes
checkcode=0
if [ -e $defdir/$vmname.SHA ]; then
# remove padding and add number field
sed 's/^ *//; s/ *$//; /^$/d; s/^/1 /' $defdir/$vmname.SHA \
>/tmp/vm-boot-protect-sha
fi
if [ -e $defdir/vms.all.SHA ]; then
sed 's/^ *//; s/ *$//; /^$/d; s/^/2 /' $defdir/vms.all.SHA \
>>/tmp/vm-boot-protect-sha
for sha_base in $vmname $tags vms.all; do
if [ -e "$defdir/$sha_base.SHA" ]; then
cat "$defdir/$sha_base.SHA" >>/tmp/vm-boot-protect-sha
fi
done
if [ -e /tmp/vm-boot-protect-sha ]; then
echo "Checking file hashes." |tee $errlog
# Get unique paths, remove field and switch path to $rw before check;
# Strip padding, get unique paths and switch path to $rw before check;
# this allows hashes in $vmname.SHA to override ones in vms.all.SHA.
sort --unique --key=3 /tmp/vm-boot-protect-sha \
| sed -r 's|^[1-2] (.*[[:space:]]*)/rw|\1'$rw'|' \
sed 's/^ *//; s/ *$//; /^$/d;' /tmp/vm-boot-protect-sha \
| sort -u -k2,2 \
| sed -r 's|^(\S+\s+)/rw|\1'$rw'|' \
| sha256sum --strict -c >>$errlog; checkcode=$?
fi
@ -157,37 +196,48 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then
abort_startup RELOCATE "Hash check failed!"
fi
# Begin write operations
if [ -e $dev ] && mount -o remount,rw $dev $rw ; then
echo Good rw remount.
else
abort_startup RELOCATE "Remount failed!"
fi
remount_rw
# Files mutable for del/copy operations
cd $rw/home/user
chattr -R -f -i $chfiles $chdirs $privdirs
chattr -R -f -i $chfiles $chfiles_add $chdirs $chdirs_add $privdirs $privdirs_add \
$rwbak/BAK-*
cd /root
# Deactivate private.img config dirs
mkdir -p $rwbak
for dir in $privdirs; do # maybe use 'eval' for privdirs quotes/escaping
echo "Deactivate $dir"
for dir in $privdirs $privdirs_add; do # maybe use 'eval' for privdirs quotes/escaping
# echo "Deactivate $dir"
subdir=`echo $dir |sed -r 's|^/rw/||'`
bakdir="$rwbak/BAK-$subdir"
origdir="$rwbak/ORIG-$subdir"
if [ -d "$bakdir" ] && [ ! -d "$origdir" ]; then
if [ -e "$bakdir" ] && [ ! -e "$origdir" ]; then
mv "$bakdir" "$origdir"
fi
if [ -e "$bakdir" ]; then
#chattr -R -i "$bakdir"
rm -rf "$bakdir"
fi
mv "$rw/$subdir" "$bakdir"
mkdir -p "$rw/$subdir"
# Populate /home/user w skel files if it was in privdirs
case "$subdir" in
"home"|"home/"|"home/user"|"home/user/")
# echo "Populating home dir"
rm -rf /home/user $rw/home/user
mount --bind -o nosuid,nodev $rw/home /home
mkhomedir_helper user
umount /home
;;
esac
done
for vmset in vms.all $vmname; do
for vmset in vms.all $tags $vmname; do
# Process whitelists...
if [ -e $defdir/$vmset.whitelist ]; then
cat $defdir/$vmset.whitelist \
| while read wlfile; do
# Must begin with '/rw/'
@ -196,17 +246,17 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then
dstfile="`echo $wlfile |sed -r \"s|^/rw/(.+)$|$rw/\1|\"`"
dstdir="`dirname \"$dstfile\"`"
if [ ! -e "$srcfile" ]; then
echo "Whitelist entry not present in filesystem:"
echo "$srcfile"
# echo "Whitelist entry not present in filesystem:"
# echo "$srcfile"
continue
# For very large dirs: mv whole dir when entry ends with '/'
elif echo $wlfile |grep -q "\/$"; then
echo "Whitelist mv $srcfile"
echo "to $dstfile"
# echo "Whitelist mv $srcfile"
# echo "to $dstfile"
mkdir -p "$dstdir"
mv -T "$srcfile" "$dstfile"
else
echo "Whitelist cp $srcfile"
# echo "Whitelist cp $srcfile"
mkdir -p "$dstdir"
cp -a --link "$srcfile" "$dstdir"
fi
@ -214,23 +264,33 @@ if qsvc vm-boot-protect-root && is_rwonly_persistent; then
echo "Whitelist path must begin with /rw/. Skipped."
fi
done
fi
# Copy default files...
if [ -d $defdir/$vmset/rw ]; then
echo "Copy files from $defdir/$vmset/rw"
# echo "Copy files from $defdir/$vmset/rw"
cp -af $defdir/$vmset/rw/* $rw
fi
done
vm_boot_finish
fi
# Remove backups if indicated
if [ $save_backup = 0 ]; then
chattr -R -f -i $rwbak
rm -rf $rwbak
fi
if qsvc vm-boot-protect || qsvc vm-boot-protect-root; then
echo "Preparing for unmount"
make_immutable
umount $rw
fi
# Keep configs invisible at runtime...
rm -rf "$defdir"
if ! is_templatevm; then
rm -rf "$defdir" $servicedir/vm-boot-tag* $servicedir/vm-boot-protect* $errlog
fi
exit 0