Commit 050f11e0 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by sanglipeng
Browse files

netfilter: nftables: update table flags from the commit phase

stable inclusion
from stable-v5.10.202
commit 7d1d3f1134254f5fae926f79fc0d94e3d7e2e452
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9DZOS

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7d1d3f1134254f5fae926f79fc0d94e3d7e2e452



--------------------------------

commit 0ce7cf41 upstream.

Do not update table flags from the preparation phase. Store the flags
update into the transaction, then update the flags from the commit
phase.

Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarsanglipeng <sanglipeng1@jd.com>
parent 8e38454c
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -1480,13 +1480,16 @@ struct nft_trans_chain {

struct nft_trans_table {
	bool				update;
	bool				enable;
	u8				state;
	u32				flags;
};

#define nft_trans_table_update(trans)	\
	(((struct nft_trans_table *)trans->data)->update)
#define nft_trans_table_enable(trans)	\
	(((struct nft_trans_table *)trans->data)->enable)
#define nft_trans_table_state(trans)	\
	(((struct nft_trans_table *)trans->data)->state)
#define nft_trans_table_flags(trans)	\
	(((struct nft_trans_table *)trans->data)->flags)

struct nft_trans_elem {
	struct nft_set			*set;
+16 −15
Original line number Diff line number Diff line
@@ -1074,6 +1074,12 @@ static void nf_tables_table_disable(struct net *net, struct nft_table *table)
	nft_table_disable(net, table, 0);
}

enum {
	NFT_TABLE_STATE_UNCHANGED	= 0,
	NFT_TABLE_STATE_DORMANT,
	NFT_TABLE_STATE_WAKEUP
};

static int nf_tables_updtable(struct nft_ctx *ctx)
{
	struct nft_trans *trans;
@@ -1097,19 +1103,17 @@ static int nf_tables_updtable(struct nft_ctx *ctx)

	if ((flags & NFT_TABLE_F_DORMANT) &&
	    !(ctx->table->flags & NFT_TABLE_F_DORMANT)) {
		nft_trans_table_enable(trans) = false;
		nft_trans_table_state(trans) = NFT_TABLE_STATE_DORMANT;
	} else if (!(flags & NFT_TABLE_F_DORMANT) &&
		   ctx->table->flags & NFT_TABLE_F_DORMANT) {
		ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
		ret = nf_tables_table_enable(ctx->net, ctx->table);
		if (ret >= 0)
			nft_trans_table_enable(trans) = true;
		else
			ctx->table->flags |= NFT_TABLE_F_DORMANT;
			nft_trans_table_state(trans) = NFT_TABLE_STATE_WAKEUP;
	}
	if (ret < 0)
		goto err;

	nft_trans_table_flags(trans) = flags;
	nft_trans_table_update(trans) = true;
	nft_trans_commit_list_add_tail(ctx->net, trans);
	return 0;
@@ -8511,11 +8515,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
		switch (trans->msg_type) {
		case NFT_MSG_NEWTABLE:
			if (nft_trans_table_update(trans)) {
				if (!nft_trans_table_enable(trans)) {
					nf_tables_table_disable(net,
								trans->ctx.table);
					trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
				}
				if (nft_trans_table_state(trans) == NFT_TABLE_STATE_DORMANT)
					nf_tables_table_disable(net, trans->ctx.table);

				trans->ctx.table->flags = nft_trans_table_flags(trans);
			} else {
				nft_clear(net, trans->ctx.table);
			}
@@ -8764,11 +8767,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
		switch (trans->msg_type) {
		case NFT_MSG_NEWTABLE:
			if (nft_trans_table_update(trans)) {
				if (nft_trans_table_enable(trans)) {
					nf_tables_table_disable(net,
								trans->ctx.table);
					trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
				}
				if (nft_trans_table_state(trans) == NFT_TABLE_STATE_WAKEUP)
					nf_tables_table_disable(net, trans->ctx.table);

				nft_trans_destroy(trans);
			} else {
				list_del_rcu(&trans->ctx.table->list);