Skip to content

Commit 5b41264

Browse files
committed
Support reloading in qubes-firewall service
1 parent 1f542b7 commit 5b41264

2 files changed

Lines changed: 34 additions & 15 deletions

File tree

qubesagent/firewall.py

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import subprocess
2828
import pwd
2929
import shutil
30+
import time
3031

3132
import qubesdb
3233
import sys
@@ -342,6 +343,7 @@ def dns_addresses(family=None):
342343

343344
def main(self):
344345
self.terminate_requested = False
346+
self.reload_requested = False
345347
self.init()
346348
self.run_firewall_dir()
347349
if not self.is_custom_persist_enabled():
@@ -355,29 +357,45 @@ def main(self):
355357
self.handle_addr(source_addr)
356358
self.update_connected_ips(4)
357359
self.update_connected_ips(6)
358-
try:
359-
for watch_path in iter(self.qdb.read_watch, None):
360-
if watch_path == '/connected-ips':
361-
self.update_connected_ips(4)
360+
while not self.terminate_requested:
361+
if self.reload_requested:
362+
clock_monotonic = time.clock_gettime(time.CLOCK_MONOTONIC)
363+
clock_monotonic = int(clock_monotonic * 1_000_000)
364+
self.sd_notify(f'RELOADING=1\nMONOTONIC_USEC={clock_monotonic}')
365+
for source_addr in self.list_targets():
366+
self.handle_addr(source_addr)
367+
self.reload_requested = False
368+
self.sd_notify('READY=1')
369+
try:
370+
watch_path = self.qdb.read_watch()
371+
except OSError: # EINTR
372+
# signal received, re-check loop condition
373+
continue
362374

363-
if watch_path == '/connected-ips6':
364-
self.update_connected_ips(6)
375+
if watch_path is None:
376+
break
365377

366-
# ignore writing rules itself - wait for final write at
367-
# source_addr level empty write (/qubes-firewall/SOURCE_ADDR)
368-
if watch_path.startswith('/qubes-firewall/') and watch_path.count('/') == 2:
369-
source_addr = watch_path.split('/')[2]
370-
self.handle_addr(source_addr)
378+
if watch_path == '/connected-ips':
379+
self.update_connected_ips(4)
380+
381+
if watch_path == '/connected-ips6':
382+
self.update_connected_ips(6)
383+
384+
# ignore writing rules itself - wait for final write at
385+
# source_addr level empty write (/qubes-firewall/SOURCE_ADDR)
386+
if watch_path.startswith('/qubes-firewall/') and watch_path.count('/') == 2:
387+
source_addr = watch_path.split('/')[2]
388+
self.handle_addr(source_addr)
371389

372-
except OSError: # EINTR
373-
# signal received, don't continue the loop
374-
pass
375390

376391
self.cleanup()
377392

378393
def terminate(self):
379394
self.terminate_requested = True
380395

396+
def reload(self):
397+
self.reload_requested = True
398+
381399
class NftablesWorker(FirewallWorker):
382400
supported_rule_opts = ['action', 'proto', 'dst4', 'dst6', 'dsthost',
383401
'dstports', 'specialtarget', 'icmptype']
@@ -662,6 +680,7 @@ def main():
662680
print('Sorry, iptables no longer supported', file=sys.stderr)
663681
sys.exit(1)
664682
signal.signal(signal.SIGTERM, lambda _signal, _stack: worker.terminate())
683+
signal.signal(signal.SIGHUP, lambda _signal, _stack: worker.reload())
665684
worker.main()
666685

667686

vm-systemd/qubes-firewall.service

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ After=qubes-iptables.service
55
Before=qubes-network.service
66

77
[Service]
8-
Type=notify
8+
Type=notify-reload
99
ExecStart=/usr/bin/qubes-firewall
1010

1111
[Install]

0 commit comments

Comments
 (0)