The ipset garbage collector has a race condition that can lead to use-after-free or data corruption during set destruction. The mechanism: the gc worker unconditionally requeues itself at the end of each run. When cancel_delayed_work_sync() is called during ipset set destruction, it blocks until the current gc run completes — but that run immediately requeues the worker into freed or partially-destructed memory before the destroy path can proceed. The synchronous cancel returns 'success' while the worker is already running again in a dangerous state.

The EPSS score (0.00163) reflects that this race is difficult to trigger reliably, which is typical for timing-dependent bugs. However, the difficulty of trigger and the severity of consequence are separate metrics. A CVSS 7.8 indicates the actual impact — corrupting netfilter packet classification state — is significant when the race does trigger.

The critical exploitation boundary is CAP_NET_ADMIN. Creating and destroying ipset sets requires this capability, which bounds direct exploitation to privileged contexts. That said, watch for kernel versions where unprivileged namespace access to ipset manipulation may have expanded — that boundary has shifted in past kernel releases.

The deeper pattern: this isn't an isolated bug. The same failure mode appears in timerfd cleanup, RCU callbacks, and block layer plug flush. Each time the fix converges on a coordination flag (a kthread_should_stop()-style boolean) that the worker checks before requeuing, not after cancel returns. The workqueue API's cancel_delayed_work_sync() guarantees the work function finishes executing, not that it won't requeue itself. That's the gap in what the API communicates versus what developers assume.

For defenders: verify your kernel version's ipset implementation uses a stop flag rather than relying on cancel alone. If you're on an older version with the race, prioritize the update — not because exploitation is easy, but because the consequence (corrupted firewall state) is severe. And check your other netfilter and timerfd code for similar patterns: the genetic sequence is well-documented in kernel commit history, and more instances may exist.