23250f84b2
The /etc/dconf/profile/user file in some distributions is part of dconf package, in some not. There are even cases where it changes between package versions (Fedora 27 don't have it, but Fedora 28 do). Also, base Debian Stretch don't have it, but Kali Linux based on it do. To avoid overly complex dependency handling, create the file dynamically on package installation if it's missing in that particular case. The file content is canonical: user-db:user system-db:local Fixes QubesOS/qubes-issues#3834
437 lines
13 KiB
Bash
437 lines
13 KiB
Bash
#!/bin/bash
|
|
qubes_preset_file="75-qubes-vm.preset"
|
|
|
|
###########################
|
|
## Pre-Install functions ##
|
|
###########################
|
|
|
|
update_default_user() {
|
|
# Make sure there is a qubes group
|
|
groupadd --force --system --gid 98 qubes
|
|
|
|
# Archlinux bash version has a 'bug' when running su -c, /etc/profile is not loaded because bash consider there is no interactive pty when running 'su - user -c' or something like this.
|
|
# See https://bugs.archlinux.org/task/31831
|
|
id -u 'user' >/dev/null 2>&1 || {
|
|
useradd --user-group --create-home --shell /bin/bash user
|
|
}
|
|
usermod -a --groups qubes user
|
|
}
|
|
|
|
## arg 1: the new package version
|
|
pre_install() {
|
|
echo "Pre install..."
|
|
|
|
update_default_user
|
|
|
|
# do this whole %pre thing only when updating for the first time...
|
|
|
|
mkdir -p /var/lib/qubes
|
|
|
|
# Backup fstab / But use archlinux defaults (cp instead of mv)
|
|
if [ -e /etc/fstab ] ; then
|
|
cp /etc/fstab /var/lib/qubes/fstab.orig
|
|
fi
|
|
|
|
# Add qubes core related fstab entries
|
|
echo "xen /proc/xen xenfs defaults 0 0" >> /etc/fstab
|
|
|
|
usermod -p '' root
|
|
usermod -L user
|
|
}
|
|
|
|
|
|
## arg 1: the new package version
|
|
## arg 2: the old package version
|
|
pre_upgrade() {
|
|
# do something here
|
|
echo "Pre upgrade..."
|
|
|
|
update_default_user
|
|
}
|
|
|
|
###################
|
|
## Install Hooks ##
|
|
###################
|
|
|
|
|
|
configure_notification-daemon() {
|
|
# Enable autostart of notification-daemon when installed
|
|
if [ ! -L /etc/xdg/autostart/notification-daemon.desktop ]; then
|
|
ln -s /usr/share/applications/notification-daemon.desktop /etc/xdg/autostart/
|
|
fi
|
|
}
|
|
|
|
configure_selinux() {
|
|
# SELinux is not enabled on archlinux
|
|
#echo "--> Disabling SELinux..."
|
|
echo "SELINUX not enabled on archlinux. skipped."
|
|
# sed -e s/^SELINUX=.*$/SELINUX=disabled/ -i /etc/selinux/config
|
|
# setenforce 0 2>/dev/null
|
|
}
|
|
|
|
############################
|
|
## Post-Install functions ##
|
|
############################
|
|
|
|
update_qubesconfig() {
|
|
# Remove old firmware updates link
|
|
if [ -L /lib/firmware/updates ]; then
|
|
rm -f /lib/firmware/updates
|
|
fi
|
|
|
|
#/usr/lib/qubes/update-proxy-configs
|
|
# Archlinux pacman configuration is handled in update_finalize
|
|
|
|
if ! [ -r /etc/dconf/profile/user ]; then
|
|
mkdir -p /etc/dconf/profile
|
|
echo "user-db:user" >> /etc/dconf/profile/user
|
|
echo "system-db:local" >> /etc/dconf/profile/user
|
|
fi
|
|
|
|
dconf update &> /dev/null || :
|
|
|
|
# Location of files which contains list of protected files
|
|
mkdir -p /etc/qubes/protected-files.d
|
|
# shellcheck source=init/functions
|
|
. /usr/lib/qubes/init/functions
|
|
|
|
# qubes-core-vm has been broken for some time - it overrides /etc/hosts; restore original content
|
|
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)
|
|
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
|
|
EOF
|
|
|
|
fi
|
|
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 ! 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
|
|
sed -i "s/^${ip}\(\s\|$\).*$/\0 $(hostname)/" /etc/hosts
|
|
else
|
|
echo "${ip} $(hostname)" >> /etc/hosts
|
|
fi
|
|
done
|
|
fi
|
|
|
|
}
|
|
|
|
############################
|
|
## Service Management Functions ##
|
|
############################
|
|
is_static() {
|
|
[ -f "/usr/lib/systemd/system/$1" ] && ! grep -q '^[[].nstall]' "/usr/lib/systemd/system/$1"
|
|
}
|
|
|
|
is_masked() {
|
|
if [ ! -L /etc/systemd/system/"$1" ]
|
|
then
|
|
return 1
|
|
fi
|
|
target=$(readlink /etc/systemd/system/"$1" 2>/dev/null) || :
|
|
if [ "$target" = "/dev/null" ]
|
|
then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
mask() {
|
|
ln -sf /dev/null /etc/systemd/system/"$1"
|
|
}
|
|
|
|
unmask() {
|
|
if ! is_masked "$1"
|
|
then
|
|
return 0
|
|
fi
|
|
rm -f /etc/systemd/system/"$1"
|
|
}
|
|
|
|
preset_units() {
|
|
local represet=
|
|
while read -r action unit_name
|
|
do
|
|
if [ "$action" = "#" ] && [ "$unit_name" = "Units below this line will be re-preset on package upgrade" ]
|
|
then
|
|
represet=1
|
|
continue
|
|
fi
|
|
echo "$action $unit_name" | grep -q '^[[:space:]]*[^#;]' || continue
|
|
[[ -n "$action" && -n "$unit_name" ]] || continue
|
|
if [ "$2" = "initial" ] || [ "$represet" = "1" ]
|
|
then
|
|
if [ "$action" = "disable" ] && is_static "$unit_name"
|
|
then
|
|
if ! is_masked "$unit_name"
|
|
then
|
|
# We must effectively mask these units, even if they are static.
|
|
mask "$unit_name"
|
|
fi
|
|
elif [ "$action" = "enable" ] && is_static "$unit_name"
|
|
then
|
|
if is_masked "$unit_name"
|
|
then
|
|
# We masked this static unit before, now we unmask it.
|
|
unmask "$unit_name"
|
|
fi
|
|
systemctl --no-reload preset "$unit_name" >/dev/null 2>&1 || :
|
|
else
|
|
systemctl --no-reload preset "$unit_name" >/dev/null 2>&1 || :
|
|
fi
|
|
fi
|
|
done < "$1"
|
|
}
|
|
|
|
restore_units() {
|
|
grep '^[[:space:]]*[^#;]' "$1" | while read -r action unit_name
|
|
do
|
|
if is_static "$unit_name" && is_masked "$unit_name"
|
|
then
|
|
# If the unit had been masked by us, we must unmask it here.
|
|
# Otherwise systemctl preset will fail badly.
|
|
unmask "$unit_name"
|
|
fi
|
|
systemctl --no-reload preset "$unit_name" >/dev/null 2>&1 || :
|
|
done
|
|
}
|
|
|
|
configure_systemd() {
|
|
if [ "$1" -eq 1 ]
|
|
then
|
|
preset_units /usr/lib/systemd/system-preset/$qubes_preset_file initial
|
|
changed=true
|
|
else
|
|
preset_units /usr/lib/systemd/system-preset/$qubes_preset_file upgrade
|
|
changed=true
|
|
# Upgrade path - now qubes-iptables is used instead
|
|
for svc in iptables ip6tables
|
|
do
|
|
if [ -f "$svc".service ]
|
|
then
|
|
systemctl --no-reload preset "$svc".service
|
|
changed=true
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ "$1" -eq 1 ]
|
|
then
|
|
# First install.
|
|
# Set default "runlevel".
|
|
# FIXME: this ought to be done via kernel command line.
|
|
# The fewer deviations of the template from the seed
|
|
# image, the better.
|
|
rm -f /etc/systemd/system/default.target
|
|
ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
|
|
changed=true
|
|
fi
|
|
|
|
# remove old symlinks
|
|
if [ -L /etc/systemd/system/sysinit.target.wants/qubes-random-seed.service ]
|
|
then
|
|
rm -f /etc/systemd/system/sysinit.target.wants/qubes-random-seed.service
|
|
changed=true
|
|
fi
|
|
if [ -L /etc/systemd/system/multi-user.target.wants/qubes-mount-home.service ]
|
|
then
|
|
rm -f /etc/systemd/system/multi-user.target.wants/qubes-mount-home.service
|
|
changed=true
|
|
fi
|
|
|
|
if [ "x$changed" != "x" ]
|
|
then
|
|
systemctl daemon-reload
|
|
fi
|
|
}
|
|
|
|
######################
|
|
## Archlinux Specific Functions ##
|
|
######################
|
|
config_prependtomark() {
|
|
FILE=$1
|
|
APPENDBEFORELINE=$2
|
|
APPENDLINE=$3
|
|
grep -F -q "$APPENDLINE" "$FILE" || sed "/$APPENDBEFORELINE/i$APPENDLINE" -i "$FILE"
|
|
}
|
|
|
|
config_appendtomark() {
|
|
FILE=$1
|
|
APPENDAFTERLINE=$2
|
|
APPENDLINE=$3
|
|
grep -F -q "$APPENDLINE" "$FILE" || sed "/$APPENDAFTERLINE/a$APPENDLINE" -i "$FILE"
|
|
}
|
|
|
|
config_cleanupmark() {
|
|
FILE="$1"
|
|
BEGINMARK="$2"
|
|
ENDMARK="$3"
|
|
if grep -F -q "$BEGINMARK" "$FILE"; then
|
|
if grep -F -q "$ENDMARK" "$FILE"; then
|
|
cp "$FILE" "$FILE.qubes-update-orig"
|
|
sed -i -e "/^$BEGINMARK$/,/^$ENDMARK$/{
|
|
/^$ENDMARK$/b
|
|
/^$BEGINMARK$/!d
|
|
}" "$FILE"
|
|
rm -f "$FILE.qubes-update-orig"
|
|
else
|
|
echo "ERROR: found $BEGINMARK marker but not $ENDMARK in $FILE. Please cleanup this file manually."
|
|
fi
|
|
elif grep -F -q "$ENDMARK" "$FILE"; then
|
|
echo "ERROR: found $ENDMARK marker but not $BEGINMARK in $FILE. Please cleanup this file manually."
|
|
fi
|
|
}
|
|
|
|
update_finalize() {
|
|
# Archlinux specific: If marker exists, cleanup text between begin and end marker
|
|
QUBES_MARKER="### QUBES CONFIG MARKER ###"
|
|
if grep -F -q "$QUBES_MARKER" /etc/pacman.conf; then
|
|
config_prependtomark "/etc/pacman.conf" "# REPOSITORIES" "### QUBES CONFIG END MARKER ###"
|
|
config_cleanupmark "/etc/pacman.conf" "$QUBES_MARKER" "### QUBES CONFIG END MARKER ###"
|
|
# Else, add qubes config block marker
|
|
else
|
|
config_prependtomark "/etc/pacman.conf" "# REPOSITORIES" "$QUBES_MARKER"
|
|
config_prependtomark "/etc/pacman.conf" "# REPOSITORIES" "### QUBES CONFIG END MARKER ###"
|
|
fi
|
|
|
|
# Include /etc/pacman.d drop-in directory
|
|
config_appendtomark "/etc/pacman.conf" "$QUBES_MARKER" "Include = /etc/pacman.d/*.conf"
|
|
|
|
/usr/lib/qubes/update-proxy-configs
|
|
|
|
# Archlinux specific: Update pam.d configuration for su to enable systemd-login wrapper
|
|
# This is required as qubes-gui agent calls xinit with su -l user without initializing properly
|
|
# the user session.
|
|
# pam_unix.so can also be removed from su configuration
|
|
# as system-login (which include system-auth) already gives pam_unix.so
|
|
# with more appropriate parameters (fix the missing nullok parameter)
|
|
if grep -q pam_unix.so /etc/pam.d/su; then
|
|
echo "Fixing pam.d"
|
|
cp /etc/pam.d/qrexec /etc/pam.d/su-l
|
|
fi
|
|
|
|
# Archlinux specific: ensure tty1 is enabled
|
|
rm -f /etc/systemd/system/getty.target.wants/getty@tty*.service
|
|
systemctl enable getty\@tty1.service
|
|
|
|
systemctl daemon-reload
|
|
}
|
|
|
|
## arg 1: the new package version
|
|
post_install() {
|
|
update_qubesconfig
|
|
|
|
# do the rest of %post thing only when updating for the first time...
|
|
if [ -e /etc/init/serial.conf ] && ! [ -f /var/lib/qubes/serial.orig ] ; then
|
|
cp /etc/init/serial.conf /var/lib/qubes/serial.orig
|
|
fi
|
|
|
|
chgrp user /var/lib/qubes/dom0-updates
|
|
|
|
# Remove most of the udev scripts to speed up the VM boot time
|
|
# Just leave the xen* scripts, that are needed if this VM was
|
|
# ever used as a net backend (e.g. as a VPN domain in the future)
|
|
#echo "--> Removing unnecessary udev scripts..."
|
|
mkdir -p /var/lib/qubes/removed-udev-scripts
|
|
for f in /etc/udev/rules.d/*
|
|
do
|
|
if [ "$(basename "$f")" == "xen-backend.rules" ] ; then
|
|
continue
|
|
fi
|
|
|
|
if [ "$(basename "$f")" == "50-qubes-misc.rules" ] ; then
|
|
continue
|
|
fi
|
|
|
|
if echo "$f" | grep -q qubes; then
|
|
continue
|
|
fi
|
|
|
|
mv "$f" /var/lib/qubes/removed-udev-scripts/
|
|
done
|
|
|
|
mkdir -p /rw
|
|
|
|
configure_notification-daemon
|
|
configure_selinux
|
|
|
|
configure_systemd 0
|
|
|
|
update_finalize
|
|
}
|
|
|
|
## arg 1: the new package version
|
|
## arg 2: the old package version
|
|
post_upgrade() {
|
|
update_qubesconfig
|
|
|
|
configure_notification-daemon
|
|
configure_selinux
|
|
|
|
configure_systemd 1
|
|
|
|
|
|
update_finalize
|
|
}
|
|
|
|
######################
|
|
## Remove functions ##
|
|
######################
|
|
|
|
## arg 1: the old package version
|
|
pre_remove() {
|
|
# no more packages left
|
|
if [ -e /var/lib/qubes/fstab.orig ] ; then
|
|
mv /var/lib/qubes/fstab.orig /etc/fstab
|
|
fi
|
|
mv /var/lib/qubes/removed-udev-scripts/* /etc/udev/rules.d/
|
|
if [ -e /var/lib/qubes/serial.orig ] ; then
|
|
mv /var/lib/qubes/serial.orig /etc/init/serial.conf
|
|
fi
|
|
|
|
if [ "$1" -eq 0 ] ; then
|
|
# Run this only during uninstall.
|
|
# Save the preset file to later use it to re-preset services there
|
|
# once the Qubes OS preset file is removed.
|
|
mkdir -p /run/qubes-uninstall
|
|
cp -f /usr/lib/systemd/system-preset/$qubes_preset_file /run/qubes-uninstall/
|
|
cp -f /usr/lib/systemd/system-preset/$qubes_preset_file /run/qubes-uninstall/
|
|
fi
|
|
}
|
|
|
|
## arg 1: the old package version
|
|
post_remove() {
|
|
changed=
|
|
|
|
if [ -d /run/qubes-uninstall ]
|
|
then
|
|
# We have a saved preset file (or more).
|
|
# Re-preset the units mentioned there.
|
|
restore_units /run/qubes-uninstall/$qubes_preset_file
|
|
rm -rf /run/qubes-uninstall
|
|
changed=true
|
|
fi
|
|
|
|
if [ "x$changed" != "x" ]
|
|
then
|
|
systemctl daemon-reload
|
|
fi
|
|
|
|
|
|
if [ -L /lib/firmware/updates ] ; then
|
|
rm /lib/firmware/updates
|
|
fi
|
|
|
|
rm -rf /var/lib/qubes/xdg
|
|
|
|
for srv in qubes-sysinit qubes-misc-post qubes-mount-dirs qubes-qrexec-agent; do
|
|
systemctl disable $srv.service
|
|
done
|
|
}
|