11 Commits

Author SHA1 Message Date
Cory Snider
624cba566d d/libn/i/nftables: fix unsynchronized SetBaseChainPolicy
SetBaseChainPolicy read the table's Chains map and modified the chain it
found without holding applyLock, only taking the lock when it called
Apply to make the change. Racing with an Apply that adds a chain, the map
read is a fatal "concurrent map read and map write".

Nothing calls it yet - the nftabler doesn't implement filterForwardDrop -
so this isn't a live bug, but the API shouldn't come with the race
attached.

Hold applyLock for the whole read-modify-apply. That needs an unexported
apply which assumes the lock is held, so split the body out of
Table.Apply, leaving the exported method as the wrapper that checks the
table and takes the lock, much like Reload and table.reload.

While here, make Reload report a closed table the same way as the other
two, rather than relying on the check in table.nftApply and reporting a
generic "invalid table" for a table that raced with Close.

The happy path of SetBaseChainPolicy had no test coverage at all, which
now matters more because it applies the table with applyLock held - a
deadlock would be silent. Add one.

Signed-off-by: Cory Snider <csnider@mirantis.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 10:52:59 -04:00
Cory Snider
558df8d6de d/libn/i/nftables: make Table a reference type
Table.Close() had a value receiver, so setting t.t = nil only modified
the callee's copy of the handle. The caller's Table was left looking
valid:

	t, _ := nftables.NewTable(...)
	t.Close()
	t.IsValid() // true

Worse, Close() only dropped the nftables handle, and nftApply() opens a
new one whenever it finds none. So Apply() and Reload() on a closed table
silently reopened a handle and carried on updating the ruleset.

At the root of it, a Table looked like a plain value but behaved like a
reference, and nothing stopped it from being copied. So embed table in
Table by value and hand out *Table instead. The Table/table split is
still needed - table's fields have to be exported for text/template -
but reference semantics are now visible at every call site, and they're
enforced: because table contains a sync.Mutex, "go vet" reports both a
copy of a Table and a method or function that takes one by value, so the
shape of this bug is no longer expressible.

Close() therefore can't invalidate the table by clearing a pointer, it
has to record the state. Add a closed flag, and refuse to open a new
nftables handle for a table that's been closed.

Apply() checked neither for a closed table nor for a nil *Table, which
would have panicked. It now reports an error, checking the closed state
with applyLock held so that it can't race with Close(), and before the
in-memory table is touched so that a rejected update isn't recorded as
applied.

The invalid table is now a nil *Table rather than a zero-value Table,
which also removes the need for consumers to return an empty Table
alongside an error. That made it obvious that the nftabler was leaking
the table it had just created when it gave up on setting up IPv6, so
close it.

Signed-off-by: Cory Snider <csnider@mirantis.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 10:52:59 -04:00
Cory Snider
c6c2df904e d/libn/i/nftables: fix setting multiple flags
Map and set flags are a comma-separated list.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-07-14 18:00:56 -04:00
Cory Snider
09001de685 d/libn/i/nftables: add netdev table support
Support specifying the device to associate a base chain with.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-07-02 18:43:38 -04:00
Cory Snider
7d4bb80d87 d/libn/i/nftables: define dynamic maps, sets
Add support for defining nftables maps and sets with size and timeout
specified, which are required values for maps and sets that are updated
from the packet path.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-07-02 18:42:45 -04:00
Cory Snider
4845c1f59a d/libn/i/nftables: add comments to elements of maps, sets
Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-07-02 18:40:47 -04:00
Cory Snider
b086f5e226 d/libn/i/nftables: drop unused golden testdata
Delete .golden files that are not referenced by any tests.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-07-02 18:40:47 -04:00
Cory Snider
f6fcfb044f d/libn/i/nftables: atomically apply many modifiers
Change (*nftables.Table).Apply() to take an arbitrary number of
Modifiers to be applied as a single atomic unit. Having the ability to
atomically apply multiple modifiers to a table enables some powerful
patterns such as atomically replacing one collection of rules or
elements with another:

    var update nftables.Modifier
    update.Create(/* ... */)
    t.Apply(reversePrevious, update)
    reversePrevious = update.Reverse()

Signed-off-by: Cory Snider <csnider@mirantis.com>
2026-06-30 18:19:18 -04:00
Rob Murray
785ae9a0f9 Rework the interface to libnet/internal/nftables
Add nftables.Modifier, to hold a queue of commands that can be applied
using Modifier.Apply. No updates are made to the underlying Table
until Apply is called, errors in the queue if commands are deferred
until Apply.

This has the advantages that:
- less error handling is needed in code that generates update commands
- it's transactional, without needing explicit transactions

Minor disadvantages are that it's slightly more difficult to debug updates,
as it's no longer possible to step through the call making an update to
the Table manipulation in a debugger - and errors in the command, and
errors like trying to update a nonexistent chain/set/vmap, deleting an
object that doesn't exist or creating a duplicate are not reported
until the updates are applied (but, the file/line where the rule was
added is reported).

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-08-28 19:27:19 +01:00
Albin Kerouanton
1d6c7663c4 d/libnet/i/nftables: move golden files into subdir
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-08-25 10:48:46 +02:00
Derek McGowan
7a720df61f Move libnetwork to daemon/libnetwork
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-14 09:25:23 -07:00