519e82b7c0
... if it doesn't exist. The /qubes-mac qubesdb entry is present on Qubes 4.1, but not 4.0. It is ok to depend on it here, but keep safer fallback if this code would need to be backported.
232 lines
6.6 KiB
Bash
232 lines
6.6 KiB
Bash
#!/bin/bash
|
|
|
|
# Location of files which contains list of protected files
|
|
PROTECTED_FILE_LIST='/etc/qubes/protected-files.d'
|
|
PER_VM_PROTECTED_FILE_LIST='/rw/config/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 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
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() {
|
|
[ "$(qubesdb-read /type)" = "DispVM" ]
|
|
}
|
|
|
|
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() {
|
|
local seed
|
|
seed=$(qubesdb-read /qubes-random-seed)
|
|
echo "$seed" | base64 -d > /dev/urandom
|
|
qubesdb-rm /qubes-random-seed
|
|
}
|
|
|
|
is_protected_file() {
|
|
local ret=1
|
|
local pfilelist
|
|
for pfilelist in "$PROTECTED_FILE_LIST" "$PER_VM_PROTECTED_FILE_LIST" ; do
|
|
if test -d "$pfilelist" ; then
|
|
# If this succeeds, we return immediately to the caller.
|
|
# If not, we let the loop continue.
|
|
grep -Fxrq --exclude='*.rpmsave' --exclude='*~' --exclude='*.rpmnew' --exclude='*.rpmold' -- "${1}" "$pfilelist" 2>/dev/null && return 0 || ret="$?"
|
|
fi
|
|
done
|
|
return "$ret"
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
get_mac_from_iface() {
|
|
local iface="$1"
|
|
local mac=
|
|
if [ "x$iface" != "x" ] && [ -e "/sys/class/net/$iface" ]; then
|
|
mac="$(cat "/sys/class/net/$iface/address")"
|
|
fi
|
|
echo "$mac"
|
|
}
|
|
|
|
get_iface_from_mac() {
|
|
local mac="$1"
|
|
local iface=
|
|
if [ "x$mac" != "x" ]; then
|
|
iface="$(ip -o link | grep -i "$mac" | awk '{print $2}' | cut -d ':' -f1)"
|
|
fi
|
|
echo "$iface"
|
|
}
|
|
|
|
get_qubes_managed_iface() {
|
|
local mac
|
|
local qubes_iface
|
|
mac="$(qubesdb-read /qubes-mac 2> /dev/null)"
|
|
qubes_iface="$(get_iface_from_mac "$mac")"
|
|
if [ "x$qubes_iface" != "x" ]; then
|
|
echo "$qubes_iface"
|
|
elif [ -e /sys/class/net/eth0 ]; then
|
|
echo eth0
|
|
fi
|
|
}
|
|
|
|
# Based on: https://forums.gentoo.org/viewtopic-t-888736-start-0.html
|
|
get_prefix_from_subnet() {
|
|
local subnet="$1"
|
|
local x=${subnet##*255.}
|
|
set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) "${x%%.*}"
|
|
x=${1%%$3*}
|
|
prefix=$(( $2 + (${#x}/4) ))
|
|
|
|
if [ "x$prefix" != "x" ]; then
|
|
echo "$prefix"
|
|
else
|
|
echo "32"
|
|
fi
|
|
}
|
|
|
|
initialize_home() {
|
|
local home_root
|
|
local mode
|
|
#local user
|
|
local uid
|
|
local gid
|
|
local homedir
|
|
local homedirwithouthome
|
|
local pair
|
|
local homedir_uid
|
|
local homedir_gid
|
|
local waitpid
|
|
local waitpids
|
|
|
|
home_root="$1"
|
|
mode="$2"
|
|
|
|
if [ -z "$home_root" ] ; then
|
|
echo "initialize_home() needs a target home root directory, such as /rw/home, as first parameter" >&2
|
|
return 64
|
|
fi
|
|
|
|
if [ "$mode" != "unconditionally" ] && [ "$mode" != "ifneeded" ] ; then
|
|
echo "initialize_home() second parameter must be 'unconditionally' or 'ifneeded'" >&2
|
|
return 64
|
|
fi
|
|
|
|
if ! [ -d "$home_root" ] ; then
|
|
echo "initialize_home: populating $home_root" >&2
|
|
mkdir -p "$home_root"
|
|
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 } ')
|
|
homedirwithouthome=${homedir#/home/}
|
|
if ! test -d "$home_root/$homedirwithouthome" || [ "$mode" = "unconditionally" ] ; then
|
|
echo "initialize_home: populating $mode $home_root/$homedirwithouthome from /etc/skel" >&2
|
|
mkdir -p "$home_root/$homedirwithouthome"
|
|
cp -af -T /etc/skel "$home_root/$homedirwithouthome"
|
|
echo "initialize_home: adjusting permissions $mode on $home_root/$homedirwithouthome" >&2
|
|
chown -R "$uid" "$home_root/$homedirwithouthome" &
|
|
waitpids="$!"
|
|
chgrp -R "$gid" "$home_root/$homedirwithouthome" &
|
|
waitpids="$waitpids $!"
|
|
chmod 700 "$home_root/$homedirwithouthome" &
|
|
waitpids="$waitpids $!"
|
|
for waitpid in $waitpids ; do wait "$waitpid" ; done ; waitpids=
|
|
fi
|
|
waitpids=
|
|
homedir_uid=$(stat --format=%u "$home_root/$homedirwithouthome")
|
|
homedir_gid=$(stat --format=%g "$home_root/$homedirwithouthome")
|
|
if [ "$uid" -ne "$homedir_uid" ]; then
|
|
echo "initialize_home: adjusting ownership on $home_root/$homedirwithouthome to $uid" >&2
|
|
find "$home_root/$homedirwithouthome" -uid "$homedir_uid" -print0 | xargs -0 chown "$uid" &
|
|
waitpids="$waitpids $!"
|
|
fi
|
|
if [ "$gid" -ne "$homedir_gid" ]; then
|
|
echo "initialize_home: adjusting groupship on $home_root/$homedirwithouthome to $gid" >&2
|
|
find "$home_root/$homedirwithouthome" -gid "$homedir_gid" -print0 | xargs -0 chgrp "$gid" &
|
|
waitpids="$waitpids $!"
|
|
fi
|
|
for waitpid in $waitpids ; do wait "$waitpid" ; done ; waitpids=
|
|
done
|
|
}
|