Lock file in world-writable /tmp with unbounded blocking wait #18
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
eric/10-wancarp#18
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The run lock is
/tmp/wancarp.lock, and CARP event runs wait on it with a blockingflock(LOCK_EX)and no timeout. Two problems:/tmp/wancarp.lockand hold anflockon it. Every CARP event run then blocks forever, so failover never changes WAN state, and every--reconcilequietly backs off (exit(0), nothing logged). Opening with'ce'doesn't truncate, so a symlink can't clobber anything; the problem is denial of service only. Low risk on a firewall with no untrusted shell users, but cheap to fix.interface_configure()stuck) blocks every later event with nothing in the log. #11 (inherited lock FD held bydhclient) was this failure mode: events blocked indefinitely and reconcile went silent. A bounded wait would have made it visible.Where
const LOCKFILE = '/tmp/wancarp.lock';(around line 171)/tmp/wancarp.lock)".Suggested fix
/var/run/wancarp.lock.LOCK_EXwith aLOCK_EX | LOCK_NBretry loop (e.g. every 0.5 s up to ~60 s, longer than a normal run). On timeout,werr("timed out waiting for lock ...")and end with the existingaborted=lockbanner. Note that a timed-out event loses its update, which is acceptable because the next reconcile re-applies the role. Mention this in the comment.'e'(close-on-exec) mode flag and its comment; it is still required.[Unreleased]entry.Acceptance
lockf -k /var/run/wancarp.lock sleep 120) makes an event run log the timeout andaborted=lockwithin the bound; reconcile still backs off quietly.Follow-up audit: the lock was still takeable by a local user
Fixed in
222180a.Finding. Moving the lock to
/var/runstopped other users from creating it, butfopen(LOCKFILE, 'ce')runs as root with umask 022, so the file came out0644.flock(LOCK_EX)works on a read-only descriptor (confirmed in PHP), so any local user could still open it read-only and hold it. With the 60 s bound, event runs would endaborted=lock(logged), but--reconcilebacks off silently whenever the lock is held, so drift would go uncorrected with nothing in the log.Fix. The lock is opened under
umask(0077), so a new file is0600, and thenchmoded to0600, which also tightens a file that already exists. Two harness cases check this: a new lock file ends up0600, and an existing0644one is tightened to0600. Both fail against the previous script.#21's #18 section now expects
-rw-------and adds a check thatnobodycan't take the lock.