I used claude to find a reproducer and was able to confirm this:
Root cause: ufw's rules-file rewrite is not atomic, and rules are read
before the lock
The reporter's theory was right — it's corruption via concurrency — but
the lockfile you pointed to in the bug can't prevent it, because of
three compounding defects (all present in his 0.36.2, in noble's
0.36.2-6, and in current trunk):
1. Non-atomic rewrite — close_files() at src/util.py:275 updates user.rules
with shutil.copy(tmpname, origname): an in-place truncate followed by a
buffered rewrite of the live file, with no fsync and no rename. Every ufw
insert/delete passes through a window where user.rules on disk is empty or
half-written.
2. State is read outside the lock — main_ufw() constructs UFWFrontend (which
runs _read_rules()) at src/main.py:119, before create_lock() at
src/main.py:134. So every ufw process — including ufw status — snapshots the
rules file unlocked, then blocks on the lock holding a possibly torn/stale
snapshot, then (if it's a writer) rewrites the entire file from that snapshot.
3. The file is propagated into the kernel — for inserts and deletes, set_rule()
calls _reload_user_rules() (src/backend_iptables.py:1237,1253), which is cat
user.rules | iptables-restore -n. A stale or truncated file doesn't just sit
there; the next operation applies it to the live firewall.
** Changed in: ufw (Ubuntu)
Status: Expired => Triaged
** Changed in: ufw (Ubuntu)
Importance: Undecided => High
** Changed in: ufw (Ubuntu)
Assignee: (unassigned) => Jamie Strandboge (jdstrand)
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2126805
Title:
ufw can corrupt its own configuration when fail2ban is adding/removing
ufw rules
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/ufw/+bug/2126805/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs