diff --git a/debian/qubes-core-agent-networking.install b/debian/qubes-core-agent-networking.install index 8c63f10..c26f251 100644 --- a/debian/qubes-core-agent-networking.install +++ b/debian/qubes-core-agent-networking.install @@ -11,9 +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/network/setup-ip b/network/setup-ip index 35e9fba..fd2db18 100755 --- a/network/setup-ip +++ b/network/setup-ip @@ -173,6 +173,14 @@ qubes_ip_change_hook() { have_qubesdb || exit 0 +ACTION="$1" +INTERFACE="$2" + +if [ -z "$INTERFACE" ]; then + echo "Missing INTERFACE argument" >&2 + exit 1 +fi + if [ -n "$INTERFACE" ]; then if [ "$ACTION" == "add" ]; then MAC="$(get_mac_from_iface "$INTERFACE")" @@ -232,8 +240,16 @@ if [ -n "$INTERFACE" ]; then fi 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 + 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/rpm_spec/core-agent.spec.in b/rpm_spec/core-agent.spec.in index 3e663d3..17720ab 100644 --- a/rpm_spec/core-agent.spec.in +++ b/rpm_spec/core-agent.spec.in @@ -797,9 +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/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-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-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"