@@ -1225,24 +1225,25 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
if ((flags ^ ctx->table->flags) & NFT_TABLE_F_PERSIST)
return -EOPNOTSUPP;
- /* No dormant off/on/off/on games in single transaction */
- if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
- return -EINVAL;
-
trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
sizeof(struct nft_trans_table));
if (trans == NULL)
return -ENOMEM;
+ ret = -EINVAL;
if ((flags & NFT_TABLE_F_DORMANT) &&
!(ctx->table->flags & NFT_TABLE_F_DORMANT)) {
- ctx->table->flags |= NFT_TABLE_F_DORMANT;
- if (!(ctx->table->flags & __NFT_TABLE_F_UPDATE))
- ctx->table->flags |= __NFT_TABLE_F_WAS_AWAKEN;
+ /* No dormant on/off/on games in single transaction */
+ if (ctx->table->flags & __NFT_TABLE_F_WAS_DORMANT)
+ goto err_flags;
+ ctx->table->flags |= NFT_TABLE_F_DORMANT | __NFT_TABLE_F_WAS_AWAKEN;
} else if (!(flags & NFT_TABLE_F_DORMANT) &&
ctx->table->flags & NFT_TABLE_F_DORMANT) {
+ /* No dormant off/on/off games in single transaction */
+ if (ctx->table->flags & __NFT_TABLE_F_WAS_AWAKEN)
+ goto err_flags;
ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
- if (!(ctx->table->flags & __NFT_TABLE_F_UPDATE)) {
+ if (!(ctx->table->flags & __NFT_TABLE_F_WAS_DORMANT)) {
ret = nf_tables_table_enable(ctx->net, ctx->table);
if (ret < 0)
goto err_register_hooks;
@@ -1265,6 +1266,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
err_register_hooks:
ctx->table->flags |= NFT_TABLE_F_DORMANT;
+err_flags:
nft_trans_destroy(trans);
return ret;
}
Updating a table with the same flags more than once in single transaction failed if its previous flags is different from the new one. For example, the 2nd transaction below would fail: nft -f -<<EOF add table ip t { flags dormant ; } EOF nft -f -<<EOF add table ip t add chain ip t c1 { type filter hook input priority 1; } add table ip t add chain ip t c2 { type filter hook input priority 2; } EOF This was because nf_tables_updtable rejected all further updates made to a table after it was updated once, even though they are consistent with the first update. The intent of the check should be to reject dormant off/on/off games, the patch fixes the check to allow consitent updates. Fixes: c9bd26513b3a ("netfilter: nf_tables: disable toggling dormant table state more than once") Signed-off-by: Quan Tian <tianquan23@gmail.com> --- net/netfilter/nf_tables_api.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)