diff --git a/linux/systemd/Makefile b/linux/systemd/Makefile index 3522d8ca..e0cbbf60 100644 --- a/linux/systemd/Makefile +++ b/linux/systemd/Makefile @@ -7,8 +7,6 @@ install: mkdir -p $(DESTDIR)$(UNITDIR) cp qubes-core.service $(DESTDIR)$(UNITDIR) cp qubes-vm@.service $(DESTDIR)$(UNITDIR) - cp qubes-reload-firewall@.service $(DESTDIR)$(UNITDIR) - cp qubes-reload-firewall@.timer $(DESTDIR)$(UNITDIR) cp qubes-qmemman.service $(DESTDIR)$(UNITDIR) cp qubesd.service $(DESTDIR)$(UNITDIR) install -d $(DESTDIR)$(UNITDIR)/lvm2-pvscan@.service.d diff --git a/qubes/firewall.py b/qubes/firewall.py index 4ed16149..99b56868 100644 --- a/qubes/firewall.py +++ b/qubes/firewall.py @@ -22,11 +22,12 @@ import datetime import string -import subprocess import itertools import os import socket + +import asyncio import lxml.etree import qubes @@ -543,10 +544,19 @@ class Firewall(object): rule = Rule(xml_rule) self.rules.append(rule) + def _expire_rules(self): + '''Function called to reload expired rules''' + old_rules = self.rules + self.load() + if self.rules != old_rules: + # this will both save rules skipping those expired and trigger + # QubesDB update; and possibly schedule another timer + self.save() + def save(self): '''Save firewall rules to a file''' firewall_conf = os.path.join(self.vm.dir_path, self.vm.firewall_conf) - expiring_rules_present = False + nearest_expire = False xml_root = lxml.etree.Element('firewall', version=str(2)) @@ -556,7 +566,9 @@ class Firewall(object): if rule.expire and rule.expire.expired: continue else: - expiring_rules_present = True + if nearest_expire is None or rule.expire.datetime < \ + nearest_expire: + nearest_expire = rule.expire.datetime xml_rule = lxml.etree.Element('rule') xml_rule.append(rule.xml_properties()) xml_rules.append(xml_rule) @@ -577,9 +589,13 @@ class Firewall(object): self.vm.fire_event('firewall-changed') - if expiring_rules_present and not self.vm.app.vmm.offline_mode: - subprocess.call(["sudo", "systemctl", "start", - "qubes-reload-firewall@%s.timer" % self.vm.name]) + if nearest_expire and not self.vm.app.vmm.offline_mode: + loop = asyncio.get_event_loop() + # by documentation call_at use loop.time() clock, which not + # necessary must be the same as time module; calculate delay and + # use call_later instead + expire_when = nearest_expire - datetime.datetime.now() + loop.call_later(expire_when, self._expire_rules) def qdb_entries(self, addr_family=None): '''Return firewall settings serialized for QubesDB entries diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index fbd74510..b1ffff2b 100644 --- a/rpm_spec/core-dom0.spec +++ b/rpm_spec/core-dom0.spec @@ -399,8 +399,6 @@ fi %{_unitdir}/qubes-qmemman.service %{_unitdir}/qubes-vm@.service %{_unitdir}/qubesd.service -%{_unitdir}/qubes-reload-firewall@.service -%{_unitdir}/qubes-reload-firewall@.timer %attr(2770,root,qubes) %dir /var/lib/qubes %attr(2770,root,qubes) %dir /var/lib/qubes/vm-templates %attr(2770,root,qubes) %dir /var/lib/qubes/appvms