We currently race when several xtables-nft-restore processes attempt to
handle rules in parallel. For instance, when no rules are present at
all, then
iptables-nft-restore < X & iptables-nft-restore < X
... can cause rules to be restored twice.
Reason is that both processes might detect 'no rules exist', so
neither issues a flush operation.
We can't unconditionally issue the flush, because it would
cause kernel to fail with -ENOENT unless the to-be-flushed table
exists.
This change passes the generation id that was used to build
the transaction to the kernel.
In case another process changed *any* rule somewhere, the transaction
will now fail with -ERESTART.
We then flush the cache, re-fetch the ruleset and refresh
our transaction.
For example, in the above 'parallel restore' case, the iptables-restore
instance that lost the race would detect that the table has been created
already, and would add the needed flush.
In a similar vein, in case --noflush is used, we will add the flush
op for user-defined chains that were created in the mean-time.
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>