diff --git a/debian/compat b/debian/compat index ec63514..f599e28 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -9 +10 diff --git a/debian/control b/debian/control index d02dd12..6984956 100644 --- a/debian/control +++ b/debian/control @@ -3,22 +3,21 @@ Section: admin Priority: extra Maintainer: unman Build-Depends: + debhelper, libpam0g-dev, libqubes-rpc-filecopy-dev (>= 3.1.3), libvchan-xen-dev, python3, python3-setuptools, - debhelper, quilt, libxen-dev, pkg-config, - dh-systemd (>= 1.5), dh-python, lsb-release, xserver-xorg-dev, config-package-dev, pandoc, -Standards-Version: 3.9.5 +Standards-Version: 4.4.0.1 Homepage: https://www.qubes-os.org Vcs-Git: https://github.com/QubesOS/qubes-core-agent-linux diff --git a/debian/qubes-core-agent-networking.install b/debian/qubes-core-agent-networking.install index 7f371ef..c26f251 100644 --- a/debian/qubes-core-agent-networking.install +++ b/debian/qubes-core-agent-networking.install @@ -11,8 +11,12 @@ etc/xen/scripts/vif-route-qubes lib/systemd/system/qubes-firewall.service lib/systemd/system/qubes-iptables.service lib/systemd/system/qubes-network.service +lib/systemd/system/qubes-network-uplink.service +lib/systemd/system/qubes-network-uplink@.service lib/systemd/system/qubes-updates-proxy.service usr/lib/qubes/init/network-proxy-setup.sh +usr/lib/qubes/init/network-proxy-stop.sh +usr/lib/qubes/init/network-uplink-wait.sh usr/lib/qubes/init/qubes-iptables usr/lib/qubes/iptables-updates-proxy usr/lib/qubes/qubes-setup-dnat-to-ns diff --git a/init/functions b/init/functions index 2582b4d..ba05485 100644 --- a/init/functions +++ b/init/functions @@ -118,7 +118,7 @@ umount_retry() { get_mac_from_iface() { local iface="$1" - local mac + local mac= if [ "x$iface" != "x" ] && [ -e "/sys/class/net/$iface" ]; then mac="$(cat "/sys/class/net/$iface/address")" fi @@ -127,7 +127,7 @@ get_mac_from_iface() { get_iface_from_mac() { local mac="$1" - local iface + local iface= if [ "x$mac" != "x" ]; then iface="$(ip -o link | grep -i "$mac" | awk '{print $2}' | cut -d ':' -f1)" fi @@ -141,7 +141,7 @@ get_qubes_managed_iface() { qubes_iface="$(get_iface_from_mac "$mac")" if [ "x$qubes_iface" != "x" ]; then echo "$qubes_iface" - else + elif [ -e /sys/class/net/eth0 ]; then echo eth0 fi } diff --git a/network/ip6tables-enabled b/network/ip6tables-enabled index fc5aec1..d2e4a56 100644 --- a/network/ip6tables-enabled +++ b/network/ip6tables-enabled @@ -26,6 +26,7 @@ COMMIT -A INPUT -m state --state INVALID -j DROP -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A INPUT ! -i vif+ -p udp -s fe80::/64 -d fe80::/64 --dport 546 -j ACCEPT -A INPUT -i vif+ -p icmpv6 --icmpv6-type router-advertisement -j DROP -A INPUT -i vif+ -p icmpv6 --icmpv6-type redirect -j DROP -A INPUT -i vif+ -p icmpv6 -j ACCEPT diff --git a/network/setup-ip b/network/setup-ip index 917b028..07c8568 100755 --- a/network/setup-ip +++ b/network/setup-ip @@ -3,6 +3,15 @@ # Source Qubes library. # shellcheck disable=SC1091 . /usr/lib/qubes/init/functions +set -uo pipefail + +add_host_route () { + /sbin/ip -- route replace to unicast "$1" dev "$2" onlink scope host +} + +add_default_route () { + /sbin/ip -- route replace to unicast default via "$1" dev "$2" onlink +} configure_network() { local MAC="$1" @@ -15,22 +24,27 @@ configure_network() { local gateway6="$8" local primary_dns="$9" local secondary_dns="${10}" + local netvm_mac=fe:ff:ff:ff:ff:ff /sbin/ifconfig "$INTERFACE" "$ip" netmask "$netmask" + /sbin/ip -- neighbour replace to "$gateway" dev "$INTERFACE" \ + lladdr "$netvm_mac" nud permanent if [ -n "$ip6" ]; then /sbin/ifconfig "$INTERFACE" add "$ip6/$netmask6" + /sbin/ip -- neighbour replace to "$gateway6" dev "$INTERFACE" \ + lladdr "$netvm_mac" nud permanent fi /sbin/ifconfig "$INTERFACE" up if [ -n "$gateway" ]; then - /sbin/route add -host "$gateway" dev "$INTERFACE" + add_host_route "$gateway" "$INTERFACE" if [ -n "$gateway6" ] && ! echo "$gateway6" | grep -q "^fe80:"; then - /sbin/route -6 add "$gateway6/$netmask6" dev "$INTERFACE" + add_host_route "$gateway6/$netmask6" "$INTERFACE" fi if ! qsvc disable-default-route ; then - /sbin/route add default gw "$gateway" + add_default_route "$gateway" "$INTERFACE" if [ -n "$gateway6" ]; then - /sbin/route -6 add default gw "$gateway6" dev "$INTERFACE" + add_default_route "$gateway6" "$INTERFACE" fi fi fi @@ -159,67 +173,80 @@ qubes_ip_change_hook() { have_qubesdb || exit 0 -if [ -n "$INTERFACE" ]; then - if [ "$ACTION" == "add" ]; then - MAC="$(get_mac_from_iface "$INTERFACE")" - if [ -n "$MAC" ]; then - ip="$(/usr/bin/qubesdb-read "/net-config/$MAC/ip" 2> /dev/null)" - ip6="$(/usr/bin/qubesdb-read "/net-config/$MAC/ip6" 2> /dev/null)" - netmask="$(/usr/bin/qubesdb-read "/net-config/$MAC/netmask" 2> /dev/null)" - netmask6="$(/usr/bin/qubesdb-read "/net-config/$MAC/netmask6" 2> /dev/null)" - gateway="$(/usr/bin/qubesdb-read "/net-config/$MAC/gateway" 2> /dev/null)" - gateway6="$(/usr/bin/qubesdb-read "/net-config/$MAC/gateway6" 2> /dev/null)" +ACTION="$1" +INTERFACE="$2" - # Handle legacy values - LEGACY_MAC="$(/usr/bin/qubesdb-read /qubes-mac 2> /dev/null)" - if [ "$MAC" == "$LEGACY_MAC" ] || [ -z "$LEGACY_MAC" ]; then - if [ -z "$ip" ]; then - ip="$(/usr/bin/qubesdb-read /qubes-ip 2> /dev/null)" - fi - if [ -z "$ip6" ]; then - ip6="$(/usr/bin/qubesdb-read /qubes-ip6 2> /dev/null)" - fi - if [ -z "$gateway" ]; then - gateway="$(/usr/bin/qubesdb-read /qubes-gateway 2> /dev/null)" - fi - if [ -z "$gateway6" ]; then - gateway6="$(/usr/bin/qubesdb-read /qubes-gateway6 2> /dev/null)" - fi +if [ -z "$INTERFACE" ]; then + echo "Missing INTERFACE argument" >&2 + exit 1 +fi + +if [ "$ACTION" == "add" ]; then + MAC="$(get_mac_from_iface "$INTERFACE")" + if [ -n "$MAC" ]; then + ip="$(/usr/bin/qubesdb-read "/net-config/$MAC/ip" 2> /dev/null)" || ip= + ip6="$(/usr/bin/qubesdb-read "/net-config/$MAC/ip6" 2> /dev/null)" || ip6= + netmask="$(/usr/bin/qubesdb-read "/net-config/$MAC/netmask" 2> /dev/null)" || netmask= + netmask6="$(/usr/bin/qubesdb-read "/net-config/$MAC/netmask6" 2> /dev/null)" || netmask6= + gateway="$(/usr/bin/qubesdb-read "/net-config/$MAC/gateway" 2> /dev/null)" || gateway= + gateway6="$(/usr/bin/qubesdb-read "/net-config/$MAC/gateway6" 2> /dev/null)" || gateway6= + + # Handle legacy values + LEGACY_MAC="$(/usr/bin/qubesdb-read /qubes-mac 2> /dev/null)" || LEGACY_MAC= + if [ "$MAC" == "$LEGACY_MAC" ] || [ -z "$LEGACY_MAC" ]; then + if [ -z "$ip" ]; then + ip="$(/usr/bin/qubesdb-read /qubes-ip 2> /dev/null)" || ip= fi - - if [ -z "$netmask" ]; then - netmask="255.255.255.255" + if [ -z "$ip6" ]; then + ip6="$(/usr/bin/qubesdb-read /qubes-ip6 2> /dev/null)" || ip6= fi - if [ -z "$netmask6" ]; then - netmask6="128" + if [ -z "$gateway" ]; then + gateway="$(/usr/bin/qubesdb-read /qubes-gateway 2> /dev/null)" || gateway= fi - - primary_dns=$(/usr/bin/qubesdb-read /qubes-primary-dns 2>/dev/null) - secondary_dns=$(/usr/bin/qubesdb-read /qubes-secondary-dns 2>/dev/null) - - if [ -n "$ip" ]; then - /sbin/ethtool -K "$INTERFACE" sg off - /sbin/ethtool -K "$INTERFACE" tx off - - # If NetworkManager is enabled, let it configure the network - if qsvc network-manager && [ -e /usr/bin/nmcli ]; then - configure_network_nm "$MAC" "$INTERFACE" "$ip" "$ip6" "$netmask" "$netmask6" "$gateway" "$gateway6" "$primary_dns" "$secondary_dns" - else - configure_network "$MAC" "$INTERFACE" "$ip" "$ip6" "$netmask" "$netmask6" "$gateway" "$gateway6" "$primary_dns" "$secondary_dns" - fi - - network=$(qubesdb-read /qubes-netvm-network 2>/dev/null) - if [ -n "$network" ]; then - if ! qsvc disable-dns-server; then - configure_qubes_ns - fi - qubes_ip_change_hook - fi + if [ -z "$gateway6" ]; then + gateway6="$(/usr/bin/qubesdb-read /qubes-gateway6 2> /dev/null)" || gateway6= + fi + fi + + if [ -z "$netmask" ]; then + netmask="255.255.255.255" + fi + if [ -z "$netmask6" ]; then + netmask6="128" + fi + + primary_dns=$(/usr/bin/qubesdb-read /qubes-primary-dns 2>/dev/null) || primary_dns= + secondary_dns=$(/usr/bin/qubesdb-read /qubes-secondary-dns 2>/dev/null) || secondary_dns= + + if [ -n "$ip" ]; then + /sbin/ethtool -K "$INTERFACE" sg off + /sbin/ethtool -K "$INTERFACE" tx off + + # If NetworkManager is enabled, let it configure the network + if qsvc network-manager && [ -e /usr/bin/nmcli ]; then + configure_network_nm "$MAC" "$INTERFACE" "$ip" "$ip6" "$netmask" "$netmask6" "$gateway" "$gateway6" "$primary_dns" "$secondary_dns" + else + configure_network "$MAC" "$INTERFACE" "$ip" "$ip6" "$netmask" "$netmask6" "$gateway" "$gateway6" "$primary_dns" "$secondary_dns" + fi + + network=$(qubesdb-read /qubes-netvm-network 2>/dev/null) || network= + if [ -n "$network" ]; then + if ! qsvc disable-dns-server; then + configure_qubes_ns + fi + qubes_ip_change_hook fi fi - elif [ "$ACTION" == "remove" ]; then - # If exists, we delete NetworkManager configuration file to prevent duplicate entries - nm_config="/etc/NetworkManager/system-connections/qubes-uplink-$INTERFACE" - rm -rf "$nm_config" fi +elif [ "$ACTION" == "remove" ]; then + # make sure network is disabled, especially on shutdown, to prevent + # leaks when firewall will get stopped too + ip link set "$INTERFACE" down 2>/dev/null || : + + # If exists, we delete NetworkManager configuration file to prevent duplicate entries + nm_config="/etc/NetworkManager/system-connections/qubes-uplink-$INTERFACE" + rm -rf "$nm_config" +else + echo "Invalid action '$ACTION'" >&2 + exit 1 fi diff --git a/network/udev-qubes-network.rules b/network/udev-qubes-network.rules index 0ae83b2..fde5fe9 100644 --- a/network/udev-qubes-network.rules +++ b/network/udev-qubes-network.rules @@ -1,5 +1,5 @@ # old udev has ENV{ID_NET_DRIVER} -SUBSYSTEMS=="xen", KERNEL=="eth*", ACTION=="add", ENV{ID_NET_DRIVER}=="vif", RUN+="/usr/lib/qubes/setup-ip" -SUBSYSTEMS=="net", KERNEL=="eth*", ACTION=="remove", ENV{ID_NET_DRIVER}=="vif", RUN+="/usr/lib/qubes/setup-ip" +SUBSYSTEMS=="xen", KERNEL=="eth*", ACTION=="add", ENV{ID_NET_DRIVER}=="vif", ENV{SYSTEMD_WANTS}+="qubes-network-uplink@%k.service" +SUBSYSTEMS=="net", KERNEL=="eth*", ACTION=="remove", ENV{ID_NET_DRIVER}=="vif", ENV{SYSTEMD_WANTS}+="qubes-network-uplink@%k.service" # new udev has DRIVERS -SUBSYSTEMS=="xen", KERNEL=="eth*", ACTION=="add", DRIVERS=="vif", RUN+="/usr/lib/qubes/setup-ip" +SUBSYSTEMS=="xen", KERNEL=="eth*", ACTION=="add", DRIVERS=="vif", ENV{SYSTEMD_WANTS}+="qubes-network-uplink@%k.service" diff --git a/network/vif-qubes-nat.sh b/network/vif-qubes-nat.sh index 9833e45..0c38731 100755 --- a/network/vif-qubes-nat.sh +++ b/network/vif-qubes-nat.sh @@ -26,6 +26,7 @@ netns_appvm_if="${vif}" # '----------------------------------' # +readonly netvm_mac=fe:ff:ff:ff:ff:ff function run { @@ -35,7 +36,12 @@ function run function netns { - run ip netns exec "$netns" "$@" + if [[ "$1" = 'ip' ]]; then + shift + run ip -n "$netns" "$@" + else + run ip netns exec "$netns" "$@" + fi } run ip addr flush dev "$netns_appvm_if" @@ -46,9 +52,12 @@ if test "$command" == online; then run ip link set "$netns_appvm_if" netns "$netns" # keep the same MAC as the real vif interface, so NetworkManager will still - # ignore it - run ip link add "$netns_netvm_if" type veth peer name "$netvm_if" address fe:ff:ff:ff:ff:ff - run ip link set "$netns_netvm_if" netns "$netns" + # ignore it. + # for the peer interface, make sure that it has the same MAC address + # as the actual VM, so that our neighbor entry works. + run ip link add name "$netns_netvm_if" address "$mac" type veth \ + peer name "$netvm_if" address "$netvm_mac" + run ip link set dev "$netns_netvm_if" netns "$netns" netns ip6tables -t raw -I PREROUTING -j DROP netns ip6tables -P INPUT DROP @@ -85,6 +94,8 @@ if test "$command" == online; then netns iptables -t nat -I POSTROUTING -o "$netns_appvm_if" -s "$netvm_dns2_ip" -j SNAT --to-source "$appvm_dns2_ip" fi + netns ip neighbour add to "$appvm_ip" dev "$netns_appvm_if" lladdr "$mac" nud permanent + netns ip neighbour add to "$netvm_gw_ip" dev "$netns_netvm_if" lladdr "$netvm_mac" nud permanent netns ip addr add "$netvm_ip" dev "$netns_netvm_if" netns ip addr add "$appvm_gw_ip" dev "$netns_appvm_if" @@ -94,10 +105,4 @@ if test "$command" == online; then netns ip route add "$appvm_ip" dev "$netns_appvm_if" src "$appvm_gw_ip" netns ip route add "$netvm_gw_ip" dev "$netns_netvm_if" src "$netvm_ip" netns ip route add default via "$netvm_gw_ip" dev "$netns_netvm_if" src "$netvm_ip" - - - #run ip addr add "$netvm_gw_ip" dev "$netvm_if" - #run ip link set "$netvm_if" up - #run ip route add "$netvm_ip" dev "$netvm_if" src "$netvm_gw_ip" fi - diff --git a/network/vif-route-qubes b/network/vif-route-qubes index 724d22a..1cf43d2 100755 --- a/network/vif-route-qubes +++ b/network/vif-route-qubes @@ -24,6 +24,7 @@ dir=$(dirname "$0") # shellcheck disable=SC1091,SC1090 . "$dir/vif-common.sh" +set -o pipefail #main_ip=$(dom0_ip) # Network Hooks for triggering supplementary actions on AppVM connect @@ -77,30 +78,34 @@ if [ "${ip}" ]; then appvm_ip="$(qubesdb-read "/mapped-ip/$ip4/visible-ip" 2>/dev/null || :)" fi -# Apply NAT if IP visible from the VM is different than the "real" one -# See vif-qubes-nat.sh for details -# XXX: supported only for the first IPv4 address, IPv6 is dropped if this -# feature is enabled -if [ -n "$appvm_ip" ] && [ -n "$appvm_gw_ip" ] && [ "$appvm_ip" != "$netvm_ip" ]; then - # shellcheck disable=SC2154 - if test "$command" == online; then - # shellcheck disable=SC2154 - echo 1 >"/proc/sys/net/ipv4/conf/${vif}/proxy_arp" - fi +readonly max_domid=32752 - # shellcheck source=network/vif-qubes-nat.sh - . "$dir/vif-qubes-nat.sh" +# if domid is 0 something is seriously wrong, so don’t check for that case +if ! [[ $vif =~ ^vif([1-9][0-9]{,4})\.(0|[1-9][0-9]*)$ ]]; then + printf 'Bad interface name %q\n' "$vif">&2 + exit 1 fi +domid=${BASH_REMATCH[1]} sub=${BASH_REMATCH[2]} + +# metric must be positive, but prefer later interface +# 32752 is max XID aka domid +if (( domid > max_domid )); then + printf %s\\n "domid $domid too large" + exit 1 +fi +metric=$(( max_domid - domid )) + # shellcheck disable=SC2154 case "$command" in online) - ifconfig "${vif}" up echo 1 >"/proc/sys/net/ipv4/conf/${vif}/proxy_arp" ipcmd='add' iptables_cmd='-I PREROUTING 1' cmdprefix='' ipv6_disabled=$(cat /proc/sys/net/ipv6/conf/"${vif}"/disable_ipv6 || echo 1) + # without a MAC address we will fail later with a confusing error + mac=$(xenstore-read "backend/vif/$domid/$sub/mac") || exit 1 ;; offline) do_without_error ifdown "${vif}" @@ -112,12 +117,46 @@ case "$command" in ;; esac -domid=${vif/vif/} -domid=${domid/.*/} -# metric must be possitive, but prefer later interface -# 32752 is max XID aka domid -metric=$(( 32752 - domid )) +# Apply NAT if IP visible from the VM is different than the "real" one +# See vif-qubes-nat.sh for details +# XXX: supported only for the first IPv4 address, IPv6 is dropped if this +# feature is enabled +if [ -n "$appvm_ip" ] && [ -n "$appvm_gw_ip" ] && [ "$appvm_ip" != "$netvm_ip" ]; then + # shellcheck source=network/vif-qubes-nat.sh + . "$dir/vif-qubes-nat.sh" +fi +# add anti-spoofing rules before enabling the interface +if [ "${ip}" ]; then + # If we’ve been given a list of IP addresses, then add routes from us to + # the VMs we serve using those addresses. + for addr in ${ip}; + do + if [[ "$addr" = *:* ]]; then + ipt=ip6tables-restore + else + ipt=iptables-restore + fi + printf '%s\n' "*raw" \ + "$iptables_cmd -i ${vif} ! -s ${addr} -j DROP" \ + "$iptables_cmd ! -i vif+ -s ${addr} -j DROP" \ + "COMMIT" | \ + ${cmdprefix} $ipt --noflush $ipt_arg + if [[ "$command" = 'online' ]]; then + ip -- neighbour "${ipcmd}" to "${addr}" \ + dev "${vif}" lladdr "$mac" nud permanent + fi + done + # if no IPv6 is assigned, block all IPv6 traffic on that interface + if ! [[ "$ip" = *:* ]]; then + echo -e "*raw\\n$iptables_cmd -i ${vif} -j DROP\\nCOMMIT" | \ + ${cmdprefix} ip6tables-restore --noflush $ipt_arg + fi +fi + +if [ "$command" = "online" ]; then + ifconfig "${vif}" up +fi if [ "${ip}" ]; then # If we've been given a list of IP addresses, then add routes from dom0 to @@ -129,21 +168,9 @@ if [ "${ip}" ]; then continue fi ${cmdprefix} ip route "${ipcmd}" "${addr}" dev "${vif}" metric "$metric" - if [[ "$addr" = *:* ]]; then - ipt=ip6tables-restore - else - ipt=iptables-restore - fi - echo -e "*raw\\n$iptables_cmd -i ${vif} ! -s ${addr} -j DROP\\nCOMMIT" | \ - ${cmdprefix} $ipt --noflush $ipt_arg network_hooks "${command}" "${vif}" "${addr}" done - # if no IPv6 is assigned, block all IPv6 traffic on that interface - if ! [[ "$ip" = *:* ]]; then - echo -e "*raw\\n$iptables_cmd -i ${vif} -j DROP\\nCOMMIT" | \ - ${cmdprefix} ip6tables-restore --noflush $ipt_arg - fi ${cmdprefix} ip addr "${ipcmd}" "${back_ip}/32" dev "${vif}" if [ "${back_ip6}" ] && [[ "${back_ip6}" != "fe80:"* ]] && [[ "$ipv6_disabled" != 1 ]]; then ${cmdprefix} ip addr "${ipcmd}" "${back_ip6}/128" dev "${vif}" diff --git a/qubes-rpc/qubes.GetAppmenus b/qubes-rpc/qubes.GetAppmenus index 2422a9b..386918f 100755 --- a/qubes-rpc/qubes.GetAppmenus +++ b/qubes-rpc/qubes.GetAppmenus @@ -9,12 +9,8 @@ # Reload scripts in /etc/profile.d/, in case they register additional # directories in XDG_DATA_DIRS and we forgot them # (e.g. because we are running under sudo). -for i in /etc/profile.d/*.sh ; do - if [ -r "$i" ]; then - # shellcheck disable=SC1090 - . "$i" >/dev/null - fi -done +# shellcheck disable=SC1091 +source /etc/profile if [ -z "$XDG_DATA_HOME" ]; then user="$(whoami)" diff --git a/qubes-rpc/qubes.ShowInTerminal b/qubes-rpc/qubes.ShowInTerminal index d8cb758..f8b5f95 100644 --- a/qubes-rpc/qubes.ShowInTerminal +++ b/qubes-rpc/qubes.ShowInTerminal @@ -1,10 +1,11 @@ #!/bin/bash -- set -eu +umask 0077 tmpdir="$(mktemp -d)" -if [[ $tmpdir =~ \" ]]; then - echo 'Error: non admissible character detected in sock path.' +if ! [[ $tmpdir =~ ^/[/A-Za-z0-9._-]+$ ]]; then + echo 'Error: non admissible character detected in sock path.'>&2 exit 1 fi diff --git a/rpm_spec/core-agent.spec.in b/rpm_spec/core-agent.spec.in index 5b51a8c..9c454c6 100644 --- a/rpm_spec/core-agent.spec.in +++ b/rpm_spec/core-agent.spec.in @@ -797,8 +797,12 @@ rm -f %{name}-%{version} /lib/systemd/system/qubes-firewall.service /lib/systemd/system/qubes-iptables.service /lib/systemd/system/qubes-network.service +/lib/systemd/system/qubes-network-uplink.service +/lib/systemd/system/qubes-network-uplink@.service /lib/systemd/system/qubes-updates-proxy.service /usr/lib/qubes/init/network-proxy-setup.sh +/usr/lib/qubes/init/network-proxy-stop.sh +/usr/lib/qubes/init/network-uplink-wait.sh /usr/lib/qubes/init/qubes-iptables /usr/lib/qubes/iptables-updates-proxy /usr/lib/qubes/qubes-setup-dnat-to-ns diff --git a/vm-systemd/75-qubes-vm.preset b/vm-systemd/75-qubes-vm.preset index a2f6cd8..c0fcbe3 100644 --- a/vm-systemd/75-qubes-vm.preset +++ b/vm-systemd/75-qubes-vm.preset @@ -91,6 +91,7 @@ enable qubes-update-check.timer enable qubes-misc-post.service enable qubes-updates-proxy.service enable qubes-network.service +enable qubes-network-uplink.service enable qubes-qrexec-agent.service enable qubes-mount-dirs.service enable qubes-rootfs-resize.service diff --git a/vm-systemd/NetworkManager.service.d/30_qubes.conf b/vm-systemd/NetworkManager.service.d/30_qubes.conf index 047cc22..5f598a1 100644 --- a/vm-systemd/NetworkManager.service.d/30_qubes.conf +++ b/vm-systemd/NetworkManager.service.d/30_qubes.conf @@ -4,6 +4,8 @@ ConditionPathExists=/var/run/qubes-service/network-manager After=qubes-mount-dirs.service # For /var/run/qubes-service After=qubes-sysinit.service +# For configuration of qubes-provided interfaces +After=qubes-network-uplink.service [Service] ExecStartPre=/usr/lib/qubes/network-manager-prepare-conf-dir diff --git a/vm-systemd/misc-post.sh b/vm-systemd/misc-post.sh index f284efd..1ffaae0 100755 --- a/vm-systemd/misc-post.sh +++ b/vm-systemd/misc-post.sh @@ -11,15 +11,6 @@ if [ -n "$(ls -A /usr/local/lib 2>/dev/null)" ] || \ ldconfig fi -# 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 -QUBES_MANAGED_IFACE="$(get_qubes_managed_iface)" -if [ "x$QUBES_MANAGED_IFACE" != "x" ]; then -INTERFACE="$QUBES_MANAGED_IFACE" ACTION="add" /usr/lib/qubes/setup-ip -fi - if [ -x /rw/config/rc.local ] ; then /rw/config/rc.local fi diff --git a/vm-systemd/network-proxy-stop.sh b/vm-systemd/network-proxy-stop.sh new file mode 100755 index 0000000..4ef924e --- /dev/null +++ b/vm-systemd/network-proxy-stop.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +echo 0 > /proc/sys/net/ipv4/ip_forward +# disable also IPv6 forwarding, if IPv6 applicable +if [ -w /proc/sys/net/ipv6/conf/all/forwarding ]; then + echo 0 > /proc/sys/net/ipv6/conf/all/forwarding +fi diff --git a/vm-systemd/network-uplink-wait.sh b/vm-systemd/network-uplink-wait.sh new file mode 100644 index 0000000..bb0bc34 --- /dev/null +++ b/vm-systemd/network-uplink-wait.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# Source Qubes library. +# shellcheck source=init/functions +. /usr/lib/qubes/init/functions + +# Setup IP address at specific time of system boot, instead of asynchronously +# by udev +QUBES_MANAGED_IFACE="$(get_qubes_managed_iface)" +if [ "x$QUBES_MANAGED_IFACE" != "x" ]; then + # systemd does not support conditional After= dependencies, nor a tool to + # just wait for the unit to be activated + # if the network interface is expected, use `systemctl start` to wait for + # it to be started - it would be started by udev (SYSTEMD_WANTS) anyway + systemctl start "qubes-network-uplink@$QUBES_MANAGED_IFACE.service" +fi diff --git a/vm-systemd/qubes-early-vm-config.service b/vm-systemd/qubes-early-vm-config.service index 36601b6..dddbc49 100644 --- a/vm-systemd/qubes-early-vm-config.service +++ b/vm-systemd/qubes-early-vm-config.service @@ -1,7 +1,7 @@ [Unit] Description=Early Qubes VM settings DefaultDependencies=no -Before=sysinit.target +Before=sysinit.target network-pre.target After=local-fs.target qubes-db.service [Service] diff --git a/vm-systemd/qubes-network-uplink.service b/vm-systemd/qubes-network-uplink.service new file mode 100644 index 0000000..acf8649 --- /dev/null +++ b/vm-systemd/qubes-network-uplink.service @@ -0,0 +1,11 @@ +[Unit] +Description=Qubes network uplink wait +Before=network.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/lib/qubes/init/network-uplink-wait.sh + +[Install] +WantedBy=multi-user.target diff --git a/vm-systemd/qubes-network-uplink@.service b/vm-systemd/qubes-network-uplink@.service new file mode 100644 index 0000000..74bf689 --- /dev/null +++ b/vm-systemd/qubes-network-uplink@.service @@ -0,0 +1,11 @@ +[Unit] +Description=Qubes network uplink (%i) setup +After=network-pre.target qubes-iptables.service +After=sys-subsystem-net-devices-%i.device +BindsTo=sys-subsystem-net-devices-%i.device + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/lib/qubes/setup-ip add "%i" +ExecStop=/usr/lib/qubes/setup-ip remove "%i" diff --git a/vm-systemd/qubes-network.service b/vm-systemd/qubes-network.service index c5aa410..5281bf1 100644 --- a/vm-systemd/qubes-network.service +++ b/vm-systemd/qubes-network.service @@ -8,6 +8,7 @@ After=network-pre.target qubes-iptables.service Type=oneshot RemainAfterExit=yes ExecStart=/usr/lib/qubes/init/network-proxy-setup.sh +ExecStop=/usr/lib/qubes/init/network-proxy-stop.sh [Install] WantedBy=multi-user.target